[
  {
    "path": ".buildscript/prepare_mkdocs.sh",
    "content": "#!/bin/bash\n\n# The website is built using MkDocs with the Material theme.\n# https://squidfunk.github.io/mkdocs-material/\n# It requires Python to run.\n# Install the packages with the following command:\n# pip install mkdocs mkdocs-material\n\nset -ex\n\n# Generate the API docs\n./gradlew dokkaHtml\n\n# Copy in special files that GitHub wants in the project root.\ncp CHANGELOG.md docs/changelog.md\ncp CONTRIBUTING.md docs/contributing.md\n"
  },
  {
    "path": ".buildscript/restore_v1_docs.sh",
    "content": "#!/bin/bash\n\n# Commit b3205fa199a19d6fbf13ee5c8e0c3d6d2b15b05f contains\n# Javadoc for Okio 1.x. Those should be present on\n# gh-pages and published along with the other website\n# content, but if for some reason they have to be re-added\n# to gh-pages - run this script locally.\n\nset -ex\n\nDIR=temp-clone\n\n# Delete any existing temporary website clone\nrm -rf $DIR\n\n# Clone the current repo into temp folder\ngit clone . $DIR\n\n# Move working directory into temp folder\ncd $DIR\n\n# Restore docs from 1.x\ngit checkout b3205fa199a19d6fbf13ee5c8e0c3d6d2b15b05f\nmkdir -p ../site\nmv ./1.x ../site/1.x\n\n# Restore docs from 2.x\ngit checkout 9235ff8faca96082aa8784e789448b5f4893af69\nmkdir -p ../site\nmv ./2.x ../site/2.x\n\n# Delete our temp folder\ncd ..\nrm -rf $DIR\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ninsert_final_newline=true\nend_of_line=lf\ncharset=utf-8\nindent_size=2\ntrim_trailing_whitespace=true\n\n[*.{kt,kts}]\nij_kotlin_allow_trailing_comma=true\nij_kotlin_allow_trailing_comma_on_call_site=true\nij_kotlin_imports_layout=*\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n\n*.bat text eol=crlf\n*.jar binary"
  },
  {
    "path": ".github/renovate.json5",
    "content": "{\n  $schema: 'https://docs.renovatebot.com/renovate-schema.json',\n  extends: [\n    'config:recommended',\n  ],\n  ignorePresets: [\n    // Ensure we get the latest version and are not pinned to old versions.\n    'workarounds:javaLTSVersions',\n  ],\n  customManagers: [\n    // Update .java-version file with the latest JDK version.\n    {\n      customType: 'regex',\n      fileMatch: [\n        '\\\\.java-version$',\n      ],\n      matchStrings: [\n        '(?<currentValue>.*)\\\\n',\n      ],\n      datasourceTemplate: 'java-version',\n      depNameTemplate: 'java',\n      // Only write the major version.\n      extractVersionTemplate: '^(?<version>\\\\d+)',\n    },\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/.java-version",
    "content": "25\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: build\n\non:\n  pull_request: {}\n  workflow_dispatch: {}\n  push:\n    branches:\n      - 'master'\n    tags-ignore:\n      - '**'\n\nenv:\n  GRADLE_OPTS: \"-Dorg.gradle.jvmargs=-Xmx2g -Dorg.gradle.daemon=false -Dkotlin.incremental=false\"\n\njobs:\n  jvm:\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        java-version:\n          - 8\n          - 11\n          - 17\n          - latest\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Validate Gradle Wrapper\n        uses: gradle/actions/wrapper-validation@v5\n\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version-file: .github/workflows/.java-version\n\n      - name: Test\n        run: |\n          ./gradlew -Dkjs=false -Dknative=false -Dkwasm=false -Dtest.java.version=${{ matrix.java-version }} build --stacktrace\n\n  emulator:\n    runs-on: ubuntu-latest\n    steps:\n      # https://github.blog/changelog/2023-02-23-hardware-accelerated-android-virtualization-on-actions-windows-and-linux-larger-hosted-runners/\n      - name: Enable KVM group perms\n        run: |\n          echo 'KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0666\", OPTIONS+=\"static_node=kvm\"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules\n          sudo udevadm control --reload-rules\n          sudo udevadm trigger --name-match=kvm\n          ls /dev/kvm\n      - uses: actions/checkout@v6\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version-file: .github/workflows/.java-version\n\n      - uses: gradle/actions/setup-gradle@v5\n\n      - uses: reactivecircus/android-emulator-runner@v2\n        with:\n          api-level: 24\n          script: ./gradlew :okio-assetfilesystem:connectedCheck\n\n  loom:\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Validate Gradle Wrapper\n        uses: gradle/actions/wrapper-validation@v5\n\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version-file: .github/workflows/.java-version\n\n      - name: Test\n        run: |\n          ./gradlew -DloomEnabled=true build\n\n  all-platforms:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ macos-14, ubuntu-latest, windows-latest ]\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Validate Gradle Wrapper\n        uses: gradle/actions/wrapper-validation@v5\n\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version-file: .github/workflows/.java-version\n\n      - name: Test\n        if: matrix.os != 'windows-latest'\n        run: |\n          ./gradlew build\n\n      - name: Test (No WASM)\n        if: matrix.os == 'windows-latest'\n        run: |\n          ./gradlew build -Dkwasm=false\n\n      - name: Save Test Reports\n        if: failure()\n        uses: actions/upload-artifact@v7\n        with:\n          name: test-reports\n          path: '**/build/reports'\n\n  publish:\n    runs-on: macos-15\n    if: github.repository == 'square/okio' && github.ref == 'refs/heads/master'\n    needs: [jvm, all-platforms, emulator]\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version-file: .github/workflows/.java-version\n\n      - name: Upload Artifacts\n        run: |\n          ./gradlew publish --stacktrace\n        env:\n          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }}\n          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }}\n          ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SECRET_KEY }}\n          ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SECRET_PASSPHRASE }}\n\n  publish-website:\n    runs-on: ubuntu-latest\n    if: github.repository == 'square/okio' && github.ref == 'refs/heads/master'\n    needs: [jvm, all-platforms, emulator]\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version-file: .github/workflows/.java-version\n\n      - name: Set up Python\n        uses: actions/setup-python@v6\n        with:\n          python-version: 3.14\n\n      - name: Prepare docs\n        run: .buildscript/prepare_mkdocs.sh\n\n      - name: Build mkdocs\n        run: |\n          pip3 install mkdocs-material mkdocs-macros-plugin\n          mkdocs build\n\n      - name: Restore 1.x docs\n        run: .buildscript/restore_v1_docs.sh\n\n      - name: Deploy docs\n        if: success()\n        uses: JamesIves/github-pages-deploy-action@releases/v3\n        with:\n          GITHUB_TOKEN: ${{ secrets.GH_CLIPPY_TOKEN }}\n          BRANCH: gh-pages\n          FOLDER: site\n          SINGLE_COMMIT: true\n"
  },
  {
    "path": ".github/workflows/release.yaml",
    "content": "name: release\n\non:\n  push:\n    tags:\n      - '**'\n\nenv:\n  GRADLE_OPTS: \"-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false\"\n\njobs:\n  publish:\n    runs-on: macos-15\n\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-java@v5\n        with:\n          distribution: 'zulu'\n          java-version-file: .github/workflows/.java-version\n\n      - run: ./gradlew publish\n        env:\n          ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_CENTRAL_USERNAME }}\n          ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_CENTRAL_PASSWORD }}\n          ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_SECRET_KEY }}\n          ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_SECRET_PASSPHRASE }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".classpath\n.gradle\n.kotlin\n.project\n.settings\neclipsebin\n\nbin\ngen\nbuild\nout\nlib\nreports\n\n.idea\n*.iml\n*.ipr\n*.iws\nclasses\nlocal.properties\n\nobj\n\n.DS_Store\n\nnode_modules\n\n# Special Mkdocs files\ndocs/3.x\ndocs/changelog.md\ndocs/contributing.md\n"
  },
  {
    "path": "BUG-BOUNTY.md",
    "content": "Serious about security\n======================\n\nSquare recognizes the important contributions the security research community\ncan make. We therefore encourage reporting security issues with the code\ncontained in this repository.\n\nIf you believe you have discovered a security vulnerability, please follow the\nguidelines at https://bugcrowd.com/engagements/blockopensource.\n\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "Change Log\n==========\n\n## Unreleased\n\n * None yet.\n\n## Version 3.17.0\n\n_2026-03-11_\n\n * New: Adjust down the Kotlin stdlib dependency to [Kotlin 2.1.21][kotlin_2_1_21]. Okio is built\n   with an up-to-date Kotlin compiler (2.2.21), but depends on an older kotlin-stdlib. We're doing\n   this so you can update Okio and Kotlin independently.\n\n * Fix: Return the correct timestamp in `FileMetadata.createdAtMillis` on Kotlin/Native on UNIX\n   platforms. We were incorrectly using the POSIX `ctime` (_change_ time) instead of the\n   `birthtime`. With this fix Okio now prefers `statx()` over `stat()` on native platforms. This\n   API first appeared in Linux in 4.11 (2017) and Android in API 30 (2020).\n\n\n## Version 3.16.4\n\n_2025-11-17_\n\n* Fix: Don't delay triggering timeouts. In 3.16.0 we introduced a regression that caused timeouts\n  to fire later than they were supposed to.\n\n\n## Version 3.16.3\n\n_2025-11-14_\n\nThis release is the same as 3.16.2. We forgot to cherry-pick a commit before we released!\n\n\n## Version 3.16.2\n\n_2025-10-14_\n\n * Fix: `okio-assetfilesystem` APIs now correctly restored as visible to Kotlin.\n\n\n## Version 3.16.1\n\n_2025-10-09_\n\n * Fix: Don't crash when calling `Socket.shutdownOutput()` or `shutdownInput()` on an `SSLSocket` on\n   Android API 21. This method throws an `UnsupportedOperationException`, so we now catch that and\n   close the underlying stream instead.\n\n\n## Version 3.16.0\n\n_2025-07-29_\n\n * Fix: Change `Socket.asOkioSocket()` to resolve its source `InputStream` and `OutputStream`\n   eagerly. This will throw a `SocketException` immediately if the socket isn’t connected.\n   This behavior is consistent with our similar APIs, `Socket.source()` and `Socket.sink()`.\n\n * Fix: Optimize `AsyncTimeout` on systems with a very large number of active timeouts. This class\n   originally kept active timeouts in a linked list; with this update the internal data structure is\n   a binary heap. The old runtime was 𝑂(𝑛²) to activate 𝑛 timeouts; with this optimization the\n   runtime is 𝑂(𝑛 log 𝑛).\n\n * Upgrade: [Kotlin 2.2.0][kotlin_2_2_0].\n\n\n## Version 3.15.0\n\n_2025-07-01_\n\n * Upgrade: [kotlinx-datetime 0.7.0-0.6.x-compat][datetime_0_7_0_compat]. The previous 3.14.0\n   release, `FakeFileSystem` broke binary-compatibility for calls to `FakeFileSystem()`. This\n   restores that compatibility.\n\n * Breaking: Change `FakeFileSystem.clock` from a JVM field to a property. This avoids a crash\n   running Okio in a Gradle 8.x plugin. This change is not binary-compatible.\n\n\n## Version 3.14.0\n\n_2025-06-28_\n\n * Upgrade: [kotlinx-datetime 0.7.0][datetime_0_7_0]. This impacts the `okio-fakefilesystem`\n   artifact only. This is a binary-incompatible backwards-incompatible change that cannot co-exist\n   with previous releases of `okio-fakefilesystem`! If you observe a `NoSuchMethodError` calling\n   `FakeFileSystem.init`, update the calling code to this release (or newer) and recompile. We don't\n   like imposing backwards-incompatible changes like this on you and do so regretfully.\n\n\n## Version 3.13.0\n\n_2025-06-13_\n\n * New: `okio.Socket` interface. This is a first step towards low-level streaming networking support\n   for Kotlin/Multiplatform. This release provides two JVM-only implementations: `asOkioSocket()`\n   adapts a `java.net.Socket` to our new interface, and `inMemorySocketPair()` returns a pair of\n   mutually-connected sockets. We also anticipate that this interface will be a useful abstraction\n   for proxies and tunnels.\n * New: In-development snapshots are now published to the [Central Portal Snapshots repository].\n\n\n## Version 3.12.0\n\n_2025-05-27_\n\n * New: Support an optional end index when searching with `BufferedSource.indexOf()`.\n * Fix: Don't do unnecessary work in `BufferedSource.rangeEquals()`.\n * Upgrade: [Kotlin 2.1.21][kotlin_2_1_21].\n\n\n## Version 3.11.0\n\n_2025-04-09_\n\n * Fix: Clear the deflater's byte array reference\n * New: Faster implementation of `String.decodeHex()` on Kotlin/JS.\n * New: Declare `EXACTLY_ONCE` execution for blocks like `Closeable.use {}` and `FileSystem.read {}`.\n * Upgrade: [Kotlin 2.1.20][kotlin_2_1_20].\n\n\n## Version 3.10.2\n\n_2025-01-08_\n\n * Fix: `okio-nodefilesystem` artifact is no longer empty.\n\n\n## Version 3.10.1\n\n_2025-01-07_\n\n * New: `FileSystem.close()` may prevent future access and/or clean up associated resources depending on the backing implementation. `FakeFileSystem` will prevent future operations once closed.\n * `InputStream`s created from `BufferedSource.inputStream()` now have a more efficient version of `InputStream.transferTo()` which reduces memory copies.\n * `okio-nodefilesystem` is no longer publised as a JS project, but a Kotlin multiplatform project with only a JS target. ~This change should not affect consumers in any way, and is motivated by the Kotlin Gradle plugin deprecating the JS-only plugin.~ Please use 3.10.2 to ensure this change actually does not affect your builds.\n\n\n## Version 3.10.0\n\n_2025-01-06_\n\nThis version is equivalent to the subsequent 3.10.1, but it did not fully publish to Maven Central due to infrastructure problems.\n\n\n## Version 3.9.1\n\n_2024-09-12_\n\n * Fix: Support paths containing a single dot (\".\") in `Path.relativeTo`.\n * Fix: Do not read from the upstream source when a 0-byte read is requested.\n * Fix: Update kotlinx.datetime to 0.6.0 to correct a Gradle module metadata problem with 0.5.0.\n   Note: this artifact is only used in 'okio-fakefilesystem' and 'okio-nodefilesystem' and not in the Okio core.\n\n\n## Version 3.9.0\n\n_2024-03-12_\n\n * New: `FileSystem.SYSTEM` can be used in source sets that target both Kotlin/Native and\n   Kotlin/JVM. Previously, we had this symbol in each source set but it wasn't available to\n   common source sets.\n * New: `COpaquePointer.readByteString(...)` creates a ByteString from a memory address.\n * New: Support `InflaterSource`, `DeflaterSink`, `GzipSink`, and `GzipSource` in Kotlin/Native.\n * New: Support openZip() on Kotlin/Native. One known bug in this implementation is that\n   `FileMetadata.lastModifiedAtMillis()` is interpreted as UTC and not the host machine's time zone.\n * New: Prefer NTFS timestamps in ZIP file systems' metadata. This avoids the time zone problems\n   of ZIP's built-in DOS timestamps, and the 2038 time bombs of ZIP's extended timestamps.\n * Fix: Don't leak file handles to opened JAR files open in `FileSystem.RESOURCES`.\n * Fix: Don't throw a `NullPointerException` if `Closeable.use { ... }` returns null.\n\n\n## Version 3.8.0\n\n_2024-02-09_\n\n * New: `TypedOptions` works like `Options`, but it returns a `T` rather than an index.\n * Fix: Don't leave sinks open when there's a race in `Pipe.fold()`.\n\n\n## Version 3.7.0\n\n_2023-12-16_\n\n * New: `Timeout.cancel()` prevents a timeout from firing.\n * Breaking: Drop the `watchosX86` Kotlin/Native target. From [the Kotlin blog][watchosX86],\n   _‘This is an obsolete simulator for Intel Macs. Use the watchosX64 target instead.’_\n * New: Add the `watchosDeviceArm64` Kotlin/Native target.\n * New: `Timeout` APIs that accept `kotlin.time.Duration`.\n * Upgrade: [Kotlin 1.9.21][kotlin_1_9_21].\n\n\n## Version 3.6.0\n\n_2023-10-01_\n\n * Fix: Don't leak file handles when using `metadata` functions on `ZipFileSystem`. We had a bug\n   where we were closing the `.zip` file, but not a stream inside of it. We would have prevented\n   this bug if only we’d used `FakeFileSystem.checkNoOpenFiles()` in our tests!\n * Fix: Don't build an index of a class loader's resources in `ResourceFileSystem.read()`. This\n   operation doesn't need this index, and building it is potentially expensive.\n * New: Experimentally support Linux on ARM64 for Kotlin/Native targets (`linuxArm64`). Note that\n   we haven't yet added CI test coverage for this platform.\n * Upgrade: [Kotlin 1.9.10][kotlin_1_9_10].\n\n\n## Version 1.17.6\n\n_2023-10-01_\n\n * Fix: Don't crash decoding GZIP files when the optional extra data (`XLEN`) is 32 KiB or larger.\n\n\n## Version 3.5.0\n\n_2023-08-02_\n\n * New: Support the WebAssembly (WASM) platform. Okio's support for WASM is experimental, but\n   improving, just like Kotlin's own support for WASM.\n * New: Adapt WebAssembly System Interface (WASI) API's as an Okio FileSystem using\n   `WasiFileSystem`. This is in the new `okio-wasifilesystem` module. It requires the [preview1]\n   WASI API. We’ll make backwards-incompatible upgrades to new WASI API versions as they become\n   available.\n * Fix: Return relative paths in the NIO adapter FileSystem when required. `FileSystem.list()`\n   had always returned absolute paths, even when the target directory was supplied as a relative\n   path.\n * Fix: Don't crash when reading into an empty array using `FileHandle` on Kotlin/Native.\n * Upgrade: [Kotlin 1.9.0][kotlin_1_9_0].\n\n\n## Version 3.4.0\n\n_2023-07-07_\n\n * New: Adapt a Java NIO FileSystem (`java.nio.file.FileSystem`) as an Okio FileSystem using\n   `fileSystem.asOkioFileSystem()`.\n * New: Adapt Android’s `AssetManager` as an Okio FileSystem using `AssetFileSystem`. This is in the\n   new `okio-assetfilesystem` module. Android applications should prefer this over\n   `FileSystem.RESOURCES` as it’s faster to load.\n * Fix: Don't crash decoding GZIP files when the optional extra data (`XLEN`) is 32 KiB or larger.\n * Fix: Resolve symlinks in `FakeFileSystem.canonicalize()`.\n * Fix: Report the correct `createdAtMillis` in `NodeJsFileSystem` file metadata. We were\n   incorrectly using `ctimeMs`, where `c` means _changed_, not _created_.\n * Fix: `UnsafeCursor` is now `Closeable`.\n\n\n## Version 3.3.0\n\n_2023-01-07_\n\n * Fix: Don't leak resources when `use {}` is used with a non-local return. We introduced this\n   performance and stability bug by not considering that non-local returns execute neither the\n   `return` nor `catch` control flows.\n * Fix: Use a sealed interface for `BufferedSink` and `BufferedSource`. These were never intended\n   for end-users to implement, and we're happy that Kotlin now allows us to express that in our API.\n * New: Change internal locks from `synchronized` to `ReentrantLock` and `Condition`. We expect this\n   to improve help when using Okio with Java virtual threads ([Project Loom][loom]).\n * Upgrade: [Kotlin 1.8.0][kotlin_1_8_0].\n\n\n## Version 3.2.0\n\n_2022-06-26_\n\n * Fix: Configure the multiplatform artifact (`com.squareup.okio:okio:3.x.x`) to depend on the\n   JVM artifact (`com.squareup.okio:okio-jvm:3.x.x`) for Maven builds. This should work-around an\n   issue where Maven doesn't interpret Gradle metadata.\n * Fix: Change `CipherSource` and `CipherSink` to recover if the cipher doesn't support streaming.\n   This should work around a crash with AES/GCM ciphers on Android.\n * New: Enable compatibility with non-hierarchical projects.\n\n\n## Version 3.1.0\n\n_2022-04-19_\n\n * Upgrade: [Kotlin 1.6.20][kotlin_1_6_20].\n * New: Support [Hierarchical project structure][hierarchical_projects]. If you're using Okio in a\n   multiplatform project please upgrade your project to Kotlin 1.6.20 (or newer) to take advantage\n   of this. With hierarchical projects it's easier to use properties like `FileSystem.SYSTEM` that\n   are available on most Okio platforms but not all of them.\n * New: `ForwardingSource` is now available on all platforms.\n * New: The `watchosX64` platform is now supported.\n * Fix: Don't crash in `NSData.toByteString()' when the input is empty.\n * Fix: Support empty ZIP files in `FileSystem.openZip()`.\n * Fix: Throw in `canonicalize()` of ZIP file systems if the path doesn't exist.\n * Fix: Don't require ZIP files start with a local file header.\n * New: `okio.ProtocolException` is a new exception type for multiplatform users. (It is aliased to\n   `java.net.ProtocolException` on JVM platforms).\n\n\n## Version 3.0.0\n\n_2021-10-28_\n\nThis is the first stable release of Okio 3.x. This release is strongly backwards-compatible with\nOkio 2.x, and the new major version signifies new capabilities more than it does backwards\nincompatibility.\n\nMost users should be able to upgrade from 2.x by just changing the version. If you're using Okio\nin a Kotlin Multiplatform project, you'll need to drop the `-multiplatform` suffix in your Gradle\ndependencies.\n\n * New: Remove `@ExperimentalFileSystem`. This annotation is no longer necessary as the file system\n   is no longer experimental!\n * New: Path no longer aggressively normalizes `..` segments. Use `Path.normalize()` to apply these\n   based on the content of the path, or `FileSystem.canonicalize()` to do it honoring any symlinks\n   on a particular file system.\n * New: Publish a [bill of materials (BOM)][bom] for Okio. Depend on this from Gradle or Maven to\n   keep all of your Okio artifacts on the same version, even if they're declared via transitive\n   dependencies. You can even omit versions when declaring other Okio dependencies.\n\n   ```kotlin\n   dependencies {\n      api(platform(\"com.squareup.okio:okio-bom:3.0.0\"))\n      api(\"com.squareup.okio:okio\")                // No version!\n      api(\"com.squareup.okio:okio-fakefilesystem\") // No version!\n   }\n   ```\n\n * New: `FileSystem.delete()` silently succeeds when deleting a file that doesn't exist. Use\n   the new `mustExist` parameter to trigger an exception instead.\n * New: `FileSystem.createDirectories()` silently succeeds when creating a directory that already\n   exists. Use the new `mustCreate` parameter to trigger an exception instead.\n * New: `FileSystem` offers Java-language overloads where appropriate. Previously functions that\n   had default parameters were potentially awkward to invoke from Java.\n * New: `Timeout.intersectWith()` returns a value instead of `Unit`. This is a binary-incompatible\n   change. We expect that this public API is very rarely used outside of Okio itself.\n * Fix: Change `BufferedSource.readDecimalLong()` to fail if the input value is just `-`. Previously\n   Okio incorrectly returned `0` for this.\n\n\n## Version 3.0.0-alpha.11\n\n_2021-10-23_\n\n * Upgrade: [Kotlin 1.5.31][kotlin_1_5_31].\n * Upgrade: [kotlinx-datetime 0.3.0][datetime_0_3_0]. (This is a dependency of `okio-fakefilesystem`\n   only.)\n * New: Support creating and accessing symlinks. We were reluctant to include symlinks in our API\n   (to keep it small!) but decided that supporting them was essential to properly implement\n   recursive traversal.\n * New: `FileMetadata.extras` can track metadata for custom `FileSystem` implementations.\n * New: Support Apple Silicon Kotlin/Native targets (`macosArm64`, `iosSimulatorArm64`,\n   `tvosSimulatorArm64`, and `watchosSimulatorArm64`).\n * New: `FileSystem.listRecursively()` returns a `Sequence` that includes all of a directory's\n   children, and all of their children recursively. The implementation does a lazy, depth-first\n   traversal.\n * New: `Path.relativeTo()` computes how to get from one path to another.\n * New: `Path.root` and `Path.segments`. These APIs decompose a path into its component parts.\n * New: `FileSystem.listOrNull()` returns a directory's children, or null if the path doesn't\n   reference a readable directory.\n * New: Option to fail if the file being updated doesn't already exist: `mustExist`. Use this to\n   avoid creating a new file when your intention is to update an existing file.\n * New: Option to fail if a file being created already exists: `mustCreate`. Use this to avoid\n   updating an existing file when your intention is to create a new file.\n * Fix: Restore support for Kotlin/JS on browser platforms. We were relying on NodeJS-only features\n   to fetch the local directory separator (`/` or `\\`) and temporary directory.\n * Fix: Don't ignore the caller's specified write offset running Okio on Kotlin/Native on Linux.\n   (`FileHandle.write()` was broken and always appended to the end of the file.)\n\n\n## Version 3.0.0-alpha.10\n\n_2021-09-09_\n\nThis release drops the `-multiplatform` suffix on Kotlin Multiplatform artifacts. All artifacts now\nshare the same name (like `com.squareup.okio:okio:3.0.0-alpha.10`) for both Kotlin/JVM and Kotlin\nMultiplatform.\n\n * Fix: Don't crash in `ResourceFileSystem` when classpath `.jar` files have special characters in\n   their paths.\n\n\n## Version 3.0.0-alpha.9\n\n_2021-08-01_\n\n * New: `ByteString.copyInto()` saves an allocation when extracting data from a `ByteString`.\n * Fix: Create `FileHandle.protectedSize()` to match other abstract functions.\n * Fix: Open files in binary mode on Windows. Without this, files that contain `0x1a` will be\n   truncated prematurely.\n\n\n## Version 3.0.0-alpha.8\n\n_2021-07-13_\n\n * Fix: Don't crash on duplicate entries in a .zip file.\n * Fix: Change `FileSystem.RESOURCES` to initialize itself lazily.\n\n\n## Version 3.0.0-alpha.7\n\n_2021-07-12_\n\n * Fix: Change `ResourceFileSystem` to load roots eagerly. We had a bug where `list()` on the root\n   returned an empty list even if resources were present.\n * New: `FileHandle.reposition()` can seek on a source or sink returned by that `FileHandle`.\n * New: Move the system resources instance to `FileSystem.RESOURCES`.\n * Upgrade: [Kotlin 1.5.20][kotlin_1_5_20].\n\n\n## Version 3.0.0-alpha.6\n\n_2021-06-01_\n\n * New: `FileHandle` supports random access reads, writes, and resizes on files. Create an instance\n   with `FileSystem.openReadOnly()` or `FileSystem.openReadWrite()`.\n * New: Remove `Cursor` which is obsoleted by `FileHandle`. (`UnsafeCursor` is still around!)\n * New: Add support for the new intermediate representation (IR) artifacts in Kotlin/JS. We still\n   support the legacy artifact format.\n * New: Support tvOS (tvosArm64, tvosX64) in multiplatform.\n * New: Change `ResourceFileSystem` to omit `.class` files when indexing `.zip` files. We expect\n   this to lower the memory footprint of `ResourceFileSystem`.\n * Fix: Don't crash on background thread access in Kotlin/Native. We had to apply `@SharedImmutable`\n   and run our test suite on a background thread.\n\n\n## Version 3.0.0-alpha.5\n\n_2021-04-27_\n\n * New: Promote the `ZipFileSystem` and `ResourceFileSystem` to the main Okio module. These are\n   currently JVM-only. The `okio-zipfilesystem` module is no longer published.\n\n\n## Version 3.0.0-alpha.4\n\n_2021-04-14_\n\n * Fix: Rename internal classes to avoid name collisions. We were seeing problems due to having\n   multiple files named `-Platform.kt`.\n\n\n## Version 3.0.0-alpha.3\n\n_2021-04-06_\n\n * New: Move `NodeJsFileSystem` into its own module. Having it built-in prevented Okio from working\n   in a browser where there's no synchronous file system API. This is in the `okio-nodefilesystem`\n   artifact.\n\n\n## Version 3.0.0-alpha.2\n\n_2021-03-24_\n\n * New: Require Java 8+ for Okio 3.x.\n * New: `Cursor` supports random access reads on a `Source`.\n * New: `FileSystem.openZip(path)` returns a file system backed by a `.zip` file. This is in the\n   `okio-zipfilesystem` artifact.\n\n\n## Version 3.0.0-alpha.1\n\n_2021-01-07_\n\n* New: Experimental file system API. The `Path`, `FileMetadata`, `FileSystem` and\n  `ForwardingFileSystem` types are subject to API changes in a future release.\n* New: Experimental `okio-fakefilesystem` artifact.\n\n\n## Version 2.10.0\n\n_2021-01-07_\n\n* New: Support Windows (mingwX64) in multiplatform.\n* New: Support watchOS (watchosArm32, watchosArm64, watchosX86) in multiplatform.\n* New: Support `HashingSource`, `HashingSink`, buffer hash functions, and `UnsafeCursor` on non-JVM\n  platforms. Previously these were all JVM-only.\n* New: Implement `Closeable` on `Sink` and `Source` on non-JVM platforms. Okio now includes a\n  multiplatform `okio.Closeable` interface and corresponding `use {}` extension. Closing resources\n  when you're done with them shouldn't be JVM-only!\n* New: `Sink.hashingSink` and `Source.hashingSource` functions that accept\n  `java.security.MessageDigest` and `javax.crypto.Mac` instances. Use these when your hash function\n  isn't built-in.\n* Fix: Don't crash with a `ShortBufferException` in `CipherSink` and `CipherSource` on Android.\n  (Android may throw a `ShortBufferException` even if the buffer is not too short. We now\n  avoid this problem!)\n* Upgrade: [Kotlin 1.4.20][kotlin_1_4_20].\n\n\n## Version 2.9.0\n\n_2020-10-04_\n\n * Fix: Don't corrupt the `Buffer` when writing a slice of a segmented `ByteString`. We had a severe\n   bug where `ByteString` instances created with `snapshot()` and `readByteString()` incorrectly\n   adjusted the buffer's size by their full length, not the length of the slice. This would have\n   caused buffer reads to crash! We do not believe data was silently corrupted.\n * New: `CipherSink` and `CipherSource`. Use these with `javax.crypto.Cipher` to encrypt and decrypt\n   streams of data. This is a low-level encryption API; most applications should use higher-level\n   APIs like TLS when available.\n * New: Promote hash functions `md5`, `sha1()`, `sha512()`, and `sha256()` to common Kotlin. These\n   are currently only available on `ByteString`, multiplatform support for `HashingSource`,\n   `HashingSink`, and `Buffer` should come in a follow-up release. We wrote and optimized our own\n   implementations of these hash functions in Kotlin. On JVM and Android platforms Okio still uses\n   the platform's built-in hash functions.\n * New: Support OSGi metadata.\n * Upgrade: [Kotlin 1.4.10][kotlin_1_4_10].\n\n\n## Version 2.8.0\n\n_2020-08-17_\n\n * New: Upgrade to Kotlin 1.4.0.\n\n\n## Version 2.7.0\n\n_2020-07-07_\n\n * New: `Pipe.cancel()` causes in-progress and future reads and writes on the pipe to immediately\n   fail with an `IOException`. The streams may still be canceled normally.\n\n * New: Enlarge Okio's internal segment pool from a fixed 64 KiB total to 64 KiB per processor. For\n   example, on an Intel i9 8-core/16-thread machine the segment pool now uses up to 1 MiB of memory.\n\n * New: Migrate from `synchronized` to lock-free when accessing the segment pool. Combined with the\n   change above we saw throughput increase 3x on a synthetic benchmark designed to create\n   contention.\n\n\n## Version 2.6.0\n\n_2020-04-22_\n\n * New: `InflaterSource.readOrInflate()` is like `InflaterSource.read()`, except it will return 0 if\n   consuming deflated bytes from the underlying stream did not produce new inflated bytes.\n\n\n## Version 2.5.0\n\n_2020-03-20_\n\n * New: Upgrade to Kotlin 1.3.70.\n\n\n## Version 2.4.3\n\n_2019-12-20_\n\n * New: Upgrade to Kotlin 1.3.61.\n\n\n## Version 2.4.2\n\n_2019-12-11_\n\n * Fix: Don't crash when an `InputStream` source is exhausted exactly at a buffer segment boundary.\n   We had a bug where a sequence of reads could violate a buffer's invariants, and this could result\n   in a crash when subsequent reads encountered an unexpected empty segment.\n\n\n## Version 1.17.5\n\n_2019-12-11_\n\n * Fix: Don't crash when an `InputStream` source is exhausted exactly at a buffer segment boundary.\n   We had a bug where a sequence of reads could violate a buffer's invariants, and this could result\n   in a crash when subsequent reads encountered an unexpected empty segment.\n\n\n## Version 2.4.1\n\n_2019-10-04_\n\n * Fix: Don't cache hash code and UTF-8 string in `ByteString` on Kotlin/Native which prevented freezing.\n\n## Version 2.4.0\n\n_2019-08-26_\n\n * New: Upgrade to Kotlin 1.3.50.\n\n\n## Version 2.3.0\n\n_2019-07-29_\n\n**This release changes our build from Kotlin-JVM to Kotlin-multiplatform (which includes JVM).**\nBoth native and JavaScript platforms are unstable preview releases and subject to\nbackwards-incompatible changes in forthcoming releases.\n\nTo try Okio in a multiplatform project use this Maven coordinate:\n\n```kotlin\napi('com.squareup.okio:okio-multiplatform:2.3.0')\n```\n\nYou’ll also need to [enable Gradle metadata][gradle_metadata] in your project's settings. The\nartifact name for JVM projects has not changed.\n\n * New: Upgrade to Kotlin 1.3.40.\n * Fix: Use Gradle `api` instead of `implementation` for the kotlin-stdlib dependency.\n * Fix: Don't block unless strictly necessary in `BufferedSource.peek()`.\n\n## Version 1.17.4\n\n_2019-04-29_\n\n * Fix: Don't block unless strictly necessary in `BufferedSource.peek()`.\n\n\n## Version 2.2.2\n\n_2019-01-28_\n\n * Fix: Make `Pipe.fold()` close the underlying sink when necessary.\n\n\n## Version 1.17.3\n\n_2019-01-28_\n\n * Fix: Make `Pipe.fold()` close the underlying sink when necessary.\n\n\n## Version 1.17.2\n\n_2019-01-17_\n\n * Fix: Make `Pipe.fold()` flush the underlying sink.\n\n\n## Version 2.2.1\n\n_2019-01-17_\n\n * Fix: Make `Pipe.fold()` flush the underlying sink.\n\n\n## Version 2.2.0\n\n_2019-01-16_\n\n * New: `Throttler` limits sources and sinks to a maximum desired throughput. Multiple sources and\n   sinks can be attached to the same throttler and their combined throughput will not exceed the\n   desired throughput. Multiple throttlers can also be used on the same source or sink and they will\n   all be honored.\n\n * New: `Pipe.fold()` replaces the actively-readable `Source` with a passively-writable `Sink`.\n   This can be used to forward one sink to a target that is initially undetermined.\n\n * New: Optimize performance of ByteStrings created with `Buffer.snapshot()`.\n\n\n## Version 1.17.1\n\n_2019-01-16_\n\n * Fix: Make the newly-backported `Pipe.fold()` public.\n\n\n## Version 1.17.0\n\n_2019-01-16_\n\n * New: Backport `Pipe.fold()` to Okio 1.x.\n\n\n## Version 1.16.0\n\n_2018-10-08_\n\n * New: Backport `BufferedSource.peek()` and `BufferedSource.getBuffer()` to Okio 1.x.\n * Fix: Enforce timeouts when closing `AsyncTimeout` sources.\n\n\n## Version 2.1.0\n\n_2018-09-22_\n\n * New: `BufferedSource.peek()` returns another `BufferedSource` that reads ahead on the current\n   source. Use this to process the same data multiple times.\n\n * New: Deprecate `BufferedSource.buffer()`, replacing it with either `BufferedSource.getBuffer()`\n   (in Java) or `BufferedSource.buffer` (in Kotlin). We have done likewise for `BufferedSink`.\n   When we introduced the new extension method `Source.buffer()` in Okio 2.0 we inadvertently\n   collided with an existing method. This fixes that.\n\n * New: Improve performance of `Buffer.writeUtf8()`. This comes alongside initial implementation of\n   UTF-8 encoding and decoding in JavaScript which [uses XOR masks][xor_utf8] for great performance.\n\n\n## Version 2.0.0\n\n_2018-08-27_\n\nThis release commits to a stable 2.0 API. Read the 2.0.0-RC1 changes for advice on upgrading from\n1.x to 2.x.\n\nWe've also added APIs to ease migration for Kotlin users. They use Kotlin's `@Deprecated` annotation\nto help you change call sites from the 1.x style to the 2.x style.\n\n\n## Version 2.0.0-RC1\n\n_2018-07-26_\n\nOkio 2 is a major release that upgrades the library's implementation language from Java to Kotlin.\n\nOkio 2.x is **binary-compatible** with Okio 1.x and does not change any behavior. Classes and .jar\nfiles compiled against 1.x can be used with 2.x without recompiling.\n\nOkio 2.x is **.java source compatible** with Okio 1.x in all but one corner case. In Okio 1.x\n`Buffer` would throw an unchecked `IllegalStateException` when attempting to read more bytes than\navailable. Okio 2.x now throws a checked `EOFException` in this case. This is now consistent with\nthe behavior of its `BufferedSource` interface. Java callers that don't already catch `IOException`\nwill now need to.\n\nOkio 2.x is **.kt source-incompatible** with Okio 1.x. This release adopts Kotlin idioms where they\nare available.\n\n| Java                                     |  Kotlin                              | Idiom              |\n| :--------------------------------------- |  :---------------------------------- | :----------------- |\n| Buffer.getByte()                         |  operator fun Buffer.get()           | operator function  |\n| Buffer.size()                            |  val Buffer.size                     | val                |\n| ByteString.decodeBase64(String)          |  fun String.decodeBase64()           | extension function |\n| ByteString.decodeHex(String)             |  fun String.decodeHex()              | extension function |\n| ByteString.encodeString(String, Charset) |  fun String.encode(Charset)          | extension function |\n| ByteString.encodeUtf8(String)            |  fun String.encodeUtf8()             | extension function |\n| ByteString.getByte()                     |  operator fun ByteString.get()       | operator function  |\n| ByteString.of(ByteBuffer)                |  fun ByteBuffer.toByteString()       | extension function |\n| ByteString.of(byte[], int, int)          |  fun ByteArray.toByteString()        | extension function |\n| ByteString.read(InputStream, int)        |  fun InputStream.readByteString(Int) | extension function |\n| ByteString.size()                        |  val ByteString.size                 | val                |\n| DeflaterSink(Sink)                       |  fun Sink.deflater()                 | extension function |\n| ForwardingSink.delegate()                |  val ForwardingSink.delegate         | val                |\n| ForwardingSource.delegate()              |  val ForwardingSource.delegate       | val                |\n| GzipSink(Sink, Deflater)                 |  fun Sink.gzip()                     | extension function |\n| GzipSink.deflater()                      |  val GzipSink.deflater               | val                |\n| GzipSource(Source)                       |  fun Source.gzip()                   | extension function |\n| HashingSink.hash()                       |  val HashingSink.hash                | val                |\n| HashingSource.hash()                     |  val HashingSource.hash              | val                |\n| InflaterSink(Source)                     |  fun Source.inflater()               | extension function |\n| Okio.appendingSink(File)                 |  fun File.appendingSink()            | extension function |\n| Okio.blackhole()                         |  fun blackholeSink()                 | top level function |\n| Okio.buffer(Sink)                        |  fun Sink.buffer()                   | extension function |\n| Okio.buffer(Source)                      |  fun Source.buffer()                 | extension function |\n| Okio.sink(File)                          |  fun File.sink()                     | extension function |\n| Okio.sink(OutputStream)                  |  fun OutputStream.sink()             | extension function |\n| Okio.sink(Path)                          |  fun Path.sink()                     | extension function |\n| Okio.sink(Socket)                        |  fun Socket.sink()                   | extension function |\n| Okio.source(File)                        |  fun File.source()                   | extension function |\n| Okio.source(InputStream)                 |  fun InputStream.source()            | extension function |\n| Okio.source(Path)                        |  fun Path.source()                   | extension function |\n| Okio.source(Socket)                      |  fun Socket.source()                 | extension function |\n| Pipe.sink()                              |  val Pipe.sink                       | val                |\n| Pipe.source()                            |  val Pipe.source                     | val                |\n| Utf8.size(String)                        |  fun String.utf8Size()               | extension function |\n\nOkio 2.x has **similar performance** to Okio 1.x. We benchmarked both versions to find potential\nperformance regressions. We found one regression and fixed it: we were using `==` instead of `===`.\n\nOther changes in this release:\n\n * New: Add a dependency on kotlin-stdlib. Okio's transitive dependencies grow from none in 1.x to\n   three in 2.x. These are kotlin-stdlib (939 KiB), kotlin-stdlib-common (104 KiB), and JetBrains'\n   annotations (17 KiB).\n\n * New: Change Okio to build with Gradle instead of Maven.\n\n\n## Version 1.15.0\n\n_2018-07-18_\n\n * New: Trie-based `Buffer.select()`. This improves performance when selecting\n   among large lists of options.\n * Fix: Retain interrupted state when throwing `InterruptedIOException`.\n\n\n## Version 1.14.0\n\n_2018-02-11_\n\n * New: `Buffer.UnsafeCursor` provides direct access to Okio internals. This API\n   is like Okio's version of Java reflection: it's a very powerful API that can\n   be used for great things and dangerous things alike. The documentation is\n   extensive and anyone using it should review it carefully before proceeding!\n * New: Change `BufferedSource` to implement `java.nio.ReadableByteChannel` and\n   `BufferedSink` to implement `java.nio.WritableByteChannel`. Now it's a little\n   easier to interop between Okio and NIO.\n * New: Automatic module name of `okio` for use with the Java Platform Module\n   System.\n * New: Optimize `Buffer.getByte()` to search backwards when doing so will be\n   more efficient.\n * Fix: Honor the requested byte count in `InflaterSource`. Previously this\n   class could return more bytes than requested.\n * Fix: Improve a performance bug in `AsyncTimeout.sink().write()`.\n\n\n## Version 1.13.0\n\n_2017-05-12_\n\n * **Okio now uses `@Nullable` to annotate all possibly-null values.** We've\n   added a compile-time dependency on the JSR 305 annotations. This is a\n   [provided][maven_provided] dependency and does not need to be included in\n   your build configuration, `.jar` file, or `.apk`. We use\n   `@ParametersAreNonnullByDefault` and all parameters and return types are\n   never null unless explicitly annotated `@Nullable`.\n\n * **Warning: this release is source-incompatible for Kotlin users.**\n   Nullability was previously ambiguous and lenient but now the compiler will\n   enforce strict null checks.\n\n\n## Version 1.12.0\n\n_2017-04-11_\n\n * **Fix: Change Pipe's sink.flush() to not block.** Previously closing a pipe's\n   sink would block until the source had been exhausted. In practice this\n   blocked the caller for no benefit.\n * **Fix: Change `writeUtf8CodePoint()` to emit `?` for partial surrogates.**\n   The previous behavior was inconsistent: given a malformed string with a\n   partial surrogate, `writeUtf8()` emitted `?` but `writeUtf8CodePoint()` threw\n   an `IllegalArgumentException`. Most applications will never encounter partial\n   surrogates, but for those that do this behavior was unexpected.\n * New: Allow length of `readUtf8LineStrict()` to be limited.\n * New: `Utf8.size()` method to get the number of bytes required to encode a\n   string as UTF-8. This may be useful for length-prefixed encodings.\n * New: SHA-512 hash and HMAC APIs.\n\n\n## Version 1.11.0\n\n_2016-10-11_\n\n * **Fix: The four-argument overload of `Buffer.writeString()` had a major bug\n   where it didn't respect offsets if the specified charset was UTF-8.** This\n   was because our short-circuit optimization omitted necessary offset\n   parameters.\n * New: HMAC support in `HashingSource`, `HashingSink`, `ByteString`, and\n   `Buffer`. This makes it easy to create a keyed-hash message authentication\n   code (HMAC) wherever your data is. Unlike the other hashes, HMAC uses a\n   `ByteString` secret key for authentication.\n * New: `ByteString.of(ByteBuffer)` makes it easier to mix NIO with Okio.\n\n\n## Version 1.10.0\n\n_2016-08-28_\n\n * Fix: Support reading files larger than 2 GiB with `GzipSource`. Previously\n   attempting to decompress such files would fail due to an overflow when\n   validating the total length.\n * Fix: Exit the watchdog thread after being idle for 60 seconds. This should\n   make it possible for class unloaders to fully unload Okio.\n * New: `Okio.blackhole()` returns a sink where all bytes written are discarded.\n   This is Okio's equivalent of `/dev/null`.\n * New: Encode a string with any charset using `ByteString.encodeString()` and\n   decode strings in any charset using `ByteString.string()`. Most applications\n   should prefer `ByteString.encodeUtf8()` and `ByteString.utf8()` unless it's\n   necessary to support a legacy charset.\n * New: `GzipSink.deflater()` makes it possible to configure the compression\n   level.\n\n\n## Version 1.9.0\n\n_2016-07-01_\n\n * New: `Pipe` makes it easy to connect a producer thread to a consumer thread.\n   Reads block until data is available to read. Writes block if the pipe's is\n   full. Both sources and sinks support timeouts.\n * New: `BufferedSource.rangeEquals()` makes it easy to compare a range in a\n   stream to an expected value. This does the right thing: it blocks to load\n   the data required return a definitive result. But it won't block\n   unnecessarily.\n * New: `Timeout.waitUntilNotified()` makes it possible to use nice timeout\n   abstractions on Java's built-in wait/notify primitives.\n * Fix: Don't return incorrect results when `HashingSource` does large reads.\n   There was a bug where it wasn't traversing through the segments of the buffer\n   being hashed. This means that `HashingSource` was returning incorrect answers\n   for any writes that spanned multiple segment boundaries.\n\n## Version 1.8.0\n\n_2016-05-02_\n\n * New: `BufferedSource.select(Options)` API for reading one of a set of\n   expected values.\n * New: Make `ByteString.toString()` and `Buffer.toString()` friendlier.\n   These methods return text if the byte string is valid UTF-8.\n * New: APIs to match byte strings: `indexOf()`, `startsWith()`, and\n   `endsWith()`.\n\n## Version 1.7.0\n\n_2016-04-10_\n\n * New: Change the segment size to 8 KiB. This has been reported to dramatically\n   improve performance in some applications.\n * New: `md5()`, `sha1()`, and `sha256()` methods on `Buffer`. Also add a\n   `sha1()` method on `ByteString` for symmetry.\n * New: `HashingSource` and `HashingSink`. These classes are Okio’s equivalent\n   to the JDK’s `DigestInputStream` and `DigestOutputStream`. They offer\n   convenient `md5()`, `sha1()`, and `sha256()` factory methods to avoid an\n   impossible `NoSuchAlgorithmException`.\n * New: `ByteString.asByteBuffer()`.\n * Fix: Limit snapshot byte strings to requested size.\n * Fix: Change write timeouts to have a maximum write size. Previously large\n   writes could easly suffer timeouts because the entire write was subject to a\n   single timeout.\n * Fix: Recover from EBADF failures, which could be triggered by asynchronously\n   closing a stream on older versions of Android.\n * Fix: Don't share segments if doing so only saves a small copy. This should\n   improve performance for all applications.\n * Fix: Optimize `BufferedSource.indexOfElement()` and `indexOf(ByteString)`.\n   Previously this method had a bug that caused it to be very slow on large\n   buffers.\n\n## Version 1.6.0\n\n_2015-08-25_\n\n * New: `BufferedSource.indexOf(ByteString)` searches a source for the next\n   occurrence of a byte string.\n * Fix: Recover from unexpected `AssertionError` thrown on Android 4.2.2 and\n   earlier when asynchronously closing a socket.\n\n## Version 1.5.0\n\n_2015-06-19_\n\n * Sockets streams now throw `SocketTimeoutException`. This builds on new\n   extension point in `AsyncTimeout` to customize the exception when a timeout\n   occurs.\n * New: `ByteString` now implements `Comparable`. The comparison sorts bytes as\n   unsigned: {@code ff} sorts after {@code 00}.\n\n## Version 1.4.0\n\n_2015-05-16_\n\n * **Timeout exception changed.** Previously `Timeout.throwIfReached()` would\n   throw `InterruptedIOException` on thread interruption, and `IOException` if\n   the deadline was reached. Now it throws `InterruptedIOException` in both\n   cases.\n * Fix: throw `EOFException` when attempting to read digits from an empty\n   source. Previously this would crash with an unchecked exception.\n * New: APIs to read and write UTF-8 code points without allocating strings.\n * New: `BufferedSink` can now write substrings directly, potentially saving an\n   allocation for some callers.\n * New: `ForwardingTimeout` class.\n\n## Version 1.3.0\n\n_2015-03-16_\n\n * New: Read and write signed decimal and unsigned hexadecimal values in\n   `BufferedSource` and `BufferedSink`. Unlike the alternatives, these methods\n   don’t do any memory allocations!\n * New: Segment sharing. This improves the runtime of operations like\n   `Buffer.clone()` and `Buffer.copyTo()` by sharing underlying segments between\n   buffers.\n * New: `Buffer.snapshot()` returns an immutable snapshot of a buffer as a\n   `ByteString`. This builds on segment sharing so that snapshots are shallow,\n   immutable copies.\n * New: `ByteString.rangeEquals()`.\n * New: `ByteString.md5()` and `ByteString.sha256()`.\n * New: `ByteString.base64Url()` returns URL-safe Base64. The existing\n   decoding method has been extended to support URL-safe Base64 input.\n * New: `ByteString.substring()` returns a prefix, infix, or suffix.\n * New: `Sink` now implements `java.io.Flushable`.\n * Fix: `Buffer.write(Source, long)` now always writes fully. The previous\n   behavior would return as soon as any data had been written; this was\n   inconsistent with all other _write()_ methods in the API.\n * Fix: don't leak empty segments in DeflaterSink and InflaterSource. (This was\n   unlikely to cause problems in practice.)\n\n## Version 1.2.0\n\n_2014-12-30_\n\n * Fix: `Okio.buffer()` _always_ buffers for better predictability.\n * Fix: Provide context when `readUtf8LineStrict()` throws.\n * Fix: Buffers do not call through the `Source` on zero-byte writes.\n\n## Version 1.1.0\n\n_2014-12-11_\n\n * Do UTF-8 encoding natively for a performance increase, particularly on Android.\n * New APIs: `BufferedSink.emit()`, `BufferedSource.request()` and `BufferedSink.indexOfElement()`.\n * Fixed a performance bug in `Buffer.indexOf()`\n\n## Version 1.0.1\n\n_2014-08-08_\n\n * Added `read(byte[])`, `read(byte[], offset, byteCount)`,  and\n   `void readFully(byte[])` to `BufferedSource`.\n * Refined declared checked exceptions on `Buffer` methods.\n\n\n## Version 1.0.0\n\n_2014-05-23_\n\n * Bumped release version. No other changes!\n\n## Version 0.9.0\n\n_2014-05-03_\n\n * Use 0 as a sentinel for no timeout.\n * Make AsyncTimeout public.\n * Remove checked exception from Buffer.readByteArray.\n\n## Version 0.8.0\n\n_2014-04-24_\n\n * Eagerly verify preconditions on public APIs.\n * Quick return on Buffer instance equivalence.\n * Add delegate types for Sink and Source.\n * Small changes to the way deadlines are managed.\n * Add append variant of Okio.sink for File.\n * Methods to exhaust BufferedSource to byte[] and ByteString.\n\n## Version 0.7.0\n\n_2014-04-18_\n\n * Don't use getters in timeout.\n * Use the watchdog to interrupt sockets that have reached deadlines.\n * Add java.io and java.nio file source/sink helpers.\n\n## Version 0.6.1\n\n_2014-04-17_\n\n * Methods to read a buffered source fully in UTF-8 or supplied charset.\n * API to read a byte[] directly.\n * New methods to move all data from a source to a sink.\n * Fix a bug on input stream exhaustion.\n\n## Version 0.6.0\n\n_2014-04-15_\n\n * Make ByteString serializable.\n * New API: `ByteString.of(byte[] data, int offset, int byteCount)`\n * New API: stream-based copy, write, and read helpers.\n\n## Version 0.5.0\n\n_2014-04-08_\n\n * Initial public release.\n * Imported from OkHttp.\n\n\n[Central Portal Snapshots repository]: https://central.sonatype.org/publish/publish-portal-snapshots/\n[bom]: https://docs.gradle.org/6.2/userguide/platforms.html#sub:bom_import\n[datetime_0_3_0]: https://github.com/Kotlin/kotlinx-datetime/releases/tag/v0.3.0\n[datetime_0_7_0]: https://github.com/Kotlin/kotlinx-datetime/releases/tag/v0.7.0\n[datetime_0_7_0_compat]: https://github.com/Kotlin/kotlinx-datetime?tab=readme-ov-file#deprecation-of-instant\n[gradle_metadata]: https://blog.gradle.org/gradle-metadata-1.0\n[hierarchical_projects]: https://kotlinlang.org/docs/multiplatform-hierarchy.html\n[kotlin_1_4_10]: https://github.com/JetBrains/kotlin/releases/tag/v1.4.10\n[kotlin_1_4_20]: https://github.com/JetBrains/kotlin/releases/tag/v1.4.20\n[kotlin_1_5_20]: https://github.com/JetBrains/kotlin/releases/tag/v1.5.20\n[kotlin_1_5_31]: https://github.com/JetBrains/kotlin/releases/tag/v1.5.31\n[kotlin_1_6_20]: https://blog.jetbrains.com/kotlin/2022/04/kotlin-1-6-20-released/\n[kotlin_1_8_0]: https://kotlinlang.org/docs/whatsnew18.html\n[kotlin_1_9_0]: https://kotlinlang.org/docs/whatsnew19.html\n[kotlin_1_9_10]: https://github.com/JetBrains/kotlin/releases/tag/v1.9.10\n[kotlin_1_9_21]: https://github.com/JetBrains/kotlin/releases/tag/v1.9.21\n[kotlin_2_1_20]: https://github.com/JetBrains/kotlin/releases/tag/v2.1.20\n[kotlin_2_1_21]: https://github.com/JetBrains/kotlin/releases/tag/v2.1.21\n[kotlin_2_2_0]: https://github.com/JetBrains/kotlin/releases/tag/v2.2.0\n[loom]: https://wiki.openjdk.org/display/loom/Getting+started\n[maven_provided]: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html\n[preview1]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\n[watchosX86]: https://blog.jetbrains.com/kotlin/2023/02/update-regarding-kotlin-native-targets/\n[xor_utf8]: https://github.com/square/okio/blob/bbb29c459e5ccf0f286e0b17ccdcacd7ac4bc2a9/okio/src/main/kotlin/okio/Utf8.kt#L302\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing\n============\n\nKeeping the project small and stable limits our ability to accept new contributors. We are not\nseeking new committers at this time, but some small contributions are welcome.\n\nIf you've found a security problem, please follow our [bug bounty][security] program.\n\nIf you've found a bug, please contribute a failing test case so we can study and fix it.\n\nBefore code can be accepted all contributors must complete our\n[Individual Contributor License Agreement (CLA)][cla].\n\n\nCode Contributions\n------------------\n\nGet working code on a personal branch with tests passing before you submit a PR:\n\n```\n./gradlew clean check\n```\n\nPlease make every effort to follow existing conventions and style in order to keep the code as\nreadable as possible.\n\nContribute code changes through GitHub by forking the repository and sending a pull request. We\nsquash all pull requests on merge.\n\n\nCommitter's Guides\n------------------\n\n * [Releasing][releasing]\n\n [cla]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1\n [releasing]: http://square.github.io/okio/releasing/\n [security]: http://square.github.io/okio/security/\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": "README.md",
    "content": "Okio\n====\n\nSee the [project website][okio] for documentation and APIs.\n\nOkio is a library that complements `java.io` and `java.nio` to make it much\neasier to access, store, and process your data. It started as a component of\n[OkHttp][1], the capable HTTP client included in Android. It's well-exercised\nand ready to solve new problems.\n\nLicense\n--------\n\n    Copyright 2013 Square, Inc.\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    \n [1]: https://github.com/square/okhttp\n [okio]: https://square.github.io/okio/\n"
  },
  {
    "path": "android-test/README.md",
    "content": "Android Test\n============\n\nThis module runs Okio's test suite on a connected Android emulator or device. It requires the same\nset-up as [OkHttp's android-test module][okhttp_android_test].\n\nIn brief, configure the Android SDK and PATH:\n\n```\nexport ANDROID_SDK_ROOT=/Users/$USER/Library/Android/sdk\nexport PATH=$PATH:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/platform-tools\n```\n\nUse `logcat` to stream test logs:\n\n```\nadb logcat '*:E' TestRunner:D TaskRunner:D GnssHAL_GnssInterface:F DeviceStateChecker:F memtrack:F\n```\n\nThen run the tests:\n\n```\n./gradlew :android-test:connectedAndroidTest\n```\n\nOr just a single test:\n\n```\n./gradlew :android-test:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=okio.SystemFileSystemTest\n```\n\n\n### Watch Out For Crashing Failures\n\nSome of Okio's tests can cause the test process to crash. The test will be reported as a failure\nwith a message like this:\n\n> Test failed to run to completion. Reason: 'Instrumentation run failed due to 'Process crashed.''.\n> Check device logcat for details\n\nWhen this happens, it's possible that tests are missing from the test run! One workaround is to\nexclude the crashing test and re-run the rest. You can confirm that the test run completed normally\nif a `run finished` line is printed in the logcat logs:\n\n```\n01-01 00:00:00.000 12345 23456 I TestRunner: run finished: 2976 tests, 0 failed, 3 ignored\n```\n\n\n[okhttp_android_test]: https://github.com/square/okhttp/tree/master/android-test\n"
  },
  {
    "path": "android-test/build.gradle.kts",
    "content": "import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask\n\nplugins {\n  id(\"com.android.library\")\n}\n\nbuildscript {\n  repositories {\n    mavenCentral()\n    gradlePluginPortal()\n    google()\n  }\n}\n\nval isIDE = properties.containsKey(\"android.injected.invoked.from.ide\") ||\n  (System.getenv(\"XPC_SERVICE_NAME\") ?: \"\").contains(\"intellij\") ||\n  System.getenv(\"IDEA_INITIAL_DIRECTORY\") != null\n\nandroid {\n  namespace = \"com.squareup.okio\"\n\n  compileOptions {\n    sourceCompatibility = JavaVersion.VERSION_1_8\n    targetCompatibility = JavaVersion.VERSION_1_8\n    isCoreLibraryDesugaringEnabled = true\n  }\n\n  compileSdk = 33\n\n  defaultConfig {\n    minSdk = 15\n\n    testInstrumentationRunner = \"androidx.test.runner.AndroidJUnitRunner\"\n\n    // AndroidJUnitRunner wasn't finding tests in multidex artifacts when running on Android 4.0.3.\n    // Work around by adding all Okio classes to the keep list. That way they'll be in the main\n    // .dx file where TestRequestBuilder will find them.\n    multiDexEnabled = true\n    multiDexKeepProguard = file(\"multidex-config.pro\")\n  }\n\n  testOptions {\n    targetSdk = 33\n  }\n\n\n  if (!isIDE) {\n    sourceSets {\n      named(\"androidTest\") {\n        java.srcDirs(\n          project.file(\"../okio-fakefilesystem/src/commonMain/kotlin\"),\n          project.file(\"../okio/src/commonMain/kotlin\"),\n          project.file(\"../okio/src/commonTest/java\"),\n          project.file(\"../okio/src/commonTest/kotlin\"),\n          project.file(\"../okio/src/hashFunctions/kotlin\"),\n          project.file(\"../okio/src/jvmMain/kotlin\"),\n          project.file(\"../okio/src/jvmTest/java\"),\n          project.file(\"../okio/src/jvmTest/kotlin\")\n        )\n      }\n    }\n  }\n}\n\nkotlin {\n  compilerOptions {\n    freeCompilerArgs.add(\"-Xmulti-platform\")\n  }\n}\n\n// https://issuetracker.google.com/issues/325146674\ntasks.withType<AndroidLintAnalysisTask> {\n  onlyIf { false }\n}\n\ndependencies {\n  coreLibraryDesugaring(libs.android.desugar.jdk.libs)\n  androidTestImplementation(libs.androidx.test.ext.junit)\n  androidTestImplementation(libs.androidx.test.runner)\n  androidTestImplementation(libs.kotlin.test)\n  androidTestImplementation(libs.kotlin.time)\n  androidTestImplementation(libs.test.assertk)\n  androidTestImplementation(libs.test.junit)\n}\n"
  },
  {
    "path": "android-test/multidex-config.pro",
    "content": "-keep class okio.** { *; }\n"
  },
  {
    "path": "android-test/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"MissingClass\"\n    >\n\n  <uses-permission android:name=\"android.permission.INTERNET\" />\n\n  <!-- To access the system temporary directory. -->\n  <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n  <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n\n  <application\n      android:name=\"androidx.multidex.MultiDexApplication\"\n      android:usesCleartextTraffic=\"true\" />\n\n</manifest>\n"
  },
  {
    "path": "android-test/src/main/res/values/strings.xml",
    "content": "<resources>\n  <string name=\"app_name\">android-test</string>\n</resources>\n"
  },
  {
    "path": "android-test/src/main/res/xml/network_security_config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<network-security-config>\n  <base-config cleartextTrafficPermitted=\"false\">\n  </base-config>\n</network-security-config>\n"
  },
  {
    "path": "build-support/build.gradle.kts",
    "content": "plugins {\n  `kotlin-dsl`\n  `java-gradle-plugin`\n}\n\nrepositories {\n  mavenCentral()\n}\n\ndependencies {\n  add(\"compileOnly\", kotlin(\"gradle-plugin\"))\n  add(\"compileOnly\", kotlin(\"gradle-plugin-api\"))\n}\n\ngradlePlugin {\n  plugins {\n    create(\"build-support\") {\n      id = \"build-support\"\n      implementationClass = \"BuildSupport\"\n    }\n  }\n}\n\ndependencies {\n  implementation(libs.kotlin.gradle.plugin)\n  implementation(libs.tapmoc.gradle.plugin)\n}\n"
  },
  {
    "path": "build-support/settings.gradle.kts",
    "content": "dependencyResolutionManagement {\n  versionCatalogs {\n    create(\"libs\") {\n      from(files(\"../gradle/libs.versions.toml\"))\n    }\n  }\n}\n"
  },
  {
    "path": "build-support/src/main/kotlin/BuildSupport.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 java.nio.charset.StandardCharsets\nimport org.gradle.api.GradleException\nimport org.gradle.api.JavaVersion\nimport org.gradle.api.Plugin\nimport org.gradle.api.Project\nimport org.gradle.api.artifacts.VersionCatalog\nimport org.gradle.api.artifacts.VersionCatalogsExtension\nimport org.gradle.api.tasks.compile.JavaCompile\nimport org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode\nimport org.jetbrains.kotlin.gradle.dsl.JvmTarget\nimport org.jetbrains.kotlin.gradle.tasks.KotlinCompile\nimport tapmoc.configureKotlinCompatibility\n\nclass BuildSupport : Plugin<Project> {\n  override fun apply(project: Project) {\n    project.configureKotlinCompatibility(project.getVersionByName(\"kotlinCoreLibrariesVersion\"))\n\n    // `project.configureJavaCompatibility(8)` is not used as the code would compile with JDK 8.\n    // This will fail as `RealBufferedSource.kt` uses a Java API not available in Java 8:` InputStream.transferTo`\n    // To use `project.configureJavaCompatibility`, the min supported Java version would need to be bumped to 11\n    project.tasks.withType(KotlinCompile::class.java).configureEach {\n      compilerOptions {\n        jvmTarget.set(JvmTarget.JVM_1_8)\n        jvmDefault.set(JvmDefaultMode.NO_COMPATIBILITY)\n      }\n    }\n    project.tasks.withType(JavaCompile::class.java) {\n      options.encoding = StandardCharsets.UTF_8.toString()\n      sourceCompatibility = JavaVersion.VERSION_1_8.toString()\n      targetCompatibility = JavaVersion.VERSION_1_8.toString()\n    }\n  }\n}\n\nval Project.versionCatalog: VersionCatalog\n  get() = project.extensions.getByType(VersionCatalogsExtension::class.java).find(\"libs\").get()\n\nfun Project.getVersionByName(name: String): String {\n  val version = versionCatalog.findVersion(name)\n  return if (version.isPresent) {\n    version.get().requiredVersion\n  } else {\n    throw GradleException(\"Could not find a version for `$name`\")\n  }\n}\n"
  },
  {
    "path": "build-support/src/main/kotlin/bom.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 java.util.Locale\nimport org.gradle.api.Project\nimport org.gradle.api.artifacts.dsl.DependencyConstraintHandler\nimport org.gradle.kotlin.dsl.getByType\nimport org.gradle.kotlin.dsl.withType\nimport org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension\nimport org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper\nimport org.jetbrains.kotlin.gradle.plugin.KotlinJsPluginWrapper\nimport org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper\nimport org.jetbrains.kotlin.gradle.plugin.KotlinTarget\nimport org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget\n\n/**\n * Collect all the root project's multiplatform targets and add them to the BOM.\n *\n * Only published subprojects are included.\n *\n * This supports Kotlin/Multiplatform and Kotlin/JS subprojects.\n */\nfun Project.collectBomConstraints() {\n  val bomConstraints: DependencyConstraintHandler = dependencies.constraints\n  rootProject.subprojects {\n    val subproject = this\n\n    subproject.plugins.withId(\"com.vanniktech.maven.publish.base\") {\n      subproject.plugins.withType<KotlinAndroidPluginWrapper> {\n        bomConstraints.api(subproject)\n      }\n\n      subproject.plugins.withType<KotlinJsPluginWrapper> {\n        bomConstraints.api(subproject)\n      }\n\n      subproject.plugins.withType<KotlinMultiplatformPluginWrapper> {\n        subproject.extensions.getByType<KotlinMultiplatformExtension>().targets.all {\n          bomConstraints.api(dependencyConstraint(this))\n        }\n      }\n    }\n  }\n}\n\n/** Returns a string like \"com.squareup.okio:okio-iosarm64:3.4.0\" for this target. */\nprivate fun Project.dependencyConstraint(target: KotlinTarget): String {\n  val artifactId = when (target) {\n    is KotlinMetadataTarget -> name\n    else -> \"$name-${target.targetName.lowercase(Locale.ROOT)}\"\n  }\n  return \"$group:$artifactId:$version\"\n}\n\nprivate fun DependencyConstraintHandler.api(constraintNotation: Any) =\n  add(\"api\", constraintNotation)\n"
  },
  {
    "path": "build-support/src/main/kotlin/jvm.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\n// If true - tests should run for a loom environment.\nval loomEnabled = System.getProperty(\"loomEnabled\", \"false\").toBoolean()\n"
  },
  {
    "path": "build-support/src/main/kotlin/kmp.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\n// If false - JS targets will not be configured in multiplatform projects.\nval kmpJsEnabled = System.getProperty(\"kjs\", \"true\").toBoolean()\n\n// If false - Native targets will not be configured in multiplatform projects.\nval kmpNativeEnabled = System.getProperty(\"knative\", \"true\").toBoolean()\n\n// If false - WASM targets will not be configured in multiplatform projects.\nval kmpWasmEnabled = System.getProperty(\"kwasm\", \"true\").toBoolean()\n"
  },
  {
    "path": "build-support/src/main/kotlin/platforms.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 org.gradle.api.NamedDomainObjectContainer\nimport org.gradle.kotlin.dsl.get\nimport org.jetbrains.kotlin.gradle.dsl.JsModuleKind.MODULE_UMD\nimport org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension\nimport org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet\n\nfun KotlinMultiplatformExtension.configureOrCreateOkioPlatforms() {\n  jvm {\n  }\n  if (kmpJsEnabled) {\n    configureOrCreateJsPlatforms()\n  }\n  if (kmpNativeEnabled) {\n    configureOrCreateNativePlatforms()\n  }\n  if (kmpWasmEnabled) {\n    configureOrCreateWasmPlatform()\n  }\n}\n\nfun KotlinMultiplatformExtension.configureOrCreateNativePlatforms() {\n  iosX64()\n  iosArm64()\n  iosSimulatorArm64()\n  tvosX64()\n  tvosArm64()\n  tvosSimulatorArm64()\n  watchosArm32()\n  watchosArm64()\n  watchosDeviceArm64()\n  watchosX64()\n  watchosSimulatorArm64()\n  // Required to generate tests tasks: https://youtrack.jetbrains.com/issue/KT-26547\n  linuxX64()\n  linuxArm64()\n  macosX64()\n  macosArm64()\n  mingwX64()\n}\n\nval appleTargets = listOf(\n  \"iosArm64\",\n  \"iosX64\",\n  \"iosSimulatorArm64\",\n  \"macosX64\",\n  \"macosArm64\",\n  \"tvosArm64\",\n  \"tvosX64\",\n  \"tvosSimulatorArm64\",\n  \"watchosArm32\",\n  \"watchosArm64\",\n  \"watchosDeviceArm64\",\n  \"watchosX64\",\n  \"watchosSimulatorArm64\",\n)\n\nval mingwTargets = listOf(\n  \"mingwX64\",\n)\n\nval linuxTargets = listOf(\n  \"linuxX64\",\n  \"linuxArm64\",\n)\n\nval nativeTargets = appleTargets + linuxTargets + mingwTargets\n\nval wasmTargets = listOf(\n  \"wasmJs\",\n  \"wasmWasi\",\n)\n\n/**\n * Creates a source set for a directory that isn't already a built-in platform. Use this to create\n * custom shared directories like `nonJvmMain` or `unixMain`.\n */\nfun NamedDomainObjectContainer<KotlinSourceSet>.createSourceSet(\n  name: String,\n  parent: KotlinSourceSet? = null,\n  children: List<String> = listOf()\n): KotlinSourceSet {\n  val result = create(name)\n\n  if (parent != null) {\n    result.dependsOn(parent)\n  }\n\n  val suffix = when {\n    name.endsWith(\"Main\") -> \"Main\"\n    name.endsWith(\"Test\") -> \"Test\"\n    else -> error(\"unexpected source set name: ${name}\")\n  }\n\n  for (childTarget in children) {\n    val childSourceSet = get(\"${childTarget}$suffix\")\n    childSourceSet.dependsOn(result)\n  }\n\n  return result\n}\n\nfun KotlinMultiplatformExtension.configureOrCreateJsPlatforms() {\n  js {\n    compilerOptions {\n      moduleKind.set(MODULE_UMD)\n      sourceMap.set(true)\n    }\n    nodejs {\n      testTask {\n        useMocha {\n          timeout = \"30s\"\n        }\n      }\n    }\n    browser {\n    }\n  }\n}\n\nfun KotlinMultiplatformExtension.configureOrCreateWasmPlatform(\n  js: Boolean = true,\n  wasi: Boolean = true,\n) {\n  if (js) {\n    wasmJs {\n      nodejs()\n    }\n  }\n  if (wasi) {\n    wasmWasi {\n      nodejs()\n    }\n  }\n}\n"
  },
  {
    "path": "build.gradle.kts",
    "content": "import aQute.bnd.gradle.BundleTaskExtension\nimport com.diffplug.gradle.spotless.SpotlessExtension\nimport com.vanniktech.maven.publish.MavenPublishBaseExtension\nimport groovy.util.Node\nimport groovy.util.NodeList\nimport org.gradle.api.tasks.testing.logging.TestExceptionFormat\nimport org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED\nimport org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED\nimport org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED\nimport org.gradle.api.tasks.testing.logging.TestLogEvent.STARTED\nimport org.jetbrains.dokka.gradle.DokkaTask\nimport org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest\nimport org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest\nimport org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest\nimport org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile\n\nplugins {\n  id(\"build-support\").apply(false)\n}\n\nbuildscript {\n  dependencies {\n    classpath(libs.android.gradle.plugin)\n    classpath(libs.burst.gradle.plugin)\n    classpath(libs.dokka)\n    classpath(libs.jmh.gradle.plugin)\n    classpath(libs.binaryCompatibilityValidator)\n    classpath(libs.spotless)\n    classpath(libs.bnd)\n    classpath(libs.vanniktech.publish.plugin)\n    classpath(libs.tapmoc.gradle.plugin)\n  }\n\n  repositories {\n    mavenCentral()\n    gradlePluginPortal()\n    google()\n  }\n}\n\napply(plugin = \"com.vanniktech.maven.publish.base\")\n\n// When scripts are applied the buildscript classes are not accessible directly therefore we save\n// the class here to make it accessible.\next.set(\"bndBundleTaskExtensionClass\", BundleTaskExtension::class.java)\n\nallprojects {\n  group = project.property(\"GROUP\") as String\n  version = project.property(\"VERSION_NAME\") as String\n\n  repositories {\n    mavenCentral()\n    google()\n  }\n\n  tasks.withType<DokkaTask>().configureEach {\n    dokkaSourceSets.configureEach {\n      reportUndocumented.set(false)\n      skipDeprecated.set(true)\n      jdkVersion.set(8)\n      perPackageOption {\n        matchingRegex.set(\"com\\\\.squareup.okio.*\")\n        suppress.set(true)\n      }\n      perPackageOption {\n        matchingRegex.set(\"okio\\\\.internal.*\")\n        suppress.set(true)\n      }\n    }\n\n    if (name == \"dokkaHtml\") {\n      outputDirectory.set(file(\"${rootDir}/docs/3.x/${project.name}\"))\n      pluginsMapConfiguration.set(\n        mapOf(\n          \"org.jetbrains.dokka.base.DokkaBase\" to \"\"\"\n          {\n            \"customStyleSheets\": [\n              \"${rootDir.toString().replace('\\\\', '/')}/docs/css/dokka-logo.css\"\n            ],\n            \"customAssets\" : [\n              \"${rootDir.toString().replace('\\\\', '/')}/docs/images/icon-square.png\"\n            ]\n          }\n          \"\"\".trimIndent()\n        )\n      )\n    }\n  }\n\n  plugins.withId(\"com.vanniktech.maven.publish.base\") {\n    configure<PublishingExtension> {\n      repositories {\n        /**\n         * Want to push to an internal repository for testing? Set the following properties in\n         * `~/.gradle/gradle.properties`.\n         *\n         * internalMavenUrl=YOUR_INTERNAL_MAVEN_REPOSITORY_URL\n         * internalMavenUsername=YOUR_USERNAME\n         * internalMavenPassword=YOUR_PASSWORD\n         */\n        val internalUrl = providers.gradleProperty(\"internalUrl\")\n        if (internalUrl.isPresent) {\n          maven {\n            name = \"internal\"\n            setUrl(internalUrl)\n            credentials(PasswordCredentials::class)\n          }\n        }\n      }\n    }\n    val publishingExtension = extensions.getByType(PublishingExtension::class.java)\n    configure<MavenPublishBaseExtension> {\n      publishToMavenCentral(automaticRelease = true)\n      signAllPublications()\n      pom {\n        description.set(\"A modern I/O library for Android, Java, and Kotlin Multiplatform.\")\n        name.set(project.name)\n        url.set(\"https://github.com/square/okio/\")\n        licenses {\n          license {\n            name.set(\"The Apache Software License, Version 2.0\")\n            url.set(\"http://www.apache.org/licenses/LICENSE-2.0.txt\")\n            distribution.set(\"repo\")\n          }\n        }\n        scm {\n          url.set(\"https://github.com/square/okio/\")\n          connection.set(\"scm:git:git://github.com/square/okio.git\")\n          developerConnection.set(\"scm:git:ssh://git@github.com/square/okio.git\")\n        }\n        developers {\n          developer {\n            id.set(\"square\")\n            name.set(\"Square, Inc.\")\n          }\n        }\n      }\n\n      // Configure the kotlinMultiplatform artifact to depend on the JVM artifact in pom.xml only.\n      // This hack allows Maven users to continue using our original Okio artifact names (like\n      // com.squareup.okio:okio:3.x.y) even though we changed that artifact from JVM-only to Kotlin\n      // Multiplatform. Note that module.json doesn't need this hack.\n      val mavenPublications = publishingExtension.publications.withType<MavenPublication>()\n      mavenPublications.configureEach {\n        if (name != \"jvm\") return@configureEach\n        val jvmPublication = this\n        val kmpPublication = mavenPublications.getByName(\"kotlinMultiplatform\")\n        kmpPublication.pom.withXml {\n          val root = asNode()\n          val dependencies = (root[\"dependencies\"] as NodeList).firstOrNull() as Node?\n            ?: root.appendNode(\"dependencies\")\n          for (child in dependencies.children().toList()) {\n            dependencies.remove(child as Node)\n          }\n          dependencies.appendNode(\"dependency\").apply {\n            appendNode(\"groupId\", jvmPublication.groupId)\n            appendNode(\"artifactId\", jvmPublication.artifactId)\n            appendNode(\"version\", jvmPublication.version)\n            appendNode(\"scope\", \"compile\")\n          }\n        }\n      }\n    }\n  }\n}\n\nsubprojects {\n  apply(plugin = \"com.diffplug.spotless\")\n  configure<SpotlessExtension> {\n    kotlin {\n      target(\"**/*.kt\")\n      ktlint(libs.versions.ktlint.get())\n    }\n  }\n\n  tasks.withType<AbstractKotlinCompile<*>>().configureEach {\n    compilerOptions.apply {\n      freeCompilerArgs.add(\"-Xexpect-actual-classes\")\n    }\n  }\n\n  val testJavaVersion = System.getProperty(\"test.java.version\", \"\").toIntOrNull()\n  tasks.withType<Test> {\n    val javaToolchains = project.extensions.getByType<JavaToolchainService>()\n    if (testJavaVersion != null) {\n      javaLauncher.set(javaToolchains.launcherFor {\n        languageVersion.set(JavaLanguageVersion.of(testJavaVersion))\n      })\n    }\n\n    testLogging {\n      events(STARTED, PASSED, SKIPPED, FAILED)\n      exceptionFormat = TestExceptionFormat.FULL\n      showStandardStreams = false\n    }\n\n    if (loomEnabled) {\n      jvmArgs = jvmArgs!! + listOf(\n        \"-Djdk.tracePinnedThread=full\",\n        \"--enable-preview\",\n        \"-DloomEnabled=true\"\n      )\n    }\n  }\n\n  tasks.withType<AbstractArchiveTask>().configureEach {\n    isPreserveFileTimestamps = false\n    isReproducibleFileOrder = true\n  }\n\n  normalization {\n    runtimeClasspath {\n      metaInf {\n        ignoreAttribute(\"Bnd-LastModified\")\n      }\n    }\n  }\n}\n\n/**\n * Set the `OKIO_ROOT` environment variable for tests to access it.\n * https://publicobject.com/2023/04/16/read-a-project-file-in-a-kotlin-multiplatform-test/\n */\nallprojects {\n  tasks.withType<KotlinJvmTest>().configureEach {\n    environment(\"OKIO_ROOT\", rootDir)\n  }\n\n  tasks.withType<KotlinNativeTest>().configureEach {\n    environment(\"SIMCTL_CHILD_OKIO_ROOT\", rootDir)\n    environment(\"OKIO_ROOT\", rootDir)\n  }\n\n  tasks.withType<KotlinJsTest>().configureEach {\n    environment(\"OKIO_ROOT\", rootDir.toString())\n  }\n}\n"
  },
  {
    "path": "docs/code_of_conduct.md",
    "content": "Open Source Code of Conduct\n===========================\n\nAt Square, we are committed to contributing to the open source community and simplifying the process\nof releasing and managing open source software. We’ve seen incredible support and enthusiasm from\nthousands of people who have already contributed to our projects — and we want to ensure our community\ncontinues to be truly open for everyone.\n\nThis code of conduct outlines our expectations for participants, as well as steps to reporting\nunacceptable behavior. We are committed to providing a welcoming and inspiring community for all and\nexpect our code of conduct to be honored.\n\nSquare’s open source community strives to:\n\n * **Be open**: We invite anyone to participate in any aspect of our projects. Our community is\n   open, and any responsibility can be carried by a contributor who demonstrates the required\n   capacity and competence.\n\n * **Be considerate**: People use our work, and we depend on the work of others. Consider users and\n   colleagues before taking action. For example, changes to code, infrastructure, policy, and\n   documentation may negatively impact others.\n\n * **Be respectful**: We expect people to work together to resolve conflict, assume good intentions,\n   and act with empathy. Do not turn disagreements into personal attacks.\n\n * **Be collaborative**: Collaboration reduces redundancy and improves the quality of our work. We\n   strive for transparency within our open source community, and we work closely with upstream\n   developers and others in the free software community to coordinate our efforts.\n\n * **Be pragmatic**: Questions are encouraged and should be asked early in the process to avoid\n   problems later. Be thoughtful and considerate when seeking out the appropriate forum for your\n   questions. Those who are asked should be responsive and helpful.\n\n * **Step down considerately**: Members of every project come and go. When somebody leaves or\n   disengages from the project, they should make it known and take the proper steps to ensure that\n   others can pick up where they left off.\n\nThis code is not exhaustive or complete. It serves to distill our common understanding of a\ncollaborative, shared environment, and goals. We expect it to be followed in spirit as much as in\nthe letter.\n\nDiversity Statement\n-------------------\n\nWe encourage everyone to participate and are committed to building a community for all. Although we\nmay not be able to satisfy everyone, we all agree that everyone is equal.\n\nWhenever a participant has made a mistake, we expect them to take responsibility for it. If someone\nhas been harmed or offended, it is our responsibility to listen carefully and respectfully, and do\nour best to right the wrong.\n\nAlthough this list cannot be exhaustive, we explicitly honor diversity in age, culture, ethnicity,\ngender identity or expression, language, national origin, political beliefs, profession, race,\nreligion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate\ndiscrimination based on any of the protected characteristics above, including participants with\ndisabilities.\n\nReporting Issues\n----------------\n\nIf you experience or witness unacceptable behavior — or have any other concerns — please report it by\nemailing [codeofconduct@squareup.com][codeofconduct_at]. For more details, please see our Reporting\nGuidelines below.\n\nThanks\n------\n\nSome of the ideas and wording for the statements and guidelines above were based on work by the\n[Twitter][twitter_coc], [Ubuntu][ubuntu_coc], [GDC][gdc_coc], and [Django][django_coc] communities.\nWe are thankful for their work.\n\nReporting Guide\n---------------\n\nIf you experience or witness unacceptable behavior — or have any other concerns — please report it by\nemailing [codeofconduct@squareup.com][codeofconduct_at]. All reports will be handled with\ndiscretion.\n\nIn your report please include:\n\n * Your contact information.\n * Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional\n   witnesses, please include them as well.\n * Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly\n   available record (e.g. a mailing list archive or a public IRC logger), please include a link.\n * Any additional information that may be helpful.\n\nAfter filing a report, a representative from the Square Code of Conduct committee will contact you\npersonally. The committee will then review the incident, follow up with any additional questions,\nand make a decision as to how to respond.\n\nAnyone asked to stop unacceptable behavior is expected to comply immediately. If an individual\nengages in unacceptable behavior, the Square Code of Conduct committee may take any action they deem\nappropriate, up to and including a permanent ban from all of Square spaces without warning.\n\n\n[codeofconduct_at]: mailto:codeofconduct@squareup.com\n[twitter_coc]: https://github.com/twitter/code-of-conduct/blob/master/code-of-conduct.md\n[ubuntu_coc]: https://ubuntu.com/community/code-of-conduct\n[gdc_coc]: https://www.gdconf.com/code-of-conduct\n[django_coc]: https://www.djangoproject.com/conduct/reporting/\n\n"
  },
  {
    "path": "docs/css/app.css",
    "content": "@font-face {\n    font-family: cash-market;\n    src: url(\"https://cash-f.squarecdn.com/static/fonts/cash-market/v2/CashMarket-Regular.woff2\") format(\"woff2\");\n    font-weight: 400;\n    font-style: normal\n}\n\n@font-face {\n    font-family: cash-market;\n    src: url(\"https://cash-f.squarecdn.com/static/fonts/cash-market/v2/CashMarket-Medium.woff2\") format(\"woff2\");\n    font-weight: 500;\n    font-style: normal\n}\n\n@font-face {\n    font-family: cash-market;\n    src: url(\"https://cash-f.squarecdn.com/static/fonts/cash-market/v2/CashMarket-Bold.woff2\") format(\"woff2\");\n    font-weight: 700;\n    font-style: normal\n}\n\nbody, input {\n    font-family: cash-market,\"Helvetica Neue\",helvetica,sans-serif;\n}\n\n.md-typeset h1, .md-typeset h2, .md-typeset h3, .md-typeset h4 {\n    font-family: cash-market,\"Helvetica Neue\",helvetica,sans-serif;\n    line-height: normal;\n    font-weight: bold;\n    color: var(--md-default-fg-color);\n}\n\nbutton.dl {\n  font-weight: 300;\n  font-size: 25px;\n  line-height: 40px;\n  padding: 3px 10px;\n  display: inline-block;\n  border-radius: 6px;\n  color: #f0f0f0;\n  margin: 5px 0;\n  width: auto;\n}\n\n.logo {\n  text-align: center;\n  margin-top: 150px;\n}\n"
  },
  {
    "path": "docs/css/dokka-logo.css",
    "content": "#logo {\n  display: none;\n}\n"
  },
  {
    "path": "docs/file_system.md",
    "content": "File System\n===========\n\nOkio's file system is designed to be easy, testable, multiplatform, and efficient.\n\n### Easy\n\nReading and writing files is concise yet flexible.\n\n```kotlin\nval path = \"README.md\".toPath()\n\nval readmeContent = FileSystem.SYSTEM.read(path) {\n  readUtf8()\n}\n\nval updatedContent = readmeContent.replace(\"red\", \"blue\")\n\nFileSystem.SYSTEM.write(path) {\n  writeUtf8(updatedContent)\n}\n```\n\n\n### Testable\n\nIt's easy to swap out the real file system with a fake. This makes tests run faster and more\nreliably.\n\n```kotlin\nval fileSystem = FakeFileSystem()\nval userHome = \"/Users/sandy\".toPath()\nval gitConfig = userHome / \".gitconfig\"\n\nfileSystem.createDirectories(userHome)\nval original = \"\"\"\n    |[user]\n    |  email = sandy@example.com\n    |\"\"\".trimMargin()\nfileSystem.write(gitConfig) { writeUtf8(original) }\n\nGitConfigFixer(fileSystem).fix(userHome)\n\nval expected = \"\"\"\n  |[user]\n  |  email = sandy@example.com\n  |[diff]\n  |  renames = true\n  |  indentHeuristic = on\n  \"\"\".trimIndent()\nassertEquals(expected, fileSystem.read(gitConfig) { readUtf8() })\n```\n\nWith `ForwardingFileSystem` you can easily inject faults to confirm your program is graceful even\nwhen the user's disk fills up.\n\n\n### Multiplatform\n\nOkio’s `Path` class supports Windows-style (like `C:\\autoexec.bat`) and UNIX-style paths\n(like `/etc/passwd`). It supports manipulating Windows paths on UNIX, and UNIX paths on Windows.\n\nThe system `FileSystem` abstracts over these platform APIs:\n\n * Android API levels <26: [java.io.File](https://developer.android.com/reference/java/io/File)\n * Java and Android API level 26+: [java.nio.file](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/nio/file/FileSystem.html)\n * Linux: [man pages](https://www.kernel.org/doc/man-pages/)\n * UNIX: [stdio.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html)\n * Windows: [fileapi.h](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/)\n * Node.js: [file system](https://nodejs.org/api/fs.html)\n\n\n### Efficient\n\nRead and write operations integrate with Okio buffers to reduce the number of system calls.\n\nIt exposes high-level operations like `atomicMove()` and `metadata` to get the OS to do all the work\nwhen appropriate.\n\n\n## Known Issues\n\n\nOkio's implementation is constrained by the capabilities its underlying APIs. This page is an\noverview of these limitations.\n\n\n### All Platforms\n\n * There are no APIs for file permissions, watches, volume management, memory mapping, or locking.\n * Paths that cannot be represented as UTF-8 strings are unsupported. The underlying APIs that Okio\n   calls through, including `java.io.File`, all treat paths as strings.\n\n\n### Kotlin/JVM\n\n#### On Android, API level less than 26:\n\n * Creating and accessing symlinks is unsupported.\n\n\n#### On Windows:\n\n * `FileSystem.atomicMove()` fails if the target file already exists.\n\n\n### Kotlin/Native\n\n * FakeFileSystem does not support concurrent use. We are [holding off on this][fake_fs_concurrency]\n   until the upcoming memory model is released.\n\n#### On Windows:\n\n * Creating and accessing symlinks is unsupported.\n\n\n### Kotlin/JS\n\n * NodeJsFileSystem's `source()` and `sink()` cannot access UNIX pipes.\n * Instead of returning null, `NodeJsFileSystem.metadataOrNull()` throws `IOException` if the path\n   is invalid. (In the Node.js API there's no mechanism to differentiate between a failure to read\n   a valid path and a rejection of an invalid path.)\n\n\n[fake_fs_concurrency]: https://github.com/square/okio/issues/950\n"
  },
  {
    "path": "docs/index.md",
    "content": "Okio\n====\n\nOkio is a library that complements `java.io` and `java.nio` to make it much\neasier to access, store, and process your data. It started as a component of\n[OkHttp][1], the capable HTTP client included in Android. It's well-exercised\nand ready to solve new problems.\n\nByteStrings and Buffers\n-----------------------\n\nOkio is built around two types that pack a lot of capability into a\nstraightforward API:\n\n * [**ByteString**][3] is an immutable sequence of bytes. For character data, `String`\n   is fundamental. `ByteString` is String's long-lost brother, making it easy to\n   treat binary data as a value. This class is ergonomic: it knows how to encode\n   and decode itself as hex, base64, and UTF-8.\n\n * [**Buffer**][4] is a mutable sequence of bytes. Like `ArrayList`, you don't need\n   to size your buffer in advance. You read and write buffers as a queue: write\n   data to the end and read it from the front. There's no obligation to manage\n   positions, limits, or capacities.\n\nInternally, `ByteString` and `Buffer` do some clever things to save CPU and\nmemory. If you encode a UTF-8 string as a `ByteString`, it caches a reference to\nthat string so that if you decode it later, there's no work to do.\n\n`Buffer` is implemented as a linked list of segments. When you move data from\none buffer to another, it _reassigns ownership_ of the segments rather than\ncopying the data across. This approach is particularly helpful for multithreaded\nprograms: a thread that talks to the network can exchange data with a worker\nthread without any copying or ceremony.\n\nSources and Sinks\n-----------------\n\nAn elegant part of the `java.io` design is how streams can be layered for\ntransformations like encryption and compression. Okio includes its own stream\ntypes called [`Source`][5] and [`Sink`][6] that work like `InputStream` and\n`OutputStream`, but with some key differences:\n\n * **Timeouts.** The streams provide access to the timeouts of the underlying\n   I/O mechanism. Unlike the `java.io` socket streams, both `read()` and\n   `write()` calls honor timeouts.\n\n * **Easy to implement.** `Source` declares three methods: `read()`, `close()`,\n   and `timeout()`. There are no hazards like `available()` or single-byte reads\n   that cause correctness and performance surprises.\n\n * **Easy to use.** Although _implementations_ of `Source` and `Sink` have only\n   three methods to write, _callers_ are given a rich API with the\n   [`BufferedSource`][7] and [`BufferedSink`][8] interfaces. These interfaces give you\n   everything you need in one place.\n\n * **No artificial distinction between byte streams and char streams.** It's all\n   data. Read and write it as bytes, UTF-8 strings, big-endian 32-bit integers,\n   little-endian shorts; whatever you want. No more `InputStreamReader`!\n\n * **Easy to test.** The `Buffer` class implements both `BufferedSource` and\n   `BufferedSink` so your test code is simple and clear.\n\nSources and sinks interoperate with `InputStream` and `OutputStream`. You can\nview any `Source` as an `InputStream`, and you can view any `InputStream` as a\n`Source`. Similarly for `Sink` and `OutputStream`.\n\n\nPresentations\n-------------\n\n[A Few “Ok” Libraries][ok_libraries_talk] ([slides][ok_libraries_slides]): An introduction to Okio\nand three libraries written with it.\n\n[Decoding the Secrets of Binary Data][encoding_talk] ([slides][encoding_slides]): How data encoding\nworks and how Okio does it.\n\n[Ok Multiplatform!][ok_multiplatform_talk] ([slides][ok_multiplatform_slides]): How we changed\nOkio’s implementation language from Java to Kotlin.\n\n[Nerding Out On Okio][apis_talk]: The story of the Okio APIs, their design and tradeoffs, as well\nas implementation notes with animated marbles diagrams.\n\n\nRequirements\n------------\n\nOkio 2.x supports Android 4.0.3+ (API level 15+) and Java 7+.\n\nOkio 3.x supports Android 4.0.3+ (API level 15+) and Java 8+.\n\nOkio depends on the [Kotlin standard library][kotlin]. It is a small library with strong\nbackward-compatibility.\n\n\nReleases\n--------\n\nOur [change log][changelog] has release history.\n\n```kotlin\nimplementation(\"com.squareup.okio:okio:3.17.0\")\n```\n\n<details>\n   <summary>Snapshot builds are also available</summary>\n\n```kotlin\nrepositories {\n  maven(\"https://central.sonatype.com/repository/maven-snapshots/\")\n}\n\ndependencies {\n  implementation(\"com.squareup.okio:okio:3.18.0-SNAPSHOT\")\n}\n```\n\n</details>\n\n\nLicense\n--------\n\n    Copyright 2013 Square, Inc.\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\n [1]: https://github.com/square/okhttp\n [3]: https://square.github.io/okio/3.x/okio/okio/okio/-byte-string/index.html\n [4]: https://square.github.io/okio/3.x/okio/okio/okio/-buffer/index.html\n [5]: https://square.github.io/okio/3.x/okio/okio/okio/-source/index.html\n [6]: https://square.github.io/okio/3.x/okio/okio/okio/-sink/index.html\n [7]: https://square.github.io/okio/3.x/okio/okio/okio/-buffered-source/index.html\n [8]: https://square.github.io/okio/3.x/okio/okio/okio/-buffered-sink/index.html\n [changelog]: http://square.github.io/okio/changelog/\n [javadoc]: https://square.github.io/okio/2.x/okio/okio/index.html\n [kotlin]: https://kotlinlang.org/\n [ok_libraries_talk]: https://www.youtube.com/watch?v=WvyScM_S88c\n [ok_libraries_slides]: https://speakerdeck.com/jakewharton/a-few-ok-libraries-droidcon-mtl-2015\n [encoding_talk]: https://www.youtube.com/watch?v=T_p22jMZSrk\n [encoding_slides]: https://speakerdeck.com/swankjesse/decoding-the-secrets-of-binary-data-droidcon-nyc-2016\n [ok_multiplatform_talk]: https://www.youtube.com/watch?v=Q8B4eDirgk0\n [ok_multiplatform_slides]: https://speakerdeck.com/swankjesse/ok-multiplatform\n [apis_talk]: https://www.youtube.com/watch?v=Du7YXPAV1M8\n"
  },
  {
    "path": "docs/java_io_recipes.md",
    "content": "java.io Recipes\n===============\n\nThese recipes use Okio with `java.io.File` instead of Okio's own `Path` and `FileSystem` types.\n\n\nRead a text file line-by-line ([Java][ReadJavaIoFileLineByLine]/[Kotlin][ReadJavaIoFileLineByLineKt])\n-----------------------------------------------------------------------------------------------------\n\nThis is similar to the other [line-by-line example](recipes.md#read-a-text-file-line-by-line-javakotlin), but it uses `java.io.File`\ninstead of `okio.Path` and `okio.FileSystem`.\n\n=== \"Java\"\n\n    ```java\n    public void readLines(File file) throws IOException {\n      try (Source fileSource = Okio.source(file);\n           BufferedSource bufferedFileSource = Okio.buffer(fileSource)) {\n\n        while (true) {\n          String line = bufferedFileSource.readUtf8Line();\n          if (line == null) break;\n\n          if (line.contains(\"square\")) {\n            System.out.println(line);\n          }\n        }\n\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    Note that static `Okio` methods become extension functions (`Okio.source(file)` =>\n    `file.source()`).\n\n    ```kotlin\n    @Throws(IOException::class)\n    fun readLines(file: File) {\n      file.source().use { fileSource ->\n        fileSource.buffer().use { bufferedFileSource ->\n          while (true) {\n            val line = bufferedFileSource.readUtf8Line() ?: break\n            if (\"square\" in line) {\n              println(line)\n            }\n          }\n        }\n      }\n    }\n    ```\n\nWrite a text file ([Java][WriteJavaIoFile]/[Kotlin][WriteJavaIoFileKt])\n-----------------------------------------------------------------------------------------------------\n\nThis is similar to the other [write example](recipes.md#write-a-text-file-javakotlin), but it uses\n`java.io.File` instead of `okio.Path` and `okio.FileSystem`.\n\n=== \"Java\"\n\n    ```java\n    public void writeEnv(File file) throws IOException {\n      try (Sink fileSink = Okio.sink(file);\n           BufferedSink bufferedSink = Okio.buffer(fileSink)) {\n\n        for (Map.Entry<String, String> entry : System.getenv().entrySet()) {\n          bufferedSink.writeUtf8(entry.getKey());\n          bufferedSink.writeUtf8(\"=\");\n          bufferedSink.writeUtf8(entry.getValue());\n          bufferedSink.writeUtf8(\"\\n\");\n        }\n\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```kotlin\n    @Throws(IOException::class)\n    fun writeEnv(file: File) {\n      file.sink().buffer().use { sink ->\n        for ((key, value) in System.getenv()) {\n          sink.writeUtf8(key)\n          sink.writeUtf8(\"=\")\n          sink.writeUtf8(value)\n          sink.writeUtf8(\"\\n\")\n        }\n      }\n    }\n    ```\n\n\n[ReadJavaIoFileLineByLineKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/ReadJavaIoFileLineByLine.kt\n[ReadJavaIoFileLineByLine]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/ReadJavaIoFileLineByLine.java\n[WriteJavaIoFileKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/WriteJavaIoFile.kt\n[WriteJavaIoFile]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/WriteJavaIoFile.java\n"
  },
  {
    "path": "docs/multiplatform.md",
    "content": "Multiplatform\n=============\n\nOkio is a [Kotlin Multiplatform][kotlin_multiplatform] project. We're still completing our feature\ncoverage.\n\n\n### Compression (Deflater, Inflater, Gzip)\n\nJVM and native platforms.\n\n\n### Concurrency (Pipe, Timeouts, Throttler)\n\nJVM-only.\n\nTimeout is on all platforms, but only the JVM has a useful implementation.\n\n\n### Core (Buffer, ByteString, Source, Sink)\n\nAvailable on all platforms.\n\n\n### File System\n\nAvailable on all platforms. For JavaScript this requires [Node.js][node_js].\n\n\n### Hashing\n\nOkio includes Kotlin implementations of MD5, SHA-1, SHA-256, and SHA-512. This includes both hash\nfunctions and HMAC functions.\n\nOkio uses the built-in implementations of these functions on the JVM.\n\n\n[kotlin_multiplatform]: https://kotlinlang.org/docs/reference/multiplatform.html\n[mingw]: http://www.mingw.org/\n[node_js]: https://nodejs.org/api/fs.html\n\n## Gradle configuration\n\n```kotlin\n// build.gradle.kts\nkotlin {\n    sourceSets {\n        val okioVersion = \"3.XXX\"\n        val commonMain by getting {\n            dependencies {\n                implementation(\"com.squareup.okio:okio:$okioVersion\")\n            }\n        }\n        val jsMain by getting {\n            dependencies {\n                implementation(\"com.squareup.okio:okio-nodefilesystem:$okioVersion\")\n            }\n        }\n        val commonTest by getting {\n            dependencies {\n                implementation(\"com.squareup.okio:okio-fakefilesystem:$okioVersion\")\n            }\n        }\n    }\n}\n```\n"
  },
  {
    "path": "docs/recipes.md",
    "content": "Recipes\n=======\n\nWe've written some recipes that demonstrate how to solve common problems with Okio. Read through\nthem to learn about how everything works together. Cut-and-paste these examples freely; that's what\nthey're for.\n\nThese recipes work on all platforms: Java, Android, Kotlin/Native, and Kotlin/JS. See\n[java.io Recipes](java_io_recipes.md) for samples that integrate Java APIs.\n\n\nRead a text file line-by-line ([Java][ReadFileLineByLine]/[Kotlin][ReadFileLineByLineKt])\n-----------------------------------------------------------------------------------------\n\nUse `FileSystem.source(Path)` to open a source stream to read a file. The returned `Source`\ninterface is very small and has limited uses. Instead we wrap the source with a buffer. This has two\nbenefits:\n\n * **It makes the API more powerful.** Instead of the basic methods offered by `Source`,\n   `BufferedSource` has dozens of methods to address most common problems concisely.\n\n * **It makes your program run faster.** Buffering allows Okio to get more done with fewer I/O\n   operations.\n\nEach `Source` that is opened needs to be closed. The code that opens the stream is responsible for\nmaking sure it is closed.\n\n=== \"Java\"\n\n    Here we use Java's `try` blocks to close our sources automatically.\n\n    ```java\n    public void readLines(Path path) throws IOException {\n      try (Source fileSource = FileSystem.SYSTEM.source(path);\n           BufferedSource bufferedFileSource = Okio.buffer(fileSource)) {\n\n        while (true) {\n          String line = bufferedFileSource.readUtf8Line();\n          if (line == null) break;\n\n          if (line.contains(\"square\")) {\n            System.out.println(line);\n          }\n        }\n\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    This uses `use` to automatically close the streams. This prevents resource leaks, even if an\n    exception is thrown.\n\n    ```kotlin\n    fun readLines(path: Path) {\n      FileSystem.SYSTEM.source(path).use { fileSource ->\n        fileSource.buffer().use { bufferedFileSource ->\n          while (true) {\n            val line = bufferedFileSource.readUtf8Line() ?: break\n            if (\"square\" in line) {\n              println(line)\n            }\n          }\n        }\n      }\n    }\n    ```\n\n\nThe `readUtf8Line()` API reads all of the data until the next line delimiter – either `\\n`, `\\r\\n`,\nor the end of the file. It returns that data as a string, omitting the delimiter at the end. When it\nencounters empty lines the method will return an empty string. If there isn’t any more data to read\nit will return null.\n\n\n=== \"Java\"\n\n    The above Java program can be written more compactly by inlining the `fileSource` variable and\n    by using a fancy `for` loop instead of a `while`:\n\n    ```java\n    public void readLines(Path path) throws IOException {\n      try (BufferedSource source = Okio.buffer(FileSystem.SYSTEM.source(path))) {\n        for (String line; (line = source.readUtf8Line()) != null; ) {\n          if (line.contains(\"square\")) {\n            System.out.println(line);\n          }\n        }\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    In Kotlin, we can use `FileSystem.read()` to buffer the source before our block and close the\n    source afterwards. In the body of the block, `this` is a `BufferedSource`.\n\n    ```kotlin\n    @Throws(IOException::class)\n    fun readLines(path: Path) {\n      FileSystem.SYSTEM.read(path) {\n        while (true) {\n          val line = readUtf8Line() ?: break\n          if (\"square\" in line) {\n            println(line)\n          }\n        }\n      }\n    }\n    ```\n\nThe `readUtf8Line()` method is suitable for parsing most files. For certain use-cases you may also\nconsider `readUtf8LineStrict()`. It is similar but it requires that each line is terminated by `\\n`\nor `\\r\\n`. If it encounters the end of the file before that it will throw an `EOFException`. The\nstrict variant also permits a byte limit to defend against malformed input.\n\n=== \"Java\"\n\n    ```java\n    public void readLines(Path path) throws IOException {\n      try (BufferedSource source = Okio.buffer(FileSystem.SYSTEM.source(path))) {\n        while (!source.exhausted()) {\n          String line = source.readUtf8LineStrict(1024L);\n          if (line.contains(\"square\")) {\n            System.out.println(line);\n          }\n        }\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```kotlin\n    @Throws(IOException::class)\n    fun readLines(path: Path) {\n      FileSystem.SYSTEM.read(path) {\n        while (!source.exhausted()) {\n          val line = source.readUtf8LineStrict(1024)\n          if (\"square\" in line) {\n            println(line)\n          }\n        }\n      }\n    }\n    ```\n\n\nWrite a text file ([Java][WriteFile]/[Kotlin][WriteFileKt])\n-----------------------------------------------------------\n\nAbove we used a `Source` and a `BufferedSource` to read a file. To write, we use a `Sink` and a\n`BufferedSink`. The advantages of buffering are the same: a more capable API and better performance.\n\n```java\npublic void writeEnv(Path path) throws IOException {\n  try (Sink fileSink = FileSystem.SYSTEM.sink(path);\n       BufferedSink bufferedSink = Okio.buffer(fileSink)) {\n\n    for (Map.Entry<String, String> entry : System.getenv().entrySet()) {\n      bufferedSink.writeUtf8(entry.getKey());\n      bufferedSink.writeUtf8(\"=\");\n      bufferedSink.writeUtf8(entry.getValue());\n      bufferedSink.writeUtf8(\"\\n\");\n    }\n\n  }\n}\n```\n\nThere isn’t an API to write a line of input; instead we manually insert our own newline character.\nMost programs should hardcode `\"\\n\"` as the newline character. In rare situations you may use\n`System.lineSeparator()` instead of `\"\\n\"`: it returns `\"\\r\\n\"` on Windows and `\"\\n\"` everywhere\nelse.\n\n=== \"Java\"\n\n    We can write the above program more compactly by inlining the `fileSink` variable and by taking\n    advantage of method chaining:\n\n    ```java\n    public void writeEnv(Path path) throws IOException {\n      try (BufferedSink sink = Okio.buffer(FileSystem.SYSTEM.sink(path))) {\n        for (Map.Entry<String, String> entry : System.getenv().entrySet()) {\n          sink.writeUtf8(entry.getKey())\n            .writeUtf8(\"=\")\n            .writeUtf8(entry.getValue())\n            .writeUtf8(\"\\n\");\n        }\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    In Kotlin, we can use `FileSystem.write()` to buffer the sink before our block and close the\n    sink afterwards. In the body of the block, `this` is a `BufferedSink`.\n\n    ```kotlin\n    @Throws(IOException::class)\n    fun writeEnv(path: Path) {\n      FileSystem.SYSTEM.write(path) {\n        for ((key, value) in System.getenv()) {\n          writeUtf8(key)\n          writeUtf8(\"=\")\n          writeUtf8(value)\n          writeUtf8(\"\\n\")\n        }\n      }\n    }\n    ```\n\nIn the above code we make four calls to `writeUtf8()`. Making four calls is more efficient than the\ncode below because the VM doesn’t have to create and garbage collect a temporary string.\n\n```java\nsink.writeUtf8(entry.getKey() + \"=\" + entry.getValue() + \"\\n\"); // Slower!\n```\n\n\nUTF-8 ([Java][ExploreCharsets]/[Kotlin][ExploreCharsetsKt])\n-----------------------------------------------------------\n\nIn the above APIs you can see that Okio really likes UTF-8. Early computer systems suffered many\nincompatible character encodings: ISO-8859-1, ShiftJIS, ASCII, EBCDIC, etc. Writing software to\nsupport multiple character sets was awful and we didn’t even have emoji! Today we're lucky that the\nworld has standardized on UTF-8 everywhere, with some rare uses of other charsets in legacy systems.\n\nIf you need another character set, `readString()` and `writeString()` are there for you. These\n methods require that you specify a character set. Otherwise you may accidentally create data that\n is only readable by the local computer. Most programs should use the UTF-8 methods only.\n\nWhen encoding strings you need to be mindful of the different ways that strings are represented and\nencoded. When a glyph has an accent or another adornment it may be represented as a single complex\n code point (`é`) or as a simple code point (`e`) followed by its modifiers (`´`). When the entire\n glyph is a single code point that’s called [NFC][nfc]; when it’s multiple it’s [NFD][nfd].\n\nThough we use UTF-8 whenever we read or write strings in I/O, when they are in memory Java Strings\nuse an obsolete character encoding called UTF-16. It is a bad encoding because it uses a 16-bit\n`char` for most characters, but some don’t fit. In particular, most emoji use two Java chars. This\nis problematic because `String.length()` returns a surprising result: the number of UTF-16 chars and\nnot the natural number of glyphs.\n\n|                       | Café 🍩                     | Café 🍩                        |\n| --------------------: | :---------------------------| :------------------------------|\n|                  Form | [NFC][nfc]                  | [NFD][nfd]                     |\n|           Code Points | `c  a  f  é    ␣   🍩     ` | `c  a  f  e  ´    ␣   🍩     ` |\n|           UTF-8 bytes | `43 61 66 c3a9 20 f09f8da9` | `43 61 66 65 cc81 20 f09f8da9` |\n| String.codePointCount | 6                           | 7                              |\n|         String.length | 7                           | 8                              |\n|             Utf8.size | 10                          | 11                             |\n\nFor the most part Okio lets you ignore these problems and focus on your data. But when you need\nthem, there are convenient APIs for dealing with low-level UTF-8 strings.\n\nUse `Utf8.size()` to count the number of bytes required to encode a string as UTF-8 without actually\nencoding it. This is handy in length-prefixed encodings like protocol buffers.\n\nUse `BufferedSource.readUtf8CodePoint()` to read a single variable-length code point, and\n`BufferedSink.writeUtf8CodePoint()` to write one.\n\n\n=== \"Java\"\n\n    ```java\n    public void dumpStringData(String s) throws IOException {\n      System.out.println(\"                       \" + s);\n      System.out.println(\"        String.length: \" + s.length());\n      System.out.println(\"String.codePointCount: \" + s.codePointCount(0, s.length()));\n      System.out.println(\"            Utf8.size: \" + Utf8.size(s));\n      System.out.println(\"          UTF-8 bytes: \" + ByteString.encodeUtf8(s).hex());\n      System.out.println();\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```kotlin\n    fun dumpStringData(s: String) {\n      println(\"                       \" + s)\n      println(\"        String.length: \" + s.length)\n      println(\"String.codePointCount: \" + s.codePointCount(0, s.length))\n      println(\"            Utf8.size: \" + s.utf8Size())\n      println(\"          UTF-8 bytes: \" + s.encodeUtf8().hex())\n      println()\n    }\n    ```\n\nGolden Values ([Java][GoldenValue]/[Kotlin][GoldenValueKt])\n-----------------------------------------------------------\n\nOkio likes testing. The library itself is heavily tested, and it has features that are often helpful\nwhen testing application code. One pattern we’ve found to be quite useful is “golden value” testing.\nThe goal of such tests is to confirm that data encoded with earlier versions of a program can safely\nbe decoded by the current program.\n\nWe’ll illustrate this by encoding a value using Java Serialization. Though we must disclaim that\nJava Serialization is an awful encoding system and most programs should prefer other formats like\nJSON or protobuf! In any case, here’s a method that takes an object, serializes it, and returns the\nresult as a `ByteString`:\n\n=== \"Java\"\n\n    ```Java\n    private ByteString serialize(Object o) throws IOException {\n      Buffer buffer = new Buffer();\n      try (ObjectOutputStream objectOut = new ObjectOutputStream(buffer.outputStream())) {\n        objectOut.writeObject(o);\n      }\n      return buffer.readByteString();\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    @Throws(IOException::class)\n    private fun serialize(o: Any?): ByteString {\n      val buffer = Buffer()\n      ObjectOutputStream(buffer.outputStream()).use { objectOut ->\n        objectOut.writeObject(o)\n      }\n      return buffer.readByteString()\n    }\n    ```\n\nThere’s a lot going on here.\n\n1. We create a buffer as a holding space for our serialized data. It’s a convenient replacement for\n   `ByteArrayOutputStream`.\n\n2. We ask the buffer for its output stream. Writes to a buffer or its output stream always append\n   data to the end of the buffer.\n\n3. We create an `ObjectOutputStream` (the encoding API for Java serialization) and write our object.\n   The try block takes care of closing the stream for us. Note that closing a buffer has no effect.\n\n4. Finally we read a byte string from the buffer. The `readByteString()` method allows us to specify\n   how many bytes to read; here we don’t specify a count in order to read the entire thing. Reads\n   from a buffer always consume data from the front of the buffer.\n\nWith our `serialize()` method handy we are ready to compute and print a golden value.\n\n=== \"Java\"\n\n    ```Java\n    Point point = new Point(8.0, 15.0);\n    ByteString pointBytes = serialize(point);\n    System.out.println(pointBytes.base64());\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val point = Point(8.0, 15.0)\n    val pointBytes = serialize(point)\n    println(pointBytes.base64())\n    ```\n\nWe print the `ByteString` as [base64][base64] because it’s a compact format that’s suitable for\nembedding in a test case. The program prints this:\n\n```\nrO0ABXNyAB5va2lvLnNhbXBsZXMuR29sZGVuVmFsdWUkUG9pbnTdUW8rMji1IwIAAkQAAXhEAAF5eHBAIAAAAAAAAEAuAAAAAAAA\n```\n\nThat’s our golden value! We can embed it in our test case using base64 again to convert it back into\na `ByteString`:\n\n=== \"Java\"\n\n    ```Java\n    ByteString goldenBytes = ByteString.decodeBase64(\"rO0ABXNyAB5va2lvLnNhbXBsZ\"\n        + \"XMuR29sZGVuVmFsdWUkUG9pbnTdUW8rMji1IwIAAkQAAXhEAAF5eHBAIAAAAAAAAEAuA\"\n        + \"AAAAAAA\");\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val goldenBytes = (\"rO0ABXNyACRva2lvLnNhbXBsZXMuS290bGluR29sZGVuVmFsdWUkUG9pbnRF9yaY7cJ9EwIAA\" +\n      \"kQAAXhEAAF5eHBAIAAAAAAAAEAuAAAAAAAA\").decodeBase64()\n    ```\n\nThe next step is to deserialize the `ByteString` back into our value class. This method reverses the\n`serialize()` method above: we append a byte string to a buffer then consume it using an\n`ObjectInputStream`:\n\n=== \"Java\"\n\n    ```Java\n    private Object deserialize(ByteString byteString) throws IOException, ClassNotFoundException {\n      Buffer buffer = new Buffer();\n      buffer.write(byteString);\n      try (ObjectInputStream objectIn = new ObjectInputStream(buffer.inputStream())) {\n        return objectIn.readObject();\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    @Throws(IOException::class, ClassNotFoundException::class)\n    private fun deserialize(byteString: ByteString): Any? {\n      val buffer = Buffer()\n      buffer.write(byteString)\n      ObjectInputStream(buffer.inputStream()).use { objectIn ->\n        return objectIn.readObject()\n      }\n    }\n    ```\n\nNow we can test the decoder against the golden value:\n\n=== \"Java\"\n\n    ```Java\n    ByteString goldenBytes = ByteString.decodeBase64(\"rO0ABXNyAB5va2lvLnNhbXBsZ\"\n        + \"XMuR29sZGVuVmFsdWUkUG9pbnTdUW8rMji1IwIAAkQAAXhEAAF5eHBAIAAAAAAAAEAuA\"\n        + \"AAAAAAA\");\n    Point decoded = (Point) deserialize(goldenBytes);\n    assertEquals(new Point(8.0, 15.0), decoded);\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val goldenBytes = (\"rO0ABXNyACRva2lvLnNhbXBsZXMuS290bGluR29sZGVuVmFsdWUkUG9pbnRF9yaY7cJ9EwIAA\" +\n      \"kQAAXhEAAF5eHBAIAAAAAAAAEAuAAAAAAAA\").decodeBase64()!!\n    val decoded = deserialize(goldenBytes) as Point\n    assertEquals(point, decoded)\n    ```\n\nWith this test we can change the serialization of the `Point` class without\nbreaking compatibility.\n\n\nWrite a binary file ([Java][BitmapEncoder]/[Kotlin][BitmapEncoderKt])\n---------------------------------------------------------------------\n\nEncoding a binary file is not unlike encoding a text file. Okio uses the same `BufferedSink` and\n`BufferedSource` bytes for both. This is handy for binary formats that include both byte and\ncharacter data.\n\nWriting binary data is more hazardous than text because if you make a mistake it is often quite\ndifficult to diagnose. Avoid such mistakes by being careful around these traps:\n\n * **The width of each field.** This is the number of bytes used. Okio doesn't include a mechanism\n   to emit partial bytes. If you need that, you’ll need to do your own bit shifting and masking\n   before writing.\n\n * **The endianness of each field.** All fields that have more than one byte have _endianness_:\n   whether the bytes are ordered most-significant to least (big endian) or least-significant to most\n   (little endian). Okio uses the `Le` suffix for little-endian methods; methods without a suffix\n   are big-endian.\n\n * **Signed vs. Unsigned.** Java doesn’t have unsigned primitive types (except for `char`!) so\n   coping with this is often something that happens at the application layer. To make this a little\n   easier Okio accepts `int` types for `writeByte()` and `writeShort()`. You can pass an “unsigned”\n   byte like 255 and Okio will do the right thing.\n\n| Method       | Width | Endianness |           Value | Encoded Value             |\n| :----------- | ----: | :--------- | --------------: | :------------------------ |\n| writeByte    |     1 |            |               3 | `03`                      |\n| writeShort   |     2 | big        |               3 | `00 03`                   |\n| writeInt     |     4 | big        |               3 | `00 00 00 03`             |\n| writeLong    |     8 | big        |               3 | `00 00 00 00 00 00 00 03` |\n| writeShortLe |     2 | little     |               3 | `03 00`                   |\n| writeIntLe   |     4 | little     |               3 | `03 00 00 00`             |\n| writeLongLe  |     8 | little     |               3 | `03 00 00 00 00 00 00 00` |\n| writeByte    |     1 |            |  Byte.MAX_VALUE | `7f`                      |\n| writeShort   |     2 | big        | Short.MAX_VALUE | `7f ff`                   |\n| writeInt     |     4 | big        |   Int.MAX_VALUE | `7f ff ff ff`             |\n| writeLong    |     8 | big        |  Long.MAX_VALUE | `7f ff ff ff ff ff ff ff` |\n| writeShortLe |     2 | little     | Short.MAX_VALUE | `ff 7f`                   |\n| writeIntLe   |     4 | little     |   Int.MAX_VALUE | `ff ff ff 7f`             |\n| writeLongLe  |     8 | little     |  Long.MAX_VALUE | `ff ff ff ff ff ff ff 7f` |\n\nThis code encodes a bitmap following the [BMP file format][bmp].\n\n=== \"Java\"\n\n    ```Java\n    void encode(Bitmap bitmap, BufferedSink sink) throws IOException {\n      int height = bitmap.height();\n      int width = bitmap.width();\n\n      int bytesPerPixel = 3;\n      int rowByteCountWithoutPadding = (bytesPerPixel * width);\n      int rowByteCount = ((rowByteCountWithoutPadding + 3) / 4) * 4;\n      int pixelDataSize = rowByteCount * height;\n      int bmpHeaderSize = 14;\n      int dibHeaderSize = 40;\n\n      // BMP Header\n      sink.writeUtf8(\"BM\"); // ID.\n      sink.writeIntLe(bmpHeaderSize + dibHeaderSize + pixelDataSize); // File size.\n      sink.writeShortLe(0); // Unused.\n      sink.writeShortLe(0); // Unused.\n      sink.writeIntLe(bmpHeaderSize + dibHeaderSize); // Offset of pixel data.\n\n      // DIB Header\n      sink.writeIntLe(dibHeaderSize);\n      sink.writeIntLe(width);\n      sink.writeIntLe(height);\n      sink.writeShortLe(1);  // Color plane count.\n      sink.writeShortLe(bytesPerPixel * Byte.SIZE);\n      sink.writeIntLe(0);    // No compression.\n      sink.writeIntLe(16);   // Size of bitmap data including padding.\n      sink.writeIntLe(2835); // Horizontal print resolution in pixels/meter. (72 dpi).\n      sink.writeIntLe(2835); // Vertical print resolution in pixels/meter. (72 dpi).\n      sink.writeIntLe(0);    // Palette color count.\n      sink.writeIntLe(0);    // 0 important colors.\n\n      // Pixel data.\n      for (int y = height - 1; y >= 0; y--) {\n        for (int x = 0; x < width; x++) {\n          sink.writeByte(bitmap.blue(x, y));\n          sink.writeByte(bitmap.green(x, y));\n          sink.writeByte(bitmap.red(x, y));\n        }\n\n        // Padding for 4-byte alignment.\n        for (int p = rowByteCountWithoutPadding; p < rowByteCount; p++) {\n          sink.writeByte(0);\n        }\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    @Throws(IOException::class)\n    fun encode(bitmap: Bitmap, sink: BufferedSink) {\n      val height = bitmap.height\n      val width = bitmap.width\n      val bytesPerPixel = 3\n      val rowByteCountWithoutPadding = bytesPerPixel * width\n      val rowByteCount = (rowByteCountWithoutPadding + 3) / 4 * 4\n      val pixelDataSize = rowByteCount * height\n      val bmpHeaderSize = 14\n      val dibHeaderSize = 40\n\n      // BMP Header\n      sink.writeUtf8(\"BM\") // ID.\n      sink.writeIntLe(bmpHeaderSize + dibHeaderSize + pixelDataSize) // File size.\n      sink.writeShortLe(0) // Unused.\n      sink.writeShortLe(0) // Unused.\n      sink.writeIntLe(bmpHeaderSize + dibHeaderSize) // Offset of pixel data.\n\n      // DIB Header\n      sink.writeIntLe(dibHeaderSize)\n      sink.writeIntLe(width)\n      sink.writeIntLe(height)\n      sink.writeShortLe(1) // Color plane count.\n      sink.writeShortLe(bytesPerPixel * Byte.SIZE_BITS)\n      sink.writeIntLe(0) // No compression.\n      sink.writeIntLe(16) // Size of bitmap data including padding.\n      sink.writeIntLe(2835) // Horizontal print resolution in pixels/meter. (72 dpi).\n      sink.writeIntLe(2835) // Vertical print resolution in pixels/meter. (72 dpi).\n      sink.writeIntLe(0) // Palette color count.\n      sink.writeIntLe(0) // 0 important colors.\n\n      // Pixel data.\n      for (y in height - 1 downTo 0) {\n        for (x in 0 until width) {\n          sink.writeByte(bitmap.blue(x, y))\n          sink.writeByte(bitmap.green(x, y))\n          sink.writeByte(bitmap.red(x, y))\n        }\n\n        // Padding for 4-byte alignment.\n        for (p in rowByteCountWithoutPadding until rowByteCount) {\n          sink.writeByte(0)\n        }\n      }\n    }\n    ```\n\nThe trickiest part of this program is the format’s required padding. The BMP format expects each row\nto begin on a 4-byte boundary so it is necessary to add zeros to maintain the alignment.\n\nEncoding other binary formats is usually quite similar. Some tips:\n\n * Write tests with golden values! Confirming that your program emits the expected result can make\n   debugging easier.\n * Use `Utf8.size()` to compute the number of bytes of an encoded string. This is essential for\n   length-prefixed formats.\n * Use `Float.floatToIntBits()` and `Double.doubleToLongBits()` to encode floating point values.\n\n\nCommunicate on a Socket ([Java][SocksProxyServer]/[Kotlin][SocksProxyServerKt])\n-------------------------------------------------------------------------------\n\nNote that Okio doesn't yet support sockets on Kotlin/Native or Kotlin/JS.\n\nSending and receiving data over the network is a bit like writing and reading files. We use\n`BufferedSink` to encode output and `BufferedSource` to decode input. Like files, network protocols\ncan be text, binary, or a mix of both. But there are also some substantial differences between the\nnetwork and the file system.\n\nWith a file you’re either reading or writing but with the network you can do both! Some protocols\nhandle this by taking turns: write a request, read a response, repeat. You can implement this kind\nof protocol with a single thread. In other protocols you may read and write simultaneously.\nTypically you’ll want one dedicated thread for reading. For writing you can use either a dedicated\nthread or use `synchronized` so that multiple threads can share a sink. Okio’s streams are not safe\nfor concurrent use.\n\nSinks buffer outbound data to minimize I/O operations. This is efficient but it means you must\nmanually call `flush()` to transmit data. Typically message-oriented protocols flush after each\nmessage. Note that Okio will automatically flush when the buffered data exceeds some threshold. This\nis intended to save memory and you shouldn’t rely on it for interactive protocols.\n\nOkio builds on `java.io.Socket` for connectivity. Create your socket as a server or as a client,\nthen use `Okio.source(Socket)` to read and `Okio.sink(Socket)` to write. These APIs also work with\n`SSLSocket`. You should use SSL unless you have a very good reason not to!\n\nCancel a socket from any thread by calling `Socket.close()`; this will cause its sources and sinks\nto immediately fail with an `IOException`. You can also configure timeouts for all socket\noperations. You don’t need a reference to the socket to adjust timeouts: `Source` and `Sink` expose\ntimeouts directly. This API works even if the streams are decorated.\n\nAs a complete example of networking with Okio we wrote a [basic SOCKS proxy][SocksProxyServer]\nserver. Some highlights:\n\n=== \"Java\"\n\n    ```Java\n    Socket fromSocket = ...\n    BufferedSource fromSource = Okio.buffer(Okio.source(fromSocket));\n    BufferedSink fromSink = Okio.buffer(Okio.sink(fromSocket));\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val fromSocket: Socket = ...\n    val fromSource = fromSocket.source().buffer()\n    val fromSink = fromSocket.sink().buffer()\n    ```\n\nCreating sources and sinks for sockets is the same as creating them for files. Once you create a\n`Source` or `Sink` for a socket you must not use its `InputStream` or `OutputStream`, respectively.\n\n=== \"Java\"\n\n    ```Java\n    Buffer buffer = new Buffer();\n    for (long byteCount; (byteCount = source.read(buffer, 8192L)) != -1; ) {\n      sink.write(buffer, byteCount);\n      sink.flush();\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val buffer = Buffer()\n    var byteCount: Long\n    while (source.read(buffer, 8192L).also { byteCount = it } != -1L) {\n      sink.write(buffer, byteCount)\n      sink.flush()\n    }\n    ```\n\nThe above loop copies data from the source to the sink, flushing after each read. If we didn’t need\nthe flushing we could replace this loop with a single call to `BufferedSink.writeAll(Source)`.\n\nThe `8192` argument to `read()` is the maximum number of bytes to read before returning. We could\nhave passed any value here, but we like 8 KiB because that’s the largest value Okio can do in a\nsingle system call. Most of the time application code doesn’t need to deal with such limits!\n\n=== \"Java\"\n\n    ```Java\n    int addressType = fromSource.readByte() & 0xff;\n    int port = fromSource.readShort() & 0xffff;\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val addressType = fromSource.readByte().toInt() and 0xff\n    val port = fromSource.readShort().toInt() and 0xffff\n    ```\n\nOkio uses signed types like `byte` and `short`, but often protocols want unsigned values. The\nbitwise `&` operator is Java’s preferred idiom to convert a signed value into an unsigned value.\nHere’s a cheat sheet for bytes, shorts, and ints:\n\n| Type  | Signed Range                  | Unsigned Range   | Signed to Unsigned          |\n| :---- | :---------------------------: | :--------------- | :-------------------------- |\n| byte  | -128..127                     | 0..255           | `int u = s & 0xff;`         |\n| short | -32,768..32,767               | 0..65,535        | `int u = s & 0xffff;`       |\n| int   | -2,147,483,648..2,147,483,647 | 0..4,294,967,295 | `long u = s & 0xffffffffL;` |\n\nJava has no primitive type that can represent unsigned longs.\n\n\nHashing ([Java][Hashing]/[Kotlin][HashingKt])\n---------------------------------------------\n\nWe’re bombarded by hashing in our lives as Java programmers. Early on we're introduced to the\n`hashCode()` method, something we know we need to override otherwise unforeseen bad things happen.\nLater we’re shown `LinkedHashMap` and its friends. These build on that `hashCode()` method to\norganize data for fast retrieval.\n\nElsewhere we have cryptographic hash functions. These get used all over the place. HTTPS\ncertificates, Git commits, BitTorrent integrity checking, and Blockchain blocks all use\ncryptographic hashes. Good use of hashes can improve the performance, privacy, security, and\nsimplicity of an application.\n\nEach cryptographic hash function accepts a variable-length stream of input bytes and produces a\nfixed-length byte string value called the “hash”. Hash functions have these important qualities:\n\n * Deterministic: each input always produces the same output.\n * Uniform: each output byte string is equally likely. It is very difficult to find or create pairs\n   of different inputs that yield the same output. This is called a “collision”.\n * Non-reversible: knowing an output doesn't help you to find the input. Note that if you know some\n   possible inputs you can hash them to see if their hashes match.\n * Well-known: the hash is implemented everywhere and rigorously understood.\n\nGood hash functions are very cheap to compute (dozens of microseconds) and expensive to reverse\n(quintillions of millenia). Steady advances in computing and mathematics have caused once-great hash\nfunctions to become inexpensive to reverse. When choosing a hash function, beware that not all are\ncreated equal! Okio supports these well-known cryptographic hash functions:\n\n * **MD5**: a 128-bit (16 byte) cryptographic hash. It is both insecure and obsolete because it is\n   inexpensive to reverse! This hash is offered because it is popular and convenient for use in\n   legacy systems that are not security-sensitive.\n * **SHA-1**: a 160-bit (20 byte) cryptographic hash. It was recently demonstrated that it is\n   feasible to create SHA-1 collisions. Consider upgrading from SHA-1 to SHA-256.\n * **SHA-256**: a 256-bit (32 byte) cryptographic hash. SHA-256 is widely understood and expensive\n   to reverse. This is the hash most systems should use.\n * **SHA-512**: a 512-bit (64 byte) cryptographic hash. It is expensive to reverse.\n\nEach hash creates a `ByteString` of the specified length. Use `hex()` to get the conventional\nhuman-readable form. Or leave it as a `ByteString` because that’s a convenient model type!\n\nOkio can produce cryptographic hashes from byte strings:\n\n=== \"Java\"\n\n    ```Java\n    ByteString byteString = readByteString(Path.get(\"README.md\"));\n    System.out.println(\"   md5: \" + byteString.md5().hex());\n    System.out.println(\"  sha1: \" + byteString.sha1().hex());\n    System.out.println(\"sha256: \" + byteString.sha256().hex());\n    System.out.println(\"sha512: \" + byteString.sha512().hex());\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val byteString = readByteString(\"README.md\".toPath())\n    println(\"       md5: \" + byteString.md5().hex())\n    println(\"      sha1: \" + byteString.sha1().hex())\n    println(\"    sha256: \" + byteString.sha256().hex())\n    println(\"    sha512: \" + byteString.sha512().hex())\n    ```\n\nFrom buffers:\n\n=== \"Java\"\n\n    ```Java\n    Buffer buffer = readBuffer(Path.get(\"README.md\"));\n    System.out.println(\"   md5: \" + buffer.md5().hex());\n    System.out.println(\"  sha1: \" + buffer.sha1().hex());\n    System.out.println(\"sha256: \" + buffer.sha256().hex());\n    System.out.println(\"sha512: \" + buffer.sha512().hex());\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val buffer = readBuffer(\"README.md\".toPath())\n    println(\"       md5: \" + buffer.md5().hex())\n    println(\"      sha1: \" + buffer.sha1().hex())\n    println(\"    sha256: \" + buffer.sha256().hex())\n    println(\"    sha512: \" + buffer.sha512().hex())\n    ```\n\nWhile streaming from a source:\n\n=== \"Java\"\n\n    ```Java\n    try (HashingSink hashingSink = HashingSink.sha256(Okio.blackhole());\n         BufferedSource source = Okio.buffer(FileSystem.SYSTEM.source(path))) {\n      source.readAll(hashingSink);\n      System.out.println(\"sha256: \" + hashingSink.hash().hex());\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    sha256(blackholeSink()).use { hashingSink ->\n      FileSystem.SYSTEM.source(path).buffer().use { source ->\n        source.readAll(hashingSink)\n        println(\"    sha256: \" + hashingSink.hash.hex())\n      }\n    }\n    ```\n\nWhile streaming to a sink:\n\n=== \"Java\"\n\n    ```Java\n    try (HashingSink hashingSink = HashingSink.sha256(Okio.blackhole());\n         BufferedSink sink = Okio.buffer(hashingSink);\n         Source source = FileSystem.SYSTEM.source(path)) {\n      sink.writeAll(source);\n      sink.close(); // Emit anything buffered.\n      System.out.println(\"sha256: \" + hashingSink.hash().hex());\n    }\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    sha256(blackholeSink()).use { hashingSink ->\n      hashingSink.buffer().use { sink ->\n        FileSystem.SYSTEM.source(path).use { source ->\n          sink.writeAll(source)\n          sink.close() // Emit anything buffered.\n          println(\"    sha256: \" + hashingSink.hash.hex())\n        }\n      }\n    }\n    ```\n\nOkio also supports HMAC (Hash Message Authentication Code) which combines a secret and a hash.\nApplications use HMAC for data integrity and authentication.\n\n=== \"Java\"\n\n    ```Java\n    ByteString secret = ByteString.decodeHex(\"7065616e7574627574746572\");\n    System.out.println(\"hmacSha256: \" + byteString.hmacSha256(secret).hex());\n    ```\n\n=== \"Kotlin\"\n\n    ```Kotlin\n    val secret = \"7065616e7574627574746572\".decodeHex()\n    println(\"hmacSha256: \" + byteString.hmacSha256(secret).hex())\n    ```\n\nAs with hashing, you can generate an HMAC from a `ByteString`, `Buffer`, `HashingSource`, and\n`HashingSink`. Note that Okio doesn’t implement HMAC for MD5.\n\nOn Android and Java, Okio uses Java’s `java.security.MessageDigest` for cryptographic hashes and\n`javax.crypto.Mac` for HMAC. On other platforms Okio uses its own optimized implementation of\nthese algorithms.\n\n\nEncryption and Decryption\n-------------------------\n\nOn Android and Java it's easy to encrypt streams.\n\nCallers are responsible for the initialization of the encryption or decryption cipher with the\nchosen algorithm, the key, and algorithm-specific additional parameters like the initialization\nvector. The following example shows a typical usage with AES encryption, in which `key` and `iv`\nparameters should both be 16 bytes long.\n\n=== \"Java\"\n\n    Use `Okio.cipherSink(Sink, Cipher)` or `Okio.cipherSource(Source, Cipher)` to encrypt or decrypt\n    a stream using a block cipher.\n\n    ```java\n    void encryptAes(ByteString bytes, Path path, byte[] key, byte[] iv)\n        throws GeneralSecurityException, IOException {\n      Cipher cipher = Cipher.getInstance(\"AES/CBC/PKCS5Padding\");\n      cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, \"AES\"), new IvParameterSpec(iv));\n      try (BufferedSink sink = Okio.buffer(\n          Okio.cipherSink(FileSystem.SYSTEM.sink(path), cipher))) {\n        sink.write(bytes);\n      }\n    }\n\n    ByteString decryptAesToByteString(Path path, byte[] key, byte[] iv)\n        throws GeneralSecurityException, IOException {\n      Cipher cipher = Cipher.getInstance(\"AES/CBC/PKCS5Padding\");\n      cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, \"AES\"), new IvParameterSpec(iv));\n      try (BufferedSource source = Okio.buffer(\n          Okio.cipherSource(FileSystem.SYSTEM.source(path), cipher))) {\n        return source.readByteString();\n      }\n    }\n    ```\n\n=== \"Kotlin\"\n\n    Encryption and decryption functions are extensions on `Cipher`:\n\n    ```kotlin\n    fun encryptAes(bytes: ByteString, path: Path, key: ByteArray, iv: ByteArray) {\n      val cipher = Cipher.getInstance(\"AES/CBC/PKCS5Padding\")\n      cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, \"AES\"), IvParameterSpec(iv))\n      val cipherSink = FileSystem.SYSTEM.sink(path).cipherSink(cipher)\n      cipherSink.buffer().use {\n        it.write(bytes)\n      }\n    }\n\n    fun decryptAesToByteString(path: Path, key: ByteArray, iv: ByteArray): ByteString {\n      val cipher = Cipher.getInstance(\"AES/CBC/PKCS5Padding\")\n      cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, \"AES\"), IvParameterSpec(iv))\n      val cipherSource = FileSystem.SYSTEM.source(path).cipherSource(cipher)\n      return cipherSource.buffer().use {\n        it.readByteString()\n      }\n    }\n    ```\n\n\n[base64]: https://tools.ietf.org/html/rfc4648#section-4\n[bmp]: https://en.wikipedia.org/wiki/BMP_file_format\n[nfd]: https://docs.oracle.com/javase/7/docs/api/java/text/Normalizer.Form.html#NFD\n[nfc]: https://docs.oracle.com/javase/7/docs/api/java/text/Normalizer.Form.html#NFC\n[BitmapEncoderKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/BitmapEncoder.kt\n[BitmapEncoder]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/BitmapEncoder.java\n[ExploreCharsetsKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/ExploreCharsets.kt\n[ExploreCharsets]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/ExploreCharsets.java\n[GoldenValueKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/GoldenValue.kt\n[GoldenValue]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/GoldenValue.java\n[HashingKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/Hashing.kt\n[Hashing]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/Hashing.java\n[ReadFileLineByLine]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/ReadFileLineByLine.java\n[ReadFileLineByLineKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/ReadJavaIoFileLineByLine.kt\n[SocksProxyServerKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/SocksProxyServer.kt\n[SocksProxyServer]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/SocksProxyServer.java\n[WriteFile]: https://github.com/square/okio/blob/master/samples/src/jvmMain/java/okio/samples/WriteFile.java\n[WriteFileKt]: https://github.com/square/okio/blob/master/samples/src/jvmMain/kotlin/okio/samples/WriteFile.kt\n"
  },
  {
    "path": "docs/releasing.md",
    "content": "Releasing\n=========\n\n1. Update `CHANGELOG.md`.\n\n2. Set versions:\n\n    ```\n    export RELEASE_VERSION=X.Y.Z\n    export NEXT_VERSION=X.Y.Z-SNAPSHOT\n    ```\n\n3. Update versions, tag the release, and prepare for the next release.\n\n    ```\n    sed -i \"\" \\\n      \"s/VERSION_NAME=.*/VERSION_NAME=$RELEASE_VERSION/g\" \\\n      gradle.properties\n    sed -i \"\" \\\n      \"s/\\\"com.squareup.okio:\\([^\\:]*\\):[0-9.]*\\\"/\\\"com.squareup.okio:\\1:$RELEASE_VERSION\\\"/g\" \\\n      `find . -name \"index.md\"`\n    sed -i \"\" \\\n      \"s/\\\"com.squareup.okio:\\([^\\:]*\\):[0-9.]*-SNAPSHOT\\\"/\\\"com.squareup.okio:\\1:$NEXT_VERSION\\\"/g\" \\\n      `find . -name \"index.md\"`\n\n    git commit -am \"Prepare for release $RELEASE_VERSION.\"\n    git tag -a parent-$RELEASE_VERSION -m \"Version $RELEASE_VERSION\"\n\n    sed -i \"\" \\\n      \"s/VERSION_NAME=.*/VERSION_NAME=$NEXT_VERSION/g\" \\\n      gradle.properties\n    git commit -am \"Prepare next development version.\"\n\n    git push && git push --tags\n    ```\n\n4. Wait for [GitHub Actions][github_actions] to build and promote the release.\n\n[github_actions]: https://github.com/square/okio/actions\n"
  },
  {
    "path": "docs/security.md",
    "content": "Security Policy\n===============\n\n## Supported Versions\n\n| Version | Supported  |\n| ------- | ---------- |\n| 3.x     | ✅         |\n| 2.x     | ✅         |\n| 1.x     | ✅         |\n\n\n## Reporting a Vulnerability\n\nSquare recognizes the important contributions the security research community\ncan make. We therefore encourage reporting security issues with the code\ncontained in this repository.\n\nIf you believe you have discovered a security vulnerability, please follow the\nguidelines at https://bugcrowd.com/squareopensource\n"
  },
  {
    "path": "gradle/libs.versions.toml",
    "content": "[versions]\nburst = \"2.10.2\"\njmh = \"1.37\"\nkotlin = \"2.2.21\"\n# Set to lower version than KGP version to maximize compatibility\nkotlinCoreLibrariesVersion = \"2.1.21\"\nktlint = \"0.48.2\"\n\n[libraries]\nandroid-desugar-jdk-libs = { module = \"com.android.tools:desugar_jdk_libs\", version = \"2.1.5\" }\nandroid-gradle-plugin = { module = \"com.android.tools.build:gradle\", version = \"9.0.1\" }\nandroidx-test-ext-junit = { module = \"androidx.test.ext:junit\", version = \"1.3.0\" }\nandroidx-test-runner = { module = \"androidx.test:runner\", version = \"1.7.0\" }\nbinaryCompatibilityValidator = { module = \"org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin\", version = \"0.18.1\" }\nbnd = { module = \"biz.aQute.bnd:biz.aQute.bnd.gradle\", version = \"7.2.1\" }\nburst-gradle-plugin = { module = \"app.cash.burst:burst-gradle-plugin\", version.ref = \"burst\" }\nburst-runtime = { module = \"app.cash.burst:burst\", version.ref = \"burst\" }\ndokka = { module = \"org.jetbrains.dokka:dokka-gradle-plugin\", version = \"2.1.0\" }\njmh-core = { module = \"org.openjdk.jmh:jmh-core\", version.ref = \"jmh\" }\njmh-generator = { module = \"org.openjdk.jmh:jmh-generator-annprocess\", version.ref = \"jmh\" }\njmh-gradle-plugin = { module = \"me.champeau.jmh:jmh-gradle-plugin\", version = \"0.7.3\" }\nkotlin-gradle-plugin = { module = \"org.jetbrains.kotlin:kotlin-gradle-plugin\", version.ref = \"kotlin\" }\nkotlin-test = { module = \"org.jetbrains.kotlin:kotlin-test\", version.ref = \"kotlin\" }\nkotlin-test-junit = { module = \"org.jetbrains.kotlin:kotlin-test-junit\", version.ref = \"kotlin\" }\nkotlin-time = { module = \"org.jetbrains.kotlinx:kotlinx-datetime\", version = \"0.7.1-0.6.x-compat\" }\nspotless = { module = \"com.diffplug.spotless:spotless-plugin-gradle\", version = \"8.0.0\" }\ntapmoc-gradle-plugin = { module =  \"com.gradleup.tapmoc:com.gradleup.tapmoc.gradle.plugin\", version = \"0.4.0\"}\ntest-assertk = \"com.willowtreeapps.assertk:assertk:0.28.1\"\ntest-jimfs = \"com.google.jimfs:jimfs:1.3.1\"\ntest-junit = { module = \"junit:junit\", version = \"4.13.2\" }\nvanniktech-publish-plugin = { module = \"com.vanniktech:gradle-maven-publish-plugin\", version = \"0.36.0\" }\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-9.4.1-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "org.gradle.jvmargs='-Dfile.encoding=UTF-8'\n\nandroid.enableJetifier=false\nandroid.useAndroidX=true\nandroid.defaults.buildfeatures.buildconfig=false\nandroid.defaults.buildfeatures.aidl=false\nandroid.defaults.buildfeatures.renderscript=false\nandroid.defaults.buildfeatures.resvalues=false\nandroid.defaults.buildfeatures.shaders=false\n\nkotlin.mpp.applyDefaultHierarchyTemplate=false\nkotlin.mpp.commonizerLogLevel=info\nkotlin.mpp.enableCInteropCommonization=true\nkotlin.mpp.stability.nowarn=true\n\nGROUP=com.squareup.okio\nVERSION_NAME=3.18.0-SNAPSHOT\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015 the original authors.\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#      https://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#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -jar \"$APP_HOME/gradle/wrapper/gradle-wrapper.jar\" \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n@rem SPDX-License-Identifier: Apache-2.0\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -jar \"%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\" %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: Okio\nsite_url: https://square.github.io/okio\nrepo_name: Okio\nrepo_url: https://github.com/square/okio\nsite_description: \"A modern I/O library for Android, Kotlin, and Java.\"\nsite_author: Square, Inc.\nremote_branch: gh-pages\nedit_uri: \"\"\n\ncopyright: 'Copyright &copy; 2019 Square, Inc.'\n\ntheme:\n  name: 'material'\n  favicon: images/icon-square.png\n  logo: images/icon-square.png\n  palette:\n    # Palette toggle for light mode\n    - scheme: default\n      media: \"(prefers-color-scheme: light)\"\n      primary: 'deep purple'\n      accent: 'white'\n      toggle:\n        icon: material/brightness-7\n        name: Switch to dark mode\n    # Palette toggle for dark mode\n    - scheme: slate\n      media: \"(prefers-color-scheme: dark)\"\n      primary: 'deep purple'\n      accent: 'white'\n      toggle:\n        icon: material/brightness-4\n        name: Switch to light mode\n  icon:\n    repo: fontawesome/brands/github\n\nextra:\n  social:\n    - icon: fontawesome/brands/twitter\n      link: https://twitter.com/squareeng\n    - icon: fontawesome/brands/stack-overflow\n      link: https://stackoverflow.com/questions/tagged/okio?sort=active\n\nextra_css:\n  - 'css/app.css'\n\nmarkdown_extensions:\n  - smarty\n  - codehilite:\n      guess_lang: false\n  - footnotes\n  - meta\n  - toc:\n      permalink: true\n  - pymdownx.betterem:\n      smart_enable: all\n  - pymdownx.caret\n  - pymdownx.inlinehilite\n  - pymdownx.magiclink\n  - pymdownx.smartsymbols\n  - pymdownx.superfences\n  - pymdownx.tabbed:\n      alternate_style: true \n  - pymdownx.tilde\n  - tables\n\nnav:\n  - 'Overview': index.md\n  - 'Stack Overflow ⏏': https://stackoverflow.com/questions/tagged/okio?sort=active\n  - 'Recipes': recipes.md\n  - 'java.io Recipes': java_io_recipes.md\n  - '3.x API':\n    - 'okio': 3.x/okio/okio/okio/index.html\n    - 'fakefilesystem': 3.x/okio-fakefilesystem/okio-fakefilesystem/okio.fakefilesystem/-fake-file-system/index.html\n    - 'nodefilesystem': 3.x/okio-nodefilesystem/okio-nodefilesystem/okio/-node-js-file-system/index.html\n  - '1.x API ⏏': https://square.github.io/okio/1.x/okio/\n  - 'Change Log': changelog.md\n  - 'File System': file_system.md\n  - 'Multiplatform': multiplatform.md\n  - 'Contributing': contributing.md\n  - 'Code of Conduct': code_of_conduct.md\n"
  },
  {
    "path": "okio/api/okio.api",
    "content": "public final class okio/-DeflaterSinkExtensions {\n\tpublic static final fun deflate (Lokio/Sink;Ljava/util/zip/Deflater;)Lokio/DeflaterSink;\n\tpublic static synthetic fun deflate$default (Lokio/Sink;Ljava/util/zip/Deflater;ILjava/lang/Object;)Lokio/DeflaterSink;\n}\n\npublic final class okio/-DeprecatedOkio {\n\tpublic static final field INSTANCE Lokio/-DeprecatedOkio;\n\tpublic final fun appendingSink (Ljava/io/File;)Lokio/Sink;\n\tpublic final fun blackhole ()Lokio/Sink;\n\tpublic final fun buffer (Lokio/Sink;)Lokio/BufferedSink;\n\tpublic final fun buffer (Lokio/Source;)Lokio/BufferedSource;\n\tpublic final fun sink (Ljava/io/File;)Lokio/Sink;\n\tpublic final fun sink (Ljava/io/OutputStream;)Lokio/Sink;\n\tpublic final fun sink (Ljava/net/Socket;)Lokio/Sink;\n\tpublic final fun sink (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Lokio/Sink;\n\tpublic final fun source (Ljava/io/File;)Lokio/Source;\n\tpublic final fun source (Ljava/io/InputStream;)Lokio/Source;\n\tpublic final fun source (Ljava/net/Socket;)Lokio/Source;\n\tpublic final fun source (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Lokio/Source;\n}\n\npublic final class okio/-DeprecatedUpgrade {\n\tpublic static final fun getOkio ()Lokio/-DeprecatedOkio;\n\tpublic static final fun getUtf8 ()Lokio/-DeprecatedUtf8;\n}\n\npublic final class okio/-DeprecatedUtf8 {\n\tpublic static final field INSTANCE Lokio/-DeprecatedUtf8;\n\tpublic final fun size (Ljava/lang/String;)J\n\tpublic final fun size (Ljava/lang/String;II)J\n}\n\npublic final class okio/-GzipSinkExtensions {\n\tpublic static final fun gzip (Lokio/Sink;)Lokio/GzipSink;\n}\n\npublic final class okio/-GzipSourceExtensions {\n\tpublic static final fun gzip (Lokio/Source;)Lokio/GzipSource;\n}\n\npublic final class okio/-InflaterSourceExtensions {\n\tpublic static final fun inflate (Lokio/Source;Ljava/util/zip/Inflater;)Lokio/InflaterSource;\n\tpublic static synthetic fun inflate$default (Lokio/Source;Ljava/util/zip/Inflater;ILjava/lang/Object;)Lokio/InflaterSource;\n}\n\npublic class okio/AsyncTimeout : okio/Timeout {\n\tpublic fun <init> ()V\n\tpublic final fun access$newTimeoutException (Ljava/io/IOException;)Ljava/io/IOException;\n\tpublic fun cancel ()V\n\tpublic final fun enter ()V\n\tpublic final fun exit ()Z\n\tprotected fun newTimeoutException (Ljava/io/IOException;)Ljava/io/IOException;\n\tpublic final fun sink (Lokio/Sink;)Lokio/Sink;\n\tpublic final fun source (Lokio/Source;)Lokio/Source;\n\tprotected fun timedOut ()V\n\tpublic final fun withTimeout (Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;\n}\n\npublic final class okio/Buffer : java/lang/Cloneable, java/nio/channels/ByteChannel, okio/BufferedSink, okio/BufferedSource {\n\tpublic final fun -deprecated_getByte (J)B\n\tpublic final fun -deprecated_size ()J\n\tpublic fun <init> ()V\n\tpublic fun buffer ()Lokio/Buffer;\n\tpublic final fun clear ()V\n\tpublic synthetic fun clone ()Ljava/lang/Object;\n\tpublic fun clone ()Lokio/Buffer;\n\tpublic fun close ()V\n\tpublic final fun completeSegmentByteCount ()J\n\tpublic final fun copy ()Lokio/Buffer;\n\tpublic final fun copyTo (Ljava/io/OutputStream;)Lokio/Buffer;\n\tpublic final fun copyTo (Ljava/io/OutputStream;J)Lokio/Buffer;\n\tpublic final fun copyTo (Ljava/io/OutputStream;JJ)Lokio/Buffer;\n\tpublic final fun copyTo (Lokio/Buffer;J)Lokio/Buffer;\n\tpublic final fun copyTo (Lokio/Buffer;JJ)Lokio/Buffer;\n\tpublic static synthetic fun copyTo$default (Lokio/Buffer;Ljava/io/OutputStream;JJILjava/lang/Object;)Lokio/Buffer;\n\tpublic static synthetic fun copyTo$default (Lokio/Buffer;Lokio/Buffer;JILjava/lang/Object;)Lokio/Buffer;\n\tpublic static synthetic fun copyTo$default (Lokio/Buffer;Lokio/Buffer;JJILjava/lang/Object;)Lokio/Buffer;\n\tpublic fun emit ()Lokio/Buffer;\n\tpublic synthetic fun emit ()Lokio/BufferedSink;\n\tpublic fun emitCompleteSegments ()Lokio/Buffer;\n\tpublic synthetic fun emitCompleteSegments ()Lokio/BufferedSink;\n\tpublic fun equals (Ljava/lang/Object;)Z\n\tpublic fun exhausted ()Z\n\tpublic fun flush ()V\n\tpublic fun getBuffer ()Lokio/Buffer;\n\tpublic final fun getByte (J)B\n\tpublic fun hashCode ()I\n\tpublic final fun hmacSha1 (Lokio/ByteString;)Lokio/ByteString;\n\tpublic final fun hmacSha256 (Lokio/ByteString;)Lokio/ByteString;\n\tpublic final fun hmacSha512 (Lokio/ByteString;)Lokio/ByteString;\n\tpublic fun indexOf (B)J\n\tpublic fun indexOf (BJ)J\n\tpublic fun indexOf (BJJ)J\n\tpublic fun indexOf (Lokio/ByteString;)J\n\tpublic fun indexOf (Lokio/ByteString;J)J\n\tpublic fun indexOf (Lokio/ByteString;JJ)J\n\tpublic fun indexOfElement (Lokio/ByteString;)J\n\tpublic fun indexOfElement (Lokio/ByteString;J)J\n\tpublic fun inputStream ()Ljava/io/InputStream;\n\tpublic fun isOpen ()Z\n\tpublic final fun md5 ()Lokio/ByteString;\n\tpublic fun outputStream ()Ljava/io/OutputStream;\n\tpublic fun peek ()Lokio/BufferedSource;\n\tpublic fun rangeEquals (JLokio/ByteString;)Z\n\tpublic fun rangeEquals (JLokio/ByteString;II)Z\n\tpublic fun read (Ljava/nio/ByteBuffer;)I\n\tpublic fun read (Lokio/Buffer;J)J\n\tpublic fun read ([B)I\n\tpublic fun read ([BII)I\n\tpublic fun readAll (Lokio/Sink;)J\n\tpublic final fun readAndWriteUnsafe ()Lokio/Buffer$UnsafeCursor;\n\tpublic final fun readAndWriteUnsafe (Lokio/Buffer$UnsafeCursor;)Lokio/Buffer$UnsafeCursor;\n\tpublic static synthetic fun readAndWriteUnsafe$default (Lokio/Buffer;Lokio/Buffer$UnsafeCursor;ILjava/lang/Object;)Lokio/Buffer$UnsafeCursor;\n\tpublic fun readByte ()B\n\tpublic fun readByteArray ()[B\n\tpublic fun readByteArray (J)[B\n\tpublic fun readByteString ()Lokio/ByteString;\n\tpublic fun readByteString (J)Lokio/ByteString;\n\tpublic fun readDecimalLong ()J\n\tpublic final fun readFrom (Ljava/io/InputStream;)Lokio/Buffer;\n\tpublic final fun readFrom (Ljava/io/InputStream;J)Lokio/Buffer;\n\tpublic fun readFully (Lokio/Buffer;J)V\n\tpublic fun readFully ([B)V\n\tpublic fun readHexadecimalUnsignedLong ()J\n\tpublic fun readInt ()I\n\tpublic fun readIntLe ()I\n\tpublic fun readLong ()J\n\tpublic fun readLongLe ()J\n\tpublic fun readShort ()S\n\tpublic fun readShortLe ()S\n\tpublic fun readString (JLjava/nio/charset/Charset;)Ljava/lang/String;\n\tpublic fun readString (Ljava/nio/charset/Charset;)Ljava/lang/String;\n\tpublic final fun readUnsafe ()Lokio/Buffer$UnsafeCursor;\n\tpublic final fun readUnsafe (Lokio/Buffer$UnsafeCursor;)Lokio/Buffer$UnsafeCursor;\n\tpublic static synthetic fun readUnsafe$default (Lokio/Buffer;Lokio/Buffer$UnsafeCursor;ILjava/lang/Object;)Lokio/Buffer$UnsafeCursor;\n\tpublic fun readUtf8 ()Ljava/lang/String;\n\tpublic fun readUtf8 (J)Ljava/lang/String;\n\tpublic fun readUtf8CodePoint ()I\n\tpublic fun readUtf8Line ()Ljava/lang/String;\n\tpublic fun readUtf8LineStrict ()Ljava/lang/String;\n\tpublic fun readUtf8LineStrict (J)Ljava/lang/String;\n\tpublic fun request (J)Z\n\tpublic fun require (J)V\n\tpublic fun select (Lokio/Options;)I\n\tpublic fun select (Lokio/TypedOptions;)Ljava/lang/Object;\n\tpublic final fun sha1 ()Lokio/ByteString;\n\tpublic final fun sha256 ()Lokio/ByteString;\n\tpublic final fun sha512 ()Lokio/ByteString;\n\tpublic final fun size ()J\n\tpublic fun skip (J)V\n\tpublic final fun snapshot ()Lokio/ByteString;\n\tpublic final fun snapshot (I)Lokio/ByteString;\n\tpublic fun timeout ()Lokio/Timeout;\n\tpublic fun toString ()Ljava/lang/String;\n\tpublic fun write (Ljava/nio/ByteBuffer;)I\n\tpublic fun write (Lokio/Buffer;J)V\n\tpublic fun write (Lokio/ByteString;)Lokio/Buffer;\n\tpublic synthetic fun write (Lokio/ByteString;)Lokio/BufferedSink;\n\tpublic fun write (Lokio/ByteString;II)Lokio/Buffer;\n\tpublic synthetic fun write (Lokio/ByteString;II)Lokio/BufferedSink;\n\tpublic fun write (Lokio/Source;J)Lokio/Buffer;\n\tpublic synthetic fun write (Lokio/Source;J)Lokio/BufferedSink;\n\tpublic fun write ([B)Lokio/Buffer;\n\tpublic synthetic fun write ([B)Lokio/BufferedSink;\n\tpublic fun write ([BII)Lokio/Buffer;\n\tpublic synthetic fun write ([BII)Lokio/BufferedSink;\n\tpublic fun writeAll (Lokio/Source;)J\n\tpublic fun writeByte (I)Lokio/Buffer;\n\tpublic synthetic fun writeByte (I)Lokio/BufferedSink;\n\tpublic fun writeDecimalLong (J)Lokio/Buffer;\n\tpublic synthetic fun writeDecimalLong (J)Lokio/BufferedSink;\n\tpublic fun writeHexadecimalUnsignedLong (J)Lokio/Buffer;\n\tpublic synthetic fun writeHexadecimalUnsignedLong (J)Lokio/BufferedSink;\n\tpublic fun writeInt (I)Lokio/Buffer;\n\tpublic synthetic fun writeInt (I)Lokio/BufferedSink;\n\tpublic fun writeIntLe (I)Lokio/Buffer;\n\tpublic synthetic fun writeIntLe (I)Lokio/BufferedSink;\n\tpublic fun writeLong (J)Lokio/Buffer;\n\tpublic synthetic fun writeLong (J)Lokio/BufferedSink;\n\tpublic fun writeLongLe (J)Lokio/Buffer;\n\tpublic synthetic fun writeLongLe (J)Lokio/BufferedSink;\n\tpublic fun writeShort (I)Lokio/Buffer;\n\tpublic synthetic fun writeShort (I)Lokio/BufferedSink;\n\tpublic fun writeShortLe (I)Lokio/Buffer;\n\tpublic synthetic fun writeShortLe (I)Lokio/BufferedSink;\n\tpublic fun writeString (Ljava/lang/String;IILjava/nio/charset/Charset;)Lokio/Buffer;\n\tpublic synthetic fun writeString (Ljava/lang/String;IILjava/nio/charset/Charset;)Lokio/BufferedSink;\n\tpublic fun writeString (Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;\n\tpublic synthetic fun writeString (Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/BufferedSink;\n\tpublic final fun writeTo (Ljava/io/OutputStream;)Lokio/Buffer;\n\tpublic final fun writeTo (Ljava/io/OutputStream;J)Lokio/Buffer;\n\tpublic static synthetic fun writeTo$default (Lokio/Buffer;Ljava/io/OutputStream;JILjava/lang/Object;)Lokio/Buffer;\n\tpublic fun writeUtf8 (Ljava/lang/String;)Lokio/Buffer;\n\tpublic synthetic fun writeUtf8 (Ljava/lang/String;)Lokio/BufferedSink;\n\tpublic fun writeUtf8 (Ljava/lang/String;II)Lokio/Buffer;\n\tpublic synthetic fun writeUtf8 (Ljava/lang/String;II)Lokio/BufferedSink;\n\tpublic fun writeUtf8CodePoint (I)Lokio/Buffer;\n\tpublic synthetic fun writeUtf8CodePoint (I)Lokio/BufferedSink;\n}\n\npublic final class okio/Buffer$UnsafeCursor : java/io/Closeable {\n\tpublic field buffer Lokio/Buffer;\n\tpublic field data [B\n\tpublic field end I\n\tpublic field offset J\n\tpublic field readWrite Z\n\tpublic field start I\n\tpublic fun <init> ()V\n\tpublic fun close ()V\n\tpublic final fun expandBuffer (I)J\n\tpublic final fun next ()I\n\tpublic final fun resizeBuffer (J)J\n\tpublic final fun seek (J)I\n}\n\npublic abstract interface class okio/BufferedSink : java/nio/channels/WritableByteChannel, okio/Sink {\n\tpublic abstract fun buffer ()Lokio/Buffer;\n\tpublic abstract fun emit ()Lokio/BufferedSink;\n\tpublic abstract fun emitCompleteSegments ()Lokio/BufferedSink;\n\tpublic abstract fun flush ()V\n\tpublic abstract fun getBuffer ()Lokio/Buffer;\n\tpublic abstract fun outputStream ()Ljava/io/OutputStream;\n\tpublic abstract fun write (Lokio/ByteString;)Lokio/BufferedSink;\n\tpublic abstract fun write (Lokio/ByteString;II)Lokio/BufferedSink;\n\tpublic abstract fun write (Lokio/Source;J)Lokio/BufferedSink;\n\tpublic abstract fun write ([B)Lokio/BufferedSink;\n\tpublic abstract fun write ([BII)Lokio/BufferedSink;\n\tpublic abstract fun writeAll (Lokio/Source;)J\n\tpublic abstract fun writeByte (I)Lokio/BufferedSink;\n\tpublic abstract fun writeDecimalLong (J)Lokio/BufferedSink;\n\tpublic abstract fun writeHexadecimalUnsignedLong (J)Lokio/BufferedSink;\n\tpublic abstract fun writeInt (I)Lokio/BufferedSink;\n\tpublic abstract fun writeIntLe (I)Lokio/BufferedSink;\n\tpublic abstract fun writeLong (J)Lokio/BufferedSink;\n\tpublic abstract fun writeLongLe (J)Lokio/BufferedSink;\n\tpublic abstract fun writeShort (I)Lokio/BufferedSink;\n\tpublic abstract fun writeShortLe (I)Lokio/BufferedSink;\n\tpublic abstract fun writeString (Ljava/lang/String;IILjava/nio/charset/Charset;)Lokio/BufferedSink;\n\tpublic abstract fun writeString (Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/BufferedSink;\n\tpublic abstract fun writeUtf8 (Ljava/lang/String;)Lokio/BufferedSink;\n\tpublic abstract fun writeUtf8 (Ljava/lang/String;II)Lokio/BufferedSink;\n\tpublic abstract fun writeUtf8CodePoint (I)Lokio/BufferedSink;\n}\n\npublic abstract interface class okio/BufferedSource : java/nio/channels/ReadableByteChannel, okio/Source {\n\tpublic abstract fun buffer ()Lokio/Buffer;\n\tpublic abstract fun exhausted ()Z\n\tpublic abstract fun getBuffer ()Lokio/Buffer;\n\tpublic abstract fun indexOf (B)J\n\tpublic abstract fun indexOf (BJ)J\n\tpublic abstract fun indexOf (BJJ)J\n\tpublic abstract fun indexOf (Lokio/ByteString;)J\n\tpublic abstract fun indexOf (Lokio/ByteString;J)J\n\tpublic abstract fun indexOf (Lokio/ByteString;JJ)J\n\tpublic abstract fun indexOfElement (Lokio/ByteString;)J\n\tpublic abstract fun indexOfElement (Lokio/ByteString;J)J\n\tpublic abstract fun inputStream ()Ljava/io/InputStream;\n\tpublic abstract fun peek ()Lokio/BufferedSource;\n\tpublic abstract fun rangeEquals (JLokio/ByteString;)Z\n\tpublic abstract fun rangeEquals (JLokio/ByteString;II)Z\n\tpublic abstract fun read ([B)I\n\tpublic abstract fun read ([BII)I\n\tpublic abstract fun readAll (Lokio/Sink;)J\n\tpublic abstract fun readByte ()B\n\tpublic abstract fun readByteArray ()[B\n\tpublic abstract fun readByteArray (J)[B\n\tpublic abstract fun readByteString ()Lokio/ByteString;\n\tpublic abstract fun readByteString (J)Lokio/ByteString;\n\tpublic abstract fun readDecimalLong ()J\n\tpublic abstract fun readFully (Lokio/Buffer;J)V\n\tpublic abstract fun readFully ([B)V\n\tpublic abstract fun readHexadecimalUnsignedLong ()J\n\tpublic abstract fun readInt ()I\n\tpublic abstract fun readIntLe ()I\n\tpublic abstract fun readLong ()J\n\tpublic abstract fun readLongLe ()J\n\tpublic abstract fun readShort ()S\n\tpublic abstract fun readShortLe ()S\n\tpublic abstract fun readString (JLjava/nio/charset/Charset;)Ljava/lang/String;\n\tpublic abstract fun readString (Ljava/nio/charset/Charset;)Ljava/lang/String;\n\tpublic abstract fun readUtf8 ()Ljava/lang/String;\n\tpublic abstract fun readUtf8 (J)Ljava/lang/String;\n\tpublic abstract fun readUtf8CodePoint ()I\n\tpublic abstract fun readUtf8Line ()Ljava/lang/String;\n\tpublic abstract fun readUtf8LineStrict ()Ljava/lang/String;\n\tpublic abstract fun readUtf8LineStrict (J)Ljava/lang/String;\n\tpublic abstract fun request (J)Z\n\tpublic abstract fun require (J)V\n\tpublic abstract fun select (Lokio/Options;)I\n\tpublic abstract fun select (Lokio/TypedOptions;)Ljava/lang/Object;\n\tpublic abstract fun skip (J)V\n}\n\npublic class okio/ByteString : java/io/Serializable, java/lang/Comparable {\n\tpublic static final field Companion Lokio/ByteString$Companion;\n\tpublic static final field EMPTY Lokio/ByteString;\n\tpublic final fun -deprecated_getByte (I)B\n\tpublic final fun -deprecated_size ()I\n\tpublic fun asByteBuffer ()Ljava/nio/ByteBuffer;\n\tpublic fun base64 ()Ljava/lang/String;\n\tpublic fun base64Url ()Ljava/lang/String;\n\tpublic synthetic fun compareTo (Ljava/lang/Object;)I\n\tpublic fun compareTo (Lokio/ByteString;)I\n\tpublic fun copyInto (I[BII)V\n\tpublic static synthetic fun copyInto$default (Lokio/ByteString;I[BIIILjava/lang/Object;)V\n\tpublic static final fun decodeBase64 (Ljava/lang/String;)Lokio/ByteString;\n\tpublic static final fun decodeHex (Ljava/lang/String;)Lokio/ByteString;\n\tpublic static final fun encodeString (Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/ByteString;\n\tpublic static final fun encodeUtf8 (Ljava/lang/String;)Lokio/ByteString;\n\tpublic final fun endsWith (Lokio/ByteString;)Z\n\tpublic final fun endsWith ([B)Z\n\tpublic fun equals (Ljava/lang/Object;)Z\n\tpublic final fun getByte (I)B\n\tpublic fun hashCode ()I\n\tpublic fun hex ()Ljava/lang/String;\n\tpublic fun hmacSha1 (Lokio/ByteString;)Lokio/ByteString;\n\tpublic fun hmacSha256 (Lokio/ByteString;)Lokio/ByteString;\n\tpublic fun hmacSha512 (Lokio/ByteString;)Lokio/ByteString;\n\tpublic final fun indexOf (Lokio/ByteString;)I\n\tpublic final fun indexOf (Lokio/ByteString;I)I\n\tpublic final fun indexOf ([B)I\n\tpublic fun indexOf ([BI)I\n\tpublic static synthetic fun indexOf$default (Lokio/ByteString;Lokio/ByteString;IILjava/lang/Object;)I\n\tpublic static synthetic fun indexOf$default (Lokio/ByteString;[BIILjava/lang/Object;)I\n\tpublic final fun lastIndexOf (Lokio/ByteString;)I\n\tpublic final fun lastIndexOf (Lokio/ByteString;I)I\n\tpublic final fun lastIndexOf ([B)I\n\tpublic fun lastIndexOf ([BI)I\n\tpublic static synthetic fun lastIndexOf$default (Lokio/ByteString;Lokio/ByteString;IILjava/lang/Object;)I\n\tpublic static synthetic fun lastIndexOf$default (Lokio/ByteString;[BIILjava/lang/Object;)I\n\tpublic final fun md5 ()Lokio/ByteString;\n\tpublic static final fun of (Ljava/nio/ByteBuffer;)Lokio/ByteString;\n\tpublic static final fun of ([B)Lokio/ByteString;\n\tpublic static final fun of ([BII)Lokio/ByteString;\n\tpublic fun rangeEquals (ILokio/ByteString;II)Z\n\tpublic fun rangeEquals (I[BII)Z\n\tpublic static final fun read (Ljava/io/InputStream;I)Lokio/ByteString;\n\tpublic final fun sha1 ()Lokio/ByteString;\n\tpublic final fun sha256 ()Lokio/ByteString;\n\tpublic final fun sha512 ()Lokio/ByteString;\n\tpublic final fun size ()I\n\tpublic final fun startsWith (Lokio/ByteString;)Z\n\tpublic final fun startsWith ([B)Z\n\tpublic fun string (Ljava/nio/charset/Charset;)Ljava/lang/String;\n\tpublic final fun substring ()Lokio/ByteString;\n\tpublic final fun substring (I)Lokio/ByteString;\n\tpublic fun substring (II)Lokio/ByteString;\n\tpublic static synthetic fun substring$default (Lokio/ByteString;IIILjava/lang/Object;)Lokio/ByteString;\n\tpublic fun toAsciiLowercase ()Lokio/ByteString;\n\tpublic fun toAsciiUppercase ()Lokio/ByteString;\n\tpublic fun toByteArray ()[B\n\tpublic fun toString ()Ljava/lang/String;\n\tpublic fun utf8 ()Ljava/lang/String;\n\tpublic fun write (Ljava/io/OutputStream;)V\n}\n\npublic final class okio/ByteString$Companion {\n\tpublic final fun -deprecated_decodeBase64 (Ljava/lang/String;)Lokio/ByteString;\n\tpublic final fun -deprecated_decodeHex (Ljava/lang/String;)Lokio/ByteString;\n\tpublic final fun -deprecated_encodeString (Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/ByteString;\n\tpublic final fun -deprecated_encodeUtf8 (Ljava/lang/String;)Lokio/ByteString;\n\tpublic final fun -deprecated_of (Ljava/nio/ByteBuffer;)Lokio/ByteString;\n\tpublic final fun -deprecated_of ([BII)Lokio/ByteString;\n\tpublic final fun -deprecated_read (Ljava/io/InputStream;I)Lokio/ByteString;\n\tpublic final fun decodeBase64 (Ljava/lang/String;)Lokio/ByteString;\n\tpublic final fun decodeHex (Ljava/lang/String;)Lokio/ByteString;\n\tpublic final fun encodeString (Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/ByteString;\n\tpublic static synthetic fun encodeString$default (Lokio/ByteString$Companion;Ljava/lang/String;Ljava/nio/charset/Charset;ILjava/lang/Object;)Lokio/ByteString;\n\tpublic final fun encodeUtf8 (Ljava/lang/String;)Lokio/ByteString;\n\tpublic final fun of (Ljava/nio/ByteBuffer;)Lokio/ByteString;\n\tpublic final fun of ([B)Lokio/ByteString;\n\tpublic final fun of ([BII)Lokio/ByteString;\n\tpublic static synthetic fun of$default (Lokio/ByteString$Companion;[BIIILjava/lang/Object;)Lokio/ByteString;\n\tpublic final fun read (Ljava/io/InputStream;I)Lokio/ByteString;\n}\n\npublic final class okio/CipherSink : okio/Sink {\n\tpublic fun <init> (Lokio/BufferedSink;Ljavax/crypto/Cipher;)V\n\tpublic fun close ()V\n\tpublic fun flush ()V\n\tpublic final fun getCipher ()Ljavax/crypto/Cipher;\n\tpublic fun timeout ()Lokio/Timeout;\n\tpublic fun write (Lokio/Buffer;J)V\n}\n\npublic final class okio/CipherSource : okio/Source {\n\tpublic fun <init> (Lokio/BufferedSource;Ljavax/crypto/Cipher;)V\n\tpublic fun close ()V\n\tpublic final fun getCipher ()Ljavax/crypto/Cipher;\n\tpublic fun read (Lokio/Buffer;J)J\n\tpublic fun timeout ()Lokio/Timeout;\n}\n\npublic final class okio/DeflaterSink : okio/Sink {\n\tpublic fun <init> (Lokio/Sink;Ljava/util/zip/Deflater;)V\n\tpublic fun close ()V\n\tpublic fun flush ()V\n\tpublic fun timeout ()Lokio/Timeout;\n\tpublic fun toString ()Ljava/lang/String;\n\tpublic fun write (Lokio/Buffer;J)V\n}\n\npublic abstract interface annotation class okio/ExperimentalFileSystem : java/lang/annotation/Annotation {\n}\n\npublic abstract class okio/FileHandle : java/io/Closeable {\n\tpublic fun <init> (Z)V\n\tpublic final fun appendingSink ()Lokio/Sink;\n\tpublic final fun close ()V\n\tpublic final fun flush ()V\n\tpublic final fun getLock ()Ljava/util/concurrent/locks/ReentrantLock;\n\tpublic final fun getReadWrite ()Z\n\tpublic final fun position (Lokio/Sink;)J\n\tpublic final fun position (Lokio/Source;)J\n\tprotected abstract fun protectedClose ()V\n\tprotected abstract fun protectedFlush ()V\n\tprotected abstract fun protectedRead (J[BII)I\n\tprotected abstract fun protectedResize (J)V\n\tprotected abstract fun protectedSize ()J\n\tprotected abstract fun protectedWrite (J[BII)V\n\tpublic final fun read (JLokio/Buffer;J)J\n\tpublic final fun read (J[BII)I\n\tpublic final fun reposition (Lokio/Sink;J)V\n\tpublic final fun reposition (Lokio/Source;J)V\n\tpublic final fun resize (J)V\n\tpublic final fun sink (J)Lokio/Sink;\n\tpublic static synthetic fun sink$default (Lokio/FileHandle;JILjava/lang/Object;)Lokio/Sink;\n\tpublic final fun size ()J\n\tpublic final fun source (J)Lokio/Source;\n\tpublic static synthetic fun source$default (Lokio/FileHandle;JILjava/lang/Object;)Lokio/Source;\n\tpublic final fun write (JLokio/Buffer;J)V\n\tpublic final fun write (J[BII)V\n}\n\npublic final class okio/FileMetadata {\n\tpublic fun <init> ()V\n\tpublic fun <init> (ZZLokio/Path;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/util/Map;)V\n\tpublic synthetic fun <init> (ZZLokio/Path;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun copy (ZZLokio/Path;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/util/Map;)Lokio/FileMetadata;\n\tpublic static synthetic fun copy$default (Lokio/FileMetadata;ZZLokio/Path;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/util/Map;ILjava/lang/Object;)Lokio/FileMetadata;\n\tpublic final fun extra (Lkotlin/reflect/KClass;)Ljava/lang/Object;\n\tpublic final fun getCreatedAtMillis ()Ljava/lang/Long;\n\tpublic final fun getExtras ()Ljava/util/Map;\n\tpublic final fun getLastAccessedAtMillis ()Ljava/lang/Long;\n\tpublic final fun getLastModifiedAtMillis ()Ljava/lang/Long;\n\tpublic final fun getSize ()Ljava/lang/Long;\n\tpublic final fun getSymlinkTarget ()Lokio/Path;\n\tpublic final fun isDirectory ()Z\n\tpublic final fun isRegularFile ()Z\n\tpublic fun toString ()Ljava/lang/String;\n}\n\npublic abstract class okio/FileSystem : java/io/Closeable {\n\tpublic static final field Companion Lokio/FileSystem$Companion;\n\tpublic static final field RESOURCES Lokio/FileSystem;\n\tpublic static final field SYSTEM Lokio/FileSystem;\n\tpublic static final field SYSTEM_TEMPORARY_DIRECTORY Lokio/Path;\n\tpublic final fun -read (Lokio/Path;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;\n\tpublic final fun -write (Lokio/Path;ZLkotlin/jvm/functions/Function1;)Ljava/lang/Object;\n\tpublic static synthetic fun -write$default (Lokio/FileSystem;Lokio/Path;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;\n\tpublic fun <init> ()V\n\tpublic final fun appendingSink (Lokio/Path;)Lokio/Sink;\n\tpublic abstract fun appendingSink (Lokio/Path;Z)Lokio/Sink;\n\tpublic static synthetic fun appendingSink$default (Lokio/FileSystem;Lokio/Path;ZILjava/lang/Object;)Lokio/Sink;\n\tpublic abstract fun atomicMove (Lokio/Path;Lokio/Path;)V\n\tpublic abstract fun canonicalize (Lokio/Path;)Lokio/Path;\n\tpublic fun close ()V\n\tpublic fun copy (Lokio/Path;Lokio/Path;)V\n\tpublic final fun createDirectories (Lokio/Path;)V\n\tpublic final fun createDirectories (Lokio/Path;Z)V\n\tpublic static synthetic fun createDirectories$default (Lokio/FileSystem;Lokio/Path;ZILjava/lang/Object;)V\n\tpublic final fun createDirectory (Lokio/Path;)V\n\tpublic abstract fun createDirectory (Lokio/Path;Z)V\n\tpublic static synthetic fun createDirectory$default (Lokio/FileSystem;Lokio/Path;ZILjava/lang/Object;)V\n\tpublic abstract fun createSymlink (Lokio/Path;Lokio/Path;)V\n\tpublic final fun delete (Lokio/Path;)V\n\tpublic abstract fun delete (Lokio/Path;Z)V\n\tpublic static synthetic fun delete$default (Lokio/FileSystem;Lokio/Path;ZILjava/lang/Object;)V\n\tpublic final fun deleteRecursively (Lokio/Path;)V\n\tpublic fun deleteRecursively (Lokio/Path;Z)V\n\tpublic static synthetic fun deleteRecursively$default (Lokio/FileSystem;Lokio/Path;ZILjava/lang/Object;)V\n\tpublic final fun exists (Lokio/Path;)Z\n\tpublic static final fun get (Ljava/nio/file/FileSystem;)Lokio/FileSystem;\n\tpublic abstract fun list (Lokio/Path;)Ljava/util/List;\n\tpublic abstract fun listOrNull (Lokio/Path;)Ljava/util/List;\n\tpublic final fun listRecursively (Lokio/Path;)Lkotlin/sequences/Sequence;\n\tpublic fun listRecursively (Lokio/Path;Z)Lkotlin/sequences/Sequence;\n\tpublic static synthetic fun listRecursively$default (Lokio/FileSystem;Lokio/Path;ZILjava/lang/Object;)Lkotlin/sequences/Sequence;\n\tpublic final fun metadata (Lokio/Path;)Lokio/FileMetadata;\n\tpublic abstract fun metadataOrNull (Lokio/Path;)Lokio/FileMetadata;\n\tpublic abstract fun openReadOnly (Lokio/Path;)Lokio/FileHandle;\n\tpublic final fun openReadWrite (Lokio/Path;)Lokio/FileHandle;\n\tpublic abstract fun openReadWrite (Lokio/Path;ZZ)Lokio/FileHandle;\n\tpublic static synthetic fun openReadWrite$default (Lokio/FileSystem;Lokio/Path;ZZILjava/lang/Object;)Lokio/FileHandle;\n\tpublic final fun sink (Lokio/Path;)Lokio/Sink;\n\tpublic abstract fun sink (Lokio/Path;Z)Lokio/Sink;\n\tpublic static synthetic fun sink$default (Lokio/FileSystem;Lokio/Path;ZILjava/lang/Object;)Lokio/Sink;\n\tpublic abstract fun source (Lokio/Path;)Lokio/Source;\n}\n\npublic final class okio/FileSystem$Companion {\n\tpublic final fun get (Ljava/nio/file/FileSystem;)Lokio/FileSystem;\n}\n\npublic abstract class okio/ForwardingFileSystem : okio/FileSystem {\n\tpublic fun <init> (Lokio/FileSystem;)V\n\tpublic fun appendingSink (Lokio/Path;Z)Lokio/Sink;\n\tpublic fun atomicMove (Lokio/Path;Lokio/Path;)V\n\tpublic fun canonicalize (Lokio/Path;)Lokio/Path;\n\tpublic fun close ()V\n\tpublic fun createDirectory (Lokio/Path;Z)V\n\tpublic fun createSymlink (Lokio/Path;Lokio/Path;)V\n\tpublic final fun delegate ()Lokio/FileSystem;\n\tpublic fun delete (Lokio/Path;Z)V\n\tpublic fun list (Lokio/Path;)Ljava/util/List;\n\tpublic fun listOrNull (Lokio/Path;)Ljava/util/List;\n\tpublic fun listRecursively (Lokio/Path;Z)Lkotlin/sequences/Sequence;\n\tpublic fun metadataOrNull (Lokio/Path;)Lokio/FileMetadata;\n\tpublic fun onPathParameter (Lokio/Path;Ljava/lang/String;Ljava/lang/String;)Lokio/Path;\n\tpublic fun onPathResult (Lokio/Path;Ljava/lang/String;)Lokio/Path;\n\tpublic fun openReadOnly (Lokio/Path;)Lokio/FileHandle;\n\tpublic fun openReadWrite (Lokio/Path;ZZ)Lokio/FileHandle;\n\tpublic fun sink (Lokio/Path;Z)Lokio/Sink;\n\tpublic fun source (Lokio/Path;)Lokio/Source;\n\tpublic fun toString ()Ljava/lang/String;\n}\n\npublic abstract class okio/ForwardingSink : okio/Sink {\n\tpublic final fun -deprecated_delegate ()Lokio/Sink;\n\tpublic fun <init> (Lokio/Sink;)V\n\tpublic fun close ()V\n\tpublic final fun delegate ()Lokio/Sink;\n\tpublic fun flush ()V\n\tpublic fun timeout ()Lokio/Timeout;\n\tpublic fun toString ()Ljava/lang/String;\n\tpublic fun write (Lokio/Buffer;J)V\n}\n\npublic abstract class okio/ForwardingSource : okio/Source {\n\tpublic final fun -deprecated_delegate ()Lokio/Source;\n\tpublic fun <init> (Lokio/Source;)V\n\tpublic fun close ()V\n\tpublic final fun delegate ()Lokio/Source;\n\tpublic fun read (Lokio/Buffer;J)J\n\tpublic fun timeout ()Lokio/Timeout;\n\tpublic fun toString ()Ljava/lang/String;\n}\n\npublic class okio/ForwardingTimeout : okio/Timeout {\n\tpublic fun <init> (Lokio/Timeout;)V\n\tpublic fun awaitSignal (Ljava/util/concurrent/locks/Condition;)V\n\tpublic fun cancel ()V\n\tpublic fun clearDeadline ()Lokio/Timeout;\n\tpublic fun clearTimeout ()Lokio/Timeout;\n\tpublic fun deadlineNanoTime ()J\n\tpublic fun deadlineNanoTime (J)Lokio/Timeout;\n\tpublic final fun delegate ()Lokio/Timeout;\n\tpublic fun hasDeadline ()Z\n\tpublic final fun setDelegate (Lokio/Timeout;)Lokio/ForwardingTimeout;\n\tpublic final synthetic fun setDelegate (Lokio/Timeout;)V\n\tpublic fun throwIfReached ()V\n\tpublic fun timeout (JLjava/util/concurrent/TimeUnit;)Lokio/Timeout;\n\tpublic fun timeoutNanos ()J\n\tpublic fun waitUntilNotified (Ljava/lang/Object;)V\n}\n\npublic final class okio/GzipSink : okio/Sink {\n\tpublic final fun -deprecated_deflater ()Ljava/util/zip/Deflater;\n\tpublic fun <init> (Lokio/Sink;)V\n\tpublic fun close ()V\n\tpublic final fun deflater ()Ljava/util/zip/Deflater;\n\tpublic fun flush ()V\n\tpublic fun timeout ()Lokio/Timeout;\n\tpublic fun write (Lokio/Buffer;J)V\n}\n\npublic final class okio/GzipSource : okio/Source {\n\tpublic fun <init> (Lokio/Source;)V\n\tpublic fun close ()V\n\tpublic fun read (Lokio/Buffer;J)J\n\tpublic fun timeout ()Lokio/Timeout;\n}\n\npublic final class okio/HashingSink : okio/ForwardingSink, okio/Sink {\n\tpublic static final field Companion Lokio/HashingSink$Companion;\n\tpublic final fun -deprecated_hash ()Lokio/ByteString;\n\tpublic final fun hash ()Lokio/ByteString;\n\tpublic static final fun hmacSha1 (Lokio/Sink;Lokio/ByteString;)Lokio/HashingSink;\n\tpublic static final fun hmacSha256 (Lokio/Sink;Lokio/ByteString;)Lokio/HashingSink;\n\tpublic static final fun hmacSha512 (Lokio/Sink;Lokio/ByteString;)Lokio/HashingSink;\n\tpublic static final fun md5 (Lokio/Sink;)Lokio/HashingSink;\n\tpublic static final fun sha1 (Lokio/Sink;)Lokio/HashingSink;\n\tpublic static final fun sha256 (Lokio/Sink;)Lokio/HashingSink;\n\tpublic static final fun sha512 (Lokio/Sink;)Lokio/HashingSink;\n\tpublic fun write (Lokio/Buffer;J)V\n}\n\npublic final class okio/HashingSink$Companion {\n\tpublic final fun hmacSha1 (Lokio/Sink;Lokio/ByteString;)Lokio/HashingSink;\n\tpublic final fun hmacSha256 (Lokio/Sink;Lokio/ByteString;)Lokio/HashingSink;\n\tpublic final fun hmacSha512 (Lokio/Sink;Lokio/ByteString;)Lokio/HashingSink;\n\tpublic final fun md5 (Lokio/Sink;)Lokio/HashingSink;\n\tpublic final fun sha1 (Lokio/Sink;)Lokio/HashingSink;\n\tpublic final fun sha256 (Lokio/Sink;)Lokio/HashingSink;\n\tpublic final fun sha512 (Lokio/Sink;)Lokio/HashingSink;\n}\n\npublic final class okio/HashingSource : okio/ForwardingSource, okio/Source {\n\tpublic static final field Companion Lokio/HashingSource$Companion;\n\tpublic final fun -deprecated_hash ()Lokio/ByteString;\n\tpublic final fun hash ()Lokio/ByteString;\n\tpublic static final fun hmacSha1 (Lokio/Source;Lokio/ByteString;)Lokio/HashingSource;\n\tpublic static final fun hmacSha256 (Lokio/Source;Lokio/ByteString;)Lokio/HashingSource;\n\tpublic static final fun hmacSha512 (Lokio/Source;Lokio/ByteString;)Lokio/HashingSource;\n\tpublic static final fun md5 (Lokio/Source;)Lokio/HashingSource;\n\tpublic fun read (Lokio/Buffer;J)J\n\tpublic static final fun sha1 (Lokio/Source;)Lokio/HashingSource;\n\tpublic static final fun sha256 (Lokio/Source;)Lokio/HashingSource;\n\tpublic static final fun sha512 (Lokio/Source;)Lokio/HashingSource;\n}\n\npublic final class okio/HashingSource$Companion {\n\tpublic final fun hmacSha1 (Lokio/Source;Lokio/ByteString;)Lokio/HashingSource;\n\tpublic final fun hmacSha256 (Lokio/Source;Lokio/ByteString;)Lokio/HashingSource;\n\tpublic final fun hmacSha512 (Lokio/Source;Lokio/ByteString;)Lokio/HashingSource;\n\tpublic final fun md5 (Lokio/Source;)Lokio/HashingSource;\n\tpublic final fun sha1 (Lokio/Source;)Lokio/HashingSource;\n\tpublic final fun sha256 (Lokio/Source;)Lokio/HashingSource;\n\tpublic final fun sha512 (Lokio/Source;)Lokio/HashingSource;\n}\n\npublic final class okio/InflaterSource : okio/Source {\n\tpublic fun <init> (Lokio/Source;Ljava/util/zip/Inflater;)V\n\tpublic fun close ()V\n\tpublic fun read (Lokio/Buffer;J)J\n\tpublic final fun readOrInflate (Lokio/Buffer;J)J\n\tpublic final fun refill ()Z\n\tpublic fun timeout ()Lokio/Timeout;\n}\n\npublic final class okio/Okio {\n\tpublic static final fun appendingSink (Ljava/io/File;)Lokio/Sink;\n\tpublic static final fun asResourceFileSystem (Ljava/lang/ClassLoader;)Lokio/FileSystem;\n\tpublic static final fun blackhole ()Lokio/Sink;\n\tpublic static final fun buffer (Lokio/Sink;)Lokio/BufferedSink;\n\tpublic static final fun buffer (Lokio/Source;)Lokio/BufferedSource;\n\tpublic static final fun cipherSink (Lokio/Sink;Ljavax/crypto/Cipher;)Lokio/CipherSink;\n\tpublic static final fun cipherSource (Lokio/Source;Ljavax/crypto/Cipher;)Lokio/CipherSource;\n\tpublic static final fun hashingSink (Lokio/Sink;Ljava/security/MessageDigest;)Lokio/HashingSink;\n\tpublic static final fun hashingSink (Lokio/Sink;Ljavax/crypto/Mac;)Lokio/HashingSink;\n\tpublic static final fun hashingSource (Lokio/Source;Ljava/security/MessageDigest;)Lokio/HashingSource;\n\tpublic static final fun hashingSource (Lokio/Source;Ljavax/crypto/Mac;)Lokio/HashingSource;\n\tpublic static final fun inMemorySocketPair (J)[Lokio/Socket;\n\tpublic static final fun openZip (Lokio/FileSystem;Lokio/Path;)Lokio/FileSystem;\n\tpublic static final fun sink (Ljava/io/File;)Lokio/Sink;\n\tpublic static final fun sink (Ljava/io/File;Z)Lokio/Sink;\n\tpublic static final fun sink (Ljava/io/OutputStream;)Lokio/Sink;\n\tpublic static final fun sink (Ljava/net/Socket;)Lokio/Sink;\n\tpublic static final fun sink (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Lokio/Sink;\n\tpublic static synthetic fun sink$default (Ljava/io/File;ZILjava/lang/Object;)Lokio/Sink;\n\tpublic static final fun socket (Ljava/net/Socket;)Lokio/Socket;\n\tpublic static final fun source (Ljava/io/File;)Lokio/Source;\n\tpublic static final fun source (Ljava/io/InputStream;)Lokio/Source;\n\tpublic static final fun source (Ljava/net/Socket;)Lokio/Source;\n\tpublic static final fun source (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Lokio/Source;\n\tpublic static final fun use (Ljava/io/Closeable;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;\n}\n\npublic final class okio/Options : kotlin/collections/AbstractList, java/util/RandomAccess {\n\tpublic static final field Companion Lokio/Options$Companion;\n\tpublic synthetic fun <init> ([Lokio/ByteString;[ILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun contains (Ljava/lang/Object;)Z\n\tpublic fun contains (Lokio/ByteString;)Z\n\tpublic synthetic fun get (I)Ljava/lang/Object;\n\tpublic fun get (I)Lokio/ByteString;\n\tpublic fun getSize ()I\n\tpublic final fun indexOf (Ljava/lang/Object;)I\n\tpublic fun indexOf (Lokio/ByteString;)I\n\tpublic final fun lastIndexOf (Ljava/lang/Object;)I\n\tpublic fun lastIndexOf (Lokio/ByteString;)I\n\tpublic static final fun of ([Lokio/ByteString;)Lokio/Options;\n}\n\npublic final class okio/Options$Companion {\n\tpublic final fun of ([Lokio/ByteString;)Lokio/Options;\n}\n\npublic final class okio/Path : java/lang/Comparable {\n\tpublic static final field Companion Lokio/Path$Companion;\n\tpublic static final field DIRECTORY_SEPARATOR Ljava/lang/String;\n\tpublic synthetic fun compareTo (Ljava/lang/Object;)I\n\tpublic fun compareTo (Lokio/Path;)I\n\tpublic fun equals (Ljava/lang/Object;)Z\n\tpublic static final fun get (Ljava/io/File;)Lokio/Path;\n\tpublic static final fun get (Ljava/io/File;Z)Lokio/Path;\n\tpublic static final fun get (Ljava/lang/String;)Lokio/Path;\n\tpublic static final fun get (Ljava/lang/String;Z)Lokio/Path;\n\tpublic static final fun get (Ljava/nio/file/Path;)Lokio/Path;\n\tpublic static final fun get (Ljava/nio/file/Path;Z)Lokio/Path;\n\tpublic final fun getRoot ()Lokio/Path;\n\tpublic final fun getSegments ()Ljava/util/List;\n\tpublic final fun getSegmentsBytes ()Ljava/util/List;\n\tpublic fun hashCode ()I\n\tpublic final fun isAbsolute ()Z\n\tpublic final fun isRelative ()Z\n\tpublic final fun isRoot ()Z\n\tpublic final fun name ()Ljava/lang/String;\n\tpublic final fun nameBytes ()Lokio/ByteString;\n\tpublic final fun normalized ()Lokio/Path;\n\tpublic final fun parent ()Lokio/Path;\n\tpublic final fun relativeTo (Lokio/Path;)Lokio/Path;\n\tpublic final fun resolve (Ljava/lang/String;)Lokio/Path;\n\tpublic final fun resolve (Ljava/lang/String;Z)Lokio/Path;\n\tpublic final fun resolve (Lokio/ByteString;)Lokio/Path;\n\tpublic final fun resolve (Lokio/ByteString;Z)Lokio/Path;\n\tpublic final fun resolve (Lokio/Path;)Lokio/Path;\n\tpublic final fun resolve (Lokio/Path;Z)Lokio/Path;\n\tpublic static synthetic fun resolve$default (Lokio/Path;Ljava/lang/String;ZILjava/lang/Object;)Lokio/Path;\n\tpublic static synthetic fun resolve$default (Lokio/Path;Lokio/ByteString;ZILjava/lang/Object;)Lokio/Path;\n\tpublic static synthetic fun resolve$default (Lokio/Path;Lokio/Path;ZILjava/lang/Object;)Lokio/Path;\n\tpublic final fun toFile ()Ljava/io/File;\n\tpublic final fun toNioPath ()Ljava/nio/file/Path;\n\tpublic fun toString ()Ljava/lang/String;\n\tpublic final fun volumeLetter ()Ljava/lang/Character;\n}\n\npublic final class okio/Path$Companion {\n\tpublic final fun get (Ljava/io/File;)Lokio/Path;\n\tpublic final fun get (Ljava/io/File;Z)Lokio/Path;\n\tpublic final fun get (Ljava/lang/String;)Lokio/Path;\n\tpublic final fun get (Ljava/lang/String;Z)Lokio/Path;\n\tpublic final fun get (Ljava/nio/file/Path;)Lokio/Path;\n\tpublic final fun get (Ljava/nio/file/Path;Z)Lokio/Path;\n\tpublic static synthetic fun get$default (Lokio/Path$Companion;Ljava/io/File;ZILjava/lang/Object;)Lokio/Path;\n\tpublic static synthetic fun get$default (Lokio/Path$Companion;Ljava/lang/String;ZILjava/lang/Object;)Lokio/Path;\n\tpublic static synthetic fun get$default (Lokio/Path$Companion;Ljava/nio/file/Path;ZILjava/lang/Object;)Lokio/Path;\n}\n\npublic final class okio/Pipe {\n\tpublic final fun -deprecated_sink ()Lokio/Sink;\n\tpublic final fun -deprecated_source ()Lokio/Source;\n\tpublic fun <init> (J)V\n\tpublic final fun cancel ()V\n\tpublic final fun fold (Lokio/Sink;)V\n\tpublic final fun getCondition ()Ljava/util/concurrent/locks/Condition;\n\tpublic final fun getLock ()Ljava/util/concurrent/locks/ReentrantLock;\n\tpublic final fun sink ()Lokio/Sink;\n\tpublic final fun source ()Lokio/Source;\n}\n\npublic abstract interface class okio/Sink : java/io/Closeable, java/io/Flushable {\n\tpublic abstract fun close ()V\n\tpublic abstract fun flush ()V\n\tpublic abstract fun timeout ()Lokio/Timeout;\n\tpublic abstract fun write (Lokio/Buffer;J)V\n}\n\npublic abstract interface class okio/Socket {\n\tpublic abstract fun cancel ()V\n\tpublic abstract fun getSink ()Lokio/Sink;\n\tpublic abstract fun getSource ()Lokio/Source;\n}\n\npublic abstract interface class okio/Source : java/io/Closeable {\n\tpublic abstract fun close ()V\n\tpublic abstract fun read (Lokio/Buffer;J)J\n\tpublic abstract fun timeout ()Lokio/Timeout;\n}\n\npublic final class okio/SystemFileSystem {\n\tpublic static final synthetic fun getSYSTEM (Lokio/FileSystem$Companion;)Lokio/FileSystem;\n}\n\npublic final class okio/Throttler {\n\tpublic fun <init> ()V\n\tpublic final fun bytesPerSecond (J)V\n\tpublic final fun bytesPerSecond (JJ)V\n\tpublic final fun bytesPerSecond (JJJ)V\n\tpublic static synthetic fun bytesPerSecond$default (Lokio/Throttler;JJJILjava/lang/Object;)V\n\tpublic final fun getCondition ()Ljava/util/concurrent/locks/Condition;\n\tpublic final fun getLock ()Ljava/util/concurrent/locks/ReentrantLock;\n\tpublic final fun sink (Lokio/Sink;)Lokio/Sink;\n\tpublic final fun source (Lokio/Source;)Lokio/Source;\n}\n\npublic class okio/Timeout {\n\tpublic static final field Companion Lokio/Timeout$Companion;\n\tpublic static final field NONE Lokio/Timeout;\n\tpublic fun <init> ()V\n\tpublic fun awaitSignal (Ljava/util/concurrent/locks/Condition;)V\n\tpublic fun cancel ()V\n\tpublic fun clearDeadline ()Lokio/Timeout;\n\tpublic fun clearTimeout ()Lokio/Timeout;\n\tpublic final fun deadline (JLjava/util/concurrent/TimeUnit;)Lokio/Timeout;\n\tpublic fun deadlineNanoTime ()J\n\tpublic fun deadlineNanoTime (J)Lokio/Timeout;\n\tpublic fun hasDeadline ()Z\n\tpublic final fun intersectWith (Lokio/Timeout;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;\n\tpublic fun throwIfReached ()V\n\tpublic fun timeout (JLjava/util/concurrent/TimeUnit;)Lokio/Timeout;\n\tpublic fun timeoutNanos ()J\n\tpublic fun waitUntilNotified (Ljava/lang/Object;)V\n}\n\npublic final class okio/Timeout$Companion {\n\tpublic final fun minTimeout (JJ)J\n\tpublic final fun timeout (Lokio/Timeout;JLkotlin/time/DurationUnit;)Lokio/Timeout;\n\tpublic final fun timeout-HG0u8IE (Lokio/Timeout;J)Lokio/Timeout;\n}\n\npublic final class okio/TypedOptions : kotlin/collections/AbstractList, java/util/RandomAccess {\n\tpublic static final field Companion Lokio/TypedOptions$Companion;\n\tpublic fun <init> (Ljava/util/List;Lokio/Options;)V\n\tpublic fun get (I)Ljava/lang/Object;\n\tpublic fun getSize ()I\n\tpublic static final fun of (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Lokio/TypedOptions;\n}\n\npublic final class okio/TypedOptions$Companion {\n\tpublic final fun of (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Lokio/TypedOptions;\n}\n\npublic final class okio/Utf8 {\n\tpublic static final fun size (Ljava/lang/String;)J\n\tpublic static final fun size (Ljava/lang/String;I)J\n\tpublic static final fun size (Ljava/lang/String;II)J\n\tpublic static synthetic fun size$default (Ljava/lang/String;IIILjava/lang/Object;)J\n}\n\npublic final class okio/_JvmPlatformKt {\n\tpublic static final fun withLock (Ljava/util/concurrent/locks/ReentrantLock;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;\n}\n\npublic final class okio/internal/_Utf8Kt {\n\tpublic static final fun commonAsUtf8ToByteArray (Ljava/lang/String;)[B\n\tpublic static final fun commonToUtf8String ([BII)Ljava/lang/String;\n\tpublic static synthetic fun commonToUtf8String$default ([BIIILjava/lang/Object;)Ljava/lang/String;\n}\n\n"
  },
  {
    "path": "okio/build.gradle.kts",
    "content": "import aQute.bnd.gradle.BundleTaskExtension\nimport com.vanniktech.maven.publish.JavadocJar\nimport com.vanniktech.maven.publish.KotlinMultiplatform\nimport com.vanniktech.maven.publish.MavenPublishBaseExtension\nimport kotlinx.validation.ApiValidationExtension\nimport org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget\nimport org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests\nimport org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType\nimport org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable\nimport org.jetbrains.kotlin.konan.target.Family\n\nplugins {\n  kotlin(\"multiplatform\")\n  id(\"app.cash.burst\")\n  id(\"org.jetbrains.dokka\")\n  id(\"com.vanniktech.maven.publish.base\")\n  id(\"build-support\")\n  id(\"binary-compatibility-validator\")\n}\n\n/*\n * Here's the main hierarchy of variants. Any `expect` functions in one level of the tree are\n * `actual` functions in a (potentially indirect) child node.\n *\n * ```\n *   common\n *   |-- js\n *   |-- jvm\n *   |-- native\n *   |   |-- mingw\n *   |   |   '-- mingwX64\n *   |   '-- unix\n *   |       |-- apple\n *   |       |   |-- iosArm64\n *   |       |   |-- iosX64\n *   |       |   |-- macosX64\n *   |       |   |-- tvosArm64\n *   |       |   |-- tvosX64\n *   |       |   |-- watchosArm32\n *   |       |   |-- watchosArm64\n *   |       '-- linux\n *   |           |-- linuxX64\n *   |           '-- linuxArm64\n *   '-- wasm\n *       '-- wasmJs\n *       '-- wasmWasi\n * ```\n *\n * The `nonJvm`, `nonJs`, `nonApple`, etc. source sets exclude the corresponding platforms.\n *\n * The `hashFunctions` source set builds on all platforms. It ships as a main source set on non-JVM\n * platforms and as a test source set on the JVM platform.\n *\n * The `systemFileSystem` source set is used on jvm and native targets, and provides the FileSystem.SYSTEM property.\n */\nkotlin {\n  configureOrCreateOkioPlatforms()\n\n  sourceSets {\n    all {\n      languageSettings.apply {\n        // Required for CPointer etc. since Kotlin 1.9.\n        optIn(\"kotlinx.cinterop.ExperimentalForeignApi\")\n        // Required for Contract API. since Kotlin 1.3.\n        optIn(\"kotlin.contracts.ExperimentalContracts\")\n      }\n    }\n    matching { it.name.endsWith(\"Test\") }.all {\n      languageSettings {\n        optIn(\"kotlin.time.ExperimentalTime\")\n      }\n    }\n\n    val commonMain by getting\n    val commonTest by getting {\n      dependencies {\n        implementation(libs.kotlin.test)\n        implementation(projects.okioTestingSupport)\n      }\n    }\n\n    val hashFunctions by creating {\n      dependsOn(commonMain)\n    }\n\n    val nonAppleMain by creating {\n      dependsOn(hashFunctions)\n    }\n\n    val nonWasmTest by creating {\n      dependsOn(commonTest)\n      dependencies {\n        implementation(libs.kotlin.time)\n        implementation(projects.okioFakefilesystem)\n      }\n    }\n\n    val nonJvmMain by creating {\n      dependsOn(hashFunctions)\n      dependsOn(commonMain)\n    }\n\n    val nonJsMain by creating {\n      dependsOn(commonMain)\n    }\n\n    val systemFileSystemMain by creating {\n      dependsOn(commonMain)\n    }\n\n    val nonJvmTest by creating {\n      dependsOn(commonTest)\n    }\n\n    val zlibMain by creating {\n      dependsOn(commonMain)\n    }\n\n    val zlibTest by creating {\n      dependsOn(commonTest)\n      dependencies {\n        implementation(libs.test.assertk)\n      }\n    }\n\n    val jvmMain by getting {\n      dependsOn(zlibMain)\n      dependsOn(systemFileSystemMain)\n      dependsOn(nonJsMain)\n    }\n    val jvmTest by getting {\n      kotlin.srcDir(\"src/hashFunctions\")\n      dependsOn(nonWasmTest)\n      dependsOn(zlibTest)\n      dependencies {\n        implementation(libs.test.junit)\n        implementation(libs.test.jimfs)\n      }\n    }\n\n    if (kmpJsEnabled) {\n      val jsMain by getting {\n        dependsOn(nonJvmMain)\n        dependsOn(nonAppleMain)\n      }\n      val jsTest by getting {\n        dependsOn(nonWasmTest)\n        dependsOn(nonJvmTest)\n      }\n    }\n\n    if (kmpNativeEnabled) {\n      createSourceSet(\"nativeMain\", parent = nonJvmMain)\n        .also { nativeMain ->\n          nativeMain.dependsOn(zlibMain)\n          nativeMain.dependsOn(systemFileSystemMain)\n          createSourceSet(\n            \"mingwMain\",\n            parent = nativeMain,\n            children = mingwTargets,\n          ).also { mingwMain ->\n            mingwMain.dependsOn(nonAppleMain)\n            mingwMain.dependsOn(nonJsMain)\n          }\n          createSourceSet(\"unixMain\", parent = nativeMain)\n            .also { unixMain ->\n              unixMain.dependsOn(nonJsMain)\n              createSourceSet(\n                \"linuxMain\",\n                parent = unixMain,\n                children = linuxTargets,\n              ).also { linuxMain ->\n                linuxMain.dependsOn(nonAppleMain)\n              }\n              createSourceSet(\n                name = \"appleMain\",\n                parent = unixMain,\n                children = appleTargets,\n              ).also { appleMain ->\n                createSourceSet(\n                  name = \"appleNonMacosX64Main\",\n                  parent = appleMain,\n                  children = appleTargets - \"macosX64\",\n                )\n              }\n            }\n        }\n\n      createSourceSet(\"nativeTest\", parent = commonTest, children = mingwTargets + linuxTargets)\n        .also { nativeTest ->\n          nativeTest.dependsOn(nonJvmTest)\n          nativeTest.dependsOn(nonWasmTest)\n          nativeTest.dependsOn(zlibTest)\n          createSourceSet(\"appleTest\", parent = nativeTest, children = appleTargets)\n        }\n    }\n\n    if (kmpWasmEnabled) {\n      createSourceSet(\"wasmMain\", parent = commonMain, children = wasmTargets)\n        .also { wasmMain ->\n          wasmMain.dependsOn(nonJsMain)\n          wasmMain.dependsOn(nonJvmMain)\n          wasmMain.dependsOn(nonAppleMain)\n        }\n      createSourceSet(\"wasmTest\", parent = commonTest, children = wasmTargets)\n        .also { wasmTest ->\n          wasmTest.dependsOn(nonJvmTest)\n        }\n    }\n  }\n\n  targets.withType<KotlinNativeTarget> {\n    if (konanTarget.family == Family.LINUX) {\n      compilations[\"main\"].cinterops.create(\"linux\") {\n        packageName(\"okio.internal.linux\")\n        headers(\n          File(project.projectDir, \"src/linuxMain/headers/include/uapi/linux/stat.h\"),\n          File(project.projectDir, \"src/linuxMain/headers/okio_statx.h\"),\n        )\n      }\n    }\n  }\n  targets.withType<KotlinNativeTargetWithTests<*>> {\n    binaries {\n      // Configure a separate test where code runs in background\n      test(\"background\", setOf(NativeBuildType.DEBUG)) {\n        freeCompilerArgs += \"-trw\"\n      }\n    }\n    testRuns {\n      val background by creating {\n        setExecutionSourceFrom(binaries.getByName(\"backgroundDebugTest\") as TestExecutable)\n      }\n    }\n  }\n}\n\ntasks {\n  val jvmJar by getting(Jar::class) {\n    // BundleTaskExtension() crashes unless there's a 'main' source set.\n    sourceSets.create(SourceSet.MAIN_SOURCE_SET_NAME)\n    val bndExtension = BundleTaskExtension(this)\n    bndExtension.setBnd(\n      \"\"\"\n      Export-Package: okio\n      Automatic-Module-Name: okio\n      Bundle-SymbolicName: com.squareup.okio\n      \"\"\",\n    )\n    // Call the extension when the task has finished to modify the jar to contain OSGi metadata.\n    doLast {\n      bndExtension.buildAction()\n        .execute(this)\n    }\n  }\n}\n\nconfigure<MavenPublishBaseExtension> {\n  configure(\n    KotlinMultiplatform(javadocJar = JavadocJar.Empty()),\n  )\n}\n\nplugins.withId(\"binary-compatibility-validator\") {\n  configure<ApiValidationExtension> {\n    ignoredProjects += \"jmh\"\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/README.md",
    "content": "Okio Benchmarks\n===============\n\nThis module contains JMH microbenchmarks. Run benchmarks locally with Gradle:\n\n```\n$ ./gradlew jmh\n```\n\nSelect and configure benchmarks in the `jmh` section of `okio/jvm/jmh/build.gradle`.\n"
  },
  {
    "path": "okio/jvm/jmh/build.gradle.kts",
    "content": "plugins {\n  kotlin(\"jvm\")\n  id(\"me.champeau.jmh\")\n}\n\njmh {\n}\n\ndependencies {\n  api(projects.okio)\n  api(libs.jmh.core)\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/AsyncTimeoutBenchmark.java",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Random;\nimport java.util.concurrent.TimeUnit;\nimport okio.AsyncTimeout;\nimport okio.PriorityQueue;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\n\n@Fork(1)\n@Warmup(iterations = 2, time = 2)\n@Measurement(iterations = 3, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.AverageTime)\n@OutputTimeUnit(TimeUnit.NANOSECONDS)\npublic class AsyncTimeoutBenchmark {\n\n  @Param({ \"1\", \"10\", \"100\", \"1000\" })\n  int queueSize;\n\n  private List<AsyncTimeout> asyncTimeouts;\n  private PriorityQueue heap = new PriorityQueue();\n  private int next = 0;\n\n  @Setup\n  public void setup() {\n    heap = new PriorityQueue();\n    asyncTimeouts = new ArrayList<>(queueSize);\n    for (int i = 0; i < queueSize; i++) {\n      AsyncTimeout timeout = new AsyncTimeout() {\n        @Override protected void timedOut() {\n          // No-op\n        }\n      };\n      timeout.timeout(i, TimeUnit.SECONDS);\n      asyncTimeouts.add(timeout);\n    }\n    Collections.shuffle(asyncTimeouts, new Random(0));\n    for (int i = 0; i < queueSize; i++) {\n      heap.add(asyncTimeouts.get(i));\n    }\n  }\n\n  @Benchmark\n  public void enterExit() {\n    AsyncTimeout timeout = asyncTimeouts.get(next++);\n    heap.remove(timeout);\n    heap.add(timeout);\n    next = next % queueSize;\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/BenchmarkUtils.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks\n\nimport okio.internal.commonAsUtf8ToByteArray\nimport okio.internal.commonToUtf8String\n\n// Necessary to make an invisible functions visible to Java.\nobject BenchmarkUtils {\n  @JvmStatic\n  fun ByteArray.decodeUtf8(): String {\n    return commonToUtf8String()\n  }\n\n  @JvmStatic\n  fun String.encodeUtf8(): ByteArray {\n    return commonAsUtf8ToByteArray()\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/BufferCursorSeekBenchmark.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.SampleTime)\n@OutputTimeUnit(TimeUnit.MICROSECONDS)\npublic class BufferCursorSeekBenchmark {\n  Buffer buffer;\n  Buffer.UnsafeCursor cursor;\n\n  @Param({ \"2097152\" })\n  int bufferSize; // 2 MB = 256 Segments\n\n  @Setup\n  public void setup() throws IOException {\n    byte[] source = new byte[8192];\n    buffer = new Buffer();\n    while (buffer.size() < bufferSize) {\n      buffer.write(source);\n    }\n    cursor = new Buffer.UnsafeCursor();\n  }\n\n  @Benchmark\n  public void seekBeginning() {\n    buffer.readUnsafe(cursor);\n    try {\n      cursor.seek(0);\n    } finally {\n      cursor.close();\n    }\n  }\n\n  @Benchmark\n  public void seekEnd() {\n    buffer.readUnsafe(cursor);\n    try {\n      cursor.seek(buffer.size() - 1);\n    } finally {\n      cursor.close();\n    }\n  }\n\n  @Benchmark\n  public void seekForward() {\n    buffer.readUnsafe(cursor);\n    try {\n      cursor.seek(0);\n      cursor.seek(1);\n    } finally {\n      cursor.close();\n    }\n  }\n\n  @Benchmark\n  public void seekBackward() {\n    buffer.readUnsafe(cursor);\n    try {\n      cursor.seek(buffer.size() - 1);\n      cursor.seek(buffer.size() - 2);\n    } finally {\n      cursor.close();\n    }\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[] {\n        BufferCursorSeekBenchmark.class.getName()\n    });\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/BufferPerformanceBenchmark.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc. and others.\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 */\n\npackage com.squareup.okio.benchmarks;\n\nimport java.io.EOFException;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.concurrent.TimeUnit;\n\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Group;\nimport org.openjdk.jmh.annotations.GroupThreads;\nimport org.openjdk.jmh.annotations.Level;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.TearDown;\nimport org.openjdk.jmh.annotations.Threads;\nimport org.openjdk.jmh.annotations.Warmup;\n\nimport okio.Buffer;\nimport okio.BufferedSource;\nimport okio.Okio;\nimport okio.Sink;\nimport okio.Timeout;\n\nimport static java.util.Objects.requireNonNull;\n\n@Fork(1)\n@Warmup(iterations = 10, time = 10)\n@Measurement(iterations = 10, time = 10)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.Throughput)\n@OutputTimeUnit(TimeUnit.SECONDS)\npublic class BufferPerformanceBenchmark {\n\n  public static final File OriginPath =\n      new File(System.getProperty(\"okio.bench.origin.path\", \"/dev/urandom\"));\n\n  /* Test Workload\n   *\n   * Each benchmark thread maintains three buffers; a receive buffer, a process buffer\n   * and a send buffer. At every operation:\n   *\n   *   - We fill up the receive buffer using the origin, write the request to the process\n   *     buffer, and consume the process buffer.\n   *   - We fill up the process buffer using the origin, write the response to the send\n   *     buffer, and consume the send buffer.\n   *\n   * We use an \"origin\" source that serves as a preexisting sequence of bytes we can read\n   * from the file system. The request and response bytes are initialized in the beginning\n   * and reused throughout the benchmark in order to eliminate GC effects.\n   *\n   * Typically, we simulate the usage of small reads and large writes. Requests and\n   * responses are satisfied with precomputed buffers to eliminate GC effects on\n   * results.\n   *\n   * There are two types of benchmark tests; hot tests are \"pedal to the metal\" and\n   * use all CPU they can take. These are useful to magnify performance effects of\n   * changes but are not realistic use cases that should drive optimization efforts.\n   * Cold tests introduce think time between the receiving of the request and sending\n   * of the response. They are more useful as a reasonably realistic workload where\n   * buffers can be read from and written to during request/response handling but\n   * may hide subtle effects of most changes on performance. Prefer to look at the cold\n   * benchmarks first to decide if a bottleneck is worth pursuing, then use the hot\n   * benchmarks to fine tune optimization efforts.\n   *\n   * Benchmark threads do not explicitly communicate between each other (except to sync\n   * iterations as needed by JMH).\n   *\n   * We simulate think time for each benchmark thread by parking the thread for a\n   * configurable number of microseconds (1000 by default).\n   */\n\n\n  @Benchmark\n  @Threads(1)\n  public void threads1hot(HotBuffers buffers) throws IOException {\n    readWriteRecycle(buffers);\n  }\n\n  @Benchmark\n  @Threads(2)\n  public void threads2hot(HotBuffers buffers) throws IOException {\n    readWriteRecycle(buffers);\n  }\n\n  @Benchmark\n  @Threads(4)\n  public void threads4hot(HotBuffers buffers) throws IOException {\n    readWriteRecycle(buffers);\n  }\n\n  @Benchmark\n  @Threads(8)\n  public void threads8hot(HotBuffers buffers) throws IOException {\n    readWriteRecycle(buffers);\n  }\n\n  @Benchmark\n  @Threads(16)\n  public void threads16hot(HotBuffers buffers) throws IOException {\n    readWriteRecycle(buffers);\n  }\n\n  @Benchmark\n  @Threads(32)\n  public void threads32hot(HotBuffers buffers) throws IOException {\n    readWriteRecycle(buffers);\n  }\n\n  @Benchmark\n  @GroupThreads(1)\n  @Group(\"cold\")\n  public void thinkReadHot(HotBuffers buffers) throws IOException {\n    buffers.receive(requestBytes).readAll(NullSink);\n  }\n\n  @Benchmark\n  @GroupThreads(3)\n  @Group(\"cold\")\n  public void thinkWriteCold(ColdBuffers buffers) throws IOException {\n    buffers.transmit(responseBytes).readAll(NullSink);\n  }\n\n  private void readWriteRecycle(HotBuffers buffers) throws IOException {\n    buffers.receive(requestBytes).readAll(NullSink);\n    buffers.transmit(responseBytes).readAll(NullSink);\n  }\n\n  @Param({ \"1000\" })\n  int maxThinkMicros = 1000;\n\n  @Param({ \"1024\" })\n  int maxReadBytes = 1024;\n\n  @Param({ \"1024\" })\n  int maxWriteBytes = 1024;\n\n  @Param({ \"2048\" })\n  int requestSize = 2048;\n\n  @Param({ \"1\" })\n  int responseFactor = 1;\n\n  byte[] requestBytes;\n\n  byte[] responseBytes;\n\n  @Setup(Level.Trial)\n  public void storeRequestResponseData() throws IOException {\n    checkOrigin(OriginPath);\n\n    requestBytes = storeSourceData(new byte[requestSize]);\n    responseBytes = storeSourceData(new byte[requestSize * responseFactor]);\n  }\n\n  private byte[] storeSourceData(byte[] dest) throws IOException {\n    requireNonNull(dest, \"dest == null\");\n    try (BufferedSource source = Okio.buffer(Okio.source(OriginPath))) {\n      source.readFully(dest);\n    }\n    return dest;\n  }\n\n  private void checkOrigin(File path) throws IOException {\n    requireNonNull(path, \"path == null\");\n\n    if (!path.canRead()) {\n      throw new IllegalArgumentException(\"can not access: \" + path);\n    }\n\n    try (InputStream in = new FileInputStream(path)) {\n      int available = in.read();\n      if (available < 0) {\n        throw new IllegalArgumentException(\"can not read: \" + path);\n      }\n    }\n  }\n\n  /*\n   * The state class hierarchy is larger than it needs to be due to a JMH\n   * issue where states inheriting setup methods depending on another state\n   * do not get initialized correctly from benchmark methods making use\n   * of groups. To work around, we leave the common setup and teardown code\n   * in superclasses and move the setup method depending on the bench state\n   * to subclasses. Without the workaround, it would have been enough for\n   * `ColdBuffers` to inherit from `HotBuffers`.\n   */\n\n  @State(Scope.Thread)\n  public static class ColdBuffers extends BufferSetup {\n\n    @Setup(Level.Trial)\n    public void setupBench(BufferPerformanceBenchmark bench) {\n      super.bench = bench;\n    }\n\n    @Setup(Level.Invocation)\n    public void lag() throws InterruptedException {\n      TimeUnit.MICROSECONDS.sleep(bench.maxThinkMicros);\n    }\n\n  }\n\n  @State(Scope.Thread)\n  public static class HotBuffers extends BufferSetup {\n\n    @Setup(Level.Trial)\n    public void setupBench(BufferPerformanceBenchmark bench) {\n      super.bench = bench;\n    }\n\n  }\n\n  @State(Scope.Thread)\n  public abstract static class BufferSetup extends BufferState {\n    BufferPerformanceBenchmark bench;\n\n    public BufferedSource receive(byte[] bytes) throws IOException {\n      return super.receive(bytes, bench.maxReadBytes);\n    }\n\n    public BufferedSource transmit(byte[] bytes) throws IOException {\n      return super.transmit(bytes, bench.maxWriteBytes);\n    }\n\n    @TearDown\n    public void dispose() throws IOException {\n      releaseBuffers();\n    }\n\n  }\n\n  public static class BufferState {\n\n    @SuppressWarnings(\"resource\")\n    final Buffer received = new Buffer();\n    @SuppressWarnings(\"resource\")\n    final Buffer sent = new Buffer();\n    @SuppressWarnings(\"resource\")\n    final Buffer process = new Buffer();\n\n    public void releaseBuffers() throws IOException {\n      received.clear();\n      sent.clear();\n      process.clear();\n    }\n\n    /**\n     * Fills up the receive buffer, hands off to process buffer and returns it for consuming.\n     * Expects receive and process buffers to be empty. Leaves the receive buffer empty and\n     * process buffer full.\n     */\n    protected Buffer receive(byte[] bytes, int maxChunkSize) throws IOException {\n      writeChunked(received, bytes, maxChunkSize).readAll(process);\n      return process;\n    }\n\n    /**\n     * Fills up the process buffer, hands off to send buffer and returns it for consuming.\n     * Expects process and sent buffers to be empty. Leaves the process buffer empty and\n     * sent buffer full.\n     */\n    protected BufferedSource transmit(byte[] bytes, int maxChunkSize) throws IOException {\n      writeChunked(process, bytes, maxChunkSize).readAll(sent);\n      return sent;\n    }\n\n    private BufferedSource writeChunked(Buffer buffer, byte[] bytes, final int chunkSize) {\n      int remaining = bytes.length;\n      int offset = 0;\n      while (remaining > 0) {\n        int bytesToWrite = Math.min(remaining, chunkSize);\n        buffer.write(bytes, offset, bytesToWrite);\n        remaining -= bytesToWrite;\n        offset += bytesToWrite;\n      }\n      return buffer;\n    }\n\n  }\n\n  @SuppressWarnings(\"resource\")\n  private static final Sink NullSink = new Sink() {\n\n    @Override public void write(Buffer source, long byteCount) throws EOFException {\n      source.skip(byteCount);\n    }\n\n    @Override public void flush() {\n      // nothing\n    }\n\n    @Override public Timeout timeout() {\n      return Timeout.NONE;\n    }\n\n    @Override public void close() {\n      // nothing\n    }\n\n    @Override public String toString() {\n      return \"NullSink{}\";\n    }\n  };\n\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/BufferUtf8Benchmark.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\nimport okio.Buffer;\nimport okio.ByteString;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.Throughput)\n@OutputTimeUnit(TimeUnit.SECONDS)\npublic class BufferUtf8Benchmark {\n  private static final Map<String, String> strings = new HashMap<>();\n\n  static {\n    strings.put(\n        \"ascii\",\n        \"Um, I'll tell you the problem with the scientific power that you're using here, \"\n            + \"it didn't require any discipline to attain it. You read what others had done and you \"\n            + \"took the next step. You didn't earn the knowledge for yourselves, so you don't take any \"\n            + \"responsibility for it. You stood on the shoulders of geniuses to accomplish something \"\n            + \"as fast as you could, and before you even knew what you had, you patented it, and \"\n            + \"packaged it, and slapped it on a plastic lunchbox, and now you're selling it, you wanna \"\n            + \"sell it.\");\n\n    strings.put(\n        \"utf8\",\n        \"Սｍ, I'll 𝓽𝖾ll ᶌօ𝘂 ᴛℎ℮ 𝜚𝕣०ｂl𝖾ｍ ｗі𝕥𝒽 𝘵𝘩𝐞 𝓼𝙘𝐢𝔢𝓷𝗍𝜄𝚏𝑖ｃ 𝛠𝝾ｗ𝚎𝑟 𝕥ｈ⍺𝞃 𝛄𝓸𝘂'𝒓𝗲 υ𝖘𝓲𝗇ɡ 𝕙𝚎𝑟ｅ, \"\n            + \"𝛊𝓽 ⅆ𝕚𝐝𝝿'𝗍 𝔯𝙚𝙦ᴜ𝜾𝒓𝘦 𝔞𝘯𝐲 ԁ𝜄𝑠𝚌ι𝘱lι𝒏ｅ 𝑡𝜎 𝕒𝚝𝖙𝓪і𝞹 𝔦𝚝. 𝒀ο𝗎 𝔯𝑒⍺𝖉 ｗ𝐡𝝰𝔱 𝞂𝞽һ𝓮𝓇ƽ հ𝖺𝖉 ⅾ𝛐𝝅ⅇ 𝝰πԁ 𝔂ᴑᴜ 𝓉ﮨ၀𝚔 \"\n            + \"т𝒽𝑒 𝗇𝕖ⅹ𝚝 𝔰𝒕е𝓅. 𝘠ⲟ𝖚 𝖉ⅰԁ𝝕'τ 𝙚𝚊ｒ𝞹 𝘵Ꮒ𝖾 𝝒𝐧هｗl𝑒𝖉ƍ𝙚 𝓯૦ｒ 𝔂𝞼𝒖𝕣𝑠𝕖l𝙫𝖊𝓼, 𐑈о ｙ𝘰𝒖 ⅆە𝗇'ｔ 𝜏α𝒌𝕖 𝛂𝟉ℽ \"\n            + \"𝐫ⅇ𝗌ⲣ๐ϖ𝖘ꙇᖯ𝓲l𝓲𝒕𝘆 𝐟𝞼𝘳 𝚤𝑡. 𝛶𝛔𝔲 ｓ𝕥σσ𝐝 ﮩ𝕟 𝒕𝗁𝔢 𝘴𝐡𝜎ᴜlⅾ𝓮𝔯𝚜 𝛐𝙛 ᶃ𝚎ᴨᎥս𝚜𝘦𝓈 𝓽𝞸 ａ𝒄𝚌𝞸ｍρl𝛊ꜱ𝐡 𝓈𝚘ｍ𝚎𝞃𝔥⍳𝞹𝔤 𝐚𝗌 𝖋ａ𝐬𝒕 \"\n            + \"αｓ γ𝛐𝕦 𝔠ﻫ𝛖lԁ, 𝚊π𝑑 Ь𝑒𝙛૦𝓇𝘦 𝓎٥𝖚 ⅇｖℯ𝝅 𝜅ո𝒆ｗ ｗ𝗵𝒂𝘁 ᶌ੦𝗎 ｈ𝐚𝗱, 𝜸ﮨ𝒖 𝓹𝝰𝔱𝖾𝗇𝓽𝔢ⅆ і𝕥, 𝚊𝜛𝓭 𝓹𝖺ⅽϰ𝘢ℊеᏧ 𝑖𝞃, \"\n            + \"𝐚𝛑ꓒ 𝙨l𝔞р𝘱𝔢𝓭 ɩ𝗍 ہ𝛑 𝕒 ｐl𝛂ѕᴛ𝗂𝐜 l𝞄ℼ𝔠𝒽𝑏ﮪ⨯, 𝔞ϖ𝒹 ｎ𝛔ｗ 𝛾𝐨𝞄'𝗿𝔢 ꜱ℮ll𝙞ｎɡ ɩ𝘁, 𝙮𝕠𝛖 ｗ𝑎ℼ𝚗𝛂 𝕤𝓮ll 𝙞𝓉.\");\n\n    // The first 't' is actually a '𝓽'\n    strings.put(\n        \"sparse\",\n        \"Um, I'll 𝓽ell you the problem with the scientific power that you're using here, \"\n            + \"it didn't require any discipline to attain it. You read what others had done and you \"\n            + \"took the next step. You didn't earn the knowledge for yourselves, so you don't take any \"\n            + \"responsibility for it. You stood on the shoulders of geniuses to accomplish something \"\n            + \"as fast as you could, and before you even knew what you had, you patented it, and \"\n            + \"packaged it, and slapped it on a plastic lunchbox, and now you're selling it, you wanna \"\n            + \"sell it.\");\n\n    strings.put(\"2bytes\", \"\\u0080\\u07ff\");\n\n    strings.put(\"3bytes\", \"\\u0800\\ud7ff\\ue000\\uffff\");\n\n    strings.put(\"4bytes\", \"\\ud835\\udeca\");\n\n    // high surrogate, 'a', low surrogate, and 'a'\n    strings.put(\"bad\", \"\\ud800\\u0061\\udc00\\u0061\");\n  }\n\n  @Param({\"20\", \"2000\", \"200000\"})\n  int length;\n\n  @Param({\"ascii\", \"utf8\", \"sparse\", \"2bytes\", \"3bytes\", \"4bytes\", \"bad\"})\n  String encoding;\n\n  Buffer buffer;\n  String encode;\n  ByteString decode;\n\n  @Setup\n  public void setup() {\n    String part = strings.get(encoding);\n\n    // Make all the strings the same length for comparison\n    StringBuilder builder = new StringBuilder(length + 1_000);\n    while (builder.length() < length) {\n      builder.append(part);\n    }\n    builder.setLength(length);\n\n    // Prepare a string and ByteString for encoding and decoding\n    buffer = new Buffer();\n    encode = builder.toString();\n    Buffer temp = new Buffer();\n    temp.writeUtf8(encode);\n    decode = temp.snapshot();\n  }\n\n  @Benchmark\n  public void writeUtf8() {\n    buffer.writeUtf8(encode);\n    buffer.clear();\n  }\n\n  @Benchmark\n  public String readUtf8() {\n    buffer.write(decode);\n    return buffer.readUtf8();\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[] {BufferUtf8Benchmark.class.getName()});\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/GetByteBenchmark.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.SampleTime)\n@OutputTimeUnit(TimeUnit.MICROSECONDS)\npublic class GetByteBenchmark {\n  Buffer buffer;\n\n  @Param({ \"2097152\" })\n  int bufferSize; // 2 MB = 256 Segments\n\n  @Setup\n  public void setup() throws IOException {\n    buffer = new Buffer();\n    while (buffer.size() < bufferSize) {\n      buffer.write(new byte[8192]);\n    }\n  }\n\n  @Benchmark\n  public void getByteBeginning() {\n    buffer.getByte(0);\n  }\n\n  @Benchmark\n  public void getByteEnd() {\n    buffer.getByte(buffer.size() - 1);\n  }\n\n  @Benchmark\n  public void getByteMiddle() {\n    buffer.getByte(buffer.size() / 2);\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[] {\n        GetByteBenchmark.class.getName()\n    });\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/HashFunctionBenchmark.java",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.concurrent.TimeUnit;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 1)\n@Measurement(iterations = 5, time = 1)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.AverageTime)\n@OutputTimeUnit(TimeUnit.MICROSECONDS)\npublic class HashFunctionBenchmark {\n\n  MessageDigest jvm;\n\n  @Param({ \"100\", \"1048576\" })\n  public int messageSize;\n\n  @Param({ \"SHA-1\", \"SHA-256\", \"SHA-512\", \"MD5\" })\n  public String algorithm;\n\n  private byte[] message;\n\n  @Setup public void setup() throws NoSuchAlgorithmException {\n    jvm = MessageDigest.getInstance(algorithm);\n    message = new byte[messageSize];\n  }\n\n  @Benchmark public void jvm() {\n    jvm.update(message, 0, messageSize);\n    jvm.digest();\n  }\n\n  public static void main(String[] args) throws IOException {\n    Main.main(new String[] { HashFunctionBenchmark.class.getName() });\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/IndexOfElementBenchmark.java",
    "content": "/*\n * Copyright (C) 2016 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport okio.ByteString;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.SampleTime)\n@OutputTimeUnit(TimeUnit.MICROSECONDS)\npublic class IndexOfElementBenchmark {\n  ByteString byteString = ByteString.encodeUtf8(\"abcd\");\n  Buffer buffer;\n\n  @Param({ \"32768\" })\n  int bufferSize;\n\n  @Setup\n  public void setup() throws IOException {\n    buffer = new Buffer()\n        .write(new byte[bufferSize / 2])\n        .write(byteString)\n        .write(new byte[(bufferSize / 2) - byteString.size()]);\n  }\n\n  @Benchmark\n  public void indexOfByte() throws IOException {\n    buffer.indexOf((byte) 'b', 0L);\n  }\n\n  @Benchmark\n  public void indexOfByteString() throws IOException {\n    buffer.indexOf(byteString, 0L);\n  }\n\n  @Benchmark\n  public void indexOfElement() throws IOException {\n    buffer.indexOfElement(byteString, 0L);\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[] {\n        IndexOfElementBenchmark.class.getName()\n    });\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/ReadByteStringBenchmark.java",
    "content": "/*\n * Copyright (C) 2019 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.SampleTime)\n@OutputTimeUnit(TimeUnit.MICROSECONDS)\npublic class ReadByteStringBenchmark {\n\n  Buffer buffer;\n\n  @Param({\"32768\"})\n  int bufferSize;\n\n  @Param({\"8\", \"16\", \"32\", \"64\", \"128\", \"256\", \"512\", \"1024\", \"2048\", \"4096\", \"8192\", \"16384\",\n      \"32768\"})\n  int byteStringSize;\n\n  @Setup\n  public void setup() {\n    buffer = new Buffer().write(new byte[bufferSize]);\n  }\n\n  @Benchmark\n  public void readByteString() throws IOException {\n    buffer.write(buffer.readByteString(byteStringSize));\n  }\n\n  @Benchmark\n  public void readByteString_toByteArray() throws IOException {\n    buffer.write(buffer.readByteString(byteStringSize).toByteArray());\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[]{\n        ReadByteStringBenchmark.class.getName()\n    });\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/SegmentedByteStringBenchmark.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport okio.ByteString;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.Throughput)\n@OutputTimeUnit(TimeUnit.SECONDS)\npublic class SegmentedByteStringBenchmark {\n\n  private static final ByteString UNKNOWN = ByteString.encodeUtf8(\"UNKNOWN\");\n  private static final ByteString SEARCH = ByteString.encodeUtf8(\"tell\");\n\n  @Param({\"20\", \"2000\", \"200000\"})\n  int length;\n\n  private ByteString byteString;\n\n  @Setup\n  public void setup() {\n    String part =\n        \"Um, I'll tell you the problem with the scientific power that you're using here, \"\n            + \"it didn't require any discipline to attain it. You read what others had done and you \"\n            + \"took the next step. You didn't earn the knowledge for yourselves, so you don't take any \"\n            + \"responsibility for it. You stood on the shoulders of geniuses to accomplish something \"\n            + \"as fast as you could, and before you even knew what you had, you patented it, and \"\n            + \"packaged it, and slapped it on a plastic lunchbox, and now you're selling it, you wanna \"\n            + \"sell it.\";\n\n    Buffer buffer = new Buffer();\n    while (buffer.size() < length) {\n      buffer.writeUtf8(part);\n    }\n    byteString = buffer.snapshot(length);\n  }\n\n  @Benchmark\n  public ByteString substring() {\n    return byteString.substring(1, byteString.size() - 1);\n  }\n\n  @Benchmark\n  public ByteString md5() {\n    return byteString.md5();\n  }\n\n  @Benchmark\n  public int indexOfUnknown() {\n    return byteString.indexOf(UNKNOWN);\n  }\n\n  @Benchmark\n  public int lastIndexOfUnknown() {\n    return byteString.lastIndexOf(UNKNOWN);\n  }\n\n  @Benchmark\n  public int indexOfEarly() {\n    return byteString.indexOf(SEARCH);\n  }\n\n  @Benchmark\n  public int lastIndexOfEarly() {\n    return byteString.lastIndexOf(SEARCH);\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[] {SegmentedByteStringBenchmark.class.getName()});\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/SelectBenchmark.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Random;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport okio.ByteString;\nimport okio.Options;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.SampleTime)\n@OutputTimeUnit(TimeUnit.MICROSECONDS)\npublic class SelectBenchmark {\n  /** Representative sample field names as one might find in a JSON document. */\n  List<String> sampleValues = Arrays.asList(\"id\", \"name\", \"description\", \"type\", \"sku_ids\",\n      \"offers\", \"start_time\", \"end_time\", \"expires\", \"start_of_availability\", \"duration\",\n      \"allow_recording\", \"thumbnail_id\", \"thumbnail_formats\", \"is_episode\", \"is_live\", \"channel_id\",\n      \"genre_list\", \"provider_networks\", \"year\", \"video_flags\", \"is_repeat\", \"series_id\",\n      \"series_name\", \"series_description\", \"original_air_date\", \"letter_box\", \"category\",\n      \"child_protection_rating\", \"parental_control_minimum_age\", \"images\", \"episode_id\",\n      \"season_number\", \"episode_number\", \"directors_list\", \"scriptwriters_list\", \"actors_list\",\n      \"drm_rights\", \"is_location_chk_reqd\", \"is_catchup_enabled\", \"catchup_duration\",\n      \"is_timeshift_enabled\", \"timeshift_duration\", \"is_startover_enabled\", \"is_recording_enabled\",\n      \"suspension_time\", \"shared_ref_id\", \"linked_channel_number\", \"audio_lang\", \"subcategory\",\n      \"metadata_root_id\", \"ref_id\", \"ref_type\", \"display_position\", \"thumbnail_format_list\",\n      \"network\", \"external_url\", \"offer_type\", \"em_format\", \"em_artist_name\", \"assets\",\n      \"media_class\", \"media_id\", \"channel_number\");\n\n  @Param({ \"4\", \"8\", \"16\", \"32\", \"64\" })\n  int optionCount;\n\n  @Param({ \"2048\" })\n  int selectCount;\n\n  Buffer buffer = new Buffer();\n  Options options;\n  ByteString sampleData;\n\n  @Setup\n  public void setup() throws IOException {\n    ByteString[] byteStrings = new ByteString[optionCount];\n    for (int i = 0; i < optionCount; i++) {\n      byteStrings[i] = ByteString.encodeUtf8(sampleValues.get(i) + \"\\\"\");\n    }\n    options = Options.of(byteStrings);\n\n    Random dice = new Random(0);\n    Buffer sampleDataBuffer = new Buffer();\n    for (int i = 0; i < selectCount; i++) {\n      sampleDataBuffer.write(byteStrings[dice.nextInt(optionCount)]);\n    }\n    sampleData = sampleDataBuffer.readByteString();\n  }\n\n  @Benchmark\n  public void select() throws IOException {\n    buffer.write(sampleData);\n    for (int i = 0; i < selectCount; i++) {\n      buffer.select(options);\n    }\n    if (!buffer.exhausted()) throw new AssertionError();\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[] {\n        SelectBenchmark.class.getName()\n    });\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/Utf8Benchmark.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.Throughput)\n@OutputTimeUnit(TimeUnit.SECONDS)\npublic class Utf8Benchmark {\n  private static final Charset utf8 = StandardCharsets.UTF_8;\n  private static final Map<String, String> strings = new HashMap<>();\n\n  static {\n    strings.put(\n        \"ascii\",\n        \"Um, I'll tell you the problem with the scientific power that you're using here, \"\n            + \"it didn't require any discipline to attain it. You read what others had done and you \"\n            + \"took the next step. You didn't earn the knowledge for yourselves, so you don't take any \"\n            + \"responsibility for it. You stood on the shoulders of geniuses to accomplish something \"\n            + \"as fast as you could, and before you even knew what you had, you patented it, and \"\n            + \"packaged it, and slapped it on a plastic lunchbox, and now you're selling it, you wanna \"\n            + \"sell it.\");\n\n    strings.put(\n        \"utf8\",\n        \"Սｍ, I'll 𝓽𝖾ll ᶌօ𝘂 ᴛℎ℮ 𝜚𝕣०ｂl𝖾ｍ ｗі𝕥𝒽 𝘵𝘩𝐞 𝓼𝙘𝐢𝔢𝓷𝗍𝜄𝚏𝑖ｃ 𝛠𝝾ｗ𝚎𝑟 𝕥ｈ⍺𝞃 𝛄𝓸𝘂'𝒓𝗲 υ𝖘𝓲𝗇ɡ 𝕙𝚎𝑟ｅ, \"\n            + \"𝛊𝓽 ⅆ𝕚𝐝𝝿'𝗍 𝔯𝙚𝙦ᴜ𝜾𝒓𝘦 𝔞𝘯𝐲 ԁ𝜄𝑠𝚌ι𝘱lι𝒏ｅ 𝑡𝜎 𝕒𝚝𝖙𝓪і𝞹 𝔦𝚝. 𝒀ο𝗎 𝔯𝑒⍺𝖉 ｗ𝐡𝝰𝔱 𝞂𝞽һ𝓮𝓇ƽ հ𝖺𝖉 ⅾ𝛐𝝅ⅇ 𝝰πԁ 𝔂ᴑᴜ 𝓉ﮨ၀𝚔 \"\n            + \"т𝒽𝑒 𝗇𝕖ⅹ𝚝 𝔰𝒕е𝓅. 𝘠ⲟ𝖚 𝖉ⅰԁ𝝕'τ 𝙚𝚊ｒ𝞹 𝘵Ꮒ𝖾 𝝒𝐧هｗl𝑒𝖉ƍ𝙚 𝓯૦ｒ 𝔂𝞼𝒖𝕣𝑠𝕖l𝙫𝖊𝓼, 𐑈о ｙ𝘰𝒖 ⅆە𝗇'ｔ 𝜏α𝒌𝕖 𝛂𝟉ℽ \"\n            + \"𝐫ⅇ𝗌ⲣ๐ϖ𝖘ꙇᖯ𝓲l𝓲𝒕𝘆 𝐟𝞼𝘳 𝚤𝑡. 𝛶𝛔𝔲 ｓ𝕥σσ𝐝 ﮩ𝕟 𝒕𝗁𝔢 𝘴𝐡𝜎ᴜlⅾ𝓮𝔯𝚜 𝛐𝙛 ᶃ𝚎ᴨᎥս𝚜𝘦𝓈 𝓽𝞸 ａ𝒄𝚌𝞸ｍρl𝛊ꜱ𝐡 𝓈𝚘ｍ𝚎𝞃𝔥⍳𝞹𝔤 𝐚𝗌 𝖋ａ𝐬𝒕 \"\n            + \"αｓ γ𝛐𝕦 𝔠ﻫ𝛖lԁ, 𝚊π𝑑 Ь𝑒𝙛૦𝓇𝘦 𝓎٥𝖚 ⅇｖℯ𝝅 𝜅ո𝒆ｗ ｗ𝗵𝒂𝘁 ᶌ੦𝗎 ｈ𝐚𝗱, 𝜸ﮨ𝒖 𝓹𝝰𝔱𝖾𝗇𝓽𝔢ⅆ і𝕥, 𝚊𝜛𝓭 𝓹𝖺ⅽϰ𝘢ℊеᏧ 𝑖𝞃, \"\n            + \"𝐚𝛑ꓒ 𝙨l𝔞р𝘱𝔢𝓭 ɩ𝗍 ہ𝛑 𝕒 ｐl𝛂ѕᴛ𝗂𝐜 l𝞄ℼ𝔠𝒽𝑏ﮪ⨯, 𝔞ϖ𝒹 ｎ𝛔ｗ 𝛾𝐨𝞄'𝗿𝔢 ꜱ℮ll𝙞ｎɡ ɩ𝘁, 𝙮𝕠𝛖 ｗ𝑎ℼ𝚗𝛂 𝕤𝓮ll 𝙞𝓉.\");\n\n    // The first 't' is actually a '𝓽'\n    strings.put(\n        \"sparse\",\n        \"Um, I'll 𝓽ell you the problem with the scientific power that you're using here, \"\n            + \"it didn't require any discipline to attain it. You read what others had done and you \"\n            + \"took the next step. You didn't earn the knowledge for yourselves, so you don't take any \"\n            + \"responsibility for it. You stood on the shoulders of geniuses to accomplish something \"\n            + \"as fast as you could, and before you even knew what you had, you patented it, and \"\n            + \"packaged it, and slapped it on a plastic lunchbox, and now you're selling it, you wanna \"\n            + \"sell it.\");\n\n    strings.put(\"2bytes\", \"\\u0080\\u07ff\");\n\n    strings.put(\"3bytes\", \"\\u0800\\ud7ff\\ue000\\uffff\");\n\n    strings.put(\"4bytes\", \"\\ud835\\udeca\");\n\n    // high surrogate, 'a', low surrogate, and 'a'\n    strings.put(\"bad\", \"\\ud800\\u0061\\udc00\\u0061\");\n  }\n\n  @Param({\"20\", \"2000\", \"200000\"})\n  int length;\n\n  @Param({\"ascii\", \"utf8\", \"sparse\", \"2bytes\", \"3bytes\", \"4bytes\", \"bad\"})\n  String encoding;\n\n  String encode;\n  byte[] decodeArray;\n\n  @Setup\n  public void setup() {\n    String part = strings.get(encoding);\n\n    // Make all the strings the same length for comparison\n    StringBuilder builder = new StringBuilder(length + 1_000);\n    while (builder.length() < length) {\n      builder.append(part);\n    }\n    builder.setLength(length);\n\n    // Prepare a string and byte array for encoding and decoding\n    encode = builder.toString();\n    decodeArray = encode.getBytes(utf8);\n  }\n\n  @Benchmark\n  public byte[] stringToBytesOkio() {\n    return BenchmarkUtils.encodeUtf8(encode);\n  }\n\n  @Benchmark\n  public byte[] stringToBytesJava() {\n    return encode.getBytes(utf8);\n  }\n\n  @Benchmark\n  public String bytesToStringOkio() {\n    // For ASCII only decoding, this will never be faster than Java. Because\n    // Java can trust the decoded char array and it will be the correct size for\n    // ASCII, it is able to avoid the extra defensive copy Okio is forced to\n    // make because it doesn't have access to String internals.\n    return BenchmarkUtils.decodeUtf8(decodeArray);\n  }\n\n  @Benchmark\n  public String bytesToStringJava() {\n    return new String(decodeArray, utf8);\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[] {Utf8Benchmark.class.getName()});\n  }\n}\n"
  },
  {
    "path": "okio/jvm/jmh/src/jmh/java/com/squareup/okio/benchmarks/WriteHexadecimalBenchmark.java",
    "content": "/*\n * Copyright (C) 2019 Square, Inc. and others.\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 */\npackage com.squareup.okio.benchmarks;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport org.openjdk.jmh.Main;\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Fork;\nimport org.openjdk.jmh.annotations.Level;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.TearDown;\nimport org.openjdk.jmh.annotations.Warmup;\nimport org.openjdk.jmh.runner.RunnerException;\n\n@Fork(1)\n@Warmup(iterations = 5, time = 2)\n@Measurement(iterations = 5, time = 2)\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.Throughput)\n@OutputTimeUnit(TimeUnit.MICROSECONDS)\npublic class WriteHexadecimalBenchmark {\n\n  Buffer buffer;\n\n  @Param({\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\"})\n  int width;\n\n  @Setup\n  public void setup() {\n    buffer = new Buffer();\n  }\n\n  @TearDown(Level.Invocation)\n  public void teardown() {\n    buffer.clear();\n  }\n\n  @Benchmark\n  public void writeHex() {\n    buffer.writeHexadecimalUnsignedLong(1L << width);\n  }\n\n  public static void main(String[] args) throws IOException, RunnerException {\n    Main.main(new String[]{\n        WriteHexadecimalBenchmark.class.getName()\n    });\n  }\n}\n"
  },
  {
    "path": "okio/src/appleMain/kotlin/okio/ByteString.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.experimental.ExperimentalNativeApi\nimport kotlinx.cinterop.UnsafeNumber\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.usePinned\nimport okio.internal.HashFunction\nimport okio.internal.Hmac\nimport okio.internal.Md5\nimport okio.internal.Sha1\nimport okio.internal.Sha256\nimport okio.internal.Sha512\nimport okio.internal.commonBase64\nimport okio.internal.commonBase64Url\nimport okio.internal.commonCompareTo\nimport okio.internal.commonCopyInto\nimport okio.internal.commonDecodeBase64\nimport okio.internal.commonDecodeHex\nimport okio.internal.commonEncodeUtf8\nimport okio.internal.commonEndsWith\nimport okio.internal.commonEquals\nimport okio.internal.commonGetByte\nimport okio.internal.commonGetSize\nimport okio.internal.commonHashCode\nimport okio.internal.commonHex\nimport okio.internal.commonIndexOf\nimport okio.internal.commonInternalArray\nimport okio.internal.commonLastIndexOf\nimport okio.internal.commonOf\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonStartsWith\nimport okio.internal.commonSubstring\nimport okio.internal.commonToAsciiLowercase\nimport okio.internal.commonToAsciiUppercase\nimport okio.internal.commonToByteArray\nimport okio.internal.commonToByteString\nimport okio.internal.commonToString\nimport okio.internal.commonUtf8\nimport okio.internal.commonWrite\nimport platform.Foundation.NSData\nimport platform.posix.memcpy\n\nactual open class ByteString\ninternal actual constructor(\n  internal actual val data: ByteArray,\n) : Comparable<ByteString> {\n  @Suppress(\"SetterBackingFieldAssignment\")\n  internal actual var hashCode: Int = 0 // 0 if unknown.\n    set(value) {\n      // Do nothing to avoid IllegalImmutabilityException.\n    }\n\n  @Suppress(\"SetterBackingFieldAssignment\")\n  internal actual var utf8: String? = null\n    set(value) {\n      // Do nothing to avoid IllegalImmutabilityException.\n    }\n\n  actual open fun utf8(): String = commonUtf8()\n\n  actual open fun base64(): String = commonBase64()\n\n  actual open fun base64Url(): String = commonBase64Url()\n\n  actual open fun hex(): String = commonHex()\n\n  actual fun md5() = digest(Md5())\n\n  actual fun sha1() = digest(Sha1())\n\n  actual fun sha256() = digest(Sha256())\n\n  actual fun sha512() = digest(Sha512())\n\n  /** Returns the 160-bit SHA-1 HMAC of this byte string.  */\n  actual fun hmacSha1(key: ByteString) = digest(Hmac.sha1(key))\n\n  /** Returns the 256-bit SHA-256 HMAC of this byte string.  */\n  actual fun hmacSha256(key: ByteString) = digest(Hmac.sha256(key))\n\n  /** Returns the 512-bit SHA-512 HMAC of this byte string.  */\n  actual fun hmacSha512(key: ByteString) = digest(Hmac.sha512(key))\n\n  internal open fun digest(hashFunction: HashFunction): ByteString {\n    hashFunction.update(data, 0, size)\n    val digestBytes = hashFunction.digest()\n    return ByteString(digestBytes)\n  }\n\n  actual open fun toAsciiLowercase(): ByteString = commonToAsciiLowercase()\n\n  actual open fun toAsciiUppercase(): ByteString = commonToAsciiUppercase()\n\n  actual open fun substring(beginIndex: Int, endIndex: Int): ByteString =\n    commonSubstring(beginIndex, endIndex)\n\n  internal actual open fun internalGet(pos: Int): Byte {\n    if (pos >= size || pos < 0) throw ArrayIndexOutOfBoundsException(\"size=$size pos=$pos\")\n    return commonGetByte(pos)\n  }\n\n  actual operator fun get(index: Int): Byte = internalGet(index)\n\n  actual val size\n    get() = getSize()\n\n  internal actual open fun getSize() = commonGetSize()\n\n  actual open fun toByteArray() = commonToByteArray()\n\n  internal actual open fun internalArray() = commonInternalArray()\n\n  internal actual open fun write(buffer: Buffer, offset: Int, byteCount: Int) =\n    commonWrite(buffer, offset, byteCount)\n\n  actual open fun rangeEquals(\n    offset: Int,\n    other: ByteString,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  actual open fun rangeEquals(\n    offset: Int,\n    other: ByteArray,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  actual open fun copyInto(\n    offset: Int,\n    target: ByteArray,\n    targetOffset: Int,\n    byteCount: Int,\n  ) = commonCopyInto(offset, target, targetOffset, byteCount)\n\n  actual fun startsWith(prefix: ByteString) = commonStartsWith(prefix)\n\n  actual fun startsWith(prefix: ByteArray) = commonStartsWith(prefix)\n\n  actual fun endsWith(suffix: ByteString) = commonEndsWith(suffix)\n\n  actual fun endsWith(suffix: ByteArray) = commonEndsWith(suffix)\n\n  actual fun indexOf(other: ByteString, fromIndex: Int) = indexOf(other.internalArray(), fromIndex)\n\n  actual open fun indexOf(other: ByteArray, fromIndex: Int) = commonIndexOf(other, fromIndex)\n\n  actual fun lastIndexOf(other: ByteString, fromIndex: Int) = commonLastIndexOf(other, fromIndex)\n\n  actual open fun lastIndexOf(other: ByteArray, fromIndex: Int) = commonLastIndexOf(other, fromIndex)\n\n  actual override fun equals(other: Any?) = commonEquals(other)\n\n  actual override fun hashCode() = commonHashCode()\n\n  actual override fun compareTo(other: ByteString) = commonCompareTo(other)\n\n  /**\n   * Returns a human-readable string that describes the contents of this byte string. Typically this\n   * is a string like `[text=Hello]` or `[hex=0000ffff]`.\n   */\n  actual override fun toString() = commonToString()\n\n  actual companion object {\n    actual val EMPTY: ByteString = ByteString(byteArrayOf())\n\n    actual fun of(vararg data: Byte) = commonOf(data)\n\n    actual fun ByteArray.toByteString(offset: Int, byteCount: Int): ByteString =\n      commonToByteString(offset, byteCount)\n\n    actual fun String.encodeUtf8(): ByteString = commonEncodeUtf8()\n\n    actual fun String.decodeBase64(): ByteString? = commonDecodeBase64()\n\n    actual fun String.decodeHex() = commonDecodeHex()\n\n    @OptIn(UnsafeNumber::class, ExperimentalNativeApi::class)\n    @CName(\"of\")\n    fun NSData.toByteString(): ByteString {\n      val data = this\n      val size = data.length.toInt()\n      return if (size != 0) {\n        ByteString(\n          ByteArray(size).apply {\n            usePinned { pinned ->\n              memcpy(pinned.addressOf(0), data.bytes, data.length)\n            }\n          },\n        )\n      } else {\n        EMPTY\n      }\n    }\n  }\n}\n\n@Deprecated(\n  message = \"Moved to ByteString companion object\",\n  replaceWith = ReplaceWith(\"this.toByteString()\", \"okio.ByteString.Companion.toByteString\"),\n)\nfun NSData.toByteString(): ByteString {\n  with(ByteString) {\n    return toByteString()\n  }\n}\n"
  },
  {
    "path": "okio/src/appleMain/kotlin/okio/SegmentedByteString.kt",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\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 */\npackage okio\n\nimport okio.internal.HashFunction\nimport okio.internal.commonCopyInto\nimport okio.internal.commonEquals\nimport okio.internal.commonGetSize\nimport okio.internal.commonHashCode\nimport okio.internal.commonInternalGet\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonSubstring\nimport okio.internal.commonToByteArray\nimport okio.internal.commonWrite\nimport okio.internal.forEachSegment\n\ninternal actual class SegmentedByteString internal actual constructor(\n  internal actual val segments: Array<ByteArray>,\n  internal actual val directory: IntArray,\n) : ByteString(EMPTY.data) {\n\n  override fun base64() = toByteString().base64()\n\n  override fun hex() = toByteString().hex()\n\n  override fun toAsciiLowercase() = toByteString().toAsciiLowercase()\n\n  override fun toAsciiUppercase() = toByteString().toAsciiUppercase()\n\n  override fun base64Url() = toByteString().base64Url()\n\n  override fun substring(beginIndex: Int, endIndex: Int): ByteString =\n    commonSubstring(beginIndex, endIndex)\n\n  override fun internalGet(pos: Int): Byte = commonInternalGet(pos)\n\n  override fun getSize() = commonGetSize()\n\n  override fun toByteArray(): ByteArray = commonToByteArray()\n\n  override fun write(buffer: Buffer, offset: Int, byteCount: Int): Unit =\n    commonWrite(buffer, offset, byteCount)\n\n  override fun rangeEquals(\n    offset: Int,\n    other: ByteString,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  override fun rangeEquals(\n    offset: Int,\n    other: ByteArray,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  override fun copyInto(\n    offset: Int,\n    target: ByteArray,\n    targetOffset: Int,\n    byteCount: Int,\n  ) = commonCopyInto(offset, target, targetOffset, byteCount)\n\n  override fun indexOf(other: ByteArray, fromIndex: Int) = toByteString().indexOf(other, fromIndex)\n\n  override fun lastIndexOf(other: ByteArray, fromIndex: Int) = toByteString().lastIndexOf(\n    other,\n    fromIndex,\n  )\n\n  override fun digest(hashFunction: HashFunction): ByteString {\n    forEachSegment { data, offset, byteCount ->\n      hashFunction.update(data, offset, byteCount)\n    }\n    val digestBytes = hashFunction.digest()\n    return ByteString(digestBytes)\n  }\n\n  /** Returns a copy as a non-segmented byte string.  */\n  private fun toByteString() = ByteString(toByteArray())\n\n  override fun internalArray() = toByteArray()\n\n  override fun equals(other: Any?): Boolean = commonEquals(other)\n\n  override fun hashCode(): Int = commonHashCode()\n\n  override fun toString() = toByteString().toString()\n}\n"
  },
  {
    "path": "okio/src/appleNonMacosX64Main/kotlin/okio/NonMacosX64PosixVariant.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.ptr\nimport platform.posix.ENOENT\nimport platform.posix.S_IFDIR\nimport platform.posix.S_IFMT\nimport platform.posix.S_IFREG\nimport platform.posix.errno\nimport platform.posix.lstat\nimport platform.posix.stat\n\ninternal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? {\n  return memScoped {\n    val stat = alloc<stat>()\n    if (lstat(path.toString(), stat.ptr) != 0) {\n      if (errno == ENOENT) return null\n      throw errnoToIOException(errno)\n    }\n    return@memScoped FileMetadata(\n      isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG,\n      isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR,\n      symlinkTarget = symlinkTarget(stat.st_mode.toInt(), path),\n      size = stat.st_size,\n      createdAtMillis = stat.st_birthtimespec.epochMillis,\n      lastModifiedAtMillis = stat.st_mtimespec.epochMillis,\n      lastAccessedAtMillis = stat.st_atimespec.epochMillis,\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/appleTest/kotlin/okio/AppleByteStringTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport platform.Foundation.NSData\nimport platform.Foundation.NSString\nimport platform.Foundation.NSUTF8StringEncoding\nimport platform.Foundation.dataUsingEncoding\n\nclass AppleByteStringTest {\n  @Test fun nsDataToByteString() {\n    val data = (\"Hello\" as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData\n\n    @Suppress(\"DEPRECATION\") // Ensure deprecated function continues to work.\n    val byteStringDeprecated = data.toByteString()\n    assertEquals(\"Hello\", byteStringDeprecated.utf8())\n\n    val byteString = with(ByteString) { data.toByteString() }\n    assertEquals(\"Hello\", byteString.utf8())\n  }\n\n  @Test fun emptyNsDataToByteString() {\n    val data = (\"\" as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData\n\n    @Suppress(\"DEPRECATION\") // Ensure deprecated function continues to work.\n    val byteStringDeprecated = data.toByteString()\n    assertEquals(ByteString.EMPTY, byteStringDeprecated)\n\n    val byteString = with(ByteString) { data.toByteString() }\n    assertEquals(ByteString.EMPTY, byteString)\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Base64.kt",
    "content": "/*\n *  Licensed to the Apache Software Foundation (ASF) under one or more\n *  contributor license agreements.  See the NOTICE file distributed with\n *  this work for additional information regarding copyright ownership.\n *  The ASF licenses this file to You under the Apache License, Version 2.0\n *  (the \"License\"); you may not use this file except in compliance with\n *  the License.  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 */\n@file:JvmName(\"-Base64\") // A leading '-' hides this class from Java.\n\npackage okio\n\nimport kotlin.jvm.JvmName\nimport okio.ByteString.Companion.encodeUtf8\n\n/** @author Alexander Y. Kleymenov */\n\ninternal val BASE64 =\n  \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\".encodeUtf8().data\n\ninternal val BASE64_URL_SAFE =\n  \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\".encodeUtf8().data\n\ninternal fun String.decodeBase64ToArray(): ByteArray? {\n  // Ignore trailing '=' padding and whitespace from the input.\n  var limit = length\n  while (limit > 0) {\n    val c = this[limit - 1]\n    if (c != '=' && c != '\\n' && c != '\\r' && c != ' ' && c != '\\t') {\n      break\n    }\n    limit--\n  }\n\n  // If the input includes whitespace, this output array will be longer than necessary.\n  val out = ByteArray((limit * 6L / 8L).toInt())\n  var outCount = 0\n  var inCount = 0\n\n  var word = 0\n  for (pos in 0 until limit) {\n    val c = this[pos]\n\n    val bits: Int\n    if (c in 'A'..'Z') {\n      // char ASCII value\n      //  A    65    0\n      //  Z    90    25 (ASCII - 65)\n      bits = c.code - 65\n    } else if (c in 'a'..'z') {\n      // char ASCII value\n      //  a    97    26\n      //  z    122   51 (ASCII - 71)\n      bits = c.code - 71\n    } else if (c in '0'..'9') {\n      // char ASCII value\n      //  0    48    52\n      //  9    57    61 (ASCII + 4)\n      bits = c.code + 4\n    } else if (c == '+' || c == '-') {\n      bits = 62\n    } else if (c == '/' || c == '_') {\n      bits = 63\n    } else if (c == '\\n' || c == '\\r' || c == ' ' || c == '\\t') {\n      continue\n    } else {\n      return null\n    }\n\n    // Append this char's 6 bits to the word.\n    word = word shl 6 or bits\n\n    // For every 4 chars of input, we accumulate 24 bits of output. Emit 3 bytes.\n    inCount++\n    if (inCount % 4 == 0) {\n      out[outCount++] = (word shr 16).toByte()\n      out[outCount++] = (word shr 8).toByte()\n      out[outCount++] = word.toByte()\n    }\n  }\n\n  val lastWordChars = inCount % 4\n  when (lastWordChars) {\n    1 -> {\n      // We read 1 char followed by \"===\". But 6 bits is a truncated byte! Fail.\n      return null\n    }\n    2 -> {\n      // We read 2 chars followed by \"==\". Emit 1 byte with 8 of those 12 bits.\n      word = word shl 12\n      out[outCount++] = (word shr 16).toByte()\n    }\n    3 -> {\n      // We read 3 chars, followed by \"=\". Emit 2 bytes for 16 of those 18 bits.\n      word = word shl 6\n      out[outCount++] = (word shr 16).toByte()\n      out[outCount++] = (word shr 8).toByte()\n    }\n  }\n\n  // If we sized our out array perfectly, we're done.\n  if (outCount == out.size) return out\n\n  // Copy the decoded bytes to a new, right-sized array.\n  return out.copyOf(outCount)\n}\n\ninternal fun ByteArray.encodeBase64(map: ByteArray = BASE64): String {\n  val length = (size + 2) / 3 * 4\n  val out = ByteArray(length)\n  var index = 0\n  val end = size - size % 3\n  var i = 0\n  while (i < end) {\n    val b0 = this[i++].toInt()\n    val b1 = this[i++].toInt()\n    val b2 = this[i++].toInt()\n    out[index++] = map[(b0 and 0xff shr 2)]\n    out[index++] = map[(b0 and 0x03 shl 4) or (b1 and 0xff shr 4)]\n    out[index++] = map[(b1 and 0x0f shl 2) or (b2 and 0xff shr 6)]\n    out[index++] = map[(b2 and 0x3f)]\n  }\n  when (size - end) {\n    1 -> {\n      val b0 = this[i].toInt()\n      out[index++] = map[b0 and 0xff shr 2]\n      out[index++] = map[b0 and 0x03 shl 4]\n      out[index++] = '='.code.toByte()\n      out[index] = '='.code.toByte()\n    }\n    2 -> {\n      val b0 = this[i++].toInt()\n      val b1 = this[i].toInt()\n      out[index++] = map[(b0 and 0xff shr 2)]\n      out[index++] = map[(b0 and 0x03 shl 4) or (b1 and 0xff shr 4)]\n      out[index++] = map[(b1 and 0x0f shl 2)]\n      out[index] = '='.code.toByte()\n    }\n  }\n  return out.toUtf8String()\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Buffer.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\n/**\n * A collection of bytes in memory.\n *\n * **Moving data from one buffer to another is fast.** Instead of copying bytes from one place in\n * memory to another, this class just changes ownership of the underlying byte arrays.\n *\n * **This buffer grows with your data.** Just like ArrayList, each buffer starts small. It consumes\n * only the memory it needs to.\n *\n * **This buffer pools its byte arrays.** When you allocate a byte array in Java, the runtime must\n * zero-fill the requested array before returning it to you. Even if you're going to write over that\n * space anyway. This class avoids zero-fill and GC churn by pooling byte arrays.\n */\nexpect class Buffer() : BufferedSource, BufferedSink {\n  internal var head: Segment?\n\n  var size: Long\n    internal set\n\n  /** Copy `byteCount` bytes from this, starting at `offset`, to `out`.  */\n  fun copyTo(\n    out: Buffer,\n    offset: Long = 0L,\n    byteCount: Long,\n  ): Buffer\n\n  /**\n   * Overload of [copyTo] with byteCount = size - offset, work around for\n   *  https://youtrack.jetbrains.com/issue/KT-30847\n   */\n  fun copyTo(\n    out: Buffer,\n    offset: Long = 0L,\n  ): Buffer\n\n  /**\n   * Returns the number of bytes in segments that are not writable. This is the number of bytes that\n   * can be flushed immediately to an underlying sink without harming throughput.\n   */\n  fun completeSegmentByteCount(): Long\n\n  /** Returns the byte at `pos`. */\n  operator fun get(pos: Long): Byte\n\n  /**\n   * Discards all bytes in this buffer. Calling this method when you're done with a buffer will\n   * return its segments to the pool.\n   */\n  fun clear()\n\n  /** Discards `byteCount` bytes from the head of this buffer.  */\n  override fun skip(byteCount: Long)\n\n  /**\n   * Returns a tail segment that we can write at least `minimumCapacity`\n   * bytes to, creating it if necessary.\n   */\n  internal fun writableSegment(minimumCapacity: Int): Segment\n\n  fun md5(): ByteString\n\n  fun sha1(): ByteString\n\n  fun sha256(): ByteString\n\n  fun sha512(): ByteString\n\n  /** Returns the 160-bit SHA-1 HMAC of this buffer.  */\n  fun hmacSha1(key: ByteString): ByteString\n\n  /** Returns the 256-bit SHA-256 HMAC of this buffer.  */\n  fun hmacSha256(key: ByteString): ByteString\n\n  /** Returns the 512-bit SHA-512 HMAC of this buffer.  */\n  fun hmacSha512(key: ByteString): ByteString\n\n  /**\n   * Returns a deep copy of this buffer. The returned [Buffer] initially shares the underlying\n   * [ByteArray]s. See [UnsafeCursor] for more details.\n   */\n  fun copy(): Buffer\n\n  /** Returns an immutable copy of this buffer as a byte string.  */\n  fun snapshot(): ByteString\n\n  /** Returns an immutable copy of the first `byteCount` bytes of this buffer as a byte string. */\n  fun snapshot(byteCount: Int): ByteString\n\n  fun readUnsafe(unsafeCursor: UnsafeCursor = UnsafeCursor()): UnsafeCursor\n\n  fun readAndWriteUnsafe(unsafeCursor: UnsafeCursor = UnsafeCursor()): UnsafeCursor\n\n  override val buffer: Buffer\n  override fun close()\n  override fun emit(): Buffer\n  override fun emitCompleteSegments(): Buffer\n  override fun exhausted(): Boolean\n  override fun flush()\n  override fun indexOf(b: Byte): Long\n  override fun indexOf(b: Byte, fromIndex: Long): Long\n  override fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long\n  override fun indexOf(bytes: ByteString): Long\n  override fun indexOf(bytes: ByteString, fromIndex: Long): Long\n  override fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long\n  override fun indexOfElement(targetBytes: ByteString): Long\n  override fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long\n  override fun peek(): BufferedSource\n  override fun rangeEquals(offset: Long, bytes: ByteString): Boolean\n  override fun rangeEquals(offset: Long, bytes: ByteString, bytesOffset: Int, byteCount: Int): Boolean\n  override fun read(sink: Buffer, byteCount: Long): Long\n  override fun read(sink: ByteArray): Int\n  override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int\n  override fun readAll(sink: Sink): Long\n  override fun readByte(): Byte\n  override fun readByteArray(): ByteArray\n  override fun readByteArray(byteCount: Long): ByteArray\n  override fun readByteString(): ByteString\n  override fun readByteString(byteCount: Long): ByteString\n  override fun readDecimalLong(): Long\n  override fun readFully(sink: Buffer, byteCount: Long)\n  override fun readFully(sink: ByteArray)\n  override fun readHexadecimalUnsignedLong(): Long\n  override fun readInt(): Int\n  override fun readIntLe(): Int\n  override fun readLong(): Long\n  override fun readLongLe(): Long\n  override fun readShort(): Short\n  override fun readShortLe(): Short\n  override fun readUtf8(): String\n  override fun readUtf8(byteCount: Long): String\n  override fun readUtf8CodePoint(): Int\n  override fun readUtf8Line(): String?\n  override fun readUtf8LineStrict(): String\n  override fun readUtf8LineStrict(limit: Long): String\n  override fun request(byteCount: Long): Boolean\n  override fun require(byteCount: Long)\n  override fun select(options: Options): Int\n  override fun <T : Any> select(options: TypedOptions<T>): T?\n  override fun timeout(): Timeout\n  override fun write(byteString: ByteString): Buffer\n  override fun write(byteString: ByteString, offset: Int, byteCount: Int): Buffer\n  override fun write(source: Buffer, byteCount: Long)\n  override fun write(source: ByteArray): Buffer\n  override fun write(source: ByteArray, offset: Int, byteCount: Int): Buffer\n  override fun write(source: Source, byteCount: Long): Buffer\n  override fun writeAll(source: Source): Long\n  override fun writeByte(b: Int): Buffer\n  override fun writeDecimalLong(v: Long): Buffer\n  override fun writeHexadecimalUnsignedLong(v: Long): Buffer\n  override fun writeInt(i: Int): Buffer\n  override fun writeIntLe(i: Int): Buffer\n  override fun writeLong(v: Long): Buffer\n  override fun writeLongLe(v: Long): Buffer\n  override fun writeShort(s: Int): Buffer\n  override fun writeShortLe(s: Int): Buffer\n  override fun writeUtf8(string: String): Buffer\n  override fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): Buffer\n  override fun writeUtf8CodePoint(codePoint: Int): Buffer\n\n  /**\n   * A handle to the underlying data in a buffer. This handle is unsafe because it does not enforce\n   * its own invariants. Instead, it assumes a careful user who has studied Okio's implementation\n   * details and their consequences.\n   *\n   * Buffer Internals\n   * ----------------\n   *\n   * Most code should use `Buffer` as a black box: a class that holds 0 or more bytes of\n   * data with efficient APIs to append data to the end and to consume data from the front. Usually\n   * this is also the most efficient way to use buffers because it allows Okio to employ several\n   * optimizations, including:\n   *\n   *  * **Fast Allocation:** Buffers use a shared pool of memory that is not zero-filled before use.\n   *  * **Fast Resize:** A buffer's capacity can change without copying its contents.\n   *  * **Fast Move:** Memory ownership can be reassigned from one buffer to another.\n   *  * **Fast Copy:** Multiple buffers can share the same underlying memory.\n   *  * **Fast Encoding and Decoding:** Common operations like UTF-8 encoding and decimal decoding\n   *    do not require intermediate objects to be allocated.\n   *\n   * These optimizations all leverage the way Okio stores data internally. Okio Buffers are\n   * implemented using a doubly-linked list of segments. Each segment is a contiguous range within a\n   * 8 KiB `ByteArray`. Each segment has two indexes, `start`, the offset of the first byte of the\n   * array containing application data, and `end`, the offset of the first byte beyond `start` whose\n   * data is undefined.\n   *\n   * New buffers are empty and have no segments:\n   *\n   * ```kotlin\n   *   val buffer = Buffer()\n   * ```\n   *\n   * We append 7 bytes of data to the end of our empty buffer. Internally, the buffer allocates a\n   * segment and writes its new data there. The lone segment has an 8 KiB byte array but only 7\n   * bytes of data:\n   *\n   * ```kotlin\n   * buffer.writeUtf8(\"sealion\")\n   *\n   * // [ 's', 'e', 'a', 'l', 'i', 'o', 'n', '?', '?', '?', ...]\n   * //    ^                                  ^\n   * // start = 0                          end = 7\n   * ```\n   *\n   * When we read 4 bytes of data from the buffer, it finds its first segment and returns that data\n   * to us. As bytes are read the data is consumed. The segment tracks this by adjusting its\n   * internal indices.\n   *\n   * ```kotlin\n   * buffer.readUtf8(4) // \"seal\"\n   *\n   * // [ 's', 'e', 'a', 'l', 'i', 'o', 'n', '?', '?', '?', ...]\n   * //                        ^              ^\n   * //                     start = 4      end = 7\n   * ```\n   *\n   * As we write data into a buffer we fill up its internal segments. When a write doesn't fit into\n   * a buffer's last segment, additional segments are allocated and appended to the linked list of\n   * segments. Each segment has its own start and end indexes tracking where the user's data begins\n   * and ends.\n   *\n   * ```kotlin\n   * val xoxo = new Buffer()\n   * xoxo.writeUtf8(\"xo\".repeat(5_000))\n   *\n   * // [ 'x', 'o', 'x', 'o', 'x', 'o', 'x', 'o', ..., 'x', 'o', 'x', 'o']\n   * //    ^                                                               ^\n   * // start = 0                                                      end = 8192\n   * //\n   * // [ 'x', 'o', 'x', 'o', ..., 'x', 'o', 'x', 'o', '?', '?', '?', ...]\n   * //    ^                                            ^\n   * // start = 0                                   end = 1808\n   * ```\n   *\n   * The start index is always **inclusive** and the end index is always **exclusive**. The data\n   * preceding the start index is undefined, and the data at and following the end index is\n   * undefined.\n   *\n   * After the last byte of a segment has been read, that segment may be returned to an internal\n   * segment pool. In addition to reducing the need to do garbage collection, segment pooling also\n   * saves the JVM from needing to zero-fill byte arrays. Okio doesn't need to zero-fill its arrays\n   * because it always writes memory before it reads it. But if you look at a segment in a debugger\n   * you may see its effects. In this example, one of the \"xoxo\" segments above is reused in an\n   * unrelated buffer:\n   *\n   * ```kotlin\n   * val abc = new Buffer()\n   * abc.writeUtf8(\"abc\")\n   *\n   * // [ 'a', 'b', 'c', 'o', 'x', 'o', 'x', 'o', ...]\n   * //    ^              ^\n   * // start = 0     end = 3\n   * ```\n   *\n   * There is an optimization in `Buffer.copy()` and other methods that allows two segments to\n   * share the same underlying byte array. Clones can't write to the shared byte array; instead they\n   * allocate a new (private) segment early.\n   *\n   * ```kotlin\n   * val nana = new Buffer()\n   * nana.writeUtf8(\"na\".repeat(2_500))\n   * nana.readUtf8(2) // \"na\"\n   *\n   * // [ 'n', 'a', 'n', 'a', ..., 'n', 'a', 'n', 'a', '?', '?', '?', ...]\n   * //              ^                                  ^\n   * //           start = 2                         end = 5000\n   *\n   * nana2 = nana.copy()\n   * nana2.writeUtf8(\"batman\")\n   *\n   * // [ 'n', 'a', 'n', 'a', ..., 'n', 'a', 'n', 'a', '?', '?', '?', ...]\n   * //              ^                                  ^\n   * //           start = 2                         end = 5000\n   * //\n   * // [ 'b', 'a', 't', 'm', 'a', 'n', '?', '?', '?', ...]\n   * //    ^                             ^\n   * //  start = 0                    end = 6\n   * ```\n   *\n   * Segments are not shared when the shared region is small (ie. less than 1 KiB). This is intended\n   * to prevent fragmentation in sharing-heavy use cases.\n   *\n   * Unsafe Cursor API\n   * -----------------\n   *\n   * This class exposes privileged access to the internal byte arrays of a buffer. A cursor either\n   * references the data of a single segment, it is before the first segment (`offset == -1`), or it\n   * is after the last segment (`offset == buffer.size`).\n   *\n   * Call [UnsafeCursor.seek] to move the cursor to the segment that contains a specified offset.\n   * After seeking, [UnsafeCursor.data] references the segment's internal byte array,\n   * [UnsafeCursor.start] is the segment's start and [UnsafeCursor.end] is its end.\n   *\n   * Call [UnsafeCursor.next] to advance the cursor to the next segment. This returns -1 if there\n   * are no further segments in the buffer.\n   *\n   * Use [Buffer.readUnsafe] to create a cursor to read buffer data and [Buffer.readAndWriteUnsafe]\n   * to create a cursor to read and write buffer data. In either case, always call\n   * [UnsafeCursor.close] when done with a cursor. This is convenient with Kotlin's\n   * [use] extension function. In this example we read all of the bytes in a buffer into a byte\n   * array:\n   *\n   * ```kotlin\n   * val bufferBytes = ByteArray(buffer.size.toInt())\n   *\n   * buffer.readUnsafe().use { cursor ->\n   *   while (cursor.next() != -1) {\n   *     System.arraycopy(cursor.data, cursor.start,\n   *         bufferBytes, cursor.offset.toInt(), cursor.end - cursor.start);\n   *   }\n   * }\n   * ```\n   *\n   * Change the capacity of a buffer with [resizeBuffer]. This is only permitted for read+write\n   * cursors. The buffer's size always changes from the end: shrinking it removes bytes from the\n   * end; growing it adds capacity to the end.\n   *\n   * Warnings\n   * --------\n   *\n   * Most application developers should avoid this API. Those that must use this API should\n   * respect these warnings.\n   *\n   * **Don't mutate a cursor.** This class has public, non-final fields because that is convenient\n   * for low-level I/O frameworks. Never assign values to these fields; instead use the cursor API\n   * to adjust these.\n   *\n   * **Never mutate `data` unless you have read+write access.** You are on the honor system to never\n   * write the buffer in read-only mode. Read-only mode may be more efficient than read+write mode\n   * because it does not need to make private copies of shared segments.\n   *\n   * **Only access data in `[start..end)`.** Other data in the byte array is undefined! It may\n   * contain private or sensitive data from other parts of your process.\n   *\n   * **Always fill the new capacity when you grow a buffer.** New capacity is not zero-filled and\n   * may contain data from other parts of your process. Avoid leaking this information by always\n   * writing something to the newly-allocated capacity. Do not assume that new capacity will be\n   * filled with `0`; it will not be.\n   *\n   * **Do not access a buffer while is being accessed by a cursor.** Even simple read-only\n   * operations like [Buffer.clone] are unsafe because they mark segments as shared.\n   *\n   * **Do not hard-code the segment size in your application.** It is possible that segment sizes\n   * will change with advances in hardware. Future versions of Okio may even have heterogeneous\n   * segment sizes.\n   *\n   * These warnings are intended to help you to use this API safely. It's here for developers\n   * that need absolutely the most throughput. Since that's you, here's one final performance tip.\n   * You can reuse instances of this class if you like. Use the overloads of [Buffer.readUnsafe] and\n   * [Buffer.readAndWriteUnsafe] that take a cursor and close it after use.\n   */\n  class UnsafeCursor constructor() : Closeable {\n    var buffer: Buffer?\n\n    var readWrite: Boolean\n\n    internal var segment: Segment?\n\n    var offset: Long\n\n    var data: ByteArray?\n\n    var start: Int\n\n    var end: Int\n\n    /**\n     * Seeks to the next range of bytes, advancing the offset by `end - start`. Returns the size of\n     * the readable range (at least 1), or -1 if we have reached the end of the buffer and there are\n     * no more bytes to read.\n     */\n    fun next(): Int\n\n    /**\n     * Reposition the cursor so that the data at [offset] is readable at `data[start]`.\n     * Returns the number of bytes readable in [data] (at least 1), or -1 if there are no data\n     * to read.\n     */\n    fun seek(offset: Long): Int\n\n    /**\n     * Change the size of the buffer so that it equals [newSize] by either adding new capacity at\n     * the end or truncating the buffer at the end. Newly added capacity may span multiple segments.\n     *\n     * As a side-effect this cursor will [seek][UnsafeCursor.seek]. If the buffer is being enlarged\n     * it will move [UnsafeCursor.offset] to the first byte of newly-added capacity. This is the\n     * size of the buffer prior to the `resizeBuffer()` call. If the buffer is being shrunk it will move\n     * [UnsafeCursor.offset] to the end of the buffer.\n     *\n     * Warning: it is the caller’s responsibility to write new data to every byte of the\n     * newly-allocated capacity. Failure to do so may cause serious security problems as the data\n     * in the returned buffers is not zero filled. Buffers may contain dirty pooled segments that\n     * hold very sensitive data from other parts of the current process.\n     *\n     * @return the previous size of the buffer.\n     */\n    fun resizeBuffer(newSize: Long): Long\n\n    /**\n     * Grow the buffer by adding a **contiguous range** of capacity in a single segment. This adds\n     * at least [minByteCount] bytes but may add up to a full segment of additional capacity.\n     *\n     * As a side-effect this cursor will [seek][UnsafeCursor.seek]. It will move\n     * [offset][UnsafeCursor.offset] to the first byte of newly-added capacity. This is the size of\n     * the buffer prior to the `expandBuffer()` call.\n     *\n     * If [minByteCount] bytes are available in the buffer's current tail segment that will be used;\n     * otherwise another segment will be allocated and appended. In either case this returns the\n     * number of bytes of capacity added to this buffer.\n     *\n     * Warning: it is the caller’s responsibility to either write new data to every byte of the\n     * newly-allocated capacity, or to [shrink][UnsafeCursor.resizeBuffer] the buffer to the data\n     * written. Failure to do so may cause serious security problems as the data in the returned\n     * buffers is not zero filled. Buffers may contain dirty pooled segments that hold very\n     * sensitive data from other parts of the current process.\n     *\n     * @param minByteCount the size of the contiguous capacity. Must be positive and not greater\n     *     than the capacity size of a single segment (8 KiB).\n     * @return the number of bytes expanded by. Not less than `minByteCount`.\n     */\n    fun expandBuffer(minByteCount: Int): Long\n\n    override fun close()\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/BufferedSink.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\n/**\n * A sink that keeps a buffer internally so that callers can do small writes without a performance\n * penalty.\n */\nexpect sealed interface BufferedSink : Sink {\n  /** This sink's internal buffer. */\n  val buffer: Buffer\n\n  fun write(byteString: ByteString): BufferedSink\n\n  fun write(byteString: ByteString, offset: Int, byteCount: Int): BufferedSink\n\n  /** Like [OutputStream.write], this writes a complete byte array to this sink. */\n  fun write(source: ByteArray): BufferedSink\n\n  /** Like [OutputStream.write], this writes `byteCount` bytes of `source`, starting at `offset`. */\n  fun write(source: ByteArray, offset: Int, byteCount: Int): BufferedSink\n\n  /**\n   * Removes all bytes from `source` and appends them to this sink. Returns the number of bytes read\n   * which will be 0 if `source` is exhausted.\n   */\n  fun writeAll(source: Source): Long\n\n  /** Removes `byteCount` bytes from `source` and appends them to this sink. */\n  fun write(source: Source, byteCount: Long): BufferedSink\n\n  /**\n   * Encodes `string` in UTF-8 and writes it to this sink.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeUtf8(\"Uh uh uh!\");\n   * buffer.writeByte(' ');\n   * buffer.writeUtf8(\"You didn't say the magic word!\");\n   *\n   * assertEquals(\"Uh uh uh! You didn't say the magic word!\", buffer.readUtf8());\n   * ```\n   */\n  fun writeUtf8(string: String): BufferedSink\n\n  /**\n   * Encodes the characters at `beginIndex` up to `endIndex` from `string` in UTF-8 and writes it to\n   * this sink.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeUtf8(\"I'm a hacker!\\n\", 6, 12);\n   * buffer.writeByte(' ');\n   * buffer.writeUtf8(\"That's what I said: you're a nerd.\\n\", 29, 33);\n   * buffer.writeByte(' ');\n   * buffer.writeUtf8(\"I prefer to be called a hacker!\\n\", 24, 31);\n   *\n   * assertEquals(\"hacker nerd hacker!\", buffer.readUtf8());\n   * ```\n   */\n  fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): BufferedSink\n\n  /** Encodes `codePoint` in UTF-8 and writes it to this sink. */\n  fun writeUtf8CodePoint(codePoint: Int): BufferedSink\n\n  /** Writes a byte to this sink. */\n  fun writeByte(b: Int): BufferedSink\n\n  /**\n   * Writes a big-endian short to this sink using two bytes.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeShort(32767);\n   * buffer.writeShort(15);\n   *\n   * assertEquals(4, buffer.size());\n   * assertEquals((byte) 0x7f, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x0f, buffer.readByte());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun writeShort(s: Int): BufferedSink\n\n  /**\n   * Writes a little-endian short to this sink using two bytes.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeShortLe(32767);\n   * buffer.writeShortLe(15);\n   *\n   * assertEquals(4, buffer.size());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0x7f, buffer.readByte());\n   * assertEquals((byte) 0x0f, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun writeShortLe(s: Int): BufferedSink\n\n  /**\n   * Writes a big-endian int to this sink using four bytes.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeInt(2147483647);\n   * buffer.writeInt(15);\n   *\n   * assertEquals(8, buffer.size());\n   * assertEquals((byte) 0x7f, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x0f, buffer.readByte());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun writeInt(i: Int): BufferedSink\n\n  /**\n   * Writes a little-endian int to this sink using four bytes.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeIntLe(2147483647);\n   * buffer.writeIntLe(15);\n   *\n   * assertEquals(8, buffer.size());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0x7f, buffer.readByte());\n   * assertEquals((byte) 0x0f, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun writeIntLe(i: Int): BufferedSink\n\n  /**\n   * Writes a big-endian long to this sink using eight bytes.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeLong(9223372036854775807L);\n   * buffer.writeLong(15);\n   *\n   * assertEquals(16, buffer.size());\n   * assertEquals((byte) 0x7f, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x0f, buffer.readByte());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun writeLong(v: Long): BufferedSink\n\n  /**\n   * Writes a little-endian long to this sink using eight bytes.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeLongLe(9223372036854775807L);\n   * buffer.writeLongLe(15);\n   *\n   * assertEquals(16, buffer.size());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0xff, buffer.readByte());\n   * assertEquals((byte) 0x7f, buffer.readByte());\n   * assertEquals((byte) 0x0f, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals((byte) 0x00, buffer.readByte());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun writeLongLe(v: Long): BufferedSink\n\n  /**\n   * Writes a long to this sink in signed decimal form (i.e., as a string in base 10).\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeDecimalLong(8675309L);\n   * buffer.writeByte(' ');\n   * buffer.writeDecimalLong(-123L);\n   * buffer.writeByte(' ');\n   * buffer.writeDecimalLong(1L);\n   *\n   * assertEquals(\"8675309 -123 1\", buffer.readUtf8());\n   * ```\n   */\n  fun writeDecimalLong(v: Long): BufferedSink\n\n  /**\n   * Writes a long to this sink in hexadecimal form (i.e., as a string in base 16).\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeHexadecimalUnsignedLong(65535L);\n   * buffer.writeByte(' ');\n   * buffer.writeHexadecimalUnsignedLong(0xcafebabeL);\n   * buffer.writeByte(' ');\n   * buffer.writeHexadecimalUnsignedLong(0x10L);\n   *\n   * assertEquals(\"ffff cafebabe 10\", buffer.readUtf8());\n   * ```\n   */\n  fun writeHexadecimalUnsignedLong(v: Long): BufferedSink\n\n  /**\n   * Writes all buffered data to the underlying sink, if one exists. Then that sink is recursively\n   * flushed which pushes data as far as possible towards its ultimate destination. Typically that\n   * destination is a network socket or file.\n   *\n   * ```java\n   * BufferedSink b0 = new Buffer();\n   * BufferedSink b1 = Okio.buffer(b0);\n   * BufferedSink b2 = Okio.buffer(b1);\n   *\n   * b2.writeUtf8(\"hello\");\n   * assertEquals(5, b2.buffer().size());\n   * assertEquals(0, b1.buffer().size());\n   * assertEquals(0, b0.buffer().size());\n   *\n   * b2.flush();\n   * assertEquals(0, b2.buffer().size());\n   * assertEquals(0, b1.buffer().size());\n   * assertEquals(5, b0.buffer().size());\n   * ```\n   */\n  override fun flush()\n\n  /**\n   * Writes all buffered data to the underlying sink, if one exists. Like [flush], but weaker. Call\n   * this before this buffered sink goes out of scope so that its data can reach its destination.\n   *\n   * ```java\n   * BufferedSink b0 = new Buffer();\n   * BufferedSink b1 = Okio.buffer(b0);\n   * BufferedSink b2 = Okio.buffer(b1);\n   *\n   * b2.writeUtf8(\"hello\");\n   * assertEquals(5, b2.buffer().size());\n   * assertEquals(0, b1.buffer().size());\n   * assertEquals(0, b0.buffer().size());\n   *\n   * b2.emit();\n   * assertEquals(0, b2.buffer().size());\n   * assertEquals(5, b1.buffer().size());\n   * assertEquals(0, b0.buffer().size());\n   *\n   * b1.emit();\n   * assertEquals(0, b2.buffer().size());\n   * assertEquals(0, b1.buffer().size());\n   * assertEquals(5, b0.buffer().size());\n   * ```\n   */\n  fun emit(): BufferedSink\n\n  /**\n   * Writes complete segments to the underlying sink, if one exists. Like [flush], but weaker. Use\n   * this to limit the memory held in the buffer to a single segment. Typically application code\n   * will not need to call this: it is only necessary when application code writes directly to this\n   * [sink's buffer][buffer].\n   *\n   * ```java\n   * BufferedSink b0 = new Buffer();\n   * BufferedSink b1 = Okio.buffer(b0);\n   * BufferedSink b2 = Okio.buffer(b1);\n   *\n   * b2.buffer().write(new byte[20_000]);\n   * assertEquals(20_000, b2.buffer().size());\n   * assertEquals(     0, b1.buffer().size());\n   * assertEquals(     0, b0.buffer().size());\n   *\n   * b2.emitCompleteSegments();\n   * assertEquals( 3_616, b2.buffer().size());\n   * assertEquals(     0, b1.buffer().size());\n   * assertEquals(16_384, b0.buffer().size()); // This example assumes 8192 byte segments.\n   * ```\n   */\n  fun emitCompleteSegments(): BufferedSink\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/BufferedSource.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\n/**\n * A source that keeps a buffer internally so that callers can do small reads without a performance\n * penalty. It also allows clients to read ahead, buffering as much as necessary before consuming\n * input.\n */\nexpect sealed interface BufferedSource : Source {\n  /** This source's internal buffer. */\n  val buffer: Buffer\n\n  /**\n   * Returns true if there are no more bytes in this source. This will block until there are bytes\n   * to read or the source is definitely exhausted.\n   */\n  fun exhausted(): Boolean\n\n  /**\n   * Returns when the buffer contains at least `byteCount` bytes. Throws an\n   * [java.io.EOFException] if the source is exhausted before the required bytes can be read.\n   */\n  fun require(byteCount: Long)\n\n  /**\n   * Returns true when the buffer contains at least `byteCount` bytes, expanding it as\n   * necessary. Returns false if the source is exhausted before the requested bytes can be read.\n   */\n  fun request(byteCount: Long): Boolean\n\n  /** Removes a byte from this source and returns it. */\n  fun readByte(): Byte\n\n  /**\n   * Removes two bytes from this source and returns a big-endian short.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeByte(0x7f)\n   *     .writeByte(0xff)\n   *     .writeByte(0x00)\n   *     .writeByte(0x0f);\n   * assertEquals(4, buffer.size());\n   *\n   * assertEquals(32767, buffer.readShort());\n   * assertEquals(2, buffer.size());\n   *\n   * assertEquals(15, buffer.readShort());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readShort(): Short\n\n  /**\n   * Removes two bytes from this source and returns a little-endian short.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeByte(0xff)\n   *     .writeByte(0x7f)\n   *     .writeByte(0x0f)\n   *     .writeByte(0x00);\n   * assertEquals(4, buffer.size());\n   *\n   * assertEquals(32767, buffer.readShortLe());\n   * assertEquals(2, buffer.size());\n   *\n   * assertEquals(15, buffer.readShortLe());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readShortLe(): Short\n\n  /**\n   * Removes four bytes from this source and returns a big-endian int.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeByte(0x7f)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x0f);\n   * assertEquals(8, buffer.size());\n   *\n   * assertEquals(2147483647, buffer.readInt());\n   * assertEquals(4, buffer.size());\n   *\n   * assertEquals(15, buffer.readInt());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readInt(): Int\n\n  /**\n   * Removes four bytes from this source and returns a little-endian int.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0x7f)\n   *     .writeByte(0x0f)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00);\n   * assertEquals(8, buffer.size());\n   *\n   * assertEquals(2147483647, buffer.readIntLe());\n   * assertEquals(4, buffer.size());\n   *\n   * assertEquals(15, buffer.readIntLe());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readIntLe(): Int\n\n  /**\n   * Removes eight bytes from this source and returns a big-endian long.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeByte(0x7f)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x0f);\n   * assertEquals(16, buffer.size());\n   *\n   * assertEquals(9223372036854775807L, buffer.readLong());\n   * assertEquals(8, buffer.size());\n   *\n   * assertEquals(15, buffer.readLong());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readLong(): Long\n\n  /**\n   * Removes eight bytes from this source and returns a little-endian long.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0xff)\n   *     .writeByte(0x7f)\n   *     .writeByte(0x0f)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00)\n   *     .writeByte(0x00);\n   * assertEquals(16, buffer.size());\n   *\n   * assertEquals(9223372036854775807L, buffer.readLongLe());\n   * assertEquals(8, buffer.size());\n   *\n   * assertEquals(15, buffer.readLongLe());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readLongLe(): Long\n\n  /**\n   * Reads a long from this source in signed decimal form (i.e., as a string in base 10 with\n   * optional leading '-'). This will iterate until a non-digit character is found.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeUtf8(\"8675309 -123 00001\");\n   *\n   * assertEquals(8675309L, buffer.readDecimalLong());\n   * assertEquals(' ', buffer.readByte());\n   * assertEquals(-123L, buffer.readDecimalLong());\n   * assertEquals(' ', buffer.readByte());\n   * assertEquals(1L, buffer.readDecimalLong());\n   * ```\n   *\n   * @throws NumberFormatException if the found digits do not fit into a `long` or a decimal\n   * number was not present.\n   */\n  fun readDecimalLong(): Long\n\n  /**\n   * Reads a long form this source in hexadecimal form (i.e., as a string in base 16). This will\n   * iterate until a non-hexadecimal character is found.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeUtf8(\"ffff CAFEBABE 10\");\n   *\n   * assertEquals(65535L, buffer.readHexadecimalUnsignedLong());\n   * assertEquals(' ', buffer.readByte());\n   * assertEquals(0xcafebabeL, buffer.readHexadecimalUnsignedLong());\n   * assertEquals(' ', buffer.readByte());\n   * assertEquals(0x10L, buffer.readHexadecimalUnsignedLong());\n   * ```\n   *\n   * @throws NumberFormatException if the found hexadecimal does not fit into a `long` or\n   * hexadecimal was not found.\n   */\n  fun readHexadecimalUnsignedLong(): Long\n\n  /**\n   * Reads and discards `byteCount` bytes from this source. Throws an [java.io.EOFException] if the\n   * source is exhausted before the requested bytes can be skipped.\n   */\n  fun skip(byteCount: Long)\n\n  /** Removes all bytes from this and returns them as a byte string. */\n  fun readByteString(): ByteString\n\n  /** Removes `byteCount` bytes from this and returns them as a byte string. */\n  fun readByteString(byteCount: Long): ByteString\n\n  /**\n   * Finds the first byte string in `options` that is a prefix of this buffer, consumes it from this\n   * source, and returns its index. If no byte string in `options` is a prefix of this buffer this\n   * returns -1 and no bytes are consumed.\n   *\n   * This can be used as an alternative to [readByteString] or even [readUtf8] if the set of\n   * expected values is known in advance.\n   *\n   * ```java\n   * Options FIELDS = Options.of(\n   *     ByteString.encodeUtf8(\"depth=\"),\n   *     ByteString.encodeUtf8(\"height=\"),\n   *     ByteString.encodeUtf8(\"width=\"));\n   *\n   * Buffer buffer = new Buffer()\n   *     .writeUtf8(\"width=640\\n\")\n   *     .writeUtf8(\"height=480\\n\");\n   *\n   * assertEquals(2, buffer.select(FIELDS));\n   * assertEquals(640, buffer.readDecimalLong());\n   * assertEquals('\\n', buffer.readByte());\n   * assertEquals(1, buffer.select(FIELDS));\n   * assertEquals(480, buffer.readDecimalLong());\n   * assertEquals('\\n', buffer.readByte());\n   * ```\n   */\n  fun select(options: Options): Int\n\n  /**\n   * Finds the first item in [options] whose encoding is a prefix of this buffer, consumes it from\n   * this buffer, and returns it. If no item in [options] is a prefix of this source, this function\n   * returns null and no bytes are consumed.\n   *\n   * This can be used as an alternative to [readByteString] or even [readUtf8] if the set of\n   * expected values is known in advance.\n   *\n   * ```java\n   * TypedOptions<Direction> options = TypedOptions.of(\n   *     Arrays.asList(Direction.values()),\n   *     (direction) -> ByteString.encodeUtf8(direction.name().toLowerCase(Locale.ROOT))\n   * );\n   *\n   * Buffer buffer = new Buffer()\n   *     .writeUtf8(\"north:100\\n\")\n   *     .writeUtf8(\"east:50\\n\");\n   *\n   * assertEquals(Direction.NORTH, buffer.select(options));\n   * assertEquals(':', buffer.readByte());\n   * assertEquals(100L, buffer.readDecimalLong());\n   * assertEquals('\\n', buffer.readByte());\n   *\n   * assertEquals(Direction.EAST, buffer.select(options));\n   * assertEquals(':', buffer.readByte());\n   * assertEquals(50L, buffer.readDecimalLong());\n   * assertEquals('\\n', buffer.readByte());\n   * ```\n   */\n  fun <T : Any> select(options: TypedOptions<T>): T?\n\n  /** Removes all bytes from this and returns them as a byte array. */\n  fun readByteArray(): ByteArray\n\n  /** Removes `byteCount` bytes from this and returns them as a byte array. */\n  fun readByteArray(byteCount: Long): ByteArray\n\n  /**\n   * Removes up to `sink.length` bytes from this and copies them into `sink`. Returns the number of\n   * bytes read, or -1 if this source is exhausted.\n   */\n  fun read(sink: ByteArray): Int\n\n  /**\n   * Removes exactly `sink.length` bytes from this and copies them into `sink`. Throws an\n   * [java.io.EOFException] if the requested number of bytes cannot be read.\n   */\n  fun readFully(sink: ByteArray)\n\n  /**\n   * Removes up to `byteCount` bytes from this and copies them into `sink` at `offset`. Returns the\n   * number of bytes read, or -1 if this source is exhausted.\n   */\n  fun read(sink: ByteArray, offset: Int, byteCount: Int): Int\n\n  /**\n   * Removes exactly `byteCount` bytes from this and appends them to `sink`. Throws an\n   * [java.io.EOFException] if the requested number of bytes cannot be read.\n   */\n  fun readFully(sink: Buffer, byteCount: Long)\n\n  /**\n   * Removes all bytes from this and appends them to `sink`. Returns the total number of bytes\n   * written to `sink` which will be 0 if this is exhausted.\n   */\n  fun readAll(sink: Sink): Long\n\n  /**\n   * Removes all bytes from this, decodes them as UTF-8, and returns the string. Returns the empty\n   * string if this source is empty.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeUtf8(\"Uh uh uh!\")\n   *     .writeByte(' ')\n   *     .writeUtf8(\"You didn't say the magic word!\");\n   *\n   * assertEquals(\"Uh uh uh! You didn't say the magic word!\", buffer.readUtf8());\n   * assertEquals(0, buffer.size());\n   *\n   * assertEquals(\"\", buffer.readUtf8());\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readUtf8(): String\n\n  /**\n   * Removes `byteCount` bytes from this, decodes them as UTF-8, and returns the string.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeUtf8(\"Uh uh uh!\")\n   *     .writeByte(' ')\n   *     .writeUtf8(\"You didn't say the magic word!\");\n   * assertEquals(40, buffer.size());\n   *\n   * assertEquals(\"Uh uh uh! You \", buffer.readUtf8(14));\n   * assertEquals(26, buffer.size());\n   *\n   * assertEquals(\"didn't say the\", buffer.readUtf8(14));\n   * assertEquals(12, buffer.size());\n   *\n   * assertEquals(\" magic word!\", buffer.readUtf8(12));\n   * assertEquals(0, buffer.size());\n   * ```\n   */\n  fun readUtf8(byteCount: Long): String\n\n  /**\n   * Removes and returns characters up to but not including the next line break. A line break is\n   * either `\"\\n\"` or `\"\\r\\n\"`; these characters are not included in the result.\n   *\n   * ```java\n   * Buffer buffer = new Buffer()\n   *     .writeUtf8(\"I'm a hacker!\\n\")\n   *     .writeUtf8(\"That's what I said: you're a nerd.\\n\")\n   *     .writeUtf8(\"I prefer to be called a hacker!\\n\");\n   * assertEquals(81, buffer.size());\n   *\n   * assertEquals(\"I'm a hacker!\", buffer.readUtf8Line());\n   * assertEquals(67, buffer.size());\n   *\n   * assertEquals(\"That's what I said: you're a nerd.\", buffer.readUtf8Line());\n   * assertEquals(32, buffer.size());\n   *\n   * assertEquals(\"I prefer to be called a hacker!\", buffer.readUtf8Line());\n   * assertEquals(0, buffer.size());\n   *\n   * assertEquals(null, buffer.readUtf8Line());\n   * assertEquals(0, buffer.size());\n   * ```\n   *\n   * **On the end of the stream this method returns null,** just like [java.io.BufferedReader]. If\n   * the source doesn't end with a line break then an implicit line break is assumed. Null is\n   * returned once the source is exhausted. Use this for human-generated data, where a trailing\n   * line break is optional.\n   */\n  fun readUtf8Line(): String?\n\n  /**\n   * Removes and returns characters up to but not including the next line break. A line break is\n   * either `\"\\n\"` or `\"\\r\\n\"`; these characters are not included in the result.\n   *\n   * **On the end of the stream this method throws.** Every call must consume either\n   * '\\r\\n' or '\\n'. If these characters are absent in the stream, an [java.io.EOFException]\n   * is thrown. Use this for machine-generated data where a missing line break implies truncated\n   * input.\n   */\n  fun readUtf8LineStrict(): String\n\n  /**\n   * Like [readUtf8LineStrict], except this allows the caller to specify the longest allowed match.\n   * Use this to protect against streams that may not include `\"\\n\"` or `\"\\r\\n\"`.\n   *\n   * The returned string will have at most `limit` UTF-8 bytes, and the maximum number of bytes\n   * scanned is `limit + 2`. If `limit == 0` this will always throw an `EOFException` because no\n   * bytes will be scanned.\n   *\n   * This method is safe. No bytes are discarded if the match fails, and the caller is free to try\n   * another match:\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeUtf8(\"12345\\r\\n\");\n   *\n   * // This will throw! There must be \\r\\n or \\n at the limit or before it.\n   * buffer.readUtf8LineStrict(4);\n   *\n   * // No bytes have been consumed so the caller can retry.\n   * assertEquals(\"12345\", buffer.readUtf8LineStrict(5));\n   * ```\n   */\n  fun readUtf8LineStrict(limit: Long): String\n\n  /**\n   * Removes and returns a single UTF-8 code point, reading between 1 and 4 bytes as necessary.\n   *\n   * If this source is exhausted before a complete code point can be read, this throws an\n   * [java.io.EOFException] and consumes no input.\n   *\n   * If this source doesn't start with a properly-encoded UTF-8 code point, this method will remove\n   * 1 or more non-UTF-8 bytes and return the replacement character (`U+FFFD`). This covers encoding\n   * problems (the input is not properly-encoded UTF-8), characters out of range (beyond the\n   * 0x10ffff limit of Unicode), code points for UTF-16 surrogates (U+d800..U+dfff) and overlong\n   * encodings (such as `0xc080` for the NUL character in modified UTF-8).\n   */\n  fun readUtf8CodePoint(): Int\n\n  /** Equivalent to [indexOf(b, 0)][indexOf]. */\n  fun indexOf(b: Byte): Long\n\n  /**\n   * Returns the index of the first `b` in the buffer at or after `fromIndex`. This expands the\n   * buffer as necessary until `b` is found. This reads an unbounded number of bytes into the\n   * buffer. Returns -1 if the stream is exhausted before the requested byte is found.\n   *\n   * ```java\n   * Buffer buffer = new Buffer();\n   * buffer.writeUtf8(\"Don't move! He can't see us if we don't move.\");\n   *\n   * byte m = 'm';\n   * assertEquals(6,  buffer.indexOf(m));\n   * assertEquals(40, buffer.indexOf(m, 12));\n   * ```\n   */\n  fun indexOf(b: Byte, fromIndex: Long): Long\n\n  /**\n   * Returns the index of `b` if it is found in the range of `fromIndex` inclusive to `toIndex`\n   * exclusive. If `b` isn't found, or if `fromIndex == toIndex`, then -1 is returned.\n   *\n   * The scan terminates at either `toIndex` or the end of the buffer, whichever comes first. The\n   * maximum number of bytes scanned is `toIndex-fromIndex`.\n   */\n  fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long\n\n  /** Equivalent to [indexOf(bytes, 0)][indexOf]. */\n  fun indexOf(bytes: ByteString): Long\n\n  /**\n   * Returns the index of the first match for `bytes` in the buffer at or after `fromIndex`. This\n   * expands the buffer as necessary until `bytes` is found. This reads an unbounded number of\n   * bytes into the buffer. Returns -1 if the stream is exhausted before the requested bytes are\n   * found.\n   *\n   * ```java\n   * ByteString MOVE = ByteString.encodeUtf8(\"move\");\n   *\n   * Buffer buffer = new Buffer();\n   * buffer.writeUtf8(\"Don't move! He can't see us if we don't move.\");\n   *\n   * assertEquals(6,  buffer.indexOf(MOVE));\n   * assertEquals(40, buffer.indexOf(MOVE, 12));\n   * ```\n   */\n  fun indexOf(bytes: ByteString, fromIndex: Long): Long\n\n  /**\n   * Returns the index of the first match for `bytes` in the buffer that is at or after `fromIndex`,\n   * and that is also less than `toIndex`. Returns -1 if `bytes` isn't found in that range. If\n   * `fromIndex == toIndex` then search range is empty and -1 is returned.\n   *\n   * This may attempt to expand the buffer. It won't attempt to expand the buffer if doing so\n   * couldn't change the result.\n   *\n   * ```java\n   * ByteString MOVE = ByteString.encodeUtf8(\"move\");\n   *\n   * Buffer buffer = new Buffer();\n   * buffer.writeUtf8(\"Don't move! He can't see us if we don't move.\");\n   *\n   * assertEquals( 6, buffer.indexOf(MOVE, 0,  40));\n   * assertEquals( 6, buffer.indexOf(MOVE, 0, 100));\n   * assertEquals(-1, buffer.indexOf(MOVE, 7,  40));\n   * assertEquals(40, buffer.indexOf(MOVE, 7, 100));\n   * ```\n   */\n  fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long\n\n  /** Equivalent to [indexOfElement(targetBytes, 0)][indexOfElement]. */\n  fun indexOfElement(targetBytes: ByteString): Long\n\n  /**\n   * Returns the first index in this buffer that is at or after `fromIndex` and that contains any of\n   * the bytes in `targetBytes`. This expands the buffer as necessary until a target byte is found.\n   * This reads an unbounded number of bytes into the buffer. Returns -1 if the stream is exhausted\n   * before the requested byte is found.\n   *\n   * ```java\n   * ByteString ANY_VOWEL = ByteString.encodeUtf8(\"AEOIUaeoiu\");\n   *\n   * Buffer buffer = new Buffer();\n   * buffer.writeUtf8(\"Dr. Alan Grant\");\n   *\n   * assertEquals(4,  buffer.indexOfElement(ANY_VOWEL));    // 'A' in 'Alan'.\n   * assertEquals(11, buffer.indexOfElement(ANY_VOWEL, 9)); // 'a' in 'Grant'.\n   * ```\n   */\n  fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long\n\n  /**\n   * Returns true if the bytes at `offset` in this source equal `bytes`. This expands the buffer as\n   * necessary until a byte does not match, all bytes are matched, or if the stream is exhausted\n   * before enough bytes could determine a match.\n   *\n   * ```java\n   * ByteString simonSays = ByteString.encodeUtf8(\"Simon says:\");\n   *\n   * Buffer standOnOneLeg = new Buffer().writeUtf8(\"Simon says: Stand on one leg.\");\n   * assertTrue(standOnOneLeg.rangeEquals(0, simonSays));\n   *\n   * Buffer payMeMoney = new Buffer().writeUtf8(\"Pay me $1,000,000.\");\n   * assertFalse(payMeMoney.rangeEquals(0, simonSays));\n   * ```\n   */\n  fun rangeEquals(offset: Long, bytes: ByteString): Boolean\n\n  /**\n   * Returns true if `byteCount` bytes at `offset` in this source equal `bytes` at `bytesOffset`.\n   * This expands the buffer as necessary until a byte does not match, all bytes are matched, or if\n   * the stream is exhausted before enough bytes could determine a match.\n   */\n  fun rangeEquals(offset: Long, bytes: ByteString, bytesOffset: Int, byteCount: Int): Boolean\n\n  /**\n   * Returns a new `BufferedSource` that can read data from this `BufferedSource` without consuming\n   * it. The returned source becomes invalid once this source is next read or closed.\n   *\n   * For example, we can use `peek()` to lookahead and read the same data multiple times.\n   *\n   * ```kotlin\n   * val buffer = Buffer()\n   * buffer.writeUtf8(\"abcdefghi\")\n   *\n   * buffer.readUtf8(3) // returns \"abc\", buffer contains \"defghi\"\n   *\n   * val peek = buffer.peek()\n   * peek.readUtf8(3) // returns \"def\", buffer contains \"defghi\"\n   * peek.readUtf8(3) // returns \"ghi\", buffer contains \"defghi\"\n   *\n   * buffer.readUtf8(3) // returns \"def\", buffer contains \"ghi\"\n   * ```\n   */\n  fun peek(): BufferedSource\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/ByteString.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.jvm.JvmName\nimport kotlin.jvm.JvmOverloads\nimport kotlin.jvm.JvmStatic\n\n/**\n * An immutable sequence of bytes.\n *\n * Byte strings compare lexicographically as a sequence of **unsigned** bytes. That is, the byte\n * string `ff` sorts after `00`. This is counter to the sort order of the corresponding bytes,\n * where `-1` sorts before `0`.\n *\n * **Full disclosure:** this class provides untrusted input and output streams with raw access to\n * the underlying byte array. A hostile stream implementation could keep a reference to the mutable\n * byte string, violating the immutable guarantee of this class. For this reason a byte string's\n * immutability guarantee cannot be relied upon for security in applets and other environments that\n * run both trusted and untrusted code in the same process.\n */\nexpect open class ByteString\n// Trusted internal constructor doesn't clone data.\ninternal constructor(data: ByteArray) : Comparable<ByteString> {\n  internal val data: ByteArray\n\n  internal var hashCode: Int\n  internal var utf8: String?\n\n  /** Constructs a new `String` by decoding the bytes as `UTF-8`. */\n  fun utf8(): String\n\n  /**\n   * Returns this byte string encoded as [Base64](http://www.ietf.org/rfc/rfc2045.txt). In violation\n   * of the RFC, the returned string does not wrap lines at 76 columns.\n   */\n  fun base64(): String\n\n  /** Returns this byte string encoded as [URL-safe Base64](http://www.ietf.org/rfc/rfc4648.txt). */\n  fun base64Url(): String\n\n  /** Returns this byte string encoded in hexadecimal. */\n  fun hex(): String\n\n  /**\n   * Returns the 128-bit MD5 hash of this byte string.\n   *\n   * MD5 has been vulnerable to collisions since 2004. It should not be used in new code.\n   */\n  fun md5(): ByteString\n\n  /**\n   * Returns the 160-bit SHA-1 hash of this byte string.\n   *\n   * SHA-1 has been vulnerable to collisions since 2017. It should not be used in new code.\n   */\n  fun sha1(): ByteString\n\n  /** Returns the 256-bit SHA-256 hash of this byte string. */\n  fun sha256(): ByteString\n\n  /** Returns the 512-bit SHA-512 hash of this byte string. */\n  fun sha512(): ByteString\n\n  /** Returns the 160-bit SHA-1 HMAC of this byte string. */\n  fun hmacSha1(key: ByteString): ByteString\n\n  /** Returns the 256-bit SHA-256 HMAC of this byte string. */\n  fun hmacSha256(key: ByteString): ByteString\n\n  /** Returns the 512-bit SHA-512 HMAC of this byte string. */\n  fun hmacSha512(key: ByteString): ByteString\n\n  /**\n   * Returns a byte string equal to this byte string, but with the bytes 'A' through 'Z' replaced\n   * with the corresponding byte in 'a' through 'z'. Returns this byte string if it contains no\n   * bytes in 'A' through 'Z'.\n   */\n  fun toAsciiLowercase(): ByteString\n\n  /**\n   * Returns a byte string that is a substring of this byte string, beginning at the specified\n   * `beginIndex` and ends at the specified `endIndex`. Returns this byte string if `beginIndex` is\n   * 0 and `endIndex` is the length of this byte string.\n   */\n  fun substring(beginIndex: Int = 0, endIndex: Int = size): ByteString\n\n  /**\n   * Returns a byte string equal to this byte string, but with the bytes 'a' through 'z' replaced\n   * with the corresponding byte in 'A' through 'Z'. Returns this byte string if it contains no\n   * bytes in 'a' through 'z'.\n   */\n  fun toAsciiUppercase(): ByteString\n\n  /** Returns the byte at `pos`. */\n  internal fun internalGet(pos: Int): Byte\n\n  /** Returns the byte at `index`. */\n  @JvmName(\"getByte\")\n  operator fun get(index: Int): Byte\n\n  /** Returns the number of bytes in this ByteString. */\n  val size: Int\n    @JvmName(\"size\")\n    get\n\n  // Hack to work around Kotlin's limitation for using JvmName on open/override vals/funs\n  internal fun getSize(): Int\n\n  /** Returns a byte array containing a copy of the bytes in this `ByteString`. */\n  fun toByteArray(): ByteArray\n\n  /** Writes the contents of this byte string to `buffer`. */\n  internal fun write(buffer: Buffer, offset: Int, byteCount: Int)\n\n  /** Returns the bytes of this string without a defensive copy. Do not mutate!  */\n  internal fun internalArray(): ByteArray\n\n  /**\n   * Returns true if the bytes of this in `[offset..offset+byteCount)` equal the bytes of `other` in\n   * `[otherOffset..otherOffset+byteCount)`. Returns false if either range is out of bounds.\n   */\n  fun rangeEquals(offset: Int, other: ByteString, otherOffset: Int, byteCount: Int): Boolean\n\n  /**\n   * Returns true if the bytes of this in `[offset..offset+byteCount)` equal the bytes of `other` in\n   * `[otherOffset..otherOffset+byteCount)`. Returns false if either range is out of bounds.\n   */\n  fun rangeEquals(offset: Int, other: ByteArray, otherOffset: Int, byteCount: Int): Boolean\n\n  /**\n   * Copies bytes of this in `[offset..offset+byteCount]` to other in\n   * `[targetOffset..targetOffset+byteCount]`.\n   *\n   * @throws IndexOutOfBoundsException if either range is out of bounds.\n   */\n  fun copyInto(offset: Int = 0, target: ByteArray, targetOffset: Int = 0, byteCount: Int)\n\n  fun startsWith(prefix: ByteString): Boolean\n\n  fun startsWith(prefix: ByteArray): Boolean\n\n  fun endsWith(suffix: ByteString): Boolean\n\n  fun endsWith(suffix: ByteArray): Boolean\n\n  @JvmOverloads\n  fun indexOf(other: ByteString, fromIndex: Int = 0): Int\n\n  @JvmOverloads\n  fun indexOf(other: ByteArray, fromIndex: Int = 0): Int\n\n  fun lastIndexOf(other: ByteString, fromIndex: Int = size): Int\n\n  fun lastIndexOf(other: ByteArray, fromIndex: Int = size): Int\n\n  override fun equals(other: Any?): Boolean\n\n  override fun hashCode(): Int\n\n  override fun compareTo(other: ByteString): Int\n\n  /**\n   * Returns a human-readable string that describes the contents of this byte string. Typically this\n   * is a string like `[text=Hello]` or `[hex=0000ffff]`.\n   */\n  override fun toString(): String\n\n  companion object {\n    /** A singleton empty `ByteString`. */\n    val EMPTY: ByteString\n\n    /** Returns a new byte string containing a clone of the bytes of `data`. */\n    @JvmStatic\n    fun of(vararg data: Byte): ByteString\n\n    /**\n     * Returns a new [ByteString] containing a copy of `byteCount` bytes of this [ByteArray]\n     * starting at `offset`.\n     */\n    @JvmStatic\n    fun ByteArray.toByteString(offset: Int = 0, byteCount: Int = size): ByteString\n\n    /** Returns a new byte string containing the `UTF-8` bytes of this [String]. */\n    @JvmStatic\n    fun String.encodeUtf8(): ByteString\n\n    /**\n     * Decodes the Base64-encoded bytes and returns their value as a byte string. Returns null if\n     * this is not a Base64-encoded sequence of bytes.\n     */\n    @JvmStatic\n    fun String.decodeBase64(): ByteString?\n\n    /** Decodes the hex-encoded bytes and returns their value a byte string. */\n    @JvmStatic\n    fun String.decodeHex(): ByteString\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/CommonPlatform.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n@file:JvmName(\"-CommonPlatform\") // A leading '-' hides this class from Java.\n\npackage okio\n\nimport kotlin.jvm.JvmName\n\ninternal expect fun ByteArray.toUtf8String(): String\n\ninternal expect fun String.asUtf8ToByteArray(): ByteArray\n\n// TODO make internal https://youtrack.jetbrains.com/issue/KT-37316\nexpect class ArrayIndexOutOfBoundsException(message: String?) : IndexOutOfBoundsException\n\nexpect class Lock\n\nexpect inline fun <T> Lock.withLock(action: () -> T): T\n\ninternal expect fun newLock(): Lock\n\nexpect open class IOException(message: String?, cause: Throwable?) : Exception {\n  constructor(message: String?)\n  constructor()\n}\n\nexpect class ProtocolException(message: String) : IOException\n\nexpect open class EOFException(message: String?) : IOException {\n  constructor()\n}\n\nexpect class FileNotFoundException(message: String?) : IOException\n\nexpect interface Closeable {\n  /**\n   * Closes this object and releases the resources it holds. It is an error to use an object after\n   * it has been closed. It is safe to close an object more than once.\n   */\n  @Throws(IOException::class)\n  fun close()\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/ExperimentalFileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.DeprecationLevel.HIDDEN\nimport kotlin.annotation.AnnotationRetention.SOURCE\nimport kotlin.annotation.AnnotationTarget.CLASS\nimport kotlin.annotation.AnnotationTarget.FUNCTION\nimport kotlin.annotation.AnnotationTarget.PROPERTY\n\n@Deprecated(\n  message = \"This annotation is obsolete and should be removed.\",\n  level = HIDDEN,\n)\n@Retention(SOURCE)\n@Target(CLASS, FUNCTION, PROPERTY)\nannotation class ExperimentalFileSystem\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/FileHandle.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\n/**\n * An open file for reading and writing; using either streaming and random access.\n *\n * Use [read] and [write] to perform one-off random-access reads and writes. Use [source], [sink],\n * and [appendingSink] for streaming reads and writes.\n *\n * File handles must be closed when they are no longer needed. It is an error to read, write, or\n * create streams after a file handle is closed. The operating system resources held by a file\n * handle will be released once the file handle **and** all of its streams are closed.\n *\n * Although this class offers both reading and writing APIs, file handle instances may be\n * read-only or write-only. For example, a handle to a file on a read-only file system will throw an\n * exception if a write is attempted.\n *\n * File handles may be used by multiple threads concurrently. But the individual sources and sinks\n * produced by a file handle are not safe for concurrent use.\n */\nabstract class FileHandle(\n  /**\n   * True if this handle supports both reading and writing. If this is false all write operations\n   * including [write], [sink], [resize], and [flush] will all throw [IllegalStateException] if\n   * called.\n   */\n  val readWrite: Boolean,\n) : Closeable {\n  /**\n   * True once the file handle is closed. Resources should be released with [protectedClose] once\n   * this is true and [openStreamCount] is 0.\n   */\n  private var closed = false\n\n  /**\n   * Reference count of the number of open sources and sinks on this file handle. Resources should\n   * be released with [protectedClose] once this is 0 and [closed] is true.\n   */\n  private var openStreamCount = 0\n\n  val lock: Lock = newLock()\n\n  /**\n   * Reads at least 1, and up to [byteCount] bytes from this starting at [fileOffset] and copies\n   * them to [array] at [arrayOffset]. Returns the number of bytes read, or -1 if [fileOffset]\n   * equals [size].\n   */\n  @Throws(IOException::class)\n  fun read(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    lock.withLock {\n      check(!closed) { \"closed\" }\n    }\n    return protectedRead(fileOffset, array, arrayOffset, byteCount)\n  }\n\n  /**\n   * Reads at least 1, and up to [byteCount] bytes from this starting at [fileOffset] and appends\n   * them to [sink]. Returns the number of bytes read, or -1 if [fileOffset] equals [size].\n   */\n  @Throws(IOException::class)\n  fun read(fileOffset: Long, sink: Buffer, byteCount: Long): Long {\n    lock.withLock {\n      check(!closed) { \"closed\" }\n    }\n    return readNoCloseCheck(fileOffset, sink, byteCount)\n  }\n\n  /**\n   * Returns the total number of bytes in the file. This will change if the file size changes.\n   */\n  @Throws(IOException::class)\n  fun size(): Long {\n    lock.withLock {\n      check(!closed) { \"closed\" }\n    }\n    return protectedSize()\n  }\n\n  /**\n   * Changes the number of bytes in this file to [size]. This will remove bytes from the end if the\n   * new size is smaller. It will add `0` bytes to the end if it is larger.\n   */\n  @Throws(IOException::class)\n  fun resize(size: Long) {\n    check(readWrite) { \"file handle is read-only\" }\n    lock.withLock {\n      check(!closed) { \"closed\" }\n    }\n    return protectedResize(size)\n  }\n\n  /** Reads [byteCount] bytes from [array] and writes them to this at [fileOffset]. */\n  fun write(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    check(readWrite) { \"file handle is read-only\" }\n    lock.withLock {\n      check(!closed) { \"closed\" }\n    }\n    return protectedWrite(fileOffset, array, arrayOffset, byteCount)\n  }\n\n  /** Removes [byteCount] bytes from [source] and writes them to this at [fileOffset]. */\n  @Throws(IOException::class)\n  fun write(fileOffset: Long, source: Buffer, byteCount: Long) {\n    check(readWrite) { \"file handle is read-only\" }\n    lock.withLock {\n      check(!closed) { \"closed\" }\n    }\n    writeNoCloseCheck(fileOffset, source, byteCount)\n  }\n\n  /** Pushes all buffered bytes to their final destination. */\n  @Throws(IOException::class)\n  fun flush() {\n    check(readWrite) { \"file handle is read-only\" }\n    lock.withLock {\n      check(!closed) { \"closed\" }\n    }\n    return protectedFlush()\n  }\n\n  /**\n   * Returns a source that reads from this starting at [fileOffset]. The returned source must be\n   * closed when it is no longer needed.\n   */\n  @Throws(IOException::class)\n  fun source(fileOffset: Long = 0L): Source {\n    lock.withLock {\n      check(!closed) { \"closed\" }\n      openStreamCount++\n    }\n    return FileHandleSource(this, fileOffset)\n  }\n\n  /**\n   * Returns the position of [source] in the file. The argument [source] must be either a source\n   * produced by this file handle, or a [BufferedSource] that directly wraps such a source. If the\n   * parameter is a [BufferedSource], it adjusts for buffered bytes.\n   */\n  @Throws(IOException::class)\n  fun position(source: Source): Long {\n    var source = source\n    var bufferSize = 0L\n\n    if (source is RealBufferedSource) {\n      bufferSize = source.buffer.size\n      source = source.source\n    }\n\n    require(source is FileHandleSource && source.fileHandle === this) {\n      \"source was not created by this FileHandle\"\n    }\n    check(!source.closed) { \"closed\" }\n\n    return source.position - bufferSize\n  }\n\n  /**\n   * Change the position of [source] in the file to [position]. The argument [source] must be either\n   * a source produced by this file handle, or a [BufferedSource] that directly wraps such a source.\n   * If the parameter is a [BufferedSource], it will skip or clear buffered bytes.\n   */\n  @Throws(IOException::class)\n  fun reposition(source: Source, position: Long) {\n    if (source is RealBufferedSource) {\n      val fileHandleSource = source.source\n      require(fileHandleSource is FileHandleSource && fileHandleSource.fileHandle === this) {\n        \"source was not created by this FileHandle\"\n      }\n      check(!fileHandleSource.closed) { \"closed\" }\n\n      val bufferSize = source.buffer.size\n      val toSkip = position - (fileHandleSource.position - bufferSize)\n      if (toSkip in 0L until bufferSize) {\n        // The new position requires only a buffer change.\n        source.skip(toSkip)\n      } else {\n        // The new position doesn't share data with the current buffer.\n        source.buffer.clear()\n        fileHandleSource.position = position\n      }\n    } else {\n      require(source is FileHandleSource && source.fileHandle === this) {\n        \"source was not created by this FileHandle\"\n      }\n      check(!source.closed) { \"closed\" }\n      source.position = position\n    }\n  }\n\n  /**\n   * Returns a sink that writes to this starting at [fileOffset]. The returned sink must be closed\n   * when it is no longer needed.\n   */\n  @Throws(IOException::class)\n  fun sink(fileOffset: Long = 0L): Sink {\n    check(readWrite) { \"file handle is read-only\" }\n    lock.withLock {\n      check(!closed) { \"closed\" }\n      openStreamCount++\n    }\n    return FileHandleSink(this, fileOffset)\n  }\n\n  /**\n   * Returns a sink that writes to this starting at the end. The returned sink must be closed when\n   * it is no longer needed.\n   */\n  @Throws(IOException::class)\n  fun appendingSink(): Sink {\n    return sink(size())\n  }\n\n  /**\n   * Returns the position of [sink] in the file. The argument [sink] must be either a sink produced\n   * by this file handle, or a [BufferedSink] that directly wraps such a sink. If the parameter is a\n   * [BufferedSink], it adjusts for buffered bytes.\n   */\n  @Throws(IOException::class)\n  fun position(sink: Sink): Long {\n    var sink = sink\n    var bufferSize = 0L\n\n    if (sink is RealBufferedSink) {\n      bufferSize = sink.buffer.size\n      sink = sink.sink\n    }\n\n    require(sink is FileHandleSink && sink.fileHandle === this) {\n      \"sink was not created by this FileHandle\"\n    }\n    check(!sink.closed) { \"closed\" }\n\n    return sink.position + bufferSize\n  }\n\n  /**\n   * Change the position of [sink] in the file to [position]. The argument [sink] must be either a\n   * sink produced by this file handle, or a [BufferedSink] that directly wraps such a sink. If the\n   * parameter is a [BufferedSink], it emits for buffered bytes.\n   */\n  @Throws(IOException::class)\n  fun reposition(sink: Sink, position: Long) {\n    if (sink is RealBufferedSink) {\n      val fileHandleSink = sink.sink\n      require(fileHandleSink is FileHandleSink && fileHandleSink.fileHandle === this) {\n        \"sink was not created by this FileHandle\"\n      }\n      check(!fileHandleSink.closed) { \"closed\" }\n\n      sink.emit()\n      fileHandleSink.position = position\n    } else {\n      require(sink is FileHandleSink && sink.fileHandle === this) {\n        \"sink was not created by this FileHandle\"\n      }\n      check(!sink.closed) { \"closed\" }\n      sink.position = position\n    }\n  }\n\n  @Throws(IOException::class)\n  final override fun close() {\n    lock.withLock {\n      if (closed) return\n      closed = true\n      if (openStreamCount != 0) return\n    }\n    protectedClose()\n  }\n\n  /** Like [read] but not performing any close check. */\n  @Throws(IOException::class)\n  protected abstract fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int\n\n  /** Like [write] but not performing any close check. */\n  @Throws(IOException::class)\n  protected abstract fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  )\n\n  /** Like [flush] but not performing any close check. */\n  @Throws(IOException::class)\n  protected abstract fun protectedFlush()\n\n  /** Like [resize] but not performing any close check. */\n  @Throws(IOException::class)\n  protected abstract fun protectedResize(size: Long)\n\n  /** Like [size] but not performing any close check. */\n  @Throws(IOException::class)\n  protected abstract fun protectedSize(): Long\n\n  /**\n   * Subclasses should implement this to release resources held by this file handle. It is invoked\n   * once both the file handle is closed, and also all sources and sinks produced by it are also\n   * closed.\n   */\n  @Throws(IOException::class)\n  protected abstract fun protectedClose()\n\n  private fun readNoCloseCheck(fileOffset: Long, sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n\n    var currentOffset = fileOffset\n    val targetOffset = fileOffset + byteCount\n\n    while (currentOffset < targetOffset) {\n      val tail = sink.writableSegment(1)\n      val readByteCount = protectedRead(\n        fileOffset = currentOffset,\n        array = tail.data,\n        arrayOffset = tail.limit,\n        byteCount = minOf(targetOffset - currentOffset, Segment.SIZE - tail.limit).toInt(),\n      )\n\n      if (readByteCount == -1) {\n        if (tail.pos == tail.limit) {\n          // We allocated a tail segment, but didn't end up needing it. Recycle!\n          sink.head = tail.pop()\n          SegmentPool.recycle(tail)\n        }\n        if (fileOffset == currentOffset) return -1L // We wanted bytes but didn't return any.\n        break\n      }\n\n      tail.limit += readByteCount\n      currentOffset += readByteCount\n      sink.size += readByteCount\n    }\n\n    return currentOffset - fileOffset\n  }\n\n  private fun writeNoCloseCheck(fileOffset: Long, source: Buffer, byteCount: Long) {\n    checkOffsetAndCount(source.size, 0L, byteCount)\n\n    var currentOffset = fileOffset\n    val targetOffset = fileOffset + byteCount\n\n    while (currentOffset < targetOffset) {\n      val head = source.head!!\n      val toCopy = minOf(targetOffset - currentOffset, head.limit - head.pos).toInt()\n      protectedWrite(currentOffset, head.data, head.pos, toCopy)\n\n      head.pos += toCopy\n      currentOffset += toCopy\n      source.size -= toCopy\n\n      if (head.pos == head.limit) {\n        source.head = head.pop()\n        SegmentPool.recycle(head)\n      }\n    }\n  }\n\n  private class FileHandleSink(\n    val fileHandle: FileHandle,\n    var position: Long,\n  ) : Sink {\n    var closed = false\n\n    override fun write(source: Buffer, byteCount: Long) {\n      check(!closed) { \"closed\" }\n      fileHandle.writeNoCloseCheck(position, source, byteCount)\n      position += byteCount\n    }\n\n    override fun flush() {\n      check(!closed) { \"closed\" }\n      fileHandle.protectedFlush()\n    }\n\n    override fun timeout() = Timeout.NONE\n\n    override fun close() {\n      if (closed) return\n      closed = true\n      fileHandle.lock.withLock {\n        fileHandle.openStreamCount--\n        if (fileHandle.openStreamCount != 0 || !fileHandle.closed) return@close\n      }\n      fileHandle.protectedClose()\n    }\n  }\n\n  private class FileHandleSource(\n    val fileHandle: FileHandle,\n    var position: Long,\n  ) : Source {\n    var closed = false\n\n    override fun read(sink: Buffer, byteCount: Long): Long {\n      check(!closed) { \"closed\" }\n      val result = fileHandle.readNoCloseCheck(position, sink, byteCount)\n      if (result != -1L) position += result\n      return result\n    }\n\n    override fun timeout() = Timeout.NONE\n\n    override fun close() {\n      if (closed) return\n      closed = true\n      fileHandle.lock.withLock {\n        fileHandle.openStreamCount--\n        if (fileHandle.openStreamCount != 0 || !fileHandle.closed) return@close\n      }\n      fileHandle.protectedClose()\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/FileMetadata.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.reflect.KClass\nimport kotlin.reflect.cast\n\n/**\n * Description of a file or another object referenced by a path.\n *\n * In simple use a file system is a mechanism for organizing files and directories on a local\n * storage device. In practice file systems are more capable and their contents more varied. For\n * example, a path may refer to:\n *\n *  * An operating system process that consumes data, produces data, or both. For example, reading\n *    from the `/dev/urandom` file on Linux returns a unique sequence of pseudorandom bytes to each\n *    reader.\n *\n *  * A stream that connects a pair of programs together. A pipe is a special file that a producing\n *    program writes to and a consuming program reads from. Both programs operate concurrently. The\n *    size of a pipe is not well defined: the writer can write as much data as the reader is able to\n *    read.\n *\n *  * A file on a remote file system. The performance and availability of remote files may be quite\n *    different from that of local files!\n *\n *  * A symbolic link (symlink) to another path. When attempting to access this path the file system\n *    will follow the link and return data from the target path.\n *\n *  * The same content as another path without a symlink. On UNIX file systems an inode is an\n *    anonymous handle to a file's content, and multiple paths may target the same inode without any\n *    other relationship to one another. A consequence of this design is that a directory with three\n *    1 GiB files may only need 1 GiB on the storage device.\n *\n * This class does not attempt to model these rich file system features! It exposes a limited view\n * useful for programs with only basic file system needs. Be cautious of the potential consequences\n * of special files when writing programs that operate on a file system.\n *\n * File metadata is subject to change, and code that operates on file systems should defend against\n * changes to the file that occur between reading metadata and subsequent operations.\n */\nclass FileMetadata(\n  /** True if this file is a container of bytes. If this is true, then [size] is non-null. */\n  val isRegularFile: Boolean = false,\n\n  /**\n   * True if the path refers to a directory that contains 0 or more child paths.\n   *\n   * Note that a path does not need to be a directory for [FileSystem.list] to return successfully.\n   * For example, mounted storage devices may have child files, but do not identify themselves as\n   * directories.\n   */\n  val isDirectory: Boolean = false,\n\n  /**\n   * The absolute or relative path that this file is a symlink to, or null if this is not a symlink.\n   * If this is a relative path, it is relative to the source file's parent directory.\n   */\n  val symlinkTarget: Path? = null,\n\n  /**\n   * The number of bytes readable from this file. The amount of storage resources consumed by this\n   * file may be larger (due to block size overhead, redundant copies for RAID, etc.), or smaller\n   * (due to file system compression, shared inodes, etc).\n   */\n  val size: Long? = null,\n\n  /**\n   * The system time of the host computer when this file was created, if the host file system\n   * supports this feature. This is typically available on Windows NTFS file systems and not\n   * available on UNIX or Windows FAT file systems.\n   */\n  val createdAtMillis: Long? = null,\n\n  /**\n   * The system time of the host computer when this file was most recently written.\n   *\n   * Note that the accuracy of the returned time may be much more coarse than its precision. In\n   * particular, this value is expressed with millisecond precision but may be accessed at\n   * second- or day-accuracy only.\n   */\n  val lastModifiedAtMillis: Long? = null,\n\n  /**\n   * The system time of the host computer when this file was most recently read or written.\n   *\n   * Note that the accuracy of the returned time may be much more coarse than its precision. In\n   * particular, this value is expressed with millisecond precision but may be accessed at\n   * second- or day-accuracy only.\n   */\n  val lastAccessedAtMillis: Long? = null,\n\n  extras: Map<KClass<*>, Any> = mapOf(),\n) {\n  /**\n   * Additional file system-specific metadata organized by the class of that metadata. File systems\n   * may use this to include information like permissions, content-type, or linked applications.\n   *\n   * Values in this map should be instances of immutable classes. Keys should be the types of those\n   * classes.\n   */\n  val extras: Map<KClass<*>, Any> = extras.toMap()\n\n  /** Returns extra metadata of type [type], or null if no such metadata is held. */\n  fun <T : Any> extra(type: KClass<out T>): T? {\n    val value = extras[type] ?: return null\n    return type.cast(value)\n  }\n\n  fun copy(\n    isRegularFile: Boolean = this.isRegularFile,\n    isDirectory: Boolean = this.isDirectory,\n    symlinkTarget: Path? = this.symlinkTarget,\n    size: Long? = this.size,\n    createdAtMillis: Long? = this.createdAtMillis,\n    lastModifiedAtMillis: Long? = this.lastModifiedAtMillis,\n    lastAccessedAtMillis: Long? = this.lastAccessedAtMillis,\n    extras: Map<KClass<*>, Any> = this.extras,\n  ): FileMetadata {\n    return FileMetadata(\n      isRegularFile = isRegularFile,\n      isDirectory = isDirectory,\n      symlinkTarget = symlinkTarget,\n      size = size,\n      createdAtMillis = createdAtMillis,\n      lastAccessedAtMillis = lastAccessedAtMillis,\n      lastModifiedAtMillis = lastModifiedAtMillis,\n      extras = extras,\n    )\n  }\n\n  override fun toString(): String {\n    val fields = mutableListOf<String>()\n    if (isRegularFile) fields += \"isRegularFile\"\n    if (isDirectory) fields += \"isDirectory\"\n    if (size != null) fields += \"byteCount=$size\"\n    if (createdAtMillis != null) fields += \"createdAt=$createdAtMillis\"\n    if (lastModifiedAtMillis != null) fields += \"lastModifiedAt=$lastModifiedAtMillis\"\n    if (lastAccessedAtMillis != null) fields += \"lastAccessedAt=$lastAccessedAtMillis\"\n    if (extras.isNotEmpty()) fields += \"extras=$extras\"\n    return fields.joinToString(separator = \", \", prefix = \"FileMetadata(\", postfix = \")\")\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/FileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\n/**\n * Read and write access to a hierarchical collection of files, addressed by [paths][Path]. This\n * is a natural interface to the current computer's local file system.\n *\n * Other implementations are possible:\n *\n *  * `FakeFileSystem` is an in-memory file system suitable for testing. Note that this class is\n *    included in the `okio-fakefilesystem` artifact.\n *\n *  * [ForwardingFileSystem] is a file system decorator. Use it to apply monitoring, encryption,\n *    compression, or filtering to another file system.\n *\n *  * A ZIP file system could provide access to the contents of a `.zip` file.\n *\n * For improved capability and testability, consider structuring your classes to dependency inject\n * a `FileSystem` rather than using `FileSystem.SYSTEM` directly.\n *\n * Small API\n * ---------\n *\n * This interface is deliberately limited in which features it supports.\n *\n * It is not suitable for high-latency or unreliable remote file systems. It lacks support for\n * retries, timeouts, cancellation, and bulk operations.\n *\n * It cannot create special file types like hard links, pipes, or mounts. Reading or writing these\n * files works as if they were regular files.\n *\n * It cannot read or write file access control features like the UNIX `chmod` and Windows access\n * control lists. It does honor these controls and will fail with an [IOException] if privileges\n * are insufficient!\n *\n * It cannot lock files or check which files are locked.\n *\n * It cannot watch the file system for changes.\n *\n * Applications that need rich file system features should use another API!\n *\n * Multiplatform\n * -------------\n *\n * This class supports a matrix of Kotlin platforms (JVM, Kotlin/Native, Kotlin/JS) and operating\n * systems (Linux, macOS, and Windows). It attempts to balance working similarly across platforms\n * with being consistent with the local operating system.\n *\n * This is a blocking API which limits its applicability on concurrent Node.js services. File\n * operations will block the event loop (and all JavaScript execution!) until they complete.\n *\n * It supports the path schemes of both Windows (like `C:\\Users`) and UNIX (like `/home`). Note that\n * path resolution rules differ by platform.\n *\n * Differences vs. Java IO APIs\n * ----------------------------\n *\n * The `java.io.File` class is Java's original file system API. The `delete` and `renameTo` methods\n * return false if the operation failed. The `list` method returns null if the file isn't a\n * directory or could not be listed. This class always throws an [IOException] when an operation\n * doesn't succeed.\n *\n * The `java.nio.file.Path` and `java.nio.file.Files` classes are the entry points of Java's new file system\n * API. Each `Path` instance is scoped to a particular file system, though that is often implicit\n * because the `Paths.get()` function automatically uses the default (ie. system) file system.\n * In Okio's API paths are just identifiers; you must use a specific `FileSystem` object to do\n * I/O with.\n *\n * Closeable\n * ---------\n *\n * Implementations of this interface may need to be closed to release resources.\n *\n * It is the file system implementor's responsibility to document whether a file system instance\n * must be closed, and what happens to its open streams when the file system is closed. For example,\n * the Java NIO FileSystem closes all of its open streams when the file system is closed.\n *\n * The built-in `FileSystem.SYSTEM` implementation does not need to be closed and closing it has no\n * effect.\n */\nexpect abstract class FileSystem() : Closeable {\n\n  /**\n   * Resolves [path] against the current working directory and symlinks in this file system. The\n   * returned path identifies the same file as [path], but with an absolute path that does not\n   * include any symbolic links.\n   *\n   * This is similar to `File.getCanonicalFile()` on the JVM and `realpath` on POSIX. Unlike\n   * `File.getCanonicalFile()`, this throws if the file doesn't exist.\n   *\n   * @throws IOException if [path] cannot be resolved. This will occur if the file doesn't exist,\n   *     if the current working directory doesn't exist or is inaccessible, or if another failure\n   *     occurs while resolving the path.\n   */\n  @Throws(IOException::class)\n  abstract fun canonicalize(path: Path): Path\n\n  /**\n   * Returns metadata of the file, directory, or object identified by [path].\n   *\n   * @throws IOException if [path] does not exist or its metadata cannot be read.\n   */\n  @Throws(IOException::class)\n  fun metadata(path: Path): FileMetadata\n\n  /**\n   * Returns metadata of the file, directory, or object identified by [path]. This returns null if\n   * there is no file at [path].\n   *\n   * @throws IOException if [path] cannot be accessed due to a connectivity problem, permissions\n   *     problem, or other issue.\n   */\n  @Throws(IOException::class)\n  abstract fun metadataOrNull(path: Path): FileMetadata?\n\n  /**\n   * Returns true if [path] identifies an object on this file system.\n   *\n   * @throws IOException if [path] cannot be accessed due to a connectivity problem, permissions\n   *     problem, or other issue.\n   */\n  @Throws(IOException::class)\n  fun exists(path: Path): Boolean\n\n  /**\n   * Returns the children of [dir]. The returned list is sorted using natural ordering. If [dir] is\n   * a relative path, the returned elements will also be relative paths. If it is an absolute path,\n   * the returned elements will also be absolute paths.\n   *\n   * Note that a path does not need to be a [directory][FileMetadata.isDirectory] for this function\n   * to return successfully. For example, mounted storage devices may have child files but do not\n   * identify themselves as directories.\n   *\n   * @throws IOException if [dir] does not exist or cannot be listed. A path cannot be listed if the\n   *     current process doesn't have access to [dir], or if there's a loop of symbolic links, or if\n   *     any name is too long.\n   */\n  @Throws(IOException::class)\n  abstract fun list(dir: Path): List<Path>\n\n  /**\n   * Returns the children of the directory identified by [dir]. The returned list is sorted using\n   * natural ordering. If [dir] is a relative path, the returned elements will also be relative\n   * paths. If it is an absolute path, the returned elements will also be absolute paths.\n   *\n   * This returns null if [dir] does not exist or cannot be listed. A directory cannot be listed if\n   * the current process doesn't have access to [dir], or if there's a loop of symbolic links, or if\n   * any name is too long.\n   */\n  abstract fun listOrNull(dir: Path): List<Path>?\n\n  /**\n   * Returns a sequence that **lazily** traverses the children of [dir] using repeated calls to\n   * [list]. If none of [dir]'s children are directories this returns the same elements as [list].\n   *\n   * The returned sequence visits the tree of files in depth-first order. Parent paths are returned\n   * before their children.\n   *\n   * Note that [listRecursively] does not throw exceptions but the returned sequence does. When it\n   * is iterated, the returned sequence throws a [FileNotFoundException] if [dir] does not exist, or\n   * an [IOException] if [dir] cannot be listed.\n   *\n   * @param followSymlinks true to follow symlinks while traversing the children. If [dir] itself is\n   *     a symlink it will be followed even if this parameter is false.\n   */\n  open fun listRecursively(dir: Path, followSymlinks: Boolean = false): Sequence<Path>\n\n  /**\n   * Returns a handle to read [file]. This will fail if the file doesn't already exist.\n   *\n   * @throws IOException if [file] does not exist, is not a file, or cannot be accessed. A file\n   *     cannot be accessed if the current process doesn't have sufficient permissions for [file],\n   *     if there's a loop of symbolic links, or if any name is too long.\n   */\n  @Throws(IOException::class)\n  abstract fun openReadOnly(file: Path): FileHandle\n\n  /**\n   * Returns a handle to read and write [file]. This will create the file if it doesn't already\n   * exist.\n   *\n   * @param mustCreate true to throw an [IOException] instead of overwriting an existing file.\n   *     This is equivalent to `O_EXCL` on POSIX and `CREATE_NEW` on Windows.\n   * @param mustExist true to throw an [IOException] instead of creating a new file. This is\n   *     equivalent to `r+` on POSIX and `OPEN_EXISTING` on Windows.\n   * @throws IOException if [file] is not a file, or cannot be accessed. A file cannot be accessed\n   *     if the current process doesn't have sufficient reading and writing permissions for [file],\n   *     if there's a loop of symbolic links, or if any name is too long.\n   */\n  @Throws(IOException::class)\n  abstract fun openReadWrite(\n    file: Path,\n    mustCreate: Boolean = false,\n    mustExist: Boolean = false,\n  ): FileHandle\n\n  /**\n   * Returns a source that reads the bytes of [file] from beginning to end.\n   *\n   * @throws IOException if [file] does not exist, is not a file, or cannot be read. A file cannot\n   *     be read if the current process doesn't have access to [file], if there's a loop of symbolic\n   *     links, or if any name is too long.\n   */\n  @Throws(IOException::class)\n  abstract fun source(file: Path): Source\n\n  /**\n   * Creates a source to read [file], executes [readerAction] to read it, and then closes the\n   * source. This is a compact way to read the contents of a file.\n   */\n  @Throws(IOException::class)\n  inline fun <T> read(file: Path, readerAction: BufferedSource.() -> T): T\n\n  /**\n   * Returns a sink that writes bytes to [file] from beginning to end. If [file] already exists it\n   * will be replaced with the new data.\n   *\n   * @param mustCreate true to throw an [IOException] instead of overwriting an existing file.\n   *     This is equivalent to `O_EXCL` on POSIX and `CREATE_NEW` on Windows.\n   *\n   * @throws IOException if [file] cannot be written. A file cannot be written if its enclosing\n   *     directory does not exist, if the current process doesn't have access to [file], if there's\n   *     a loop of symbolic links, or if any name is too long.\n   */\n  @Throws(IOException::class)\n  abstract fun sink(file: Path, mustCreate: Boolean = false): Sink\n\n  /**\n   * Creates a sink to write [file], executes [writerAction] to write it, and then closes the sink.\n   * This is a compact way to write a file.\n   *\n   * @param mustCreate true to throw an [IOException] instead of overwriting an existing file.\n   *     This is equivalent to `O_EXCL` on POSIX and `CREATE_NEW` on Windows.\n   */\n  @Throws(IOException::class)\n  inline fun <T> write(\n    file: Path,\n    mustCreate: Boolean = false,\n    writerAction: BufferedSink.() -> T,\n  ): T\n\n  /**\n   * Returns a sink that appends bytes to the end of [file], creating it if it doesn't already\n   * exist.\n   *\n   * @param mustExist true to throw an [IOException] instead of creating a new file. This is\n   *     equivalent to `r+` on POSIX and `OPEN_EXISTING` on Windows.\n   *\n   * @throws IOException if [file] cannot be written. A file cannot be written if its enclosing\n   *     directory does not exist, if the current process doesn't have access to [file], if there's\n   *     a loop of symbolic links, or if any name is too long.\n   */\n  @Throws(IOException::class)\n  abstract fun appendingSink(file: Path, mustExist: Boolean = false): Sink\n\n  /**\n   * Creates a directory at the path identified by [dir].\n   *\n   * @param mustCreate true to throw an [IOException] if the directory already exists.\n   * @throws IOException if [dir]'s parent does not exist, is not a directory, or cannot be written.\n   *     A directory cannot be created if the current process doesn't have access, if there's a loop\n   *     of symbolic links, or if any name is too long.\n   */\n  @Throws(IOException::class)\n  abstract fun createDirectory(dir: Path, mustCreate: Boolean = false)\n\n  /**\n   * Creates a directory at the path identified by [dir], and any enclosing parent path directories,\n   * recursively.\n   *\n   * @param mustCreate true to throw an [IOException] instead of overwriting an existing directory.\n   * @throws IOException if any [metadata] or [createDirectory] operation fails.\n   */\n  @Throws(IOException::class)\n  fun createDirectories(dir: Path, mustCreate: Boolean = false)\n\n  /**\n   * Moves [source] to [target] in-place if the underlying file system supports it. If [target]\n   * exists, it is first removed. If `source == target`, this operation does nothing. This may be\n   * used to move a file or a directory.\n   *\n   * **Only as Atomic as the Underlying File System Supports**\n   *\n   * FAT and NTFS file systems cannot atomically move a file over an existing file. If the target\n   * file already exists, the move is performed into two steps:\n   *\n   *  1. Atomically delete the target file.\n   *  2. Atomically rename the source file to the target file.\n   *\n   * The delete step and move step are each atomic but not atomic in aggregate! If this process\n   * crashes, the host operating system crashes, or the hardware fails it is possible that the\n   * delete step will succeed and the rename will not.\n   *\n   * **Entire-file or nothing**\n   *\n   * These are the possible results of this operation:\n   *\n   *  * This operation returns normally, the source file is absent, and the target file contains the\n   *    data previously held by the source file. This is the success case.\n   *\n   *  * The operation throws an [IOException] and the file system is unchanged. For example, this\n   *    occurs if this process lacks permissions to perform the move.\n   *\n   *  * This operation throws an [IOException], the target file is deleted, but the source file is\n   *    unchanged. This is the partial failure case described above and is only possible on\n   *    file systems like FAT and NTFS that do not support atomic file replacement. Typically in\n   *    such cases this operation won't return at all because the process or operating system has\n   *    also crashed.\n   *\n   * There is no failure mode where the target file holds a subset of the bytes of the source file.\n   * If the rename step cannot be performed atomically, this function will throw an [IOException]\n   * before attempting a move. Typically this occurs if the source and target files are on different\n   * physical volumes.\n   *\n   * **Non-Atomic Moves**\n   *\n   * If you need to move files across volumes, use [copy] followed by [delete], and change your\n   * application logic to recover should the copy step suffer a partial failure.\n   *\n   * @throws IOException if the move cannot be performed, or cannot be performed atomically. Moves\n   *     fail if the source doesn't exist, if the target is not writable, if the target already\n   *     exists and cannot be replaced, or if the move would cause physical or quota limits to be\n   *     exceeded. This list of potential problems is not exhaustive.\n   */\n  @Throws(IOException::class)\n  abstract fun atomicMove(source: Path, target: Path)\n\n  /**\n   * Copies all the bytes from the file at [source] to the file at [target]. This does not copy\n   * file metadata like last modified time, permissions, or extended attributes.\n   *\n   * This function is not atomic; a failure may leave [target] in an inconsistent state. For\n   * example, [target] may be empty or contain only a prefix of [source].\n   *\n   * @throws IOException if [source] cannot be read or if [target] cannot be written.\n   */\n  @Throws(IOException::class)\n  open fun copy(source: Path, target: Path)\n\n  /**\n   * Deletes the file or directory at [path].\n   *\n   * @param mustExist true to throw an [IOException] if there is nothing at [path] to delete.\n   * @throws IOException if there is a file or directory but it could not be deleted. Deletes fail\n   *     if the current process doesn't have access, if the file system is readonly, or if [path]\n   *     is a non-empty directory. This list of potential problems is not exhaustive.\n   */\n  @Throws(IOException::class)\n  abstract fun delete(path: Path, mustExist: Boolean = false)\n\n  /**\n   * Recursively deletes all children of [fileOrDirectory] if it is a directory, then deletes\n   * [fileOrDirectory] itself.\n   *\n   * This function does not defend against race conditions. For example, if child files are created\n   * or deleted in [fileOrDirectory] while this function is executing, this may fail with an\n   * [IOException].\n   *\n   * @param mustExist true to throw an [IOException] if there is nothing at [fileOrDirectory] to\n   *     delete.\n   * @throws IOException if any [metadata], [list], or [delete] operation fails.\n   */\n  @Throws(IOException::class)\n  open fun deleteRecursively(fileOrDirectory: Path, mustExist: Boolean = false)\n\n  /**\n   * Creates a symbolic link at [source] that resolves to [target]. If [target] is a relative path,\n   * it is relative to `source.parent`.\n   *\n   * @throws IOException if [source] cannot be created. This may be because it already exists\n   *     or because its storage doesn't support symlinks. This list of potential problems is not\n   *     exhaustive.\n   */\n  @Throws(IOException::class)\n  abstract fun createSymlink(source: Path, target: Path)\n\n  @Throws(IOException::class)\n  override fun close()\n\n  companion object {\n    /**\n     * Returns a writable temporary directory on [SYSTEM].\n     *\n     * This is platform-specific.\n     *\n     *  * **JVM and Android**: the path in the `java.io.tmpdir` system property\n     *  * **Linux, iOS, and macOS**: the path in the `TMPDIR` environment variable.\n     *  * **Windows**: the first non-null of `TEMP`, `TMP`, and `USERPROFILE` environment variables.\n     *\n     * **Note that the returned directory is not generally private.** Other users or processes that\n     * share this file system may read data that is written to this directory, or write malicious\n     * data for this process to receive.\n     */\n    val SYSTEM_TEMPORARY_DIRECTORY: Path\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/ForwardingFileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.jvm.JvmName\n\n/**\n * A [FileSystem] that forwards calls to another, intended for subclassing.\n *\n * ### Fault Injection\n *\n * You can use this to deterministically trigger file system failures in tests. This is useful to\n * confirm that your program behaves correctly even if its file system operations fail. For example,\n * this subclass fails every access of files named `unlucky.txt`:\n *\n * ```kotlin\n * val faultyFileSystem = object : ForwardingFileSystem(FileSystem.SYSTEM) {\n *   override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n *     if (path.name == \"unlucky.txt\") throw IOException(\"synthetic failure!\")\n *     return path\n *   }\n * }\n * ```\n *\n * You can fail specific operations by overriding them directly:\n *\n * ```kotlin\n * val faultyFileSystem = object : ForwardingFileSystem(FileSystem.SYSTEM) {\n *   override fun delete(path: Path) {\n *     throw IOException(\"synthetic failure!\")\n *   }\n * }\n * ```\n *\n * ### Observability\n *\n * You can extend this to verify which files your program accesses. This is a testing file system\n * that records accesses as they happen:\n *\n * ```kotlin\n * class LoggingFileSystem : ForwardingFileSystem(FileSystem.SYSTEM) {\n *   val log = mutableListOf<String>()\n *\n *   override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n *     log += \"$functionName($parameterName=$path)\"\n *     return path\n *   }\n * }\n * ```\n *\n * This makes it easy for tests to assert exactly which files were accessed.\n *\n * ```kotlin\n * @Test\n * fun testMergeJsonReports() {\n *   createSampleJsonReports()\n *   loggingFileSystem.log.clear()\n *\n *   mergeJsonReports()\n *\n *   assertThat(loggingFileSystem.log).containsExactly(\n *     \"list(dir=json_reports)\",\n *     \"source(file=json_reports/2020-10.json)\",\n *     \"source(file=json_reports/2020-12.json)\",\n *     \"source(file=json_reports/2020-11.json)\",\n *     \"sink(file=json_reports/2020-all.json)\"\n *   )\n * }\n * ```\n *\n * ### Transformations\n *\n * Subclasses can transform file names and content.\n *\n * For example, your program may be written to operate on a well-known directory like `/etc/` or\n * `/System`. You can rewrite paths to make such operations safer to test.\n *\n * You may also transform file content to apply application-layer encryption or compression. This\n * is particularly useful in situations where it's difficult or impossible to enable those features\n * in the underlying file system.\n *\n * ### Abstract Functions Only\n *\n * Some file system functions like [copy] are implemented by using other features. These are the\n * non-abstract functions in the [FileSystem] interface.\n *\n * **This class forwards only the abstract functions;** non-abstract functions delegate to the\n * other functions of this class. If desired, subclasses may override non-abstract functions to\n * forward them.\n *\n * ### Closeable\n *\n * Closing this file system closes the delegate file system.\n */\nabstract class ForwardingFileSystem(\n  /** [FileSystem] to which this instance is delegating. */\n  @get:JvmName(\"delegate\")\n  val delegate: FileSystem,\n) : FileSystem() {\n\n  /**\n   * Invoked each time a path is passed as a parameter to this file system. This returns the path to\n   * pass to [delegate], which should be [path] itself or a path on [delegate] that corresponds to\n   * it.\n   *\n   * Subclasses may override this to log accesses, fail on unexpected accesses, or map paths across\n   * file systems.\n   *\n   * The base implementation returns [path].\n   *\n   * Note that this function will be called twice for calls to [atomicMove]; once for the source\n   * file and once for the target file.\n   *\n   * @param path the path passed to any of the functions of this.\n   * @param functionName a string like \"canonicalize\", \"metadataOrNull\", or \"appendingSink\".\n   * @param parameterName a string like \"path\", \"file\", \"source\", or \"target\".\n   * @return the path to pass to [delegate] for the same parameter.\n   */\n  open fun onPathParameter(path: Path, functionName: String, parameterName: String): Path = path\n\n  /**\n   * Invoked each time a path is returned by [delegate]. This returns the path to return to the\n   * caller, which should be [path] itself or a path on this that corresponds to it.\n   *\n   * Subclasses may override this to log accesses, fail on unexpected path accesses, or map\n   * directories or path names.\n   *\n   * The base implementation returns [path].\n   *\n   * @param path the path returned by any of the functions of this.\n   * @param functionName a string like \"canonicalize\" or \"list\".\n   * @return the path to return to the caller.\n   */\n  open fun onPathResult(path: Path, functionName: String): Path = path\n\n  @Throws(IOException::class)\n  override fun canonicalize(path: Path): Path {\n    val path = onPathParameter(path, \"canonicalize\", \"path\")\n    val result = delegate.canonicalize(path)\n    return onPathResult(result, \"canonicalize\")\n  }\n\n  @Throws(IOException::class)\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    val path = onPathParameter(path, \"metadataOrNull\", \"path\")\n    val metadataOrNull = delegate.metadataOrNull(path) ?: return null\n    if (metadataOrNull.symlinkTarget == null) return metadataOrNull\n\n    val symlinkTarget = onPathResult(metadataOrNull.symlinkTarget, \"metadataOrNull\")\n    return metadataOrNull.copy(symlinkTarget = symlinkTarget)\n  }\n\n  @Throws(IOException::class)\n  override fun list(dir: Path): List<Path> {\n    val dir = onPathParameter(dir, \"list\", \"dir\")\n    val result = delegate.list(dir)\n    val paths = result.mapTo(mutableListOf()) { onPathResult(it, \"list\") }\n    paths.sort()\n    return paths\n  }\n\n  override fun listOrNull(dir: Path): List<Path>? {\n    val dir = onPathParameter(dir, \"listOrNull\", \"dir\")\n    val result = delegate.listOrNull(dir) ?: return null\n    val paths = result.mapTo(mutableListOf()) { onPathResult(it, \"listOrNull\") }\n    paths.sort()\n    return paths\n  }\n\n  override fun listRecursively(dir: Path, followSymlinks: Boolean): Sequence<Path> {\n    val dir = onPathParameter(dir, \"listRecursively\", \"dir\")\n    val result = delegate.listRecursively(dir, followSymlinks)\n    return result.map { onPathResult(it, \"listRecursively\") }\n  }\n\n  @Throws(IOException::class)\n  override fun openReadOnly(file: Path): FileHandle {\n    val file = onPathParameter(file, \"openReadOnly\", \"file\")\n    return delegate.openReadOnly(file)\n  }\n\n  @Throws(IOException::class)\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    val file = onPathParameter(file, \"openReadWrite\", \"file\")\n    return delegate.openReadWrite(file, mustCreate, mustExist)\n  }\n\n  @Throws(IOException::class)\n  override fun source(file: Path): Source {\n    val file = onPathParameter(file, \"source\", \"file\")\n    return delegate.source(file)\n  }\n\n  @Throws(IOException::class)\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    val file = onPathParameter(file, \"sink\", \"file\")\n    return delegate.sink(file, mustCreate)\n  }\n\n  @Throws(IOException::class)\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    val file = onPathParameter(file, \"appendingSink\", \"file\")\n    return delegate.appendingSink(file, mustExist)\n  }\n\n  @Throws(IOException::class)\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    val dir = onPathParameter(dir, \"createDirectory\", \"dir\")\n    delegate.createDirectory(dir, mustCreate)\n  }\n\n  @Throws(IOException::class)\n  override fun atomicMove(source: Path, target: Path) {\n    val source = onPathParameter(source, \"atomicMove\", \"source\")\n    val target = onPathParameter(target, \"atomicMove\", \"target\")\n    delegate.atomicMove(source, target)\n  }\n\n  @Throws(IOException::class)\n  override fun delete(path: Path, mustExist: Boolean) {\n    val path = onPathParameter(path, \"delete\", \"path\")\n    delegate.delete(path, mustExist)\n  }\n\n  @Throws(IOException::class)\n  override fun createSymlink(source: Path, target: Path) {\n    val source = onPathParameter(source, \"createSymlink\", \"source\")\n    val target = onPathParameter(target, \"createSymlink\", \"target\")\n    delegate.createSymlink(source, target)\n  }\n\n  @Throws(IOException::class)\n  override fun close() {\n    delegate.close()\n  }\n\n  override fun toString() = \"${this::class.simpleName}($delegate)\"\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/ForwardingSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\n/** A [Source] which forwards calls to another. Useful for subclassing. */\nexpect abstract class ForwardingSource constructor(\n  /** [Source] to which this instance is delegating. */\n  delegate: Source,\n) : Source {\n  /** [Source] to which this instance is delegating. */\n  val delegate: Source\n\n  // TODO 'Source by delegate' once https://youtrack.jetbrains.com/issue/KT-23935 is fixed.\n\n  @Throws(IOException::class)\n  override fun read(sink: Buffer, byteCount: Long): Long\n\n  override fun timeout(): Timeout\n\n  @Throws(IOException::class)\n  override fun close()\n\n  override fun toString(): String\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/HashingSink.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\n/**\n * A sink that computes a hash of the full stream of bytes it has accepted. To use, create an\n * instance with your preferred hash algorithm. Write all of the data to the sink and then call\n * [hash] to compute the final hash value.\n *\n * In this example we use `HashingSink` with a [BufferedSink] to make writing to the\n * sink easier.\n *\n * ```java\n * HashingSink hashingSink = HashingSink.sha256(s);\n * BufferedSink bufferedSink = Okio.buffer(hashingSink);\n *\n * ... // Write to bufferedSink and either flush or close it.\n *\n * ByteString hash = hashingSink.hash();\n * ```\n */\nexpect class HashingSink : Sink {\n\n  /**\n   * Returns the hash of the bytes accepted thus far and resets the internal state of this sink.\n   *\n   * **Warning:** This method is not idempotent. Each time this method is called its\n   * internal state is cleared. This starts a new hash with zero bytes accepted.\n   */\n  val hash: ByteString\n\n  override fun close()\n  override fun flush()\n  override fun timeout(): Timeout\n  override fun write(source: Buffer, byteCount: Long)\n\n  companion object {\n    /**\n     * Returns a sink that uses the obsolete MD5 hash algorithm to produce 128-bit hashes.\n     *\n     * MD5 has been vulnerable to collisions since 2004. It should not be used in new code.\n     */\n    fun md5(sink: Sink): HashingSink\n\n    /**\n     * Returns a sink that uses the obsolete SHA-1 hash algorithm to produce 160-bit hashes.\n     *\n     * SHA-1 has been vulnerable to collisions since 2017. It should not be used in new code.\n     */\n    fun sha1(sink: Sink): HashingSink\n\n    /** Returns a sink that uses the SHA-256 hash algorithm to produce 256-bit hashes. */\n    fun sha256(sink: Sink): HashingSink\n\n    /** Returns a sink that uses the SHA-512 hash algorithm to produce 512-bit hashes. */\n    fun sha512(sink: Sink): HashingSink\n\n    /** Returns a sink that uses the obsolete SHA-1 HMAC algorithm to produce 160-bit hashes. */\n    fun hmacSha1(sink: Sink, key: ByteString): HashingSink\n\n    /** Returns a sink that uses the SHA-256 HMAC algorithm to produce 256-bit hashes. */\n    fun hmacSha256(sink: Sink, key: ByteString): HashingSink\n\n    /** Returns a sink that uses the SHA-512 HMAC algorithm to produce 512-bit hashes. */\n    fun hmacSha512(sink: Sink, key: ByteString): HashingSink\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/HashingSource.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\n/**\n * A source that computes a hash of the full stream of bytes it has supplied. To use, create an\n * instance with your preferred hash algorithm. Exhaust the source by reading all of its bytes and\n * then call [hash] to compute the final hash value.\n *\n *\n * In this example we use `HashingSource` with a [BufferedSource] to make reading\n * from the source easier.\n *\n * ```java\n * HashingSource hashingSource = HashingSource.sha256(rawSource);\n * BufferedSource bufferedSource = Okio.buffer(hashingSource);\n *\n * ... // Read all of bufferedSource.\n *\n * ByteString hash = hashingSource.hash();\n * ```\n */\nexpect class HashingSource : Source {\n\n  /**\n   * Returns the hash of the bytes supplied thus far and resets the internal state of this source.\n   *\n   * **Warning:** This method is not idempotent. Each time this method is called its\n   * internal state is cleared. This starts a new hash with zero bytes supplied.\n   */\n  val hash: ByteString\n\n  override fun close()\n  override fun read(sink: Buffer, byteCount: Long): Long\n  override fun timeout(): Timeout\n\n  companion object {\n    /**\n     * Returns a source that uses the obsolete MD5 hash algorithm to produce 128-bit hashes.\n     *\n     * MD5 has been vulnerable to collisions since 2004. It should not be used in new code.\n     */\n    fun md5(source: Source): HashingSource\n\n    /**\n     * Returns a source that uses the obsolete SHA-1 hash algorithm to produce 160-bit hashes.\n     *\n     * SHA-1 has been vulnerable to collisions since 2017. It should not be used in new code.\n     */\n    fun sha1(source: Source): HashingSource\n\n    /** Returns a source that uses the SHA-256 hash algorithm to produce 256-bit hashes. */\n    fun sha256(source: Source): HashingSource\n\n    /** Returns a source that uses the SHA-512 hash algorithm to produce 512-bit hashes. */\n    fun sha512(source: Source): HashingSource\n\n    /** Returns a source that uses the obsolete SHA-1 HMAC algorithm to produce 160-bit hashes. */\n    fun hmacSha1(source: Source, key: ByteString): HashingSource\n\n    /** Returns a source that uses the SHA-256 HMAC algorithm to produce 256-bit hashes. */\n    fun hmacSha256(source: Source, key: ByteString): HashingSource\n\n    /** Returns a source that uses the SHA-512 HMAC algorithm to produce 512-bit hashes. */\n    fun hmacSha512(source: Source, key: ByteString): HashingSource\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Okio.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\n/** Essential APIs for working with Okio. */\n@file:JvmMultifileClass\n@file:JvmName(\"Okio\")\n\npackage okio\n\nimport kotlin.contracts.InvocationKind\nimport kotlin.contracts.contract\nimport kotlin.jvm.JvmMultifileClass\nimport kotlin.jvm.JvmName\n\n/**\n * Returns a new source that buffers reads from `source`. The returned source will perform bulk\n * reads into its in-memory buffer. Use this wherever you read a source to get an ergonomic and\n * efficient access to data.\n */\nfun Source.buffer(): BufferedSource = RealBufferedSource(this)\n\n/**\n * Returns a new sink that buffers writes to `sink`. The returned sink will batch writes to `sink`.\n * Use this wherever you write to a sink to get an ergonomic and efficient access to data.\n */\nfun Sink.buffer(): BufferedSink = RealBufferedSink(this)\n\n/** Returns a sink that writes nowhere. */\n@JvmName(\"blackhole\")\nfun blackholeSink(): Sink = BlackholeSink()\n\nprivate class BlackholeSink : Sink {\n  override fun write(source: Buffer, byteCount: Long) = source.skip(byteCount)\n  override fun flush() {}\n  override fun timeout() = Timeout.NONE\n  override fun close() {}\n}\n\n/** Execute [block] then close this. This will be closed even if [block] throws. */\ninline fun <T : Closeable?, R> T.use(block: (T) -> R): R {\n  contract {\n    callsInPlace(block, InvocationKind.EXACTLY_ONCE)\n  }\n\n  var thrown: Throwable? = null\n\n  val result = try {\n    block(this)\n  } catch (t: Throwable) {\n    thrown = t\n    null\n  } finally {\n    try {\n      this?.close()\n    } catch (t: Throwable) {\n      if (thrown == null) {\n        thrown = t\n      } else {\n        thrown.addSuppressed(t)\n      }\n    }\n  }\n\n  if (thrown != null) throw thrown\n  @Suppress(\"UNCHECKED_CAST\")\n  return result as R\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Options.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport kotlin.jvm.JvmStatic\n\n/**\n * An indexed set of values that may be read with [BufferedSource.select].\n *\n * Also consider [TypedOptions] to select a typed value _T_.\n */\nclass Options private constructor(\n  internal val byteStrings: Array<out ByteString>,\n  internal val trie: IntArray,\n) : AbstractList<ByteString>(), RandomAccess {\n\n  override val size: Int\n    get() = byteStrings.size\n\n  override fun get(index: Int) = byteStrings[index]\n\n  companion object {\n    @JvmStatic\n    fun of(vararg byteStrings: ByteString): Options {\n      if (byteStrings.isEmpty()) {\n        // With no choices we must always return -1. Create a trie that selects from an empty set.\n        return Options(arrayOf(), intArrayOf(0, -1))\n      }\n\n      // Sort the byte strings which is required when recursively building the trie. Map the sorted\n      // indexes to the caller's indexes.\n      val list = byteStrings.toMutableList()\n      list.sort()\n      val indexes = MutableList(list.size) { -1 }\n      byteStrings.forEachIndexed { callerIndex, byteString ->\n        val sortedIndex = list.binarySearch(byteString)\n        indexes[sortedIndex] = callerIndex\n      }\n      require(list[0].size > 0) { \"the empty byte string is not a supported option\" }\n\n      // Strip elements that will never be returned because they follow their own prefixes. For\n      // example, if the caller provides [\"abc\", \"abcde\"] we will never return \"abcde\" because we\n      // return as soon as we encounter \"abc\".\n      var a = 0\n      while (a < list.size) {\n        val prefix = list[a]\n        var b = a + 1\n        while (b < list.size) {\n          val byteString = list[b]\n          if (!byteString.startsWith(prefix)) break\n          require(byteString.size != prefix.size) { \"duplicate option: $byteString\" }\n          if (indexes[b] > indexes[a]) {\n            list.removeAt(b)\n            indexes.removeAt(b)\n          } else {\n            b++\n          }\n        }\n        a++\n      }\n\n      val trieBytes = Buffer()\n      buildTrieRecursive(node = trieBytes, byteStrings = list, indexes = indexes)\n\n      val trie = IntArray(trieBytes.intCount.toInt()) {\n        trieBytes.readInt()\n      }\n\n      return Options(byteStrings.copyOf() /* Defensive copy. */, trie)\n    }\n\n    /**\n     * Builds a trie encoded as an int array. Nodes in the trie are of two types: SELECT and SCAN.\n     *\n     * SELECT nodes are encoded as:\n     *  - selectChoiceCount: the number of bytes to choose between (a positive int)\n     *  - prefixIndex: the result index at the current position or -1 if the current position is not\n     *    a result on its own\n     *  - a sorted list of selectChoiceCount bytes to match against the input string\n     *  - a heterogeneous list of selectChoiceCount result indexes (>= 0) or offsets (< 0) of the\n     *    next node to follow. Elements in this list correspond to elements in the preceding list.\n     *    Offsets are negative and must be multiplied by -1 before being used.\n     *\n     * SCAN nodes are encoded as:\n     *  - scanByteCount: the number of bytes to match in sequence. This count is negative and must\n     *    be multiplied by -1 before being used.\n     *  - prefixIndex: the result index at the current position or -1 if the current position is not\n     *    a result on its own\n     *  - a list of scanByteCount bytes to match\n     *  - nextStep: the result index (>= 0) or offset (< 0) of the next node to follow. Offsets are\n     *    negative and must be multiplied by -1 before being used.\n     *\n     * This structure is used to improve locality and performance when selecting from a list of\n     * options.\n     */\n    private fun buildTrieRecursive(\n      nodeOffset: Long = 0L,\n      node: Buffer,\n      byteStringOffset: Int = 0,\n      byteStrings: List<ByteString>,\n      fromIndex: Int = 0,\n      toIndex: Int = byteStrings.size,\n      indexes: List<Int>,\n    ) {\n      require(fromIndex < toIndex)\n      for (i in fromIndex until toIndex) {\n        require(byteStrings[i].size >= byteStringOffset)\n      }\n\n      var fromIndex = fromIndex\n      var from = byteStrings[fromIndex]\n      val to = byteStrings[toIndex - 1]\n      var prefixIndex = -1\n\n      // If the first element is already matched, that's our prefix.\n      if (byteStringOffset == from.size) {\n        prefixIndex = indexes[fromIndex]\n        fromIndex++\n        from = byteStrings[fromIndex]\n      }\n\n      if (from[byteStringOffset] != to[byteStringOffset]) {\n        // If we have multiple bytes to choose from, encode a SELECT node.\n        var selectChoiceCount = 1\n        for (i in fromIndex + 1 until toIndex) {\n          if (byteStrings[i - 1][byteStringOffset] != byteStrings[i][byteStringOffset]) {\n            selectChoiceCount++\n          }\n        }\n\n        // Compute the offset that childNodes will get when we append it to node.\n        val childNodesOffset = nodeOffset + node.intCount + 2 + (selectChoiceCount * 2)\n\n        node.writeInt(selectChoiceCount)\n        node.writeInt(prefixIndex)\n\n        for (i in fromIndex until toIndex) {\n          val rangeByte = byteStrings[i][byteStringOffset]\n          if (i == fromIndex || rangeByte != byteStrings[i - 1][byteStringOffset]) {\n            node.writeInt(rangeByte and 0xff)\n          }\n        }\n\n        val childNodes = Buffer()\n        var rangeStart = fromIndex\n        while (rangeStart < toIndex) {\n          val rangeByte = byteStrings[rangeStart][byteStringOffset]\n          var rangeEnd = toIndex\n          for (i in rangeStart + 1 until toIndex) {\n            if (rangeByte != byteStrings[i][byteStringOffset]) {\n              rangeEnd = i\n              break\n            }\n          }\n\n          if (rangeStart + 1 == rangeEnd &&\n            byteStringOffset + 1 == byteStrings[rangeStart].size\n          ) {\n            // The result is a single index.\n            node.writeInt(indexes[rangeStart])\n          } else {\n            // The result is another node.\n            node.writeInt(-1 * (childNodesOffset + childNodes.intCount).toInt())\n            buildTrieRecursive(\n              nodeOffset = childNodesOffset,\n              node = childNodes,\n              byteStringOffset = byteStringOffset + 1,\n              byteStrings = byteStrings,\n              fromIndex = rangeStart,\n              toIndex = rangeEnd,\n              indexes = indexes,\n            )\n          }\n\n          rangeStart = rangeEnd\n        }\n\n        node.writeAll(childNodes)\n      } else {\n        // If all of the bytes are the same, encode a SCAN node.\n        var scanByteCount = 0\n        for (i in byteStringOffset until minOf(from.size, to.size)) {\n          if (from[i] == to[i]) {\n            scanByteCount++\n          } else {\n            break\n          }\n        }\n\n        // Compute the offset that childNodes will get when we append it to node.\n        val childNodesOffset = nodeOffset + node.intCount + 2 + scanByteCount + 1\n\n        node.writeInt(-scanByteCount)\n        node.writeInt(prefixIndex)\n\n        for (i in byteStringOffset until byteStringOffset + scanByteCount) {\n          node.writeInt(from[i] and 0xff)\n        }\n\n        if (fromIndex + 1 == toIndex) {\n          // The result is a single index.\n          check(byteStringOffset + scanByteCount == byteStrings[fromIndex].size)\n          node.writeInt(indexes[fromIndex])\n        } else {\n          // The result is another node.\n          val childNodes = Buffer()\n          node.writeInt(-1 * (childNodesOffset + childNodes.intCount).toInt())\n          buildTrieRecursive(\n            nodeOffset = childNodesOffset,\n            node = childNodes,\n            byteStringOffset = byteStringOffset + scanByteCount,\n            byteStrings = byteStrings,\n            fromIndex = fromIndex,\n            toIndex = toIndex,\n            indexes = indexes,\n          )\n          node.writeAll(childNodes)\n        }\n      }\n    }\n\n    private val Buffer.intCount get() = size / 4\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Path.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport okio.Path.Companion.toPath\n\n/**\n * A hierarchical address on a file system. A path is an identifier only; a [FileSystem] is required\n * to access the file that a path refers to, if any.\n *\n * UNIX and Windows Paths\n * ----------------------\n *\n * Paths follow different rules on UNIX vs. Windows operating systems. On UNIX operating systems\n * (including Linux, Android, macOS, and iOS), the `/` slash character separates path segments. On\n * Windows, the `\\` backslash character separates path segments. The two platforms each have their\n * own rules for path resolution. This class implements all rules on all platforms; for example you\n * can model a Linux path in a native Windows application.\n *\n * Absolute and Relative Paths\n * ---------------------------\n *\n * * **Absolute paths** identify a location independent of any working directory. On UNIX, absolute\n *   paths are prefixed with a slash, `/`. On Windows, absolute paths are one of two forms. The\n *   first is a volume letter, a colon, and a backslash, like `C:\\`. The second is called a\n *   Universal Naming Convention (UNC) path, and it is prefixed by two backslashes `\\\\`. The term\n *   ‘fully-qualified path’ is a synonym of ‘absolute path’.\n *\n * * **Relative paths** are everything else. On their own, relative paths do not identify a\n *   location on a file system; they are relative to the system's current working directory. Use\n *   [FileSystem.canonicalize] to convert a relative path to its absolute path on a particular\n *   file system.\n *\n * There are some special cases when working with relative paths.\n *\n * On Windows, each volume (like `A:\\` and `C:\\`) has its own current working directory. A path\n * prefixed with a volume letter and colon but no slash (like `A:letter.doc`) is relative to the\n * working directory on the named volume. For example, if the working directory on `A:\\` is\n * `A:\\jesse`, then the path `A:letter.doc` resolves to `A:\\jesse\\letter.doc`.\n *\n * The path string `C:\\Windows` is an absolute path when following Windows rules and a relative\n * path when following UNIX rules. For example, if the current working directory is\n * `/Users/jesse`, then `C:\\Windows` resolves to `/Users/jesse/C:/Windows`.\n *\n * This class decides which rules to follow by inspecting the first slash character in the path\n * string. If the path contains no slash characters, it uses the host platform's rules. Or you may\n * explicitly specify which rules to use by specifying the `directorySeparator` parameter in\n * [toPath]. Pass `\"/\"` to get UNIX rules and `\"\\\"` to get Windows rules.\n *\n * Path Traversal\n * --------------\n *\n * After the optional path root (like `/` on UNIX, like `X:\\` or `\\\\` on Windows), the remainder of\n * the path is a sequence of segments separated by `/` or `\\` characters. Segments satisfy these\n * rules:\n *\n *  * Segments are always non-empty.\n *  * If the segment is `.`, then the full path must be `.`.\n *  * For normalized paths, if the segment is `..`, then the path must be relative. All `..`\n *    segments precede all other segments. In all cases, a segment `..` cannot be the first segment\n *    of an absolute path.\n *\n * The only path that ends with `/` is the file system root, `/`. The dot path `.` is a relative\n * path that resolves to whichever path it is resolved against.\n *\n * The [name] is the last segment in a path. It is typically a file or directory name, like\n * `README.md` or `Desktop`. The name may be another special value:\n *\n *  * The empty string is the name of the file system root path (full path `/`).\n *  * `.` is the name of the identity relative path (full path `.`).\n *  * `..` is the name of a path consisting of only `..` segments (such as `../../..`).\n *\n * Comparing Paths\n * ---------------\n *\n * Path implements [Comparable], [equals], and [hashCode]. If two paths are equal then they operate\n * on the same file on the file system.\n *\n * Note that the converse is not true: **if two paths are non-equal, they may still resolve to the\n * same file on the file system.** Here are some of the ways non-equal paths resolve to the same\n * file:\n *\n *  * **Case differences.** The default file system on macOS is case-insensitive. The paths\n *    `/Users/jesse/notes.txt` and `/USERS/JESSE/NOTES.TXT` are non-equal but these paths resolve to\n *    the same file.\n *  * **Mounting differences.** Volumes may be mounted at multiple paths. On macOS,\n *    `/Users/jesse/notes.txt`  and `/Volumes/Macintosh HD/Users/jesse/notes.txt` typically resolve\n *    to the same file. On Windows, `C:\\project\\notes.txt` and `\\\\localhost\\c$\\project\\notes.txt`\n *    typically resolve to the same file.\n *  * **Hard links.** UNIX file systems permit multiple paths to refer for same file. The paths may\n *    be wildly different, like `/Users/jesse/bruce_wayne.vcard` and\n *    `/Users/jesse/batman.vcard`, but changes via either path are reflected in both.\n *  * **Symlinks.** Symlinks permit multiple paths and directories to refer to the same file. On\n *     macOS `/tmp` is symlinked to `/private/tmp`, so `/tmp/notes.txt` and `/private/tmp/notes.txt`\n *     resolve to the same file.\n *\n * To test whether two paths refer to the same file, try [FileSystem.canonicalize] first. This\n * follows symlinks and looks up the preserved casing for case-insensitive case-preserved paths.\n * **This method does not guarantee a unique result, however.** For example, each hard link to a\n * file may return its own canonical path.\n *\n * Paths are sorted in case-sensitive order.\n *\n * Sample Paths\n * ------------\n *\n * <table>\n * <tr><th> Path                         <th> Parent             <th> Root       <th> Name          <th> Notes                          </tr>\n * <tr><td> `/`                          <td> null               <td> `/`        <td> (empty)       <td> root                           </tr>\n * <tr><td> `/home/jesse/notes.txt`      <td> `/home/jesse`      <td> `/`        <td> `notes.txt`   <td> absolute path                  </tr>\n * <tr><td> `project/notes.txt`          <td> `project`          <td> null       <td> `notes.txt`   <td> relative path                  </tr>\n * <tr><td> `../../project/notes.txt`    <td> `../../project`    <td> null       <td> `notes.txt`   <td> relative path with traversal   </tr>\n * <tr><td> `../../..`                   <td> null               <td> null       <td> `..`          <td> relative path with traversal   </tr>\n * <tr><td> `.`                          <td> null               <td> null       <td> `.`           <td> current working directory      </tr>\n * <tr><td> `C:\\`                        <td> null               <td> `C:\\`      <td> (empty)       <td> volume root (Windows)          </tr>\n * <tr><td> `C:\\Windows\\notepad.exe`     <td> `C:\\Windows`       <td> `C:\\`      <td> `notepad.exe` <td> volume absolute path (Windows) </tr>\n * <tr><td> `\\`                          <td> null               <td> `\\`        <td> (empty)       <td> absolute path (Windows)        </tr>\n * <tr><td> `\\Windows\\notepad.exe`       <td> `\\Windows`         <td> `\\`        <td> `notepad.exe` <td> absolute path (Windows)        </tr>\n * <tr><td> `C:`                         <td> null               <td> null       <td> (empty)       <td> volume-relative path (Windows) </tr>\n * <tr><td> `C:project\\notes.txt`        <td> `C:project`        <td> null       <td> `notes.txt`   <td> volume-relative path (Windows) </tr>\n * <tr><td> `\\\\server`                   <td> null               <td> `\\\\server` <td> `server`      <td> UNC server (Windows)           </tr>\n * <tr><td> `\\\\server\\project\\notes.txt` <td> `\\\\server\\project` <td> `\\\\server` <td> `notes.txt`   <td> UNC absolute path (Windows)    </tr>\n * </table>\n */\nexpect class Path internal constructor(bytes: ByteString) : Comparable<Path> {\n  /**\n   * This is the root path if this is an absolute path, or null if it is a relative path. UNIX paths\n   * have a single root, `/`. Each volume on Windows is its own root, like `C:\\` and `D:\\`. The\n   * path to the current volume `\\` is its own root. Windows UNC paths like `\\\\server` are also\n   * roots.\n   */\n  val root: Path?\n\n  /**\n   * The components of this path that are usually delimited by slashes. If the root is not null it\n   * precedes these segments. If this path is a root its segments list is empty.\n   */\n  val segments: List<String>\n\n  val segmentsBytes: List<ByteString>\n\n  internal val bytes: ByteString\n\n  /** This is true if [root] is not null. */\n  val isAbsolute: Boolean\n\n  /** This is true if [root] is null. */\n  val isRelative: Boolean\n\n  /**\n   * This is the volume letter like \"C\" on Windows paths that starts with a volume letter. For\n   * example, on the path \"C:\\Windows\" this returns \"C\". This property is null if this is not a\n   * Windows path, or if it doesn't have a volume letter.\n   *\n   * Note that paths that start with a volume letter are not necessarily absolute paths. For\n   * example, the path \"C:notepad.exe\" is relative to whatever the current working directory is on\n   * the C: drive.\n   */\n  val volumeLetter: Char?\n\n  val nameBytes: ByteString\n\n  val name: String\n\n  /**\n   * Returns the path immediately enclosing this path.\n   *\n   * This returns null if this has no parent. That includes these paths:\n   *\n   *  * The file system root (`/`)\n   *  * The identity relative path (`.`)\n   *  * A Windows volume root (like `C:\\`)\n   *  * A Windows Universal Naming Convention (UNC) root path (`\\\\server`)\n   *  * A reference to the current working directory on a Windows volume (`C:`).\n   *  * A series of relative paths (like `..` and `../..`).\n   */\n  val parent: Path?\n\n  /** Returns true if `this == this.root`. That is, this is an absolute path with no parent. */\n  val isRoot: Boolean\n\n  /**\n   * Returns a path that resolves [child] relative to this path. Note that the result isn't\n   * guaranteed to be normalized even if this and [child] are both normalized themselves.\n   *\n   * If [child] is an [absolute path][isAbsolute] or [has a volume letter][hasVolumeLetter] then\n   * this function is equivalent to `child.toPath()`.\n   */\n  operator fun div(child: String): Path\n\n  /**\n   * Returns a path that resolves [child] relative to this path. Note that the result isn't\n   * guaranteed to be normalized even if this and [child] are both normalized themselves.\n   *\n   * If [child] is an [absolute path][isAbsolute] or [has a volume letter][hasVolumeLetter] then\n   * this function is equivalent to `child.toPath()`.\n   */\n  operator fun div(child: ByteString): Path\n\n  /**\n   * Returns a path that resolves [child] relative to this path. Note that the result isn't\n   * guaranteed to be normalized even if this and [child] are both normalized themselves.\n   *\n   * If [child] is an [absolute path][isAbsolute] or [has a volume letter][hasVolumeLetter] then\n   * this function is equivalent to `child.toPath()`.\n   */\n  operator fun div(child: Path): Path\n\n  /**\n   * Returns a path that resolves [child] relative to this path.\n   *\n   * Set [normalize] to true to eagerly consume `..` segments on the resolved path. In all cases,\n   * leading `..` on absolute paths will be removed. If [normalize] is false, note that the result\n   * isn't guaranteed to be normalized even if this and [child] are both normalized themselves.\n   *\n   * If [child] is an [absolute path][isAbsolute] or [has a volume letter][hasVolumeLetter] then\n   * this function is equivalent to `child.toPath(normalize)`.\n   */\n  fun resolve(child: String, normalize: Boolean = false): Path\n\n  /**\n   * Returns a path that resolves [child] relative to this path.\n   *\n   * Set [normalize] to true to eagerly consume `..` segments on the resolved path. In all cases,\n   * leading `..` on absolute paths will be removed. If [normalize] is false, note that the result\n   * isn't guaranteed to be normalized even if this and [child] are both normalized themselves.\n   *\n   * If [child] is an [absolute path][isAbsolute] or [has a volume letter][hasVolumeLetter] then\n   * this function is equivalent to `child.toPath(normalize)`.\n   */\n  fun resolve(child: ByteString, normalize: Boolean = false): Path\n\n  /**\n   * Returns a path that resolves [child] relative to this path.\n   *\n   * Set [normalize] to true to eagerly consume `..` segments on the resolved path. In all cases,\n   * leading `..` on absolute paths will be removed. If [normalize] is false, note that the result\n   * isn't guaranteed to be normalized even if this and [child] are both normalized themselves.\n   *\n   * If [child] is an [absolute path][isAbsolute] or [has a volume letter][hasVolumeLetter] then\n   * this function is equivalent to `child.toPath(normalize)`.\n   */\n  fun resolve(child: Path, normalize: Boolean = false): Path\n\n  /**\n   * Returns this path relative to [other]. This effectively inverts the resolve operator, `/`. For\n   * any two paths `a` and `b` that have the same root, `a / (b.relativeTo(a))` is equal to `b`. If\n   * both paths don't use the same slash, the resolved path will use the slash of the [other] path.\n   *\n   * @throws IllegalArgumentException if this path and the [other] path are not both\n   * [absolute paths][isAbsolute] or both [relative paths][isRelative], or if they are both\n   * [absolute paths][isAbsolute] but of different roots (C: vs D:, or C: vs \\\\server, etc.).\n   * It will also throw if the relative path is impossible to resolve. For instance, it is\n   * impossible to resolve the path `../a` relative to `../../b`.\n   */\n  @Throws(IllegalArgumentException::class)\n  fun relativeTo(other: Path): Path\n\n  /**\n   * Returns the normalized version of this path. This has the same effect as\n   * `this.toString().toPath(normalize = true)`.\n   */\n  fun normalized(): Path\n\n  override fun compareTo(other: Path): Int\n\n  override fun equals(other: Any?): Boolean\n\n  override fun hashCode(): Int\n\n  override fun toString(): String\n\n  companion object {\n    /**\n     * Either `/` (on UNIX-like systems including Android, iOS, and Linux) or `\\` (on Windows\n     * systems).\n     *\n     * This separator is used by `FileSystem.SYSTEM` and possibly other file systems on the host\n     * system. Some file system implementations may not use this separator.\n     */\n    val DIRECTORY_SEPARATOR: String\n\n    /**\n     * Returns the [Path] representation for this string.\n     *\n     * Set [normalize] to true to eagerly consume `..` segments in your path. In all cases, leading\n     * `..` on absolute paths will be removed.\n     *\n     * ```\n     * \"/Users/jesse/Documents/../notes.txt\".toPath(normalize = false).toString() => \"/Users/jesse/Documents/../notes.txt\"\n     * \"/Users/jesse/Documents/../notes.txt\".toPath(normalize = true).toString() => \"/Users/jesse/notes.txt\"\n     * ```\n     */\n    fun String.toPath(normalize: Boolean = false): Path\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/PeekSource.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\n/**\n * A [Source] which peeks into an upstream [BufferedSource] and allows reading and expanding of the\n * buffered data without consuming it. Does this by requesting additional data from the upstream\n * source if needed and copying out of the internal buffer of the upstream source if possible.\n *\n * This source also maintains a snapshot of the starting location of the upstream buffer which it\n * validates against on every read. If the upstream buffer is read from, this source will become\n * invalid and throw [IllegalStateException] on any future reads.\n */\ninternal class PeekSource(\n  private val upstream: BufferedSource,\n) : Source {\n  private val buffer = upstream.buffer\n  private var expectedSegment = buffer.head\n  private var expectedPos = buffer.head?.pos ?: -1\n\n  private var closed = false\n  private var pos = 0L\n\n  override fun read(sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    check(!closed) { \"closed\" }\n    // Source becomes invalid if there is an expected Segment and it and the expected position\n    // do not match the current head and head position of the upstream buffer\n    check(\n      expectedSegment == null ||\n        expectedSegment === buffer.head && expectedPos == buffer.head!!.pos,\n    ) {\n      \"Peek source is invalid because upstream source was used\"\n    }\n    if (byteCount == 0L) return 0L\n    if (!upstream.request(pos + 1)) return -1L\n\n    if (expectedSegment == null && buffer.head != null) {\n      // Only once the buffer actually holds data should an expected Segment and position be\n      // recorded. This allows reads from the peek source to repeatedly return -1 and for data to be\n      // added later. Unit tests depend on this behavior.\n      expectedSegment = buffer.head\n      expectedPos = buffer.head!!.pos\n    }\n\n    val toCopy = minOf(byteCount, buffer.size - pos)\n    buffer.copyTo(sink, pos, toCopy)\n    pos += toCopy\n    return toCopy\n  }\n\n  override fun timeout(): Timeout {\n    return upstream.timeout()\n  }\n\n  override fun close() {\n    closed = true\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/RealBufferedSink.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\ninternal expect class RealBufferedSink(\n  sink: Sink,\n) : BufferedSink {\n  val sink: Sink\n  var closed: Boolean\n\n  override val buffer: Buffer\n  override fun close()\n  override fun emit(): BufferedSink\n  override fun emitCompleteSegments(): BufferedSink\n  override fun flush()\n  override fun timeout(): Timeout\n  override fun write(byteString: ByteString): BufferedSink\n  override fun write(byteString: ByteString, offset: Int, byteCount: Int): BufferedSink\n  override fun write(source: Buffer, byteCount: Long)\n  override fun write(source: ByteArray): BufferedSink\n  override fun write(source: ByteArray, offset: Int, byteCount: Int): BufferedSink\n  override fun write(source: Source, byteCount: Long): BufferedSink\n  override fun writeAll(source: Source): Long\n  override fun writeByte(b: Int): BufferedSink\n  override fun writeDecimalLong(v: Long): BufferedSink\n  override fun writeHexadecimalUnsignedLong(v: Long): BufferedSink\n  override fun writeInt(i: Int): BufferedSink\n  override fun writeIntLe(i: Int): BufferedSink\n  override fun writeLong(v: Long): BufferedSink\n  override fun writeLongLe(v: Long): BufferedSink\n  override fun writeShort(s: Int): BufferedSink\n  override fun writeShortLe(s: Int): BufferedSink\n  override fun writeUtf8(string: String): BufferedSink\n  override fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): BufferedSink\n  override fun writeUtf8CodePoint(codePoint: Int): BufferedSink\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/RealBufferedSource.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\ninternal expect class RealBufferedSource(\n  source: Source,\n) : BufferedSource {\n  val source: Source\n  var closed: Boolean\n\n  override val buffer: Buffer\n  override fun close()\n  override fun exhausted(): Boolean\n  override fun indexOf(b: Byte): Long\n  override fun indexOf(b: Byte, fromIndex: Long): Long\n  override fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long\n  override fun indexOf(bytes: ByteString): Long\n  override fun indexOf(bytes: ByteString, fromIndex: Long): Long\n  override fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long\n  override fun indexOfElement(targetBytes: ByteString): Long\n  override fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long\n  override fun peek(): BufferedSource\n  override fun rangeEquals(offset: Long, bytes: ByteString): Boolean\n  override fun rangeEquals(offset: Long, bytes: ByteString, bytesOffset: Int, byteCount: Int): Boolean\n  override fun read(sink: Buffer, byteCount: Long): Long\n  override fun read(sink: ByteArray): Int\n  override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int\n  override fun readAll(sink: Sink): Long\n  override fun readByte(): Byte\n  override fun readByteArray(): ByteArray\n  override fun readByteArray(byteCount: Long): ByteArray\n  override fun readByteString(): ByteString\n  override fun readByteString(byteCount: Long): ByteString\n  override fun readDecimalLong(): Long\n  override fun readFully(sink: Buffer, byteCount: Long)\n  override fun readFully(sink: ByteArray)\n  override fun readHexadecimalUnsignedLong(): Long\n  override fun readInt(): Int\n  override fun readIntLe(): Int\n  override fun readLong(): Long\n  override fun readLongLe(): Long\n  override fun readShort(): Short\n  override fun readShortLe(): Short\n  override fun readUtf8(): String\n  override fun readUtf8(byteCount: Long): String\n  override fun readUtf8CodePoint(): Int\n  override fun readUtf8Line(): String?\n  override fun readUtf8LineStrict(): String\n  override fun readUtf8LineStrict(limit: Long): String\n  override fun request(byteCount: Long): Boolean\n  override fun require(byteCount: Long)\n  override fun select(options: Options): Int\n  override fun <T : Any> select(options: TypedOptions<T>): T?\n  override fun skip(byteCount: Long)\n  override fun timeout(): Timeout\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Segment.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport kotlin.jvm.JvmField\n\n/**\n * A segment of a buffer.\n *\n * Each segment in a buffer is a circularly-linked list node referencing the following and\n * preceding segments in the buffer.\n *\n * Each segment in the pool is a singly-linked list node referencing the rest of segments in the\n * pool.\n *\n * The underlying byte arrays of segments may be shared between buffers and byte strings. When a\n * segment's byte array is shared the segment may not be recycled, nor may its byte data be changed.\n * The lone exception is that the owner segment is allowed to append to the segment, writing data at\n * `limit` and beyond. There is a single owning segment for each byte array. Positions,\n * limits, prev, and next references are not shared.\n */\ninternal class Segment {\n  @JvmField val data: ByteArray\n\n  /** The next byte of application data byte to read in this segment. */\n  @JvmField var pos: Int = 0\n\n  /**\n   * The first byte of available data ready to be written to.\n   *\n   * If the segment is free and linked in the segment pool, the field contains total\n   * byte count of this and next segments.\n   */\n  @JvmField var limit: Int = 0\n\n  /** True if other segments or byte strings use the same byte array. */\n  @JvmField var shared: Boolean = false\n\n  /** True if this segment owns the byte array and can append to it, extending `limit`. */\n  @JvmField var owner: Boolean = false\n\n  /** Next segment in a linked or circularly-linked list. */\n  @JvmField var next: Segment? = null\n\n  /** Previous segment in a circularly-linked list. */\n  @JvmField var prev: Segment? = null\n\n  constructor() {\n    this.data = ByteArray(SIZE)\n    this.owner = true\n    this.shared = false\n  }\n\n  constructor(data: ByteArray, pos: Int, limit: Int, shared: Boolean, owner: Boolean) {\n    this.data = data\n    this.pos = pos\n    this.limit = limit\n    this.shared = shared\n    this.owner = owner\n  }\n\n  /**\n   * Returns a new segment that shares the underlying byte array with this. Adjusting pos and limit\n   * are safe but writes are forbidden. This also marks the current segment as shared, which\n   * prevents it from being pooled.\n   */\n  fun sharedCopy(): Segment {\n    shared = true\n    return Segment(data, pos, limit, true, false)\n  }\n\n  /** Returns a new segment that its own private copy of the underlying byte array.  */\n  fun unsharedCopy() = Segment(data.copyOf(), pos, limit, false, true)\n\n  /**\n   * Removes this segment of a circularly-linked list and returns its successor.\n   * Returns null if the list is now empty.\n   */\n  fun pop(): Segment? {\n    val result = if (next !== this) next else null\n    prev!!.next = next\n    next!!.prev = prev\n    next = null\n    prev = null\n    return result\n  }\n\n  /**\n   * Appends `segment` after this segment in the circularly-linked list. Returns the pushed segment.\n   */\n  fun push(segment: Segment): Segment {\n    segment.prev = this\n    segment.next = next\n    next!!.prev = segment\n    next = segment\n    return segment\n  }\n\n  /**\n   * Splits this head of a circularly-linked list into two segments. The first segment contains the\n   * data in `[pos..pos+byteCount)`. The second segment contains the data in\n   * `[pos+byteCount..limit)`. This can be useful when moving partial segments from one buffer to\n   * another.\n   *\n   * Returns the new head of the circularly-linked list.\n   */\n  fun split(byteCount: Int): Segment {\n    require(byteCount > 0 && byteCount <= limit - pos) { \"byteCount out of range\" }\n    val prefix: Segment\n\n    // We have two competing performance goals:\n    //  - Avoid copying data. We accomplish this by sharing segments.\n    //  - Avoid short shared segments. These are bad for performance because they are readonly and\n    //    may lead to long chains of short segments.\n    // To balance these goals we only share segments when the copy will be large.\n    if (byteCount >= SHARE_MINIMUM) {\n      prefix = sharedCopy()\n    } else {\n      prefix = SegmentPool.take()\n      data.copyInto(prefix.data, startIndex = pos, endIndex = pos + byteCount)\n    }\n\n    prefix.limit = prefix.pos + byteCount\n    pos += byteCount\n    prev!!.push(prefix)\n    return prefix\n  }\n\n  /**\n   * Call this when the tail and its predecessor may both be less than half full. This will copy\n   * data so that segments can be recycled.\n   */\n  fun compact() {\n    check(prev !== this) { \"cannot compact\" }\n    if (!prev!!.owner) return // Cannot compact: prev isn't writable.\n    val byteCount = limit - pos\n    val availableByteCount = SIZE - prev!!.limit + if (prev!!.shared) 0 else prev!!.pos\n    if (byteCount > availableByteCount) return // Cannot compact: not enough writable space.\n    writeTo(prev!!, byteCount)\n    pop()\n    SegmentPool.recycle(this)\n  }\n\n  /** Moves `byteCount` bytes from this segment to `sink`.  */\n  fun writeTo(sink: Segment, byteCount: Int) {\n    check(sink.owner) { \"only owner can write\" }\n    if (sink.limit + byteCount > SIZE) {\n      // We can't fit byteCount bytes at the sink's current position. Shift sink first.\n      if (sink.shared) throw IllegalArgumentException()\n      if (sink.limit + byteCount - sink.pos > SIZE) throw IllegalArgumentException()\n      sink.data.copyInto(sink.data, startIndex = sink.pos, endIndex = sink.limit)\n      sink.limit -= sink.pos\n      sink.pos = 0\n    }\n\n    data.copyInto(\n      sink.data,\n      destinationOffset = sink.limit,\n      startIndex = pos,\n      endIndex = pos + byteCount,\n    )\n    sink.limit += byteCount\n    pos += byteCount\n  }\n\n  companion object {\n    /** The size of all segments in bytes.  */\n    const val SIZE = 8192\n\n    /** Segments will be shared when doing so avoids `arraycopy()` of this many bytes.  */\n    const val SHARE_MINIMUM = 1024\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/SegmentPool.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\n/**\n * A collection of unused segments, necessary to avoid GC churn and zero-fill.\n * This pool is a thread-safe static singleton.\n */\ninternal expect object SegmentPool {\n  val MAX_SIZE: Int\n\n  /**\n   * For testing only. Returns a snapshot of the number of bytes currently in the pool. If the pool\n   * is segmented such as by thread, this returns the byte count accessible to the calling thread.\n   */\n  val byteCount: Int\n\n  /** Return a segment for the caller's use. */\n  fun take(): Segment\n\n  /** Recycle a segment that the caller no longer needs. */\n  fun recycle(segment: Segment)\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/SegmentedByteString.kt",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\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 */\npackage okio\n\n/**\n * An immutable byte string composed of segments of byte arrays. This class exists to implement\n * efficient snapshots of buffers. It is implemented as an array of segments, plus a directory in\n * two halves that describes how the segments compose this byte string.\n *\n * The first half of the directory is the cumulative byte count covered by each segment. The\n * element at `directory[0]` contains the number of bytes held in `segments[0]`; the\n * element at `directory[1]` contains the number of bytes held in `segments[0] +\n * segments[1]`, and so on. The element at `directory[segments.length - 1]` contains the total\n * size of this byte string. The first half of the directory is always monotonically increasing.\n *\n * The second half of the directory is the offset in `segments` of the first content byte.\n * Bytes preceding this offset are unused, as are bytes beyond the segment's effective size.\n *\n * Suppose we have a byte string, `[A, B, C, D, E, F, G, H, I, J, K, L, M]` that is stored\n * across three byte arrays: `[x, x, x, x, A, B, C, D, E, x, x, x]`, `[x, F, G]`, and `[H, I, J, K,\n * L, M, x, x, x, x, x, x]`. The three byte arrays would be stored in `segments` in order. Since the\n * arrays contribute 5, 2, and 6 elements respectively, the directory starts with `[5, 7, 13` to\n * hold the cumulative total at each position. Since the offsets into the arrays are 4, 1, and 0\n * respectively, the directory ends with `4, 1, 0]`. Concatenating these two halves, the complete\n * directory is `[5, 7, 13, 4, 1, 0]`.\n *\n * This structure is chosen so that the segment holding a particular offset can be found by\n * binary search. We use one array rather than two for the directory as a micro-optimization.\n */\ninternal expect class SegmentedByteString internal constructor(\n  segments: Array<ByteArray>,\n  directory: IntArray,\n) : ByteString {\n\n  internal val segments: Array<ByteArray>\n  internal val directory: IntArray\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Sink.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\n/**\n * Receives a stream of bytes. Use this interface to write data wherever it's needed: to the\n * network, storage, or a buffer in memory. Sinks may be layered to transform received data, such as\n * to compress, encrypt, throttle, or add protocol framing.\n *\n * Most application code shouldn't operate on a sink directly, but rather on a [BufferedSink] which\n * is both more efficient and more convenient. Use [buffer] to wrap any sink with a buffer.\n *\n * Sinks are easy to test: just use a [Buffer] in your tests, and read from it to confirm it\n * received the data that was expected.\n *\n * ### Comparison with OutputStream\n *\n * This interface is functionally equivalent to [java.io.OutputStream].\n *\n * `OutputStream` requires multiple layers when emitted data is heterogeneous: a `DataOutputStream`\n * for primitive values, a `BufferedOutputStream` for buffering, and `OutputStreamWriter` for\n * charset encoding. This library uses `BufferedSink` for all of the above.\n *\n * Sink is also easier to layer: there is no [write()][java.io.OutputStream.write] method that is\n * awkward to implement efficiently.\n *\n * ### Interop with OutputStream\n *\n * Use [sink] to adapt an `OutputStream` to a sink. Use [outputStream()][BufferedSink.outputStream]\n * to adapt a sink to an `OutputStream`.\n */\nexpect interface Sink : Closeable {\n  /** Removes `byteCount` bytes from `source` and appends them to this.  */\n  @Throws(IOException::class)\n  fun write(source: Buffer, byteCount: Long)\n\n  /** Pushes all buffered bytes to their final destination.  */\n  @Throws(IOException::class)\n  fun flush()\n\n  /** Returns the timeout for this sink.  */\n  fun timeout(): Timeout\n\n  /**\n   * Pushes all buffered bytes to their final destination and releases the resources held by this\n   * sink. It is an error to write a closed sink. It is safe to close a sink more than once.\n   */\n  @Throws(IOException::class)\n  override fun close()\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Socket.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio\n\n/**\n * A pair of streams for interactive communication with another machine.\n *\n * Send data to the peer by writing to [sink], and read data from the peer by reading from [source].\n *\n * This can be implemented by a plain TCP socket. It can also be layered to add features like\n * security (as in a TLS socket) or connectivity (as in a proxy socket).\n *\n * Closing the [source] does not impact the [sink], and vice versa.\n *\n * You must close the source and the sink to release the resources held by this socket. If you're using both from the\n * same thread, you can do that with nested `use` blocks:\n *\n * ```kotlin\n * socket.source.use { source ->\n *   socket.sink.use { sink ->\n *     readAndWrite(source, sink)\n *   }\n * }\n * ```\n */\ninterface Socket {\n  val source: Source\n  val sink: Sink\n\n  /**\n   * Fail any in-flight and future operations. After canceling:\n   *\n   *  * Any attempt to write or flush [sink] will fail immediately with an [IOException].\n   *  * Any attempt to read [source] will fail immediately with an [IOException].\n   *\n   * Closing the source and the sink will complete normally even after a socket has been canceled.\n   *\n   * This operation may be called by any thread at any time. It is safe to call concurrently while\n   * operating on the source or the sink.\n   */\n  fun cancel()\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Source.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\n/**\n * Supplies a stream of bytes. Use this interface to read data from wherever it's located: from the\n * network, storage, or a buffer in memory. Sources may be layered to transform supplied data, such\n * as to decompress, decrypt, or remove protocol framing.\n *\n * Most applications shouldn't operate on a source directly, but rather on a [BufferedSource] which\n * is both more efficient and more convenient. Use [buffer] to wrap any source with a buffer.\n *\n * Sources are easy to test: just use a [Buffer] in your tests, and fill it with the data your\n * application is to read.\n *\n * ### Comparison with InputStream\n\n * This interface is functionally equivalent to [java.io.InputStream].\n *\n * `InputStream` requires multiple layers when consumed data is heterogeneous: a `DataInputStream`\n * for primitive values, a `BufferedInputStream` for buffering, and `InputStreamReader` for strings.\n * This library uses `BufferedSource` for all of the above.\n *\n * Source avoids the impossible-to-implement [available()][java.io.InputStream.available] method.\n * Instead callers specify how many bytes they [require][BufferedSource.require].\n *\n * Source omits the unsafe-to-compose [mark and reset][java.io.InputStream.mark] state that's\n * tracked by `InputStream`; instead, callers just buffer what they need.\n *\n * When implementing a source, you don't need to worry about the [read()][java.io.InputStream.read]\n * method that is awkward to implement efficiently and returns one of 257 possible values.\n *\n * And source has a stronger `skip` method: [BufferedSource.skip] won't return prematurely.\n *\n * ### Interop with InputStream\n *\n * Use [source] to adapt an `InputStream` to a source. Use [BufferedSource.inputStream] to adapt a\n * source to an `InputStream`.\n */\ninterface Source : Closeable {\n  /**\n   * Removes at least 1, and up to `byteCount` bytes from this and appends them to `sink`. Returns\n   * the number of bytes read, or -1 if this source is exhausted.\n   */\n  @Throws(IOException::class)\n  fun read(sink: Buffer, byteCount: Long): Long\n\n  /** Returns the timeout for this source.  */\n  fun timeout(): Timeout\n\n  /**\n   * Closes this source and releases the resources held by this source. It is an error to read a\n   * closed source. It is safe to close a source more than once.\n   */\n  @Throws(IOException::class)\n  override fun close()\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Timeout.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\n/**\n * A policy on how much time to spend on a task before giving up. When a task times out, it is left\n * in an unspecified state and should be abandoned. For example, if reading from a source times out,\n * that source should be closed and the read should be retried later. If writing to a sink times\n * out, the same rules apply: close the sink and retry later.\n *\n * ### Timeouts and Deadlines\n *\n * This class offers two complementary controls to define a timeout policy.\n *\n * **Timeouts** specify the maximum time to wait for a single operation to complete. Timeouts are\n * typically used to detect problems like network partitions. For example, if a remote peer doesn't\n * return *any* data for ten seconds, we may assume that the peer is unavailable.\n *\n * **Deadlines** specify the maximum time to spend on a job, composed of one or more operations. Use\n * deadlines to set an upper bound on the time invested on a job. For example, a battery-conscious\n * app may limit how much time it spends pre-loading content.\n */\nexpect open class Timeout {\n  companion object {\n    /**\n     * An empty timeout that neither tracks nor detects timeouts. Use this when timeouts aren't\n     * necessary, such as in implementations whose operations do not block.\n     */\n    val NONE: Timeout\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/TypedOptions.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.jvm.JvmStatic\n\n/**\n * A list of values that may be read with [BufferedSource.select].\n *\n * Also consider [Options] to select an integer index.\n */\nclass TypedOptions<T : Any>(\n  list: List<T>,\n  internal val options: Options,\n) : AbstractList<T>(), RandomAccess {\n  internal val list = list.toList() // Defensive copy.\n\n  init {\n    require(this.list.size == options.size)\n  }\n\n  override val size: Int\n    get() = list.size\n\n  override fun get(index: Int) = list[index]\n\n  companion object {\n    @JvmStatic\n    inline fun <T : Any> of(\n      values: Iterable<T>,\n      encode: (T) -> ByteString,\n    ): TypedOptions<T> {\n      val list = values.toList()\n      val options = Options.of(*Array(list.size) { encode(list[it]) })\n      return TypedOptions(list, options)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Utf8.kt",
    "content": "/*\n * Copyright (C) 2017 Square, Inc.\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 */\n\n/**\n * Okio assumes most applications use UTF-8 exclusively, and offers optimized implementations of\n * common operations on UTF-8 strings.\n *\n * <table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" summary=\"\">\n * <tr>\n * <th></th>\n * <th>[ByteString]</th>\n * <th>[Buffer], [BufferedSink], [BufferedSource]</th>\n * </tr>\n * <tr>\n * <td>Encode a string</td>\n * <td>[ByteString.encodeUtf8]</td>\n * <td>[BufferedSink.writeUtf8]</td>\n * </tr>\n * <tr>\n * <td>Encode a code point</td>\n * <td></td>\n * <td>[BufferedSink.writeUtf8CodePoint]</td>\n * </tr>\n * <tr>\n * <td>Decode a string</td>\n * <td>[ByteString.utf8]</td>\n * <td>[BufferedSource.readUtf8], [BufferedSource.readUtf8]</td>\n * </tr>\n * <tr>\n * <td>Decode a code point</td>\n * <td></td>\n * <td>[BufferedSource.readUtf8CodePoint]</td>\n * </tr>\n * <tr>\n * <td>Decode until the next `\\r\\n` or `\\n`</td>\n * <td></td>\n * <td>[BufferedSource.readUtf8LineStrict],\n * [BufferedSource.readUtf8LineStrict]</td>\n * </tr>\n * <tr>\n * <td>Decode until the next `\\r\\n`, `\\n`, or `EOF`</td>\n * <td></td>\n * <td>[BufferedSource.readUtf8Line]</td>\n * </tr>\n * <tr>\n * <td>Measure the bytes in a UTF-8 string</td>\n * <td colspan=\"2\">[Utf8.size], [Utf8.size]</td>\n * </tr>\n * </table>\n */\n@file:JvmName(\"Utf8\")\n\npackage okio\n\nimport kotlin.jvm.JvmName\nimport kotlin.jvm.JvmOverloads\n\n/**\n * Returns the number of bytes used to encode the slice of `string` as UTF-8 when using\n * [BufferedSink.writeUtf8].\n */\n@JvmOverloads\n@JvmName(\"size\")\nfun String.utf8Size(beginIndex: Int = 0, endIndex: Int = length): Long {\n  require(beginIndex >= 0) { \"beginIndex < 0: $beginIndex\" }\n  require(endIndex >= beginIndex) { \"endIndex < beginIndex: $endIndex < $beginIndex\" }\n  require(endIndex <= length) { \"endIndex > string.length: $endIndex > $length\" }\n\n  var result = 0L\n  var i = beginIndex\n  while (i < endIndex) {\n    val c = this[i].code\n\n    if (c < 0x80) {\n      // A 7-bit character with 1 byte.\n      result++\n      i++\n    } else if (c < 0x800) {\n      // An 11-bit character with 2 bytes.\n      result += 2\n      i++\n    } else if (c < 0xd800 || c > 0xdfff) {\n      // A 16-bit character with 3 bytes.\n      result += 3\n      i++\n    } else {\n      val low = if (i + 1 < endIndex) this[i + 1].code else 0\n      if (c > 0xdbff || low < 0xdc00 || low > 0xdfff) {\n        // A malformed surrogate, which yields '?'.\n        result++\n        i++\n      } else {\n        // A 21-bit character with 4 bytes.\n        result += 4\n        i += 2\n      }\n    }\n  }\n\n  return result\n}\n\ninternal const val REPLACEMENT_BYTE: Byte = '?'.code.toByte()\ninternal const val REPLACEMENT_CHARACTER: Char = '\\ufffd'\ninternal const val REPLACEMENT_CODE_POINT: Int = REPLACEMENT_CHARACTER.code\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline fun isIsoControl(codePoint: Int): Boolean =\n  (codePoint in 0x00..0x1F) || (codePoint in 0x7F..0x9F)\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline fun isUtf8Continuation(byte: Byte): Boolean {\n  // 0b10xxxxxx\n  return byte and 0xc0 == 0x80\n}\n\n// TODO combine with Buffer.writeUtf8?\n// TODO combine with Buffer.writeUtf8CodePoint?\ninternal inline fun String.processUtf8Bytes(\n  beginIndex: Int,\n  endIndex: Int,\n  yield: (Byte) -> Unit,\n) {\n  // Transcode a UTF-16 String to UTF-8 bytes.\n  var index = beginIndex\n  while (index < endIndex) {\n    val c = this[index]\n\n    when {\n      c < '\\u0080' -> {\n        // Emit a 7-bit character with 1 byte.\n        yield(c.code.toByte()) // 0xxxxxxx\n        index++\n\n        // Assume there is going to be more ASCII\n        while (index < endIndex && this[index] < '\\u0080') {\n          yield(this[index++].code.toByte())\n        }\n      }\n\n      c < '\\u0800' -> {\n        // Emit a 11-bit character with 2 bytes.\n        /* ktlint-disable no-multi-spaces */\n        yield((c.code shr 6          or 0xc0).toByte()) // 110xxxxx\n        yield((c.code and 0x3f or 0x80).toByte()) // 10xxxxxx\n        /* ktlint-enable no-multi-spaces */\n        index++\n      }\n\n      c !in '\\ud800'..'\\udfff' -> {\n        // Emit a 16-bit character with 3 bytes.\n        /* ktlint-disable no-multi-spaces */\n        yield((c.code shr 12          or 0xe0).toByte()) // 1110xxxx\n        yield((c.code shr  6 and 0x3f or 0x80).toByte()) // 10xxxxxx\n        yield((c.code and 0x3f or 0x80).toByte()) // 10xxxxxx\n        /* ktlint-enable no-multi-spaces */\n        index++\n      }\n\n      else -> {\n        // c is a surrogate. Make sure it is a high surrogate & that its successor is a low\n        // surrogate. If not, the UTF-16 is invalid, in which case we emit a replacement\n        // byte.\n        if (c > '\\udbff' ||\n          endIndex <= index + 1 ||\n          this[index + 1] !in '\\udc00'..'\\udfff'\n        ) {\n          yield(REPLACEMENT_BYTE)\n          index++\n        } else {\n          // UTF-16 high surrogate: 110110xxxxxxxxxx (10 bits)\n          // UTF-16 low surrogate:  110111yyyyyyyyyy (10 bits)\n          // Unicode code point:    00010000000000000000 + xxxxxxxxxxyyyyyyyyyy (21 bits)\n          val codePoint = (\n            ((c.code shl 10) + this[index + 1].code) +\n              (0x010000 - (0xd800 shl 10) - 0xdc00)\n            )\n\n          // Emit a 21-bit character with 4 bytes.\n          /* ktlint-disable no-multi-spaces */\n          yield((codePoint shr 18          or 0xf0).toByte()) // 11110xxx\n          yield((codePoint shr 12 and 0x3f or 0x80).toByte()) // 10xxxxxx\n          yield((codePoint shr 6  and 0x3f or 0x80).toByte()) // 10xxyyyy\n          yield((codePoint        and 0x3f or 0x80).toByte()) // 10yyyyyy\n          /* ktlint-enable no-multi-spaces */\n          index += 2\n        }\n      }\n    }\n  }\n}\n\n// TODO combine with Buffer.readUtf8CodePoint?\ninternal inline fun ByteArray.processUtf8CodePoints(\n  beginIndex: Int,\n  endIndex: Int,\n  yield: (Int) -> Unit,\n) {\n  var index = beginIndex\n  while (index < endIndex) {\n    val b0 = this[index]\n    when {\n      b0 >= 0 -> {\n        // 0b0xxxxxxx\n        yield(b0.toInt())\n        index++\n\n        // Assume there is going to be more ASCII\n        while (index < endIndex && this[index] >= 0) {\n          yield(this[index++].toInt())\n        }\n      }\n      b0 shr 5 == -2 -> {\n        // 0b110xxxxx\n        index += process2Utf8Bytes(index, endIndex) { yield(it) }\n      }\n      b0 shr 4 == -2 -> {\n        // 0b1110xxxx\n        index += process3Utf8Bytes(index, endIndex) { yield(it) }\n      }\n      b0 shr 3 == -2 -> {\n        // 0b11110xxx\n        index += process4Utf8Bytes(index, endIndex) { yield(it) }\n      }\n      else -> {\n        // 0b10xxxxxx - Unexpected continuation\n        // 0b111111xxx - Unknown encoding\n        yield(REPLACEMENT_CODE_POINT)\n        index++\n      }\n    }\n  }\n}\n\n// Value added to the high UTF-16 surrogate after shifting\ninternal const val HIGH_SURROGATE_HEADER = 0xd800 - (0x010000 ushr 10)\n\n// Value added to the low UTF-16 surrogate after masking\ninternal const val LOG_SURROGATE_HEADER = 0xdc00\n\n// TODO combine with Buffer.readUtf8?\ninternal inline fun ByteArray.processUtf16Chars(\n  beginIndex: Int,\n  endIndex: Int,\n  yield: (Char) -> Unit,\n) {\n  var index = beginIndex\n  while (index < endIndex) {\n    val b0 = this[index]\n    when {\n      b0 >= 0 -> {\n        // 0b0xxxxxxx\n        yield(b0.toInt().toChar())\n        index++\n\n        // Assume there is going to be more ASCII\n        // This is almost double the performance of the outer loop\n        while (index < endIndex && this[index] >= 0) {\n          yield(this[index++].toInt().toChar())\n        }\n      }\n      b0 shr 5 == -2 -> {\n        // 0b110xxxxx\n        index += process2Utf8Bytes(index, endIndex) { yield(it.toChar()) }\n      }\n      b0 shr 4 == -2 -> {\n        // 0b1110xxxx\n        index += process3Utf8Bytes(index, endIndex) { yield(it.toChar()) }\n      }\n      b0 shr 3 == -2 -> {\n        // 0b11110xxx\n        index += process4Utf8Bytes(index, endIndex) { codePoint ->\n          if (codePoint != REPLACEMENT_CODE_POINT) {\n            // Unicode code point:    00010000000000000000 + xxxxxxxxxxyyyyyyyyyy (21 bits)\n            // UTF-16 high surrogate: 110110xxxxxxxxxx (10 bits)\n            // UTF-16 low surrogate:  110111yyyyyyyyyy (10 bits)\n            /* ktlint-disable no-multi-spaces paren-spacing */\n            yield(((codePoint ushr 10   ) + HIGH_SURROGATE_HEADER).toChar())\n            /* ktlint-enable no-multi-spaces paren-spacing */\n            yield(((codePoint and 0x03ff) + LOG_SURROGATE_HEADER).toChar())\n          } else {\n            yield(REPLACEMENT_CHARACTER)\n          }\n        }\n      }\n      else -> {\n        // 0b10xxxxxx - Unexpected continuation\n        // 0b111111xxx - Unknown encoding\n        yield(REPLACEMENT_CHARACTER)\n        index++\n      }\n    }\n  }\n}\n\n// ===== UTF-8 Encoding and Decoding ===== //\n/*\nThe following 3 methods take advantage of using XOR on 2's complement store\nnumbers to quickly and efficiently combine the important data of UTF-8 encoded\nbytes. This will be best explained using an example, so lets take the following\nencoded character '∇' = \\u2207.\n\nUsing the Unicode code point for this character, 0x2207, we will split the\nbinary representation into 3 sections as follows:\n\n    0x2207 = 0b0010 0010 0000 0111\n               xxxx yyyy yyzz zzzz\n\nNow take each section of bits and add the appropriate header:\n\n    utf8(0x2207) = 0b1110 xxxx 0b10yy yyyy 0b10zz zzzz\n                 = 0b1110 0010 0b1000 1000 0b1000 0111\n                 = 0xe2        0x88        0x87\n\nWe have now just encoded this as a 3 byte UTF-8 character. More information\nabout different sizes of characters can be found here:\n    https://en.wikipedia.org/wiki/UTF-8\n\nEncoding was pretty easy, but decoding is a bit more complicated. We need to\nfirst determine the number of bytes used to represent the character, strip all\nthe headers, and then combine all the bits into a single integer. Let's use the\ncharacter we just encoded and work backwards, taking advantage of 2's complement\ninteger representation and the XOR function.\n\nLet's look at the decimal representation of these bytes:\n\n    0xe2, 0x88, 0x87 = -30, -120, -121\n\nThe first interesting thing to notice is that UTF-8 headers all start with 1 -\nexcept for ASCII which is encoded as a single byte - which means all UTF-8 bytes\nwill be negative. So converting these to integers results in a lot of 1's added\nbecause they are store as 2's complement:\n\n    0xe2 =  -30 = 0xffff ffe2\n    0x88 = -120 = 0xffff ff88\n    0x87 = -121 = 0xffff ff87\n\nNow let's XOR these with their corresponding UTF-8 byte headers to see what\nhappens:\n\n    0xffff ffe2 xor 0xffff ffe0 = 0x0000 0002\n    0xffff ff88 xor 0xffff ff80 = 0x0000 0008\n    0xffff ff87 xor 0xffff ff80 = 0x0000 0007\n\n***This is why we must first convert the byte header mask to a byte and then\nback to an integer, so it is properly converted to a 2's complement negative\nnumber which can be applied to each byte.***\n\nNow let's look at the binary representation to see how we can combine these to\ncreate the Unicode code point:\n\n    0b0000 0010    0b0000 1000    0b0000 0111\n    0b1110 xxxx    0b10yy yyyy    0b10zz zzzz\n\nCombining each section will require some bit shifting, but then they can just\nbe OR'd together. They can also be XOR'd together which makes use of a single,\nCOMMUTATIVE, operator through the entire calculation.\n\n      << 12 = 00000010\n      <<  6 =       00001000\n      <<  0 =             00000111\n        XOR = 00000010001000000111\n\n code point = 0b0010 0010 0000 0111\n            = 0x2207\n\nAnd there we have it! The decoded UTF-8 character '∇'! And because the XOR\noperator is commutative, we can re-arrange all this XOR and shifting to create\na single mask that can be applied to 3-byte UTF-8 characters after their bytes\nhave been shifted and XOR'd together.\n */\n\n// Mask used to remove byte headers from a 2 byte encoded UTF-8 character\ninternal const val MASK_2BYTES = 0x0f80\n// MASK_2BYTES =\n//    (0xc0.toByte() shl 6) xor\n//    (0x80.toByte().toInt())\n\ninternal inline fun ByteArray.process2Utf8Bytes(\n  beginIndex: Int,\n  endIndex: Int,\n  yield: (Int) -> Unit,\n): Int {\n  if (endIndex <= beginIndex + 1) {\n    yield(REPLACEMENT_CODE_POINT)\n    // Only 1 byte remaining - underflow\n    return 1\n  }\n\n  val b0 = this[beginIndex]\n  val b1 = this[beginIndex + 1]\n  if (!isUtf8Continuation(b1)) {\n    yield(REPLACEMENT_CODE_POINT)\n    return 1\n  }\n\n  val codePoint =\n    (\n      MASK_2BYTES\n        xor (b1.toInt())\n        xor (b0.toInt() shl 6)\n      )\n\n  when {\n    codePoint < 0x80 -> {\n      yield(REPLACEMENT_CODE_POINT) // Reject overlong code points.\n    }\n    else -> {\n      yield(codePoint)\n    }\n  }\n  return 2\n}\n\n// Mask used to remove byte headers from a 3 byte encoded UTF-8 character\ninternal const val MASK_3BYTES = -0x01e080\n// MASK_3BYTES =\n//    (0xe0.toByte() shl 12) xor\n//    (0x80.toByte() shl 6) xor\n//    (0x80.toByte().toInt())\n\ninternal inline fun ByteArray.process3Utf8Bytes(\n  beginIndex: Int,\n  endIndex: Int,\n  yield: (Int) -> Unit,\n): Int {\n  if (endIndex <= beginIndex + 2) {\n    // At least 2 bytes remaining\n    yield(REPLACEMENT_CODE_POINT)\n    if (endIndex <= beginIndex + 1 || !isUtf8Continuation(this[beginIndex + 1])) {\n      // Only 1 byte remaining - underflow\n      // Or 2nd byte is not a continuation - malformed\n      return 1\n    } else {\n      // Only 2 bytes remaining - underflow\n      return 2\n    }\n  }\n\n  val b0 = this[beginIndex]\n  val b1 = this[beginIndex + 1]\n  if (!isUtf8Continuation(b1)) {\n    yield(REPLACEMENT_CODE_POINT)\n    return 1\n  }\n  val b2 = this[beginIndex + 2]\n  if (!isUtf8Continuation(b2)) {\n    yield(REPLACEMENT_CODE_POINT)\n    return 2\n  }\n\n  val codePoint =\n    (\n      MASK_3BYTES\n        xor (b2.toInt())\n        xor (b1.toInt() shl 6)\n        xor (b0.toInt() shl 12)\n      )\n\n  when {\n    codePoint < 0x800 -> {\n      yield(REPLACEMENT_CODE_POINT) // Reject overlong code points.\n    }\n    codePoint in 0xd800..0xdfff -> {\n      yield(REPLACEMENT_CODE_POINT) // Reject partial surrogates.\n    }\n    else -> {\n      yield(codePoint)\n    }\n  }\n  return 3\n}\n\n// Mask used to remove byte headers from a 4 byte encoded UTF-8 character\ninternal const val MASK_4BYTES = 0x381f80\n// MASK_4BYTES =\n//    (0xf0.toByte() shl 18) xor\n//    (0x80.toByte() shl 12) xor\n//    (0x80.toByte() shl 6) xor\n//    (0x80.toByte().toInt())\n\ninternal inline fun ByteArray.process4Utf8Bytes(\n  beginIndex: Int,\n  endIndex: Int,\n  yield: (Int) -> Unit,\n): Int {\n  if (endIndex <= beginIndex + 3) {\n    // At least 3 bytes remaining\n    yield(REPLACEMENT_CODE_POINT)\n    if (endIndex <= beginIndex + 1 || !isUtf8Continuation(this[beginIndex + 1])) {\n      // Only 1 byte remaining - underflow\n      // Or 2nd byte is not a continuation - malformed\n      return 1\n    } else if (endIndex <= beginIndex + 2 || !isUtf8Continuation(this[beginIndex + 2])) {\n      // Only 2 bytes remaining - underflow\n      // Or 3rd byte is not a continuation - malformed\n      return 2\n    } else {\n      // Only 3 bytes remaining - underflow\n      return 3\n    }\n  }\n\n  val b0 = this[beginIndex]\n  val b1 = this[beginIndex + 1]\n  if (!isUtf8Continuation(b1)) {\n    yield(REPLACEMENT_CODE_POINT)\n    return 1\n  }\n  val b2 = this[beginIndex + 2]\n  if (!isUtf8Continuation(b2)) {\n    yield(REPLACEMENT_CODE_POINT)\n    return 2\n  }\n  val b3 = this[beginIndex + 3]\n  if (!isUtf8Continuation(b3)) {\n    yield(REPLACEMENT_CODE_POINT)\n    return 3\n  }\n\n  val codePoint =\n    (\n      MASK_4BYTES\n        xor (b3.toInt())\n        xor (b2.toInt() shl 6)\n        xor (b1.toInt() shl 12)\n        xor (b0.toInt() shl 18)\n      )\n\n  when {\n    codePoint > 0x10ffff -> {\n      yield(REPLACEMENT_CODE_POINT) // Reject code points larger than the Unicode maximum.\n    }\n    codePoint in 0xd800..0xdfff -> {\n      yield(REPLACEMENT_CODE_POINT) // Reject partial surrogates.\n    }\n    codePoint < 0x10000 -> {\n      yield(REPLACEMENT_CODE_POINT) // Reject overlong code points.\n    }\n    else -> {\n      yield(codePoint)\n    }\n  }\n  return 4\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/Util.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n@file:JvmName(\"-SegmentedByteString\") // A leading '-' hides this class from Java.\n\npackage okio\n\nimport kotlin.jvm.JvmName\nimport okio.internal.HEX_DIGIT_CHARS\n\ninternal fun checkOffsetAndCount(size: Long, offset: Long, byteCount: Long) {\n  if (offset or byteCount < 0 || offset > size || size - offset < byteCount) {\n    throw ArrayIndexOutOfBoundsException(\"size=$size offset=$offset byteCount=$byteCount\")\n  }\n}\n\n/* ktlint-disable no-multi-spaces indent */\n\ninternal fun Short.reverseBytes(): Short {\n  val i = toInt() and 0xffff\n  val reversed = (i and 0xff00 ushr 8) or\n    (i and 0x00ff  shl 8)\n  return reversed.toShort()\n}\n\ninternal fun Int.reverseBytes(): Int {\n  return (this and -0x1000000 ushr 24) or\n    (this and 0x00ff0000 ushr  8) or\n    (this and 0x0000ff00  shl  8) or\n    (this and 0x000000ff  shl 24)\n}\n\ninternal fun Long.reverseBytes(): Long {\n  return (this and -0x100000000000000L ushr 56) or\n    (this and 0x00ff000000000000L ushr 40) or\n    (this and 0x0000ff0000000000L ushr 24) or\n    (this and 0x000000ff00000000L ushr  8) or\n    (this and 0x00000000ff000000L  shl  8) or\n    (this and 0x0000000000ff0000L  shl 24) or\n    (this and 0x000000000000ff00L  shl 40) or\n    (this and 0x00000000000000ffL  shl 56)\n}\n\n/* ktlint-enable no-multi-spaces indent */\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline infix fun Int.leftRotate(bitCount: Int): Int {\n  return (this shl bitCount) or (this ushr (32 - bitCount))\n}\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline infix fun Long.rightRotate(bitCount: Int): Long {\n  return (this ushr bitCount) or (this shl (64 - bitCount))\n}\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline infix fun Byte.shr(other: Int): Int = toInt() shr other\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline infix fun Byte.shl(other: Int): Int = toInt() shl other\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline infix fun Byte.and(other: Int): Int = toInt() and other\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline infix fun Byte.and(other: Long): Long = toLong() and other\n\n@Suppress(\"NOTHING_TO_INLINE\") // Pending `kotlin.experimental.xor` becoming stable\ninternal inline infix fun Byte.xor(other: Byte): Byte = (toInt() xor other.toInt()).toByte()\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline infix fun Int.and(other: Long): Long = toLong() and other\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline fun minOf(a: Long, b: Int): Long = minOf(a, b.toLong())\n\n@Suppress(\"NOTHING_TO_INLINE\") // Syntactic sugar.\ninternal inline fun minOf(a: Int, b: Long): Long = minOf(a.toLong(), b)\n\ninternal fun arrayRangeEquals(\n  a: ByteArray,\n  aOffset: Int,\n  b: ByteArray,\n  bOffset: Int,\n  byteCount: Int,\n): Boolean {\n  for (i in 0 until byteCount) {\n    if (a[i + aOffset] != b[i + bOffset]) return false\n  }\n  return true\n}\n\ninternal fun Byte.toHexString(): String {\n  val result = CharArray(2)\n  result[0] = HEX_DIGIT_CHARS[this shr 4 and 0xf]\n  result[1] = HEX_DIGIT_CHARS[this       and 0xf] // ktlint-disable no-multi-spaces\n  return result.concatToString()\n}\n\ninternal fun Int.toHexString(): String {\n  if (this == 0) return \"0\" // Required as code below does not handle 0\n\n  val result = CharArray(8)\n  result[0] = HEX_DIGIT_CHARS[this shr 28 and 0xf]\n  result[1] = HEX_DIGIT_CHARS[this shr 24 and 0xf]\n  result[2] = HEX_DIGIT_CHARS[this shr 20 and 0xf]\n  result[3] = HEX_DIGIT_CHARS[this shr 16 and 0xf]\n  result[4] = HEX_DIGIT_CHARS[this shr 12 and 0xf]\n  result[5] = HEX_DIGIT_CHARS[this shr 8  and 0xf] // ktlint-disable no-multi-spaces\n  result[6] = HEX_DIGIT_CHARS[this shr 4  and 0xf] // ktlint-disable no-multi-spaces\n  result[7] = HEX_DIGIT_CHARS[this        and 0xf] // ktlint-disable no-multi-spaces\n\n  // Find the first non-zero index\n  var i = 0\n  while (i < result.size) {\n    if (result[i] != '0') break\n    i++\n  }\n\n  return result.concatToString(i, result.size)\n}\n\ninternal fun Long.toHexString(): String {\n  if (this == 0L) return \"0\" // Required as code below does not handle 0\n\n  val result = CharArray(16)\n  result[ 0] = HEX_DIGIT_CHARS[(this shr 60 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 1] = HEX_DIGIT_CHARS[(this shr 56 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 2] = HEX_DIGIT_CHARS[(this shr 52 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 3] = HEX_DIGIT_CHARS[(this shr 48 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 4] = HEX_DIGIT_CHARS[(this shr 44 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 5] = HEX_DIGIT_CHARS[(this shr 40 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 6] = HEX_DIGIT_CHARS[(this shr 36 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 7] = HEX_DIGIT_CHARS[(this shr 32 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 8] = HEX_DIGIT_CHARS[(this shr 28 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[ 9] = HEX_DIGIT_CHARS[(this shr 24 and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[10] = HEX_DIGIT_CHARS[(this shr 20 and 0xf).toInt()]\n  result[11] = HEX_DIGIT_CHARS[(this shr 16 and 0xf).toInt()]\n  result[12] = HEX_DIGIT_CHARS[(this shr 12 and 0xf).toInt()]\n  result[13] = HEX_DIGIT_CHARS[(this shr 8  and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[14] = HEX_DIGIT_CHARS[(this shr 4  and 0xf).toInt()] // ktlint-disable no-multi-spaces\n  result[15] = HEX_DIGIT_CHARS[(this        and 0xf).toInt()] // ktlint-disable no-multi-spaces\n\n  // Find the first non-zero index\n  var i = 0\n  while (i < result.size) {\n    if (result[i] != '0') break\n    i++\n  }\n\n  return result.concatToString(i, result.size)\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/-Utf8.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.ArrayIndexOutOfBoundsException\nimport okio.processUtf16Chars\nimport okio.processUtf8Bytes\n\n// TODO For benchmarking, these methods need to be available but preferably invisible\n// to everything else. Putting them in this file, `-Utf8.kt`, makes them invisible to\n// Java but still visible to Kotlin.\n\nfun ByteArray.commonToUtf8String(beginIndex: Int = 0, endIndex: Int = size): String {\n  if (beginIndex < 0 || endIndex > size || beginIndex > endIndex) {\n    throw ArrayIndexOutOfBoundsException(\"size=$size beginIndex=$beginIndex endIndex=$endIndex\")\n  }\n  val chars = CharArray(endIndex - beginIndex)\n\n  var length = 0\n  processUtf16Chars(beginIndex, endIndex) { c ->\n    chars[length++] = c\n  }\n\n  return chars.concatToString(0, length)\n}\n\nfun String.commonAsUtf8ToByteArray(): ByteArray {\n  val bytes = ByteArray(4 * length)\n\n  // Assume ASCII until a UTF-8 code point is observed. This is ugly but yields\n  // about a 2x performance increase for pure ASCII.\n  for (index in 0 until length) {\n    val b0 = this[index]\n    if (b0 >= '\\u0080') {\n      var size = index\n      processUtf8Bytes(index, length) { c ->\n        bytes[size++] = c\n      }\n      return bytes.copyOf(size)\n    }\n    bytes[index] = b0.code.toByte()\n  }\n\n  return bytes.copyOf(length)\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/Buffer.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n@file:JvmName(\"-Buffer\") // A leading '-' hides this class from Java.\n\n// TODO move to Buffer class: https://youtrack.jetbrains.com/issue/KT-20427\n@file:Suppress(\"NOTHING_TO_INLINE\")\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.ArrayIndexOutOfBoundsException\nimport okio.Buffer\nimport okio.Buffer.UnsafeCursor\nimport okio.ByteString\nimport okio.EOFException\nimport okio.Options\nimport okio.REPLACEMENT_CODE_POINT\nimport okio.Segment\nimport okio.SegmentPool\nimport okio.SegmentedByteString\nimport okio.Sink\nimport okio.Source\nimport okio.and\nimport okio.asUtf8ToByteArray\nimport okio.checkOffsetAndCount\nimport okio.minOf\nimport okio.toHexString\n\ninternal val HEX_DIGIT_BYTES = \"0123456789abcdef\".asUtf8ToByteArray()\n\n// Threshold determined empirically via ReadByteStringBenchmark\n/** Create SegmentedByteString when size is greater than this many bytes.  */\ninternal const val SEGMENTING_THRESHOLD = 4096\n\n/**\n * Returns true if the range within this buffer starting at `segmentPos` in `segment` is equal to\n * `bytes[bytesOffset..bytesLimit)`.\n */\ninternal fun rangeEquals(\n  segment: Segment,\n  segmentPos: Int,\n  bytes: ByteArray,\n  bytesOffset: Int,\n  bytesLimit: Int,\n): Boolean {\n  var segment = segment\n  var segmentPos = segmentPos\n  var segmentLimit = segment.limit\n  var data = segment.data\n\n  var i = bytesOffset\n  while (i < bytesLimit) {\n    if (segmentPos == segmentLimit) {\n      segment = segment.next!!\n      data = segment.data\n      segmentPos = segment.pos\n      segmentLimit = segment.limit\n    }\n\n    if (data[segmentPos] != bytes[i]) {\n      return false\n    }\n\n    segmentPos++\n    i++\n  }\n\n  return true\n}\n\ninternal fun Buffer.readUtf8Line(newline: Long): String {\n  return when {\n    newline > 0 && this[newline - 1] == '\\r'.code.toByte() -> {\n      // Read everything until '\\r\\n', then skip the '\\r\\n'.\n      val result = readUtf8(newline - 1L)\n      skip(2L)\n      result\n    }\n    else -> {\n      // Read everything until '\\n', then skip the '\\n'.\n      val result = readUtf8(newline)\n      skip(1L)\n      result\n    }\n  }\n}\n\n/**\n * Invoke `lambda` with the segment and offset at `fromIndex`. Searches from the front or the back\n * depending on what's closer to `fromIndex`.\n */\ninternal inline fun <T> Buffer.seek(\n  fromIndex: Long,\n  lambda: (Segment?, Long) -> T,\n): T {\n  var s: Segment = head ?: return lambda(null, -1L)\n\n  if (size - fromIndex < fromIndex) {\n    // We're scanning in the back half of this buffer. Find the segment starting at the back.\n    var offset = size\n    while (offset > fromIndex) {\n      s = s.prev!!\n      offset -= (s.limit - s.pos).toLong()\n    }\n    return lambda(s, offset)\n  } else {\n    // We're scanning in the front half of this buffer. Find the segment starting at the front.\n    var offset = 0L\n    while (true) {\n      val nextOffset = offset + (s.limit - s.pos)\n      if (nextOffset > fromIndex) break\n      s = s.next!!\n      offset = nextOffset\n    }\n    return lambda(s, offset)\n  }\n}\n\n/**\n * Returns the index of a value in options that is a prefix of this buffer. Returns -1 if no value\n * is found. This method does two simultaneous iterations: it iterates the trie and it iterates\n * this buffer. It returns when it reaches a result in the trie, when it mismatches in the trie,\n * and when the buffer is exhausted.\n *\n * @param selectTruncated true to return -2 if a possible result is present but truncated. For\n *     example, this will return -2 if the buffer contains [ab] and the options are [abc, abd].\n *     Note that this is made complicated by the fact that options are listed in preference order,\n *     and one option may be a prefix of another. For example, this returns -2 if the buffer\n *     contains [ab] and the options are [abc, a].\n */\ninternal fun Buffer.selectPrefix(options: Options, selectTruncated: Boolean = false): Int {\n  val head = head ?: return if (selectTruncated) -2 else -1\n\n  var s: Segment? = head\n  var data = head.data\n  var pos = head.pos\n  var limit = head.limit\n\n  val trie = options.trie\n  var triePos = 0\n\n  var prefixIndex = -1\n\n  navigateTrie@\n  while (true) {\n    val scanOrSelect = trie[triePos++]\n\n    val possiblePrefixIndex = trie[triePos++]\n    if (possiblePrefixIndex != -1) {\n      prefixIndex = possiblePrefixIndex\n    }\n\n    val nextStep: Int\n\n    if (s == null) {\n      break@navigateTrie\n    } else if (scanOrSelect < 0) {\n      // Scan: take multiple bytes from the buffer and the trie, looking for any mismatch.\n      val scanByteCount = -1 * scanOrSelect\n      val trieLimit = triePos + scanByteCount\n      while (true) {\n        val byte = data[pos++] and 0xff\n        if (byte != trie[triePos++]) return prefixIndex // Fail 'cause we found a mismatch.\n        val scanComplete = (triePos == trieLimit)\n\n        // Advance to the next buffer segment if this one is exhausted.\n        if (pos == limit) {\n          s = s!!.next!!\n          pos = s.pos\n          data = s.data\n          limit = s.limit\n          if (s === head) {\n            if (!scanComplete) break@navigateTrie // We were exhausted before the scan completed.\n            s = null // We were exhausted at the end of the scan.\n          }\n        }\n\n        if (scanComplete) {\n          nextStep = trie[triePos]\n          break\n        }\n      }\n    } else {\n      // Select: take one byte from the buffer and find a match in the trie.\n      val selectChoiceCount = scanOrSelect\n      val byte = data[pos++] and 0xff\n      val selectLimit = triePos + selectChoiceCount\n      while (true) {\n        if (triePos == selectLimit) return prefixIndex // Fail 'cause we didn't find a match.\n\n        if (byte == trie[triePos]) {\n          nextStep = trie[triePos + selectChoiceCount]\n          break\n        }\n\n        triePos++\n      }\n\n      // Advance to the next buffer segment if this one is exhausted.\n      if (pos == limit) {\n        s = s.next!!\n        pos = s.pos\n        data = s.data\n        limit = s.limit\n        if (s === head) {\n          s = null // No more segments! The next trie node will be our last.\n        }\n      }\n    }\n\n    if (nextStep >= 0) return nextStep // Found a matching option.\n    triePos = -nextStep // Found another node to continue the search.\n  }\n\n  // We break out of the loop above when we've exhausted the buffer without exhausting the trie.\n  if (selectTruncated) return -2 // The buffer is a prefix of at least one option.\n  return prefixIndex // Return any matches we encountered while searching for a deeper match.\n}\n\n// TODO Kotlin's expect classes can't have default implementations, so platform implementations\n// have to call these functions. Remove all this nonsense when expect class allow actual code.\n\ninternal inline fun Buffer.commonCopyTo(\n  out: Buffer,\n  offset: Long,\n  byteCount: Long,\n): Buffer {\n  var offset = offset\n  var byteCount = byteCount\n  checkOffsetAndCount(size, offset, byteCount)\n  if (byteCount == 0L) return this\n\n  out.size += byteCount\n\n  // Skip segments that we aren't copying from.\n  var s = head\n  while (offset >= s!!.limit - s.pos) {\n    offset -= (s.limit - s.pos).toLong()\n    s = s.next\n  }\n\n  // Copy one segment at a time.\n  while (byteCount > 0L) {\n    val copy = s!!.sharedCopy()\n    copy.pos += offset.toInt()\n    copy.limit = minOf(copy.pos + byteCount.toInt(), copy.limit)\n    if (out.head == null) {\n      copy.prev = copy\n      copy.next = copy.prev\n      out.head = copy.next\n    } else {\n      out.head!!.prev!!.push(copy)\n    }\n    byteCount -= (copy.limit - copy.pos).toLong()\n    offset = 0L\n    s = s.next\n  }\n\n  return this\n}\n\ninternal inline fun Buffer.commonCompleteSegmentByteCount(): Long {\n  var result = size\n  if (result == 0L) return 0L\n\n  // Omit the tail if it's still writable.\n  val tail = head!!.prev!!\n  if (tail.limit < Segment.SIZE && tail.owner) {\n    result -= (tail.limit - tail.pos).toLong()\n  }\n\n  return result\n}\n\ninternal inline fun Buffer.commonReadByte(): Byte {\n  if (size == 0L) throw EOFException()\n\n  val segment = head!!\n  var pos = segment.pos\n  val limit = segment.limit\n\n  val data = segment.data\n  val b = data[pos++]\n  size -= 1L\n\n  if (pos == limit) {\n    head = segment.pop()\n    SegmentPool.recycle(segment)\n  } else {\n    segment.pos = pos\n  }\n\n  return b\n}\n\ninternal inline fun Buffer.commonReadShort(): Short {\n  if (size < 2L) throw EOFException()\n\n  val segment = head!!\n  var pos = segment.pos\n  val limit = segment.limit\n\n  // If the short is split across multiple segments, delegate to readByte().\n  if (limit - pos < 2) {\n    val s = readByte() and 0xff shl 8 or (readByte() and 0xff)\n    return s.toShort()\n  }\n\n  val data = segment.data\n  val s = data[pos++] and 0xff shl 8 or (data[pos++] and 0xff)\n  size -= 2L\n\n  if (pos == limit) {\n    head = segment.pop()\n    SegmentPool.recycle(segment)\n  } else {\n    segment.pos = pos\n  }\n\n  return s.toShort()\n}\n\ninternal inline fun Buffer.commonReadInt(): Int {\n  if (size < 4L) throw EOFException()\n\n  val segment = head!!\n  var pos = segment.pos\n  val limit = segment.limit\n\n  // If the int is split across multiple segments, delegate to readByte().\n  if (limit - pos < 4L) {\n    return (\n      readByte() and 0xff shl 24\n        or (readByte() and 0xff shl 16)\n        or (readByte() and 0xff shl 8) // ktlint-disable no-multi-spaces\n        or (readByte() and 0xff)\n      )\n  }\n\n  val data = segment.data\n  val i = (\n    data[pos++] and 0xff shl 24\n      or (data[pos++] and 0xff shl 16)\n      or (data[pos++] and 0xff shl 8)\n      or (data[pos++] and 0xff)\n    )\n  size -= 4L\n\n  if (pos == limit) {\n    head = segment.pop()\n    SegmentPool.recycle(segment)\n  } else {\n    segment.pos = pos\n  }\n\n  return i\n}\n\ninternal inline fun Buffer.commonReadLong(): Long {\n  if (size < 8L) throw EOFException()\n\n  val segment = head!!\n  var pos = segment.pos\n  val limit = segment.limit\n\n  // If the long is split across multiple segments, delegate to readInt().\n  if (limit - pos < 8L) {\n    return (\n      readInt() and 0xffffffffL shl 32\n        or (readInt() and 0xffffffffL)\n      )\n  }\n\n  val data = segment.data\n  val v = (\n    data[pos++] and 0xffL shl 56\n      or (data[pos++] and 0xffL shl 48)\n      or (data[pos++] and 0xffL shl 40)\n      or (data[pos++] and 0xffL shl 32)\n      or (data[pos++] and 0xffL shl 24)\n      or (data[pos++] and 0xffL shl 16)\n      or (data[pos++] and 0xffL shl 8) // ktlint-disable no-multi-spaces\n      or (data[pos++] and 0xffL)\n    )\n  size -= 8L\n\n  if (pos == limit) {\n    head = segment.pop()\n    SegmentPool.recycle(segment)\n  } else {\n    segment.pos = pos\n  }\n\n  return v\n}\n\ninternal inline fun Buffer.commonGet(pos: Long): Byte {\n  checkOffsetAndCount(size, pos, 1L)\n  seek(pos) { s, offset ->\n    return s!!.data[(s.pos + pos - offset).toInt()]\n  }\n}\n\ninternal inline fun Buffer.commonClear() = skip(size)\n\ninternal inline fun Buffer.commonSkip(byteCount: Long) {\n  var byteCount = byteCount\n  while (byteCount > 0) {\n    val head = this.head ?: throw EOFException()\n\n    val toSkip = minOf(byteCount, head.limit - head.pos).toInt()\n    size -= toSkip.toLong()\n    byteCount -= toSkip.toLong()\n    head.pos += toSkip\n\n    if (head.pos == head.limit) {\n      this.head = head.pop()\n      SegmentPool.recycle(head)\n    }\n  }\n}\n\ninternal inline fun Buffer.commonWrite(\n  byteString: ByteString,\n  offset: Int = 0,\n  byteCount: Int = byteString.size,\n): Buffer {\n  byteString.write(this, offset, byteCount)\n  return this\n}\n\ninternal inline fun Buffer.commonWriteDecimalLong(v: Long): Buffer {\n  var v = v\n  if (v == 0L) {\n    // Both a shortcut and required since the following code can't handle zero.\n    return writeByte('0'.code)\n  }\n\n  var negative = false\n  if (v < 0L) {\n    v = -v\n    if (v < 0L) { // Only true for Long.MIN_VALUE.\n      return writeUtf8(\"-9223372036854775808\")\n    }\n    negative = true\n  }\n\n  var width = countDigitsIn(v)\n  if (negative) {\n    ++width\n  }\n\n  val tail = writableSegment(width)\n  val data = tail.data\n  var pos = tail.limit + width // We write backwards from right to left.\n  while (v != 0L) {\n    val digit = (v % 10).toInt()\n    data[--pos] = HEX_DIGIT_BYTES[digit]\n    v /= 10\n  }\n  if (negative) {\n    data[--pos] = '-'.code.toByte()\n  }\n\n  tail.limit += width\n  this.size += width.toLong()\n  return this\n}\n\nprivate fun countDigitsIn(v: Long): Int {\n  val guess = ((64 - v.countLeadingZeroBits()) * 10) ushr 5\n  return guess + (if (v > DigitCountToLargestValue[guess]) 1 else 0)\n}\n\nprivate val DigitCountToLargestValue = longArrayOf(\n  -1, // Every value has more than 0 digits.\n  9L, // For 1 digit (index 1), the largest value is 9.\n  99L,\n  999L,\n  9999L,\n  99999L,\n  999999L,\n  9999999L,\n  99999999L,\n  999999999L,\n  9999999999L,\n  99999999999L,\n  999999999999L,\n  9999999999999L,\n  99999999999999L,\n  999999999999999L,\n  9999999999999999L,\n  99999999999999999L,\n  999999999999999999L, // For 18 digits (index 18), the largest value is 999999999999999999.\n  Long.MAX_VALUE, // For 19 digits (index 19), the largest value is MAX_VALUE.\n)\n\ninternal inline fun Buffer.commonWriteHexadecimalUnsignedLong(v: Long): Buffer {\n  var v = v\n  if (v == 0L) {\n    // Both a shortcut and required since the following code can't handle zero.\n    return writeByte('0'.code)\n  }\n\n  // Mask every bit below the most significant bit to a 1\n  // http://aggregate.org/MAGIC/#Most%20Significant%201%20Bit\n  var x = v\n  x = x or (x ushr 1)\n  x = x or (x ushr 2)\n  x = x or (x ushr 4)\n  x = x or (x ushr 8)\n  x = x or (x ushr 16)\n  x = x or (x ushr 32)\n\n  // Count the number of 1s\n  // http://aggregate.org/MAGIC/#Population%20Count%20(Ones%20Count)\n  x -= x ushr 1 and 0x5555555555555555\n  x = (x ushr 2 and 0x3333333333333333) + (x and 0x3333333333333333)\n  x = (x ushr 4) + x and 0x0f0f0f0f0f0f0f0f\n  x += x ushr 8\n  x += x ushr 16\n  x = (x and 0x3f) + ((x ushr 32) and 0x3f)\n\n  // Round up to the nearest full byte\n  val width = ((x + 3) / 4).toInt()\n\n  val tail = writableSegment(width)\n  val data = tail.data\n  var pos = tail.limit + width - 1\n  val start = tail.limit\n  while (pos >= start) {\n    data[pos] = HEX_DIGIT_BYTES[(v and 0xF).toInt()]\n    v = v ushr 4\n    pos--\n  }\n  tail.limit += width\n  size += width.toLong()\n  return this\n}\n\ninternal inline fun Buffer.commonWritableSegment(minimumCapacity: Int): Segment {\n  require(minimumCapacity >= 1 && minimumCapacity <= Segment.SIZE) { \"unexpected capacity\" }\n\n  if (head == null) {\n    val result = SegmentPool.take() // Acquire a first segment.\n    head = result\n    result.prev = result\n    result.next = result\n    return result\n  }\n\n  var tail = head!!.prev\n  if (tail!!.limit + minimumCapacity > Segment.SIZE || !tail.owner) {\n    tail = tail.push(SegmentPool.take()) // Append a new empty segment to fill up.\n  }\n  return tail\n}\n\ninternal inline fun Buffer.commonWrite(source: ByteArray) = write(source, 0, source.size)\n\ninternal inline fun Buffer.commonWrite(\n  source: ByteArray,\n  offset: Int,\n  byteCount: Int,\n): Buffer {\n  var offset = offset\n  checkOffsetAndCount(source.size.toLong(), offset.toLong(), byteCount.toLong())\n\n  val limit = offset + byteCount\n  while (offset < limit) {\n    val tail = writableSegment(1)\n\n    val toCopy = minOf(limit - offset, Segment.SIZE - tail.limit)\n    source.copyInto(\n      destination = tail.data,\n      destinationOffset = tail.limit,\n      startIndex = offset,\n      endIndex = offset + toCopy,\n    )\n\n    offset += toCopy\n    tail.limit += toCopy\n  }\n\n  size += byteCount.toLong()\n  return this\n}\n\ninternal inline fun Buffer.commonReadByteArray() = readByteArray(size)\n\ninternal inline fun Buffer.commonReadByteArray(byteCount: Long): ByteArray {\n  require(byteCount >= 0 && byteCount <= Int.MAX_VALUE) { \"byteCount: $byteCount\" }\n  if (size < byteCount) throw EOFException()\n\n  val result = ByteArray(byteCount.toInt())\n  readFully(result)\n  return result\n}\n\ninternal inline fun Buffer.commonRead(sink: ByteArray) = read(sink, 0, sink.size)\n\ninternal inline fun Buffer.commonReadFully(sink: ByteArray) {\n  var offset = 0\n  while (offset < sink.size) {\n    val read = read(sink, offset, sink.size - offset)\n    if (read == -1) throw EOFException()\n    offset += read\n  }\n}\n\ninternal inline fun Buffer.commonRead(sink: ByteArray, offset: Int, byteCount: Int): Int {\n  checkOffsetAndCount(sink.size.toLong(), offset.toLong(), byteCount.toLong())\n\n  val s = head ?: return -1\n  val toCopy = minOf(byteCount, s.limit - s.pos)\n  s.data.copyInto(\n    destination = sink,\n    destinationOffset = offset,\n    startIndex = s.pos,\n    endIndex = s.pos + toCopy,\n  )\n\n  s.pos += toCopy\n  size -= toCopy.toLong()\n\n  if (s.pos == s.limit) {\n    head = s.pop()\n    SegmentPool.recycle(s)\n  }\n\n  return toCopy\n}\n\ninternal const val OVERFLOW_ZONE = Long.MIN_VALUE / 10L\ninternal const val OVERFLOW_DIGIT_START = Long.MIN_VALUE % 10L + 1\n\ninternal inline fun Buffer.commonReadDecimalLong(): Long {\n  if (size == 0L) throw EOFException()\n\n  // This value is always built negatively in order to accommodate Long.MIN_VALUE.\n  var value = 0L\n  var seen = 0\n  var negative = false\n  var done = false\n\n  var overflowDigit = OVERFLOW_DIGIT_START\n\n  do {\n    val segment = head!!\n\n    val data = segment.data\n    var pos = segment.pos\n    val limit = segment.limit\n\n    while (pos < limit) {\n      val b = data[pos]\n      if (b >= '0'.code.toByte() && b <= '9'.code.toByte()) {\n        val digit = '0'.code.toByte() - b\n\n        // Detect when the digit would cause an overflow.\n        if (value < OVERFLOW_ZONE || value == OVERFLOW_ZONE && digit < overflowDigit) {\n          val buffer = Buffer().writeDecimalLong(value).writeByte(b.toInt())\n          if (!negative) buffer.readByte() // Skip negative sign.\n          throw NumberFormatException(\"Number too large: ${buffer.readUtf8()}\")\n        }\n        value *= 10L\n        value += digit.toLong()\n      } else if (b == '-'.code.toByte() && seen == 0) {\n        negative = true\n        overflowDigit -= 1\n      } else {\n        // Set a flag to stop iteration. We still need to run through segment updating below.\n        done = true\n        break\n      }\n      pos++\n      seen++\n    }\n\n    if (pos == limit) {\n      head = segment.pop()\n      SegmentPool.recycle(segment)\n    } else {\n      segment.pos = pos\n    }\n  } while (!done && head != null)\n\n  size -= seen.toLong()\n\n  val minimumSeen = if (negative) 2 else 1\n  if (seen < minimumSeen) {\n    if (size == 0L) throw EOFException()\n    val expected = if (negative) \"Expected a digit\" else \"Expected a digit or '-'\"\n    throw NumberFormatException(\"$expected but was 0x${get(0).toHexString()}\")\n  }\n\n  return if (negative) value else -value\n}\n\ninternal inline fun Buffer.commonReadHexadecimalUnsignedLong(): Long {\n  if (size == 0L) throw EOFException()\n\n  var value = 0L\n  var seen = 0\n  var done = false\n\n  do {\n    val segment = head!!\n\n    val data = segment.data\n    var pos = segment.pos\n    val limit = segment.limit\n\n    while (pos < limit) {\n      val digit: Int\n\n      val b = data[pos]\n      if (b >= '0'.code.toByte() && b <= '9'.code.toByte()) {\n        digit = b - '0'.code.toByte()\n      } else if (b >= 'a'.code.toByte() && b <= 'f'.code.toByte()) {\n        digit = b - 'a'.code.toByte() + 10\n      } else if (b >= 'A'.code.toByte() && b <= 'F'.code.toByte()) {\n        digit = b - 'A'.code.toByte() + 10 // We never write uppercase, but we support reading it.\n      } else {\n        if (seen == 0) {\n          throw NumberFormatException(\n            \"Expected leading [0-9a-fA-F] character but was 0x${b.toHexString()}\",\n          )\n        }\n        // Set a flag to stop iteration. We still need to run through segment updating below.\n        done = true\n        break\n      }\n\n      // Detect when the shift will overflow.\n      if (value and -0x1000000000000000L != 0L) {\n        val buffer = Buffer().writeHexadecimalUnsignedLong(value).writeByte(b.toInt())\n        throw NumberFormatException(\"Number too large: \" + buffer.readUtf8())\n      }\n\n      value = value shl 4\n      value = value or digit.toLong()\n      pos++\n      seen++\n    }\n\n    if (pos == limit) {\n      head = segment.pop()\n      SegmentPool.recycle(segment)\n    } else {\n      segment.pos = pos\n    }\n  } while (!done && head != null)\n\n  size -= seen.toLong()\n  return value\n}\n\ninternal inline fun Buffer.commonReadByteString(): ByteString = readByteString(size)\n\ninternal inline fun Buffer.commonReadByteString(byteCount: Long): ByteString {\n  require(byteCount >= 0 && byteCount <= Int.MAX_VALUE) { \"byteCount: $byteCount\" }\n  if (size < byteCount) throw EOFException()\n\n  if (byteCount >= SEGMENTING_THRESHOLD) {\n    return snapshot(byteCount.toInt()).also { skip(byteCount) }\n  } else {\n    return ByteString(readByteArray(byteCount))\n  }\n}\n\ninternal inline fun Buffer.commonSelect(options: Options): Int {\n  val index = selectPrefix(options)\n  if (index == -1) return -1\n\n  // If the prefix match actually matched a full byte string, consume it and return it.\n  val selectedSize = options.byteStrings[index].size\n  skip(selectedSize.toLong())\n  return index\n}\n\ninternal inline fun Buffer.commonReadFully(sink: Buffer, byteCount: Long) {\n  if (size < byteCount) {\n    sink.write(this, size) // Exhaust ourselves.\n    throw EOFException()\n  }\n  sink.write(this, byteCount)\n}\n\ninternal inline fun Buffer.commonReadAll(sink: Sink): Long {\n  val byteCount = size\n  if (byteCount > 0L) {\n    sink.write(this, byteCount)\n  }\n  return byteCount\n}\n\ninternal inline fun Buffer.commonReadUtf8(byteCount: Long): String {\n  require(byteCount >= 0 && byteCount <= Int.MAX_VALUE) { \"byteCount: $byteCount\" }\n  if (size < byteCount) throw EOFException()\n  if (byteCount == 0L) return \"\"\n\n  val s = head!!\n  if (s.pos + byteCount > s.limit) {\n    // If the string spans multiple segments, delegate to readBytes().\n\n    return readByteArray(byteCount).commonToUtf8String()\n  }\n\n  val result = s.data.commonToUtf8String(s.pos, s.pos + byteCount.toInt())\n  s.pos += byteCount.toInt()\n  size -= byteCount\n\n  if (s.pos == s.limit) {\n    head = s.pop()\n    SegmentPool.recycle(s)\n  }\n\n  return result\n}\n\ninternal inline fun Buffer.commonReadUtf8Line(): String? {\n  val newline = indexOf('\\n'.code.toByte())\n\n  return when {\n    newline != -1L -> readUtf8Line(newline)\n    size != 0L -> readUtf8(size)\n    else -> null\n  }\n}\n\ninternal inline fun Buffer.commonReadUtf8LineStrict(limit: Long): String {\n  require(limit >= 0L) { \"limit < 0: $limit\" }\n  val scanLength = if (limit == Long.MAX_VALUE) Long.MAX_VALUE else limit + 1L\n  val newline = indexOf('\\n'.code.toByte(), 0L, scanLength)\n  if (newline != -1L) return readUtf8Line(newline)\n  if (scanLength < size &&\n    this[scanLength - 1] == '\\r'.code.toByte() &&\n    this[scanLength] == '\\n'.code.toByte()\n  ) {\n    return readUtf8Line(scanLength) // The line was 'limit' UTF-8 bytes followed by \\r\\n.\n  }\n  val data = Buffer()\n  copyTo(data, 0, minOf(32, size))\n  throw EOFException(\n    \"\\\\n not found: limit=${minOf(\n      size,\n      limit,\n    )} content=${data.readByteString().hex()}${'…'}\",\n  )\n}\n\ninternal inline fun Buffer.commonReadUtf8CodePoint(): Int {\n  if (size == 0L) throw EOFException()\n\n  val b0 = this[0]\n  var codePoint: Int\n  val byteCount: Int\n  val min: Int\n\n  when {\n    b0 and 0x80 == 0 -> {\n      // 0xxxxxxx.\n      codePoint = b0 and 0x7f\n      byteCount = 1 // 7 bits (ASCII).\n      min = 0x0\n    }\n    b0 and 0xe0 == 0xc0 -> {\n      // 0x110xxxxx\n      codePoint = b0 and 0x1f\n      byteCount = 2 // 11 bits (5 + 6).\n      min = 0x80\n    }\n    b0 and 0xf0 == 0xe0 -> {\n      // 0x1110xxxx\n      codePoint = b0 and 0x0f\n      byteCount = 3 // 16 bits (4 + 6 + 6).\n      min = 0x800\n    }\n    b0 and 0xf8 == 0xf0 -> {\n      // 0x11110xxx\n      codePoint = b0 and 0x07\n      byteCount = 4 // 21 bits (3 + 6 + 6 + 6).\n      min = 0x10000\n    }\n    else -> {\n      // We expected the first byte of a code point but got something else.\n      skip(1)\n      return REPLACEMENT_CODE_POINT\n    }\n  }\n\n  if (size < byteCount) {\n    throw EOFException(\"size < $byteCount: $size (to read code point prefixed 0x${b0.toHexString()})\")\n  }\n\n  // Read the continuation bytes. If we encounter a non-continuation byte, the sequence consumed\n  // thus far is truncated and is decoded as the replacement character. That non-continuation byte\n  // is left in the stream for processing by the next call to readUtf8CodePoint().\n  for (i in 1 until byteCount) {\n    val b = this[i.toLong()]\n    if (b and 0xc0 == 0x80) {\n      // 0x10xxxxxx\n      codePoint = codePoint shl 6\n      codePoint = codePoint or (b and 0x3f)\n    } else {\n      skip(i.toLong())\n      return REPLACEMENT_CODE_POINT\n    }\n  }\n\n  skip(byteCount.toLong())\n\n  return when {\n    codePoint > 0x10ffff -> {\n      REPLACEMENT_CODE_POINT // Reject code points larger than the Unicode maximum.\n    }\n    codePoint in 0xd800..0xdfff -> {\n      REPLACEMENT_CODE_POINT // Reject partial surrogates.\n    }\n    codePoint < min -> {\n      REPLACEMENT_CODE_POINT // Reject overlong code points.\n    }\n    else -> codePoint\n  }\n}\n\ninternal inline fun Buffer.commonWriteUtf8(string: String, beginIndex: Int, endIndex: Int): Buffer {\n  require(beginIndex >= 0) { \"beginIndex < 0: $beginIndex\" }\n  require(endIndex >= beginIndex) { \"endIndex < beginIndex: $endIndex < $beginIndex\" }\n  require(endIndex <= string.length) { \"endIndex > string.length: $endIndex > ${string.length}\" }\n\n  // Transcode a UTF-16 Java String to UTF-8 bytes.\n  var i = beginIndex\n  while (i < endIndex) {\n    var c = string[i].code\n\n    when {\n      c < 0x80 -> {\n        val tail = writableSegment(1)\n        val data = tail.data\n        val segmentOffset = tail.limit - i\n        val runLimit = minOf(endIndex, Segment.SIZE - segmentOffset)\n\n        // Emit a 7-bit character with 1 byte.\n        data[segmentOffset + i++] = c.toByte() // 0xxxxxxx\n\n        // Fast-path contiguous runs of ASCII characters. This is ugly, but yields a ~4x performance\n        // improvement over independent calls to writeByte().\n        while (i < runLimit) {\n          c = string[i].code\n          if (c >= 0x80) break\n          data[segmentOffset + i++] = c.toByte() // 0xxxxxxx\n        }\n\n        val runSize = i + segmentOffset - tail.limit // Equivalent to i - (previous i).\n        tail.limit += runSize\n        size += runSize.toLong()\n      }\n\n      c < 0x800 -> {\n        // Emit a 11-bit character with 2 bytes.\n        val tail = writableSegment(2)\n        /* ktlint-disable no-multi-spaces */\n        tail.data[tail.limit    ] = (c shr 6          or 0xc0).toByte() // 110xxxxx\n        tail.data[tail.limit + 1] = (c       and 0x3f or 0x80).toByte() // 10xxxxxx\n        /* ktlint-enable no-multi-spaces */\n        tail.limit += 2\n        size += 2L\n        i++\n      }\n\n      c < 0xd800 || c > 0xdfff -> {\n        // Emit a 16-bit character with 3 bytes.\n        val tail = writableSegment(3)\n        /* ktlint-disable no-multi-spaces */\n        tail.data[tail.limit    ] = (c shr 12          or 0xe0).toByte() // 1110xxxx\n        tail.data[tail.limit + 1] = (c shr  6 and 0x3f or 0x80).toByte() // 10xxxxxx\n        tail.data[tail.limit + 2] = (c        and 0x3f or 0x80).toByte() // 10xxxxxx\n        /* ktlint-enable no-multi-spaces */\n        tail.limit += 3\n        size += 3L\n        i++\n      }\n\n      else -> {\n        // c is a surrogate. Make sure it is a high surrogate & that its successor is a low\n        // surrogate. If not, the UTF-16 is invalid, in which case we emit a replacement\n        // character.\n        val low = (if (i + 1 < endIndex) string[i + 1].code else 0)\n        if (c > 0xdbff || low !in 0xdc00..0xdfff) {\n          writeByte('?'.code)\n          i++\n        } else {\n          // UTF-16 high surrogate: 110110xxxxxxxxxx (10 bits)\n          // UTF-16 low surrogate:  110111yyyyyyyyyy (10 bits)\n          // Unicode code point:    00010000000000000000 + xxxxxxxxxxyyyyyyyyyy (21 bits)\n          val codePoint = 0x010000 + (c and 0x03ff shl 10 or (low and 0x03ff))\n\n          // Emit a 21-bit character with 4 bytes.\n          val tail = writableSegment(4)\n          /* ktlint-disable no-multi-spaces */\n          tail.data[tail.limit    ] = (codePoint shr 18          or 0xf0).toByte() // 11110xxx\n          tail.data[tail.limit + 1] = (codePoint shr 12 and 0x3f or 0x80).toByte() // 10xxxxxx\n          tail.data[tail.limit + 2] = (codePoint shr  6 and 0x3f or 0x80).toByte() // 10xxyyyy\n          tail.data[tail.limit + 3] = (codePoint        and 0x3f or 0x80).toByte() // 10yyyyyy\n          /* ktlint-enable no-multi-spaces */\n          tail.limit += 4\n          size += 4L\n          i += 2\n        }\n      }\n    }\n  }\n\n  return this\n}\n\ninternal inline fun Buffer.commonWriteUtf8CodePoint(codePoint: Int): Buffer {\n  when {\n    codePoint < 0x80 -> {\n      // Emit a 7-bit code point with 1 byte.\n      writeByte(codePoint)\n    }\n    codePoint < 0x800 -> {\n      // Emit a 11-bit code point with 2 bytes.\n      val tail = writableSegment(2)\n      /* ktlint-disable no-multi-spaces */\n      tail.data[tail.limit    ] = (codePoint shr 6          or 0xc0).toByte() // 110xxxxx\n      tail.data[tail.limit + 1] = (codePoint       and 0x3f or 0x80).toByte() // 10xxxxxx\n      /* ktlint-enable no-multi-spaces */\n      tail.limit += 2\n      size += 2L\n    }\n    codePoint in 0xd800..0xdfff -> {\n      // Emit a replacement character for a partial surrogate.\n      writeByte('?'.code)\n    }\n    codePoint < 0x10000 -> {\n      // Emit a 16-bit code point with 3 bytes.\n      val tail = writableSegment(3)\n      /* ktlint-disable no-multi-spaces */\n      tail.data[tail.limit    ] = (codePoint shr 12          or 0xe0).toByte() // 1110xxxx\n      tail.data[tail.limit + 1] = (codePoint shr  6 and 0x3f or 0x80).toByte() // 10xxxxxx\n      tail.data[tail.limit + 2] = (codePoint        and 0x3f or 0x80).toByte() // 10xxxxxx\n      /* ktlint-enable no-multi-spaces */\n      tail.limit += 3\n      size += 3L\n    }\n    codePoint <= 0x10ffff -> {\n      // Emit a 21-bit code point with 4 bytes.\n      val tail = writableSegment(4)\n      /* ktlint-disable no-multi-spaces */\n      tail.data[tail.limit    ] = (codePoint shr 18          or 0xf0).toByte() // 11110xxx\n      tail.data[tail.limit + 1] = (codePoint shr 12 and 0x3f or 0x80).toByte() // 10xxxxxx\n      tail.data[tail.limit + 2] = (codePoint shr  6 and 0x3f or 0x80).toByte() // 10xxyyyy\n      tail.data[tail.limit + 3] = (codePoint        and 0x3f or 0x80).toByte() // 10yyyyyy\n      /* ktlint-enable no-multi-spaces */\n      tail.limit += 4\n      size += 4L\n    }\n    else -> {\n      throw IllegalArgumentException(\"Unexpected code point: 0x${codePoint.toHexString()}\")\n    }\n  }\n\n  return this\n}\n\ninternal inline fun Buffer.commonWriteAll(source: Source): Long {\n  var totalBytesRead = 0L\n  while (true) {\n    val readCount = source.read(this, Segment.SIZE.toLong())\n    if (readCount == -1L) break\n    totalBytesRead += readCount\n  }\n  return totalBytesRead\n}\n\ninternal inline fun Buffer.commonWrite(source: Source, byteCount: Long): Buffer {\n  var byteCount = byteCount\n  while (byteCount > 0L) {\n    val read = source.read(this, byteCount)\n    if (read == -1L) throw EOFException()\n    byteCount -= read\n  }\n  return this\n}\n\ninternal inline fun Buffer.commonWriteByte(b: Int): Buffer {\n  val tail = writableSegment(1)\n  tail.data[tail.limit++] = b.toByte()\n  size += 1L\n  return this\n}\n\ninternal inline fun Buffer.commonWriteShort(s: Int): Buffer {\n  val tail = writableSegment(2)\n  val data = tail.data\n  var limit = tail.limit\n  data[limit++] = (s ushr 8 and 0xff).toByte()\n  data[limit++] = (s        and 0xff).toByte() // ktlint-disable no-multi-spaces\n  tail.limit = limit\n  size += 2L\n  return this\n}\n\ninternal inline fun Buffer.commonWriteInt(i: Int): Buffer {\n  val tail = writableSegment(4)\n  val data = tail.data\n  var limit = tail.limit\n  data[limit++] = (i ushr 24 and 0xff).toByte()\n  data[limit++] = (i ushr 16 and 0xff).toByte()\n  data[limit++] = (i ushr  8 and 0xff).toByte() // ktlint-disable no-multi-spaces\n  data[limit++] = (i         and 0xff).toByte() // ktlint-disable no-multi-spaces\n  tail.limit = limit\n  size += 4L\n  return this\n}\n\ninternal inline fun Buffer.commonWriteLong(v: Long): Buffer {\n  val tail = writableSegment(8)\n  val data = tail.data\n  var limit = tail.limit\n  data[limit++] = (v ushr 56 and 0xffL).toByte()\n  data[limit++] = (v ushr 48 and 0xffL).toByte()\n  data[limit++] = (v ushr 40 and 0xffL).toByte()\n  data[limit++] = (v ushr 32 and 0xffL).toByte()\n  data[limit++] = (v ushr 24 and 0xffL).toByte()\n  data[limit++] = (v ushr 16 and 0xffL).toByte()\n  data[limit++] = (v ushr  8 and 0xffL).toByte() // ktlint-disable no-multi-spaces\n  data[limit++] = (v         and 0xffL).toByte() // ktlint-disable no-multi-spaces\n  tail.limit = limit\n  size += 8L\n  return this\n}\n\ninternal inline fun Buffer.commonWrite(source: Buffer, byteCount: Long) {\n  var byteCount = byteCount\n  // Move bytes from the head of the source buffer to the tail of this buffer\n  // while balancing two conflicting goals: don't waste CPU and don't waste\n  // memory.\n  //\n  //\n  // Don't waste CPU (ie. don't copy data around).\n  //\n  // Copying large amounts of data is expensive. Instead, we prefer to\n  // reassign entire segments from one buffer to the other.\n  //\n  //\n  // Don't waste memory.\n  //\n  // As an invariant, adjacent pairs of segments in a buffer should be at\n  // least 50% full, except for the head segment and the tail segment.\n  //\n  // The head segment cannot maintain the invariant because the application is\n  // consuming bytes from this segment, decreasing its level.\n  //\n  // The tail segment cannot maintain the invariant because the application is\n  // producing bytes, which may require new nearly-empty tail segments to be\n  // appended.\n  //\n  //\n  // Moving segments between buffers\n  //\n  // When writing one buffer to another, we prefer to reassign entire segments\n  // over copying bytes into their most compact form. Suppose we have a buffer\n  // with these segment levels [91%, 61%]. If we append a buffer with a\n  // single [72%] segment, that yields [91%, 61%, 72%]. No bytes are copied.\n  //\n  // Or suppose we have a buffer with these segment levels: [100%, 2%], and we\n  // want to append it to a buffer with these segment levels [99%, 3%]. This\n  // operation will yield the following segments: [100%, 2%, 99%, 3%]. That\n  // is, we do not spend time copying bytes around to achieve more efficient\n  // memory use like [100%, 100%, 4%].\n  //\n  // When combining buffers, we will compact adjacent buffers when their\n  // combined level doesn't exceed 100%. For example, when we start with\n  // [100%, 40%] and append [30%, 80%], the result is [100%, 70%, 80%].\n  //\n  //\n  // Splitting segments\n  //\n  // Occasionally we write only part of a source buffer to a sink buffer. For\n  // example, given a sink [51%, 91%], we may want to write the first 30% of\n  // a source [92%, 82%] to it. To simplify, we first transform the source to\n  // an equivalent buffer [30%, 62%, 82%] and then move the head segment,\n  // yielding sink [51%, 91%, 30%] and source [62%, 82%].\n\n  require(source !== this) { \"source == this\" }\n  checkOffsetAndCount(source.size, 0, byteCount)\n\n  while (byteCount > 0L) {\n    // Is a prefix of the source's head segment all that we need to move?\n    if (byteCount < source.head!!.limit - source.head!!.pos) {\n      val tail = if (head != null) head!!.prev else null\n      if (tail != null && tail.owner &&\n        byteCount + tail.limit - (if (tail.shared) 0 else tail.pos) <= Segment.SIZE\n      ) {\n        // Our existing segments are sufficient. Move bytes from source's head to our tail.\n        source.head!!.writeTo(tail, byteCount.toInt())\n        source.size -= byteCount\n        size += byteCount\n        return\n      } else {\n        // We're going to need another segment. Split the source's head\n        // segment in two, then move the first of those two to this buffer.\n        source.head = source.head!!.split(byteCount.toInt())\n      }\n    }\n\n    // Remove the source's head segment and append it to our tail.\n    val segmentToMove = source.head\n    val movedByteCount = (segmentToMove!!.limit - segmentToMove.pos).toLong()\n    source.head = segmentToMove.pop()\n    if (head == null) {\n      head = segmentToMove\n      segmentToMove.prev = segmentToMove\n      segmentToMove.next = segmentToMove.prev\n    } else {\n      var tail = head!!.prev\n      tail = tail!!.push(segmentToMove)\n      tail.compact()\n    }\n    source.size -= movedByteCount\n    size += movedByteCount\n    byteCount -= movedByteCount\n  }\n}\n\ninternal inline fun Buffer.commonRead(sink: Buffer, byteCount: Long): Long {\n  var byteCount = byteCount\n  require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n  if (size == 0L) return -1L\n  if (byteCount > size) byteCount = size\n  sink.write(this, byteCount)\n  return byteCount\n}\n\ninternal inline fun Buffer.commonIndexOf(b: Byte, fromIndex: Long, toIndex: Long): Long {\n  var fromIndex = fromIndex\n  var toIndex = toIndex\n  require(fromIndex in 0..toIndex) { \"size=$size fromIndex=$fromIndex toIndex=$toIndex\" }\n\n  if (toIndex > size) toIndex = size\n  if (fromIndex == toIndex) return -1L\n\n  seek(fromIndex) { s, offset ->\n    var s = s ?: return -1L\n    var offset = offset\n\n    // Scan through the segments, searching for b.\n    while (offset < toIndex) {\n      val data = s.data\n      val limit = minOf(s.limit.toLong(), s.pos + toIndex - offset).toInt()\n      var pos = (s.pos + fromIndex - offset).toInt()\n      while (pos < limit) {\n        if (data[pos] == b) {\n          return pos - s.pos + offset\n        }\n        pos++\n      }\n\n      // Not in this segment. Try the next one.\n      offset += (s.limit - s.pos).toLong()\n      fromIndex = offset\n      s = s.next!!\n    }\n\n    return -1L\n  }\n}\n\ninternal fun Buffer.commonIndexOf(\n  bytes: ByteString,\n  fromIndex: Long,\n  toIndex: Long = Long.MAX_VALUE,\n  bytesOffset: Int = 0,\n  byteCount: Int = bytes.size,\n): Long {\n  checkOffsetAndCount(bytes.size.toLong(), bytesOffset.toLong(), byteCount.toLong())\n  require(byteCount > 0) { \"byteCount == 0\" }\n  require(fromIndex >= 0) { \"fromIndex < 0: $fromIndex\" }\n  require(fromIndex <= toIndex) { \"fromIndex > toIndex: $fromIndex > $toIndex\" }\n\n  var fromIndex = fromIndex\n  var toIndex = toIndex\n  if (toIndex > size) toIndex = size\n  if (fromIndex == toIndex) return -1L\n\n  seek(fromIndex) { s, offset ->\n    var s = s ?: return -1L\n    var offset = offset\n\n    // Scan through the segments, searching for the lead byte. Each time that is found, delegate\n    // to rangeEquals() to check for a complete match.\n    val targetByteArray = bytes.internalArray()\n    val b0 = targetByteArray[bytesOffset]\n    val resultLimit = minOf(toIndex, size - byteCount + 1L)\n    while (offset < resultLimit) {\n      // Scan through the current segment.\n      val data = s.data\n      val segmentLimit = minOf(s.limit, s.pos + resultLimit - offset).toInt()\n      for (pos in (s.pos + fromIndex - offset).toInt() until segmentLimit) {\n        if (\n          data[pos] == b0 &&\n          rangeEquals(s, pos + 1, targetByteArray, bytesOffset + 1, byteCount)\n        ) {\n          return pos - s.pos + offset\n        }\n      }\n\n      // Not in this segment. Try the next one.\n      offset += (s.limit - s.pos).toLong()\n      fromIndex = offset\n      s = s.next!!\n    }\n\n    return -1L\n  }\n}\n\ninternal inline fun Buffer.commonIndexOfElement(targetBytes: ByteString, fromIndex: Long): Long {\n  var fromIndex = fromIndex\n  require(fromIndex >= 0L) { \"fromIndex < 0: $fromIndex\" }\n\n  seek(fromIndex) { s, offset ->\n    var s = s ?: return -1L\n    var offset = offset\n\n    // Special case searching for one of two bytes. This is a common case for tools like Moshi,\n    // which search for pairs of chars like `\\r` and `\\n` or {@code `\"` and `\\`. The impact of this\n    // optimization is a ~5x speedup for this case without a substantial cost to other cases.\n    if (targetBytes.size == 2) {\n      // Scan through the segments, searching for either of the two bytes.\n      val b0 = targetBytes[0]\n      val b1 = targetBytes[1]\n      while (offset < size) {\n        val data = s.data\n        var pos = (s.pos + fromIndex - offset).toInt()\n        val limit = s.limit\n        while (pos < limit) {\n          val b = data[pos].toInt()\n          if (b == b0.toInt() || b == b1.toInt()) {\n            return pos - s.pos + offset\n          }\n          pos++\n        }\n\n        // Not in this segment. Try the next one.\n        offset += (s.limit - s.pos).toLong()\n        fromIndex = offset\n        s = s.next!!\n      }\n    } else {\n      // Scan through the segments, searching for a byte that's also in the array.\n      val targetByteArray = targetBytes.internalArray()\n      while (offset < size) {\n        val data = s.data\n        var pos = (s.pos + fromIndex - offset).toInt()\n        val limit = s.limit\n        while (pos < limit) {\n          val b = data[pos].toInt()\n          for (t in targetByteArray) {\n            if (b == t.toInt()) return pos - s.pos + offset\n          }\n          pos++\n        }\n\n        // Not in this segment. Try the next one.\n        offset += (s.limit - s.pos).toLong()\n        fromIndex = offset\n        s = s.next!!\n      }\n    }\n\n    return -1L\n  }\n}\n\ninternal inline fun Buffer.commonRangeEquals(\n  offset: Long,\n  bytes: ByteString,\n  bytesOffset: Int,\n  byteCount: Int,\n): Boolean {\n  if (byteCount < 0) return false\n  if (offset < 0 || offset + byteCount > size) return false\n  if (bytesOffset < 0 || bytesOffset + byteCount > bytes.size) return false\n  if (byteCount == 0) return true\n\n  return commonIndexOf(\n    bytes = bytes,\n    bytesOffset = bytesOffset,\n    byteCount = byteCount,\n    fromIndex = offset,\n    toIndex = offset + 1,\n  ) != -1L\n}\n\ninternal inline fun Buffer.commonEquals(other: Any?): Boolean {\n  if (this === other) return true\n  if (other !is Buffer) return false\n  if (size != other.size) return false\n  if (size == 0L) return true // Both buffers are empty.\n\n  var sa = this.head!!\n  var sb = other.head!!\n  var posA = sa.pos\n  var posB = sb.pos\n\n  var pos = 0L\n  var count: Long\n  while (pos < size) {\n    count = minOf(sa.limit - posA, sb.limit - posB).toLong()\n\n    for (i in 0L until count) {\n      if (sa.data[posA++] != sb.data[posB++]) return false\n    }\n\n    if (posA == sa.limit) {\n      sa = sa.next!!\n      posA = sa.pos\n    }\n\n    if (posB == sb.limit) {\n      sb = sb.next!!\n      posB = sb.pos\n    }\n    pos += count\n  }\n\n  return true\n}\n\ninternal inline fun Buffer.commonHashCode(): Int {\n  var s = head ?: return 0\n  var result = 1\n  do {\n    var pos = s.pos\n    val limit = s.limit\n    while (pos < limit) {\n      result = 31 * result + s.data[pos]\n      pos++\n    }\n    s = s.next!!\n  } while (s !== head)\n  return result\n}\n\ninternal inline fun Buffer.commonCopy(): Buffer {\n  val result = Buffer()\n  if (size == 0L) return result\n\n  val head = head!!\n  val headCopy = head.sharedCopy()\n\n  result.head = headCopy\n  headCopy.prev = result.head\n  headCopy.next = headCopy.prev\n\n  var s = head.next\n  while (s !== head) {\n    headCopy.prev!!.push(s!!.sharedCopy())\n    s = s.next\n  }\n\n  result.size = size\n  return result\n}\n\n/** Returns an immutable copy of this buffer as a byte string.  */\ninternal inline fun Buffer.commonSnapshot(): ByteString {\n  check(size <= Int.MAX_VALUE) { \"size > Int.MAX_VALUE: $size\" }\n  return snapshot(size.toInt())\n}\n\n/** Returns an immutable copy of the first `byteCount` bytes of this buffer as a byte string. */\ninternal inline fun Buffer.commonSnapshot(byteCount: Int): ByteString {\n  if (byteCount == 0) return ByteString.EMPTY\n  checkOffsetAndCount(size, 0, byteCount.toLong())\n\n  // Walk through the buffer to count how many segments we'll need.\n  var offset = 0\n  var segmentCount = 0\n  var s = head\n  while (offset < byteCount) {\n    if (s!!.limit == s.pos) {\n      throw AssertionError(\"s.limit == s.pos\") // Empty segment. This should not happen!\n    }\n    offset += s.limit - s.pos\n    segmentCount++\n    s = s.next\n  }\n\n  // Walk through the buffer again to assign segments and build the directory.\n  val segments = arrayOfNulls<ByteArray?>(segmentCount)\n  val directory = IntArray(segmentCount * 2)\n  offset = 0\n  segmentCount = 0\n  s = head\n  while (offset < byteCount) {\n    segments[segmentCount] = s!!.data\n    offset += s.limit - s.pos\n    // Despite sharing more bytes, only report having up to byteCount.\n    directory[segmentCount] = minOf(offset, byteCount)\n    directory[segmentCount + segments.size] = s.pos\n    s.shared = true\n    segmentCount++\n    s = s.next\n  }\n  @Suppress(\"UNCHECKED_CAST\")\n  return SegmentedByteString(segments as Array<ByteArray>, directory)\n}\n\ninternal fun Buffer.commonReadUnsafe(unsafeCursor: UnsafeCursor): UnsafeCursor {\n  check(unsafeCursor.buffer == null) { \"already attached to a buffer\" }\n\n  unsafeCursor.buffer = this\n  unsafeCursor.readWrite = false\n  return unsafeCursor\n}\n\ninternal fun Buffer.commonReadAndWriteUnsafe(unsafeCursor: UnsafeCursor): UnsafeCursor {\n  check(unsafeCursor.buffer == null) { \"already attached to a buffer\" }\n\n  unsafeCursor.buffer = this\n  unsafeCursor.readWrite = true\n  return unsafeCursor\n}\n\ninternal inline fun UnsafeCursor.commonNext(): Int {\n  check(offset != buffer!!.size) { \"no more bytes\" }\n  return if (offset == -1L) seek(0L) else seek(offset + (end - start))\n}\n\ninternal inline fun UnsafeCursor.commonSeek(offset: Long): Int {\n  val buffer = checkNotNull(buffer) { \"not attached to a buffer\" }\n  if (offset < -1 || offset > buffer.size) {\n    throw ArrayIndexOutOfBoundsException(\"offset=$offset > size=${buffer.size}\")\n  }\n\n  if (offset == -1L || offset == buffer.size) {\n    this.segment = null\n    this.offset = offset\n    this.data = null\n    this.start = -1\n    this.end = -1\n    return -1\n  }\n\n  // Navigate to the segment that contains `offset`. Start from our current segment if possible.\n  var min = 0L\n  var max = buffer.size\n  var head = buffer.head\n  var tail = buffer.head\n  if (this.segment != null) {\n    val segmentOffset = this.offset - (this.start - this.segment!!.pos)\n    if (segmentOffset > offset) {\n      // Set the cursor segment to be the 'end'\n      max = segmentOffset\n      tail = this.segment\n    } else {\n      // Set the cursor segment to be the 'beginning'\n      min = segmentOffset\n      head = this.segment\n    }\n  }\n\n  var next: Segment?\n  var nextOffset: Long\n  if (max - offset > offset - min) {\n    // Start at the 'beginning' and search forwards\n    next = head\n    nextOffset = min\n    while (offset >= nextOffset + (next!!.limit - next.pos)) {\n      nextOffset += (next.limit - next.pos).toLong()\n      next = next.next\n    }\n  } else {\n    // Start at the 'end' and search backwards\n    next = tail\n    nextOffset = max\n    while (nextOffset > offset) {\n      next = next!!.prev\n      nextOffset -= (next!!.limit - next.pos).toLong()\n    }\n  }\n\n  // If we're going to write and our segment is shared, swap it for a read-write one.\n  if (readWrite && next!!.shared) {\n    val unsharedNext = next.unsharedCopy()\n    if (buffer.head === next) {\n      buffer.head = unsharedNext\n    }\n    next = next.push(unsharedNext)\n    next.prev!!.pop()\n  }\n\n  // Update this cursor to the requested offset within the found segment.\n  this.segment = next\n  this.offset = offset\n  this.data = next!!.data\n  this.start = next.pos + (offset - nextOffset).toInt()\n  this.end = next.limit\n  return end - start\n}\n\ninternal inline fun UnsafeCursor.commonResizeBuffer(newSize: Long): Long {\n  val buffer = checkNotNull(buffer) { \"not attached to a buffer\" }\n  check(readWrite) { \"resizeBuffer() only permitted for read/write buffers\" }\n\n  val oldSize = buffer.size\n  if (newSize <= oldSize) {\n    require(newSize >= 0L) { \"newSize < 0: $newSize\" }\n    // Shrink the buffer by either shrinking segments or removing them.\n    var bytesToSubtract = oldSize - newSize\n    while (bytesToSubtract > 0L) {\n      val tail = buffer.head!!.prev\n      val tailSize = tail!!.limit - tail.pos\n      if (tailSize <= bytesToSubtract) {\n        buffer.head = tail.pop()\n        SegmentPool.recycle(tail)\n        bytesToSubtract -= tailSize.toLong()\n      } else {\n        tail.limit -= bytesToSubtract.toInt()\n        break\n      }\n    }\n    // Seek to the end.\n    this.segment = null\n    this.offset = newSize\n    this.data = null\n    this.start = -1\n    this.end = -1\n  } else if (newSize > oldSize) {\n    // Enlarge the buffer by either enlarging segments or adding them.\n    var needsToSeek = true\n    var bytesToAdd = newSize - oldSize\n    while (bytesToAdd > 0L) {\n      val tail = buffer.writableSegment(1)\n      val segmentBytesToAdd = minOf(bytesToAdd, Segment.SIZE - tail.limit).toInt()\n      tail.limit += segmentBytesToAdd\n      bytesToAdd -= segmentBytesToAdd.toLong()\n\n      // If this is the first segment we're adding, seek to it.\n      if (needsToSeek) {\n        this.segment = tail\n        this.offset = oldSize\n        this.data = tail.data\n        this.start = tail.limit - segmentBytesToAdd\n        this.end = tail.limit\n        needsToSeek = false\n      }\n    }\n  }\n\n  buffer.size = newSize\n\n  return oldSize\n}\n\ninternal inline fun UnsafeCursor.commonExpandBuffer(minByteCount: Int): Long {\n  require(minByteCount > 0) { \"minByteCount <= 0: $minByteCount\" }\n  require(minByteCount <= Segment.SIZE) { \"minByteCount > Segment.SIZE: $minByteCount\" }\n  val buffer = checkNotNull(buffer) { \"not attached to a buffer\" }\n  check(readWrite) { \"expandBuffer() only permitted for read/write buffers\" }\n\n  val oldSize = buffer.size\n  val tail = buffer.writableSegment(minByteCount)\n  val result = Segment.SIZE - tail.limit\n  tail.limit = Segment.SIZE\n  buffer.size = oldSize + result\n\n  // Seek to the old size.\n  this.segment = tail\n  this.offset = oldSize\n  this.data = tail.data\n  this.start = Segment.SIZE - result\n  this.end = Segment.SIZE\n\n  return result.toLong()\n}\n\ninternal inline fun UnsafeCursor.commonClose() {\n  // TODO(jwilson): use edit counts or other information to track unexpected changes?\n  check(buffer != null) { \"not attached to a buffer\" }\n\n  buffer = null\n  segment = null\n  offset = -1L\n  data = null\n  start = -1\n  end = -1\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/BufferedSource.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\n\n@file:JvmName(\"-BufferedSource\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.BufferedSource\nimport okio.TypedOptions\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun <T : Any> BufferedSource.commonSelect(options: TypedOptions<T>): T? {\n  return when (val index = select(options.options)) {\n    -1 -> null\n    else -> options[index]\n  }\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/ByteString.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n@file:JvmName(\"-ByteString\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.BASE64_URL_SAFE\nimport okio.Buffer\nimport okio.ByteString\nimport okio.REPLACEMENT_CODE_POINT\nimport okio.and\nimport okio.arrayRangeEquals\nimport okio.asUtf8ToByteArray\nimport okio.checkOffsetAndCount\nimport okio.decodeBase64ToArray\nimport okio.encodeBase64\nimport okio.isIsoControl\nimport okio.processUtf8CodePoints\nimport okio.shr\nimport okio.toUtf8String\n\n// TODO Kotlin's expect classes can't have default implementations, so platform implementations\n// have to call these functions. Remove all this nonsense when expect class allow actual code.\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonUtf8(): String {\n  var result = utf8\n  if (result == null) {\n    // We don't care if we double-allocate in racy code.\n    result = internalArray().toUtf8String()\n    utf8 = result\n  }\n  return result\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonBase64(): String = data.encodeBase64()\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonBase64Url() = data.encodeBase64(map = BASE64_URL_SAFE)\n\ninternal val HEX_DIGIT_CHARS =\n  charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonHex(): String {\n  val result = CharArray(data.size * 2)\n  var c = 0\n  for (b in data) {\n    result[c++] = HEX_DIGIT_CHARS[b shr 4 and 0xf]\n    result[c++] = HEX_DIGIT_CHARS[b       and 0xf] // ktlint-disable no-multi-spaces\n  }\n  return result.concatToString()\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonToAsciiLowercase(): ByteString {\n  // Search for an uppercase character. If we don't find one, return this.\n  var i = 0\n  while (i < data.size) {\n    var c = data[i]\n    if (c < 'A'.code.toByte() || c > 'Z'.code.toByte()) {\n      i++\n      continue\n    }\n\n    // This string is needs to be lowercased. Create and return a new byte string.\n    val lowercase = data.copyOf()\n    lowercase[i++] = (c - ('A' - 'a')).toByte()\n    while (i < lowercase.size) {\n      c = lowercase[i]\n      if (c < 'A'.code.toByte() || c > 'Z'.code.toByte()) {\n        i++\n        continue\n      }\n      lowercase[i] = (c - ('A' - 'a')).toByte()\n      i++\n    }\n    return ByteString(lowercase)\n  }\n  return this\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonToAsciiUppercase(): ByteString {\n  // Search for an lowercase character. If we don't find one, return this.\n  var i = 0\n  while (i < data.size) {\n    var c = data[i]\n    if (c < 'a'.code.toByte() || c > 'z'.code.toByte()) {\n      i++\n      continue\n    }\n\n    // This string is needs to be uppercased. Create and return a new byte string.\n    val lowercase = data.copyOf()\n    lowercase[i++] = (c - ('a' - 'A')).toByte()\n    while (i < lowercase.size) {\n      c = lowercase[i]\n      if (c < 'a'.code.toByte() || c > 'z'.code.toByte()) {\n        i++\n        continue\n      }\n      lowercase[i] = (c - ('a' - 'A')).toByte()\n      i++\n    }\n    return ByteString(lowercase)\n  }\n  return this\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonSubstring(beginIndex: Int, endIndex: Int): ByteString {\n  require(beginIndex >= 0) { \"beginIndex < 0\" }\n  require(endIndex <= data.size) { \"endIndex > length(${data.size})\" }\n\n  val subLen = endIndex - beginIndex\n  require(subLen >= 0) { \"endIndex < beginIndex\" }\n\n  if (beginIndex == 0 && endIndex == data.size) {\n    return this\n  }\n  return ByteString(data.copyOfRange(beginIndex, endIndex))\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonGetByte(pos: Int) = data[pos]\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonGetSize() = data.size\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonToByteArray() = data.copyOf()\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonInternalArray() = data\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonRangeEquals(\n  offset: Int,\n  other: ByteString,\n  otherOffset: Int,\n  byteCount: Int,\n): Boolean = other.rangeEquals(otherOffset, this.data, offset, byteCount)\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonRangeEquals(\n  offset: Int,\n  other: ByteArray,\n  otherOffset: Int,\n  byteCount: Int,\n): Boolean {\n  return (\n    offset >= 0 && offset <= data.size - byteCount &&\n      otherOffset >= 0 && otherOffset <= other.size - byteCount &&\n      arrayRangeEquals(data, offset, other, otherOffset, byteCount)\n    )\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonCopyInto(\n  offset: Int,\n  target: ByteArray,\n  targetOffset: Int,\n  byteCount: Int,\n) {\n  data.copyInto(target, targetOffset, offset, offset + byteCount)\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonStartsWith(prefix: ByteString) =\n  rangeEquals(0, prefix, 0, prefix.size)\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonStartsWith(prefix: ByteArray) =\n  rangeEquals(0, prefix, 0, prefix.size)\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonEndsWith(suffix: ByteString) =\n  rangeEquals(size - suffix.size, suffix, 0, suffix.size)\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonEndsWith(suffix: ByteArray) =\n  rangeEquals(size - suffix.size, suffix, 0, suffix.size)\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonIndexOf(other: ByteArray, fromIndex: Int): Int {\n  val limit = data.size - other.size\n  for (i in maxOf(fromIndex, 0)..limit) {\n    if (arrayRangeEquals(data, i, other, 0, other.size)) {\n      return i\n    }\n  }\n  return -1\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonLastIndexOf(\n  other: ByteString,\n  fromIndex: Int,\n) = lastIndexOf(other.internalArray(), fromIndex)\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonLastIndexOf(other: ByteArray, fromIndex: Int): Int {\n  val limit = data.size - other.size\n  for (i in minOf(fromIndex, limit) downTo 0) {\n    if (arrayRangeEquals(data, i, other, 0, other.size)) {\n      return i\n    }\n  }\n  return -1\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonEquals(other: Any?): Boolean {\n  return when {\n    other === this -> true\n    other is ByteString -> other.size == data.size && other.rangeEquals(0, data, 0, data.size)\n    else -> false\n  }\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonHashCode(): Int {\n  val result = hashCode\n  if (result != 0) return result\n  return data.contentHashCode().also {\n    hashCode = it\n  }\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonCompareTo(other: ByteString): Int {\n  val sizeA = size\n  val sizeB = other.size\n  var i = 0\n  val size = minOf(sizeA, sizeB)\n  while (i < size) {\n    val byteA = this[i] and 0xff\n    val byteB = other[i] and 0xff\n    if (byteA == byteB) {\n      i++\n      continue\n    }\n    return if (byteA < byteB) -1 else 1\n  }\n  if (sizeA == sizeB) return 0\n  return if (sizeA < sizeB) -1 else 1\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun commonOf(data: ByteArray) = ByteString(data.copyOf())\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteArray.commonToByteString(offset: Int, byteCount: Int): ByteString {\n  checkOffsetAndCount(size.toLong(), offset.toLong(), byteCount.toLong())\n  return ByteString(copyOfRange(offset, offset + byteCount))\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun String.commonEncodeUtf8(): ByteString {\n  val byteString = ByteString(asUtf8ToByteArray())\n  byteString.utf8 = this\n  return byteString\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun String.commonDecodeBase64(): ByteString? {\n  val decoded = decodeBase64ToArray()\n  return if (decoded != null) ByteString(decoded) else null\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal expect inline fun String.commonDecodeHex(): ByteString\n\n/** Writes the contents of this byte string to `buffer`.  */\ninternal fun ByteString.commonWrite(buffer: Buffer, offset: Int, byteCount: Int) {\n  buffer.write(data, offset, byteCount)\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun ByteString.commonToString(): String {\n  if (data.isEmpty()) return \"[size=0]\"\n\n  val i = codePointIndexToCharIndex(data, 64)\n  if (i == -1) {\n    return if (data.size <= 64) {\n      \"[hex=${hex()}]\"\n    } else {\n      \"[size=${data.size} hex=${commonSubstring(0, 64).hex()}…]\"\n    }\n  }\n\n  val text = utf8()\n  val safeText = text.substring(0, i)\n    .replace(\"\\\\\", \"\\\\\\\\\")\n    .replace(\"\\n\", \"\\\\n\")\n    .replace(\"\\r\", \"\\\\r\")\n  return if (i < text.length) {\n    \"[size=${data.size} text=$safeText…]\"\n  } else {\n    \"[text=$safeText]\"\n  }\n}\n\nprivate fun codePointIndexToCharIndex(s: ByteArray, codePointCount: Int): Int {\n  var charCount = 0\n  var j = 0\n  s.processUtf8CodePoints(0, s.size) { c ->\n    if (j++ == codePointCount) {\n      return charCount\n    }\n\n    if ((c != '\\n'.code && c != '\\r'.code && isIsoControl(c)) ||\n      c == REPLACEMENT_CODE_POINT\n    ) {\n      return -1\n    }\n\n    charCount += if (c < 0x10000) 1 else 2\n  }\n  return charCount\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/FileSystem.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\n@file:JvmName(\"-FileSystem\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.FileMetadata\nimport okio.FileNotFoundException\nimport okio.FileSystem\nimport okio.IOException\nimport okio.Path\nimport okio.buffer\nimport okio.use\n\n/**\n * Returns metadata of the file, directory, or object identified by [path].\n *\n * @throws IOException if [path] does not exist or its metadata cannot be read.\n */\n@Throws(IOException::class)\ninternal fun FileSystem.commonMetadata(path: Path): FileMetadata {\n  return metadataOrNull(path) ?: throw FileNotFoundException(\"no such file: $path\")\n}\n\n@Throws(IOException::class)\ninternal fun FileSystem.commonExists(path: Path): Boolean {\n  return metadataOrNull(path) != null\n}\n\n@Throws(IOException::class)\ninternal fun FileSystem.commonCreateDirectories(dir: Path, mustCreate: Boolean) {\n  // Compute the sequence of directories to create.\n  val directories = ArrayDeque<Path>()\n  var path: Path? = dir\n  while (path != null && !exists(path)) {\n    directories.addFirst(path)\n    path = path.parent\n  }\n\n  if (mustCreate && directories.isEmpty()) throw IOException(\"$dir already exists.\")\n\n  // Create them.\n  for (toCreate in directories) {\n    // We know we are creating new directories by now so we don't have to pass down `mustCreate`.\n    createDirectory(toCreate)\n  }\n}\n\n@Throws(IOException::class)\ninternal fun FileSystem.commonCopy(source: Path, target: Path) {\n  source(source).use { bytesIn ->\n    sink(target).buffer().use { bytesOut ->\n      bytesOut.writeAll(bytesIn)\n    }\n  }\n}\n\n@Throws(IOException::class)\ninternal fun FileSystem.commonDeleteRecursively(fileOrDirectory: Path, mustExist: Boolean) {\n  val sequence = sequence {\n    collectRecursively(\n      fileSystem = this@commonDeleteRecursively,\n      stack = ArrayDeque(),\n      path = fileOrDirectory,\n      followSymlinks = false,\n      postorder = true,\n    )\n  }\n  val iterator = sequence.iterator()\n  while (iterator.hasNext()) {\n    val toDelete = iterator.next()\n    delete(toDelete, mustExist = mustExist && !iterator.hasNext())\n  }\n}\n\n@Throws(IOException::class)\ninternal fun FileSystem.commonListRecursively(dir: Path, followSymlinks: Boolean): Sequence<Path> {\n  return sequence {\n    val stack = ArrayDeque<Path>()\n    stack.addLast(dir)\n    for (child in list(dir)) {\n      collectRecursively(\n        fileSystem = this@commonListRecursively,\n        stack = stack,\n        path = child,\n        followSymlinks = followSymlinks,\n        postorder = false,\n      )\n    }\n  }\n}\n\ninternal suspend fun SequenceScope<Path>.collectRecursively(\n  fileSystem: FileSystem,\n  stack: ArrayDeque<Path>,\n  path: Path,\n  followSymlinks: Boolean,\n  postorder: Boolean,\n) {\n  // For listRecursively, visit enclosing directory first.\n  if (!postorder) {\n    yield(path)\n  }\n\n  val children = fileSystem.listOrNull(path) ?: listOf()\n  if (children.isNotEmpty()) {\n    // Figure out if path is a symlink and detect symlink cycles.\n    var symlinkPath = path\n    var symlinkCount = 0\n    while (true) {\n      if (followSymlinks && symlinkPath in stack) throw IOException(\"symlink cycle at $path\")\n      symlinkPath = fileSystem.symlinkTarget(symlinkPath) ?: break\n      symlinkCount++\n    }\n\n    // Recursively visit children.\n    if (followSymlinks || symlinkCount == 0) {\n      stack.addLast(symlinkPath)\n      try {\n        for (child in children) {\n          collectRecursively(fileSystem, stack, child, followSymlinks, postorder)\n        }\n      } finally {\n        stack.removeLast()\n      }\n    }\n  }\n\n  // For deleteRecursively, visit enclosing directory last.\n  if (postorder) {\n    yield(path)\n  }\n}\n\n/** Returns a resolved path to the symlink target, resolving it if necessary. */\n@Throws(IOException::class)\ninternal fun FileSystem.symlinkTarget(path: Path): Path? {\n  val target = metadata(path).symlinkTarget ?: return null\n  return path.parent!!.div(target)\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/Path.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\n@file:JvmName(\"-Path\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.Buffer\nimport okio.ByteString\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.Path\nimport okio.Path.Companion.toPath\n\nprivate val SLASH = \"/\".encodeUtf8()\n\nprivate val BACKSLASH = \"\\\\\".encodeUtf8()\n\nprivate val ANY_SLASH = \"/\\\\\".encodeUtf8()\n\nprivate val DOT = \".\".encodeUtf8()\n\nprivate val DOT_DOT = \"..\".encodeUtf8()\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonRoot(): Path? {\n  return when (val rootLength = rootLength()) {\n    -1 -> null\n    else -> Path(bytes.substring(0, rootLength))\n  }\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonSegments(): List<String> {\n  return commonSegmentsBytes().map { it.utf8() }\n}\n\n/** This function skips the root then splits on slash. */\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonSegmentsBytes(): List<ByteString> {\n  val result = mutableListOf<ByteString>()\n  var segmentStart = rootLength()\n\n  // segmentStart should always follow a `\\`, but for UNC paths it doesn't.\n  if (segmentStart == -1) {\n    segmentStart = 0\n  } else if (segmentStart < bytes.size && bytes[segmentStart] == '\\\\'.code.toByte()) {\n    segmentStart++\n  }\n\n  for (i in segmentStart until bytes.size) {\n    if (bytes[i] == '/'.code.toByte() || bytes[i] == '\\\\'.code.toByte()) {\n      result += bytes.substring(segmentStart, i)\n      segmentStart = i + 1\n    }\n  }\n\n  if (segmentStart < bytes.size) {\n    result += bytes.substring(segmentStart, bytes.size)\n  }\n\n  return result\n}\n\n/** Return the length of the prefix of this that is the root path, or -1 if it has no root. */\nprivate fun Path.rootLength(): Int {\n  if (bytes.size == 0) return -1\n  if (bytes[0] == '/'.code.toByte()) return 1\n\n  if (bytes[0] == '\\\\'.code.toByte()) {\n    if (bytes.size > 2 && bytes[1] == '\\\\'.code.toByte()) {\n      // Look for a root like `\\\\localhost`.\n      var uncRootEnd = bytes.indexOf(BACKSLASH, fromIndex = 2)\n      if (uncRootEnd == -1) uncRootEnd = bytes.size\n      return uncRootEnd\n    }\n\n    // We found a root like `\\`.\n    return 1\n  }\n\n  // Look for a root like `C:\\`.\n  if (bytes.size > 2 && bytes[1] == ':'.code.toByte() && bytes[2] == '\\\\'.code.toByte()) {\n    val c = bytes[0].toInt().toChar()\n    if (c !in 'a'..'z' && c !in 'A'..'Z') return -1\n    return 3\n  }\n\n  return -1\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonIsAbsolute(): Boolean {\n  return rootLength() != -1\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonIsRelative(): Boolean {\n  return rootLength() == -1\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonVolumeLetter(): Char? {\n  if (bytes.indexOf(SLASH) != -1) return null\n  if (bytes.size < 2) return null\n  if (bytes[1] != ':'.code.toByte()) return null\n  val c = bytes[0].toInt().toChar()\n  if (c !in 'a'..'z' && c !in 'A'..'Z') return null\n  return c\n}\n\nprivate val Path.indexOfLastSlash: Int\n  get() {\n    val lastSlash = bytes.lastIndexOf(SLASH)\n    if (lastSlash != -1) return lastSlash\n    return bytes.lastIndexOf(BACKSLASH)\n  }\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonNameBytes(): ByteString {\n  val lastSlash = indexOfLastSlash\n  return when {\n    lastSlash != -1 -> bytes.substring(lastSlash + 1)\n    volumeLetter != null && bytes.size == 2 -> ByteString.EMPTY // \"C:\" has no name.\n    else -> bytes\n  }\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonName(): String {\n  return nameBytes.utf8()\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonParent(): Path? {\n  if (bytes == DOT || bytes == SLASH || bytes == BACKSLASH || lastSegmentIsDotDot()) {\n    return null // Terminal path.\n  }\n\n  val lastSlash = indexOfLastSlash\n  when {\n    lastSlash == 2 && volumeLetter != null -> {\n      if (bytes.size == 3) return null // \"C:\\\" has no parent.\n      return Path(bytes.substring(endIndex = 3)) // Keep the trailing '\\' in C:\\.\n    }\n    lastSlash == 1 && bytes.startsWith(BACKSLASH) -> {\n      return null // \"\\\\server\" is a UNC path with no parent.\n    }\n    lastSlash == -1 && volumeLetter != null -> {\n      if (bytes.size == 2) return null // \"C:\" has no parent.\n      return Path(bytes.substring(endIndex = 2)) // C: is volume-relative.\n    }\n    lastSlash == -1 -> {\n      return Path(DOT) // Parent is the current working directory.\n    }\n    lastSlash == 0 -> {\n      return Path(bytes.substring(endIndex = 1)) // Parent is the filesystem root '/'.\n    }\n    else -> {\n      return Path(bytes.substring(endIndex = lastSlash))\n    }\n  }\n}\n\nprivate fun Path.lastSegmentIsDotDot(): Boolean {\n  if (bytes.endsWith(DOT_DOT)) {\n    if (bytes.size == 2) return true // \"..\" is the whole string.\n    if (bytes.rangeEquals(bytes.size - 3, SLASH, 0, 1)) return true // Ends with \"/..\".\n    if (bytes.rangeEquals(bytes.size - 3, BACKSLASH, 0, 1)) return true // Ends with \"\\..\".\n  }\n  return false\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonIsRoot(): Boolean {\n  return rootLength() == bytes.size\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonResolve(child: String, normalize: Boolean): Path {\n  return commonResolve(Buffer().writeUtf8(child), normalize = normalize)\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonResolve(child: ByteString, normalize: Boolean): Path {\n  return commonResolve(Buffer().write(child), normalize = normalize)\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonResolve(child: Buffer, normalize: Boolean): Path {\n  return commonResolve(child.toPath(normalize = false), normalize = normalize)\n}\n\ninternal fun Path.commonResolve(child: Path, normalize: Boolean): Path {\n  if (child.isAbsolute || child.volumeLetter != null) return child\n\n  val slash = slash ?: child.slash ?: Path.DIRECTORY_SEPARATOR.toSlash()\n\n  val buffer = Buffer()\n  buffer.write(bytes)\n  if (buffer.size > 0) {\n    buffer.write(slash)\n  }\n  buffer.write(child.bytes)\n  return buffer.toPath(normalize = normalize)\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonRelativeTo(other: Path): Path {\n  require(root == other.root) {\n    \"Paths of different roots cannot be relative to each other: $this and $other\"\n  }\n\n  val thisSegments = this.segmentsBytes\n  val otherSegments = other.segmentsBytes\n\n  // We look at the path both have in common.\n  var firstNewSegmentIndex = 0\n  val minSegmentsSize = minOf(thisSegments.size, otherSegments.size)\n  while (firstNewSegmentIndex < minSegmentsSize &&\n    thisSegments[firstNewSegmentIndex] == otherSegments[firstNewSegmentIndex]\n  ) {\n    firstNewSegmentIndex++\n  }\n\n  if (firstNewSegmentIndex == minSegmentsSize && bytes.size == other.bytes.size) {\n    // `this` and `other` are the same path.\n    return \".\".toPath()\n  }\n\n  require(otherSegments.subList(firstNewSegmentIndex, otherSegments.size).indexOf(DOT_DOT) == -1) {\n    \"Impossible relative path to resolve: $this and $other\"\n  }\n\n  if (other.bytes == DOT) {\n    // Anything relative to \".\" is itself!\n    return this\n  }\n\n  val buffer = Buffer()\n  val slash = other.slash ?: slash ?: Path.DIRECTORY_SEPARATOR.toSlash()\n  for (i in firstNewSegmentIndex until otherSegments.size) {\n    buffer.write(DOT_DOT)\n    buffer.write(slash)\n  }\n  for (i in firstNewSegmentIndex until thisSegments.size) {\n    buffer.write(thisSegments[i])\n    buffer.write(slash)\n  }\n  return buffer.toPath(normalize = false)\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonNormalized(): Path {\n  return toString().toPath(normalize = true)\n}\n\nprivate val Path.slash: ByteString?\n  get() {\n    return when {\n      bytes.indexOf(SLASH) != -1 -> SLASH\n      bytes.indexOf(BACKSLASH) != -1 -> BACKSLASH\n      else -> null\n    }\n  }\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonCompareTo(other: Path): Int {\n  return bytes.compareTo(other.bytes)\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonEquals(other: Any?): Boolean {\n  return other is Path && other.bytes == bytes\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonHashCode(): Int {\n  return bytes.hashCode()\n}\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal inline fun Path.commonToString(): String {\n  return bytes.utf8()\n}\n\ninternal fun String.commonToPath(normalize: Boolean): Path {\n  return Buffer().writeUtf8(this).toPath(normalize)\n}\n\n/** Consume the buffer and return it as a path. */\ninternal fun Buffer.toPath(normalize: Boolean): Path {\n  var slash: ByteString? = null\n  val result = Buffer()\n\n  // Consume the absolute path prefix, like `/`, `\\\\`, `C:`, or `C:\\` and write the\n  // canonicalized prefix to result.\n  var leadingSlashCount = 0\n  while (rangeEquals(0L, SLASH) || rangeEquals(0L, BACKSLASH)) {\n    val byte = readByte()\n    slash = slash ?: byte.toSlash()\n    leadingSlashCount++\n  }\n  val windowsUncPath = leadingSlashCount >= 2 && slash == BACKSLASH\n  if (windowsUncPath) {\n    // This is a Windows UNC path, like \\\\server\\directory\\file.txt.\n    result.write(slash!!)\n    result.write(slash)\n  } else if (leadingSlashCount > 0) {\n    // This is platform-dependent:\n    //  * On UNIX: an absolute path like /home\n    //  * On Windows: this is relative to the current volume, like \\Windows.\n    result.write(slash!!)\n  } else {\n    // This path doesn't start with any slash. We must initialize the slash character to use.\n    val limit = indexOfElement(ANY_SLASH)\n    slash = slash ?: when (limit) {\n      -1L -> Path.DIRECTORY_SEPARATOR.toSlash()\n      else -> get(limit).toSlash()\n    }\n    if (startsWithVolumeLetterAndColon(slash)) {\n      if (limit == 2L) {\n        result.write(this, 3L) // Absolute on a named volume, like `C:\\`.\n      } else {\n        result.write(this, 2L) // Relative to the named volume, like `C:`.\n      }\n    }\n  }\n\n  val absolute = result.size > 0\n\n  val canonicalParts = mutableListOf<ByteString>()\n  while (!exhausted()) {\n    val limit = indexOfElement(ANY_SLASH)\n\n    val part: ByteString\n    if (limit == -1L) {\n      part = readByteString()\n    } else {\n      part = readByteString(limit)\n      readByte()\n    }\n\n    if (part == DOT_DOT) {\n      if (absolute && canonicalParts.isEmpty()) {\n        // Silently consume `..`.\n      } else if (!normalize || !absolute && (canonicalParts.isEmpty() || canonicalParts.last() == DOT_DOT)) {\n        canonicalParts.add(part) // '..' doesn't pop '..' for relative paths.\n      } else if (windowsUncPath && canonicalParts.size == 1) {\n        // `..` doesn't pop UNC hostnames.\n      } else {\n        canonicalParts.removeLastOrNull()\n      }\n    } else if (part != DOT && part != ByteString.EMPTY) {\n      canonicalParts.add(part)\n    }\n  }\n\n  for (i in 0 until canonicalParts.size) {\n    if (i > 0) result.write(slash)\n    result.write(canonicalParts[i])\n  }\n  if (result.size == 0L) {\n    result.write(DOT)\n  }\n\n  return Path(result.readByteString())\n}\n\nprivate fun String.toSlash(): ByteString {\n  return when (this) {\n    \"/\" -> SLASH\n    \"\\\\\" -> BACKSLASH\n    else -> throw IllegalArgumentException(\"not a directory separator: $this\")\n  }\n}\n\nprivate fun Byte.toSlash(): ByteString {\n  return when (toInt()) {\n    '/'.code -> SLASH\n    '\\\\'.code -> BACKSLASH\n    else -> throw IllegalArgumentException(\"not a directory separator: $this\")\n  }\n}\n\nprivate fun Buffer.startsWithVolumeLetterAndColon(slash: ByteString): Boolean {\n  if (slash != BACKSLASH) return false\n  if (size < 2) return false\n  if (get(1) != ':'.code.toByte()) return false\n  val b = get(0).toInt().toChar()\n  return b in 'a'..'z' || b in 'A'..'Z'\n}\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/RealBufferedSink.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\n// TODO move to RealBufferedSink class: https://youtrack.jetbrains.com/issue/KT-20427\n@file:Suppress(\"NOTHING_TO_INLINE\")\n\n@file:JvmName(\"-RealBufferedSink\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.Buffer\nimport okio.BufferedSink\nimport okio.ByteString\nimport okio.EOFException\nimport okio.RealBufferedSink\nimport okio.Segment\nimport okio.Source\n\ninternal inline fun RealBufferedSink.commonWrite(source: Buffer, byteCount: Long) {\n  check(!closed) { \"closed\" }\n  buffer.write(source, byteCount)\n  emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWrite(byteString: ByteString): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.write(byteString)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWrite(\n  byteString: ByteString,\n  offset: Int,\n  byteCount: Int,\n): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.write(byteString, offset, byteCount)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteUtf8(string: String): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeUtf8(string)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteUtf8(\n  string: String,\n  beginIndex: Int,\n  endIndex: Int,\n): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeUtf8(string, beginIndex, endIndex)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteUtf8CodePoint(codePoint: Int): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeUtf8CodePoint(codePoint)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWrite(source: ByteArray): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.write(source)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWrite(\n  source: ByteArray,\n  offset: Int,\n  byteCount: Int,\n): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.write(source, offset, byteCount)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteAll(source: Source): Long {\n  var totalBytesRead = 0L\n  while (true) {\n    val readCount: Long = source.read(buffer, Segment.SIZE.toLong())\n    if (readCount == -1L) break\n    totalBytesRead += readCount\n    emitCompleteSegments()\n  }\n  return totalBytesRead\n}\n\ninternal inline fun RealBufferedSink.commonWrite(source: Source, byteCount: Long): BufferedSink {\n  var byteCount = byteCount\n  while (byteCount > 0L) {\n    val read = source.read(buffer, byteCount)\n    if (read == -1L) throw EOFException()\n    byteCount -= read\n    emitCompleteSegments()\n  }\n  return this\n}\n\ninternal inline fun RealBufferedSink.commonWriteByte(b: Int): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeByte(b)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteShort(s: Int): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeShort(s)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteShortLe(s: Int): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeShortLe(s)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteInt(i: Int): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeInt(i)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteIntLe(i: Int): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeIntLe(i)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteLong(v: Long): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeLong(v)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteLongLe(v: Long): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeLongLe(v)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteDecimalLong(v: Long): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeDecimalLong(v)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonWriteHexadecimalUnsignedLong(v: Long): BufferedSink {\n  check(!closed) { \"closed\" }\n  buffer.writeHexadecimalUnsignedLong(v)\n  return emitCompleteSegments()\n}\n\ninternal inline fun RealBufferedSink.commonEmitCompleteSegments(): BufferedSink {\n  check(!closed) { \"closed\" }\n  val byteCount = buffer.completeSegmentByteCount()\n  if (byteCount > 0L) sink.write(buffer, byteCount)\n  return this\n}\n\ninternal inline fun RealBufferedSink.commonEmit(): BufferedSink {\n  check(!closed) { \"closed\" }\n  val byteCount = buffer.size\n  if (byteCount > 0L) sink.write(buffer, byteCount)\n  return this\n}\n\ninternal inline fun RealBufferedSink.commonFlush() {\n  check(!closed) { \"closed\" }\n  if (buffer.size > 0L) {\n    sink.write(buffer, buffer.size)\n  }\n  sink.flush()\n}\n\ninternal inline fun RealBufferedSink.commonClose() {\n  if (closed) return\n\n  // Emit buffered data to the underlying sink. If this fails, we still need\n  // to close the sink; otherwise we risk leaking resources.\n  var thrown: Throwable? = null\n  try {\n    if (buffer.size > 0) {\n      sink.write(buffer, buffer.size)\n    }\n  } catch (e: Throwable) {\n    thrown = e\n  }\n\n  try {\n    sink.close()\n  } catch (e: Throwable) {\n    if (thrown == null) thrown = e\n  }\n\n  closed = true\n\n  if (thrown != null) throw thrown\n}\n\ninternal inline fun RealBufferedSink.commonTimeout() = sink.timeout()\n\ninternal inline fun RealBufferedSink.commonToString() = \"buffer($sink)\"\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/RealBufferedSource.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\n// TODO move to RealBufferedSource class: https://youtrack.jetbrains.com/issue/KT-20427\n@file:Suppress(\"NOTHING_TO_INLINE\")\n\n@file:JvmName(\"-RealBufferedSource\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.Buffer\nimport okio.BufferedSource\nimport okio.ByteString\nimport okio.EOFException\nimport okio.Options\nimport okio.PeekSource\nimport okio.RealBufferedSource\nimport okio.Segment\nimport okio.Sink\nimport okio.buffer\nimport okio.checkOffsetAndCount\nimport okio.minOf\n\ninternal inline fun RealBufferedSource.commonRead(sink: Buffer, byteCount: Long): Long {\n  require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n  check(!closed) { \"closed\" }\n\n  if (buffer.size == 0L) {\n    if (byteCount == 0L) return 0L\n    val read = source.read(buffer, Segment.SIZE.toLong())\n    if (read == -1L) return -1L\n  }\n\n  val toRead = minOf(byteCount, buffer.size)\n  return buffer.read(sink, toRead)\n}\n\ninternal inline fun RealBufferedSource.commonExhausted(): Boolean {\n  check(!closed) { \"closed\" }\n  return buffer.exhausted() && source.read(buffer, Segment.SIZE.toLong()) == -1L\n}\n\ninternal inline fun RealBufferedSource.commonRequire(byteCount: Long) {\n  if (!request(byteCount)) throw EOFException()\n}\n\ninternal inline fun RealBufferedSource.commonRequest(byteCount: Long): Boolean {\n  require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n  check(!closed) { \"closed\" }\n  while (buffer.size < byteCount) {\n    if (source.read(buffer, Segment.SIZE.toLong()) == -1L) return false\n  }\n  return true\n}\n\ninternal inline fun RealBufferedSource.commonReadByte(): Byte {\n  require(1)\n  return buffer.readByte()\n}\n\ninternal inline fun RealBufferedSource.commonReadByteString(): ByteString {\n  buffer.writeAll(source)\n  return buffer.readByteString()\n}\n\ninternal inline fun RealBufferedSource.commonReadByteString(byteCount: Long): ByteString {\n  require(byteCount)\n  return buffer.readByteString(byteCount)\n}\n\ninternal inline fun RealBufferedSource.commonSelect(options: Options): Int {\n  check(!closed) { \"closed\" }\n\n  while (true) {\n    val index = buffer.selectPrefix(options, selectTruncated = true)\n    when (index) {\n      -1 -> {\n        return -1\n      }\n      -2 -> {\n        // We need to grow the buffer. Do that, then try it all again.\n        if (source.read(buffer, Segment.SIZE.toLong()) == -1L) return -1\n      }\n      else -> {\n        // We matched a full byte string: consume it and return it.\n        val selectedSize = options.byteStrings[index].size\n        buffer.skip(selectedSize.toLong())\n        return index\n      }\n    }\n  }\n}\n\ninternal inline fun RealBufferedSource.commonReadByteArray(): ByteArray {\n  buffer.writeAll(source)\n  return buffer.readByteArray()\n}\n\ninternal inline fun RealBufferedSource.commonReadByteArray(byteCount: Long): ByteArray {\n  require(byteCount)\n  return buffer.readByteArray(byteCount)\n}\n\ninternal inline fun RealBufferedSource.commonReadFully(sink: ByteArray) {\n  try {\n    require(sink.size.toLong())\n  } catch (e: EOFException) {\n    // The underlying source is exhausted. Copy the bytes we got before rethrowing.\n    var offset = 0\n    while (buffer.size > 0L) {\n      val read = buffer.read(sink, offset, buffer.size.toInt())\n      if (read == -1) throw AssertionError()\n      offset += read\n    }\n    throw e\n  }\n\n  buffer.readFully(sink)\n}\n\ninternal inline fun RealBufferedSource.commonRead(sink: ByteArray, offset: Int, byteCount: Int): Int {\n  checkOffsetAndCount(sink.size.toLong(), offset.toLong(), byteCount.toLong())\n\n  if (buffer.size == 0L) {\n    if (byteCount == 0) return 0\n    val read = source.read(buffer, Segment.SIZE.toLong())\n    if (read == -1L) return -1\n  }\n\n  val toRead = okio.minOf(byteCount, buffer.size).toInt()\n  return buffer.read(sink, offset, toRead)\n}\n\ninternal inline fun RealBufferedSource.commonReadFully(sink: Buffer, byteCount: Long) {\n  try {\n    require(byteCount)\n  } catch (e: EOFException) {\n    // The underlying source is exhausted. Copy the bytes we got before rethrowing.\n    sink.writeAll(buffer)\n    throw e\n  }\n\n  buffer.readFully(sink, byteCount)\n}\n\ninternal inline fun RealBufferedSource.commonReadAll(sink: Sink): Long {\n  var totalBytesWritten: Long = 0\n  while (source.read(buffer, Segment.SIZE.toLong()) != -1L) {\n    val emitByteCount = buffer.completeSegmentByteCount()\n    if (emitByteCount > 0L) {\n      totalBytesWritten += emitByteCount\n      sink.write(buffer, emitByteCount)\n    }\n  }\n  if (buffer.size > 0L) {\n    totalBytesWritten += buffer.size\n    sink.write(buffer, buffer.size)\n  }\n  return totalBytesWritten\n}\n\ninternal inline fun RealBufferedSource.commonReadUtf8(): String {\n  buffer.writeAll(source)\n  return buffer.readUtf8()\n}\n\ninternal inline fun RealBufferedSource.commonReadUtf8(byteCount: Long): String {\n  require(byteCount)\n  return buffer.readUtf8(byteCount)\n}\n\ninternal inline fun RealBufferedSource.commonReadUtf8Line(): String? {\n  val newline = indexOf('\\n'.code.toByte())\n\n  return if (newline == -1L) {\n    if (buffer.size != 0L) {\n      readUtf8(buffer.size)\n    } else {\n      null\n    }\n  } else {\n    buffer.readUtf8Line(newline)\n  }\n}\n\ninternal inline fun RealBufferedSource.commonReadUtf8LineStrict(limit: Long): String {\n  require(limit >= 0) { \"limit < 0: $limit\" }\n  val scanLength = if (limit == Long.MAX_VALUE) Long.MAX_VALUE else limit + 1\n  val newline = indexOf('\\n'.code.toByte(), 0, scanLength)\n  if (newline != -1L) return buffer.readUtf8Line(newline)\n  if (scanLength < Long.MAX_VALUE &&\n    request(scanLength) && buffer[scanLength - 1] == '\\r'.code.toByte() &&\n    request(scanLength + 1) && buffer[scanLength] == '\\n'.code.toByte()\n  ) {\n    return buffer.readUtf8Line(scanLength) // The line was 'limit' UTF-8 bytes followed by \\r\\n.\n  }\n  val data = Buffer()\n  buffer.copyTo(data, 0, okio.minOf(32, buffer.size))\n  throw EOFException(\n    \"\\\\n not found: limit=\" + minOf(buffer.size, limit) +\n      \" content=\" + data.readByteString().hex() + '…'.toString(),\n  )\n}\n\ninternal inline fun RealBufferedSource.commonReadUtf8CodePoint(): Int {\n  require(1)\n\n  val b0 = buffer[0].toInt()\n  when {\n    b0 and 0xe0 == 0xc0 -> require(2)\n    b0 and 0xf0 == 0xe0 -> require(3)\n    b0 and 0xf8 == 0xf0 -> require(4)\n  }\n\n  return buffer.readUtf8CodePoint()\n}\n\ninternal inline fun RealBufferedSource.commonReadShort(): Short {\n  require(2)\n  return buffer.readShort()\n}\n\ninternal inline fun RealBufferedSource.commonReadShortLe(): Short {\n  require(2)\n  return buffer.readShortLe()\n}\n\ninternal inline fun RealBufferedSource.commonReadInt(): Int {\n  require(4)\n  return buffer.readInt()\n}\n\ninternal inline fun RealBufferedSource.commonReadIntLe(): Int {\n  require(4)\n  return buffer.readIntLe()\n}\n\ninternal inline fun RealBufferedSource.commonReadLong(): Long {\n  require(8)\n  return buffer.readLong()\n}\n\ninternal inline fun RealBufferedSource.commonReadLongLe(): Long {\n  require(8)\n  return buffer.readLongLe()\n}\n\ninternal inline fun RealBufferedSource.commonReadDecimalLong(): Long {\n  require(1)\n\n  var pos = 0L\n  while (request(pos + 1)) {\n    val b = buffer[pos]\n    if ((b < '0'.code.toByte() || b > '9'.code.toByte()) && (pos != 0L || b != '-'.code.toByte())) {\n      // Non-digit, or non-leading negative sign.\n      if (pos == 0L) {\n        throw NumberFormatException(\"Expected a digit or '-' but was 0x${b.toString(16)}\")\n      }\n      break\n    }\n    pos++\n  }\n\n  return buffer.readDecimalLong()\n}\n\ninternal inline fun RealBufferedSource.commonReadHexadecimalUnsignedLong(): Long {\n  require(1)\n\n  var pos = 0\n  while (request((pos + 1).toLong())) {\n    val b = buffer[pos.toLong()]\n    if ((b < '0'.code.toByte() || b > '9'.code.toByte()) &&\n      (b < 'a'.code.toByte() || b > 'f'.code.toByte()) &&\n      (b < 'A'.code.toByte() || b > 'F'.code.toByte())\n    ) {\n      // Non-digit, or non-leading negative sign.\n      if (pos == 0) {\n        throw NumberFormatException(\"Expected leading [0-9a-fA-F] character but was 0x${b.toString(16)}\")\n      }\n      break\n    }\n    pos++\n  }\n\n  return buffer.readHexadecimalUnsignedLong()\n}\n\ninternal inline fun RealBufferedSource.commonSkip(byteCount: Long) {\n  var byteCount = byteCount\n  check(!closed) { \"closed\" }\n  while (byteCount > 0) {\n    if (buffer.size == 0L && source.read(buffer, Segment.SIZE.toLong()) == -1L) {\n      throw EOFException()\n    }\n    val toSkip = minOf(byteCount, buffer.size)\n    buffer.skip(toSkip)\n    byteCount -= toSkip\n  }\n}\n\ninternal inline fun RealBufferedSource.commonIndexOf(b: Byte, fromIndex: Long, toIndex: Long): Long {\n  var fromIndex = fromIndex\n  check(!closed) { \"closed\" }\n  require(fromIndex in 0L..toIndex) { \"fromIndex=$fromIndex toIndex=$toIndex\" }\n\n  while (fromIndex < toIndex) {\n    val result = buffer.indexOf(b, fromIndex, toIndex)\n    if (result != -1L) return result\n\n    // The byte wasn't in the buffer. Give up if we've already reached our target size or if the\n    // underlying stream is exhausted.\n    val lastBufferSize = buffer.size\n    if (lastBufferSize >= toIndex || source.read(buffer, Segment.SIZE.toLong()) == -1L) return -1L\n\n    // Continue the search from where we left off.\n    fromIndex = maxOf(fromIndex, lastBufferSize)\n  }\n  return -1L\n}\n\ninternal fun RealBufferedSource.commonIndexOf(\n  bytes: ByteString,\n  bytesOffset: Int = 0,\n  byteCount: Int = bytes.size,\n  fromIndex: Long,\n  toIndex: Long = Long.MAX_VALUE,\n): Long {\n  checkOffsetAndCount(bytes.size.toLong(), bytesOffset.toLong(), byteCount.toLong())\n\n  var fromIndex = fromIndex\n  check(!closed) { \"closed\" }\n\n  while (true) {\n    val result = buffer.commonIndexOf(\n      bytes = bytes,\n      bytesOffset = bytesOffset,\n      byteCount = byteCount,\n      fromIndex = fromIndex,\n      toIndex = toIndex,\n    )\n    if (result != -1L) return result\n\n    val lastBufferSize = buffer.size\n    val nextFromIndex = lastBufferSize - byteCount + 1\n    if (nextFromIndex >= toIndex) return -1L\n    if (\n      !buffer.isMatchPossibleByExpandingBuffer(\n        bytes = bytes,\n        bytesOffset = bytesOffset,\n        byteCount = byteCount,\n        fromIndex = fromIndex,\n        toIndex = toIndex,\n      )\n    ) {\n      return -1L\n    }\n    if (source.read(buffer, Segment.SIZE.toLong()) == -1L) return -1L\n\n    // Keep searching, picking up from where we left off.\n    fromIndex = maxOf(fromIndex, nextFromIndex)\n  }\n}\n\n/**\n * Returns true if loading more data could result in an `indexOf` match.\n *\n * This function's utility is avoiding potentially-slow `read` calls that cannot impact the result\n * of an `indexOf` call. For example, consider this situation:\n *\n * ```\n * val source = ...\n * source.indexOf(\"hello\", fromIndex = 0, toIndex = 4)\n * ```\n *\n * If the source's loaded content is the string \"shell\", it is necessary to load more data because\n * if the next loaded byte is 'o' then the result will be 1. But if the source's loaded content is\n * 'look', we know the result is -1 without loading more data.\n */\nprivate fun Buffer.isMatchPossibleByExpandingBuffer(\n  bytes: ByteString,\n  bytesOffset: Int,\n  byteCount: Int,\n  fromIndex: Long,\n  toIndex: Long,\n): Boolean {\n  // Load new data if the match could come entirely in that new data.\n  if (size < toIndex) return true\n\n  // Load new data if a prefix of 'bytes' matches a suffix of 'buffer'.\n  val begin = maxOf(1, size - toIndex + 1).toInt()\n  val limit = minOf(byteCount, size - fromIndex + 1).toInt()\n  for (i in limit - 1 downTo begin) {\n    if (rangeEquals(size - i, bytes, bytesOffset, i)) {\n      return true\n    }\n  }\n\n  // No matter what we load, we won't find a match.\n  return false\n}\n\ninternal inline fun RealBufferedSource.commonIndexOfElement(\n  targetBytes: ByteString,\n  fromIndex: Long,\n): Long {\n  var fromIndex = fromIndex\n  check(!closed) { \"closed\" }\n\n  while (true) {\n    val result = buffer.indexOfElement(targetBytes, fromIndex)\n    if (result != -1L) return result\n\n    val lastBufferSize = buffer.size\n    if (source.read(buffer, Segment.SIZE.toLong()) == -1L) return -1L\n\n    // Keep searching, picking up from where we left off.\n    fromIndex = maxOf(fromIndex, lastBufferSize)\n  }\n}\n\ninternal inline fun RealBufferedSource.commonRangeEquals(\n  offset: Long,\n  bytes: ByteString,\n  bytesOffset: Int,\n  byteCount: Int,\n): Boolean {\n  check(!closed) { \"closed\" }\n\n  if (byteCount < 0) return false\n  if (offset < 0) return false\n  if (bytesOffset < 0 || bytesOffset + byteCount > bytes.size) return false\n  if (byteCount == 0) return true\n\n  return commonIndexOf(\n    bytes = bytes,\n    bytesOffset = bytesOffset,\n    byteCount = byteCount,\n    fromIndex = offset,\n    toIndex = offset + 1,\n  ) != -1L\n}\n\ninternal inline fun RealBufferedSource.commonPeek(): BufferedSource {\n  return PeekSource(this).buffer()\n}\n\ninternal inline fun RealBufferedSource.commonClose() {\n  if (closed) return\n  closed = true\n  source.close()\n  buffer.clear()\n}\n\ninternal inline fun RealBufferedSource.commonTimeout() = source.timeout()\n\ninternal inline fun RealBufferedSource.commonToString() = \"buffer($source)\"\n"
  },
  {
    "path": "okio/src/commonMain/kotlin/okio/internal/SegmentedByteString.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\n// TODO move to SegmentedByteString class: https://youtrack.jetbrains.com/issue/KT-20427\n@file:Suppress(\"NOTHING_TO_INLINE\")\n\n@file:JvmName(\"-SegmentedByteString\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.Buffer\nimport okio.ByteString\nimport okio.Segment\nimport okio.SegmentedByteString\nimport okio.arrayRangeEquals\nimport okio.checkOffsetAndCount\n\ninternal fun IntArray.binarySearch(value: Int, fromIndex: Int, toIndex: Int): Int {\n  var left = fromIndex\n  var right = toIndex - 1\n\n  while (left <= right) {\n    val mid = (left + right) ushr 1 // protect from overflow\n    val midVal = this[mid]\n\n    when {\n      midVal < value -> left = mid + 1\n      midVal > value -> right = mid - 1\n      else -> return mid\n    }\n  }\n\n  // no exact match, return negative of where it should match\n  return -left - 1\n}\n\n/** Returns the index of the segment that contains the byte at `pos`.  */\ninternal fun SegmentedByteString.segment(pos: Int): Int {\n  // Search for (pos + 1) instead of (pos) because the directory holds sizes, not indexes.\n  val i = directory.binarySearch(pos + 1, 0, segments.size)\n  return if (i >= 0) i else i.inv() // If i is negative, bitflip to get the insert position.\n}\n\n/** Processes all segments, invoking `action` with the ByteArray and range of valid data. */\ninternal inline fun SegmentedByteString.forEachSegment(\n  action: (data: ByteArray, offset: Int, byteCount: Int) -> Unit,\n) {\n  val segmentCount = segments.size\n  var s = 0\n  var pos = 0\n  while (s < segmentCount) {\n    val segmentPos = directory[segmentCount + s]\n    val nextSegmentOffset = directory[s]\n\n    action(segments[s], segmentPos, nextSegmentOffset - pos)\n    pos = nextSegmentOffset\n    s++\n  }\n}\n\n/**\n * Processes the segments between `beginIndex` and `endIndex`, invoking `action` with the ByteArray\n * and range of the valid data.\n */\nprivate inline fun SegmentedByteString.forEachSegment(\n  beginIndex: Int,\n  endIndex: Int,\n  action: (data: ByteArray, offset: Int, byteCount: Int) -> Unit,\n) {\n  var s = segment(beginIndex)\n  var pos = beginIndex\n  while (pos < endIndex) {\n    val segmentOffset = if (s == 0) 0 else directory[s - 1]\n    val segmentSize = directory[s] - segmentOffset\n    val segmentPos = directory[segments.size + s]\n\n    val byteCount = minOf(endIndex, segmentOffset + segmentSize) - pos\n    val offset = segmentPos + (pos - segmentOffset)\n    action(segments[s], offset, byteCount)\n    pos += byteCount\n    s++\n  }\n}\n\n// TODO Kotlin's expect classes can't have default implementations, so platform implementations\n// have to call these functions. Remove all this nonsense when expect class allow actual code.\n\ninternal inline fun SegmentedByteString.commonSubstring(beginIndex: Int, endIndex: Int): ByteString {\n  require(beginIndex >= 0) { \"beginIndex=$beginIndex < 0\" }\n  require(endIndex <= size) { \"endIndex=$endIndex > length($size)\" }\n\n  val subLen = endIndex - beginIndex\n  require(subLen >= 0) { \"endIndex=$endIndex < beginIndex=$beginIndex\" }\n\n  when {\n    beginIndex == 0 && endIndex == size -> return this\n    beginIndex == endIndex -> return ByteString.EMPTY\n  }\n\n  val beginSegment = segment(beginIndex) // First segment to include\n  val endSegment = segment(endIndex - 1) // Last segment to include\n\n  val newSegments = segments.copyOfRange(beginSegment, endSegment + 1)\n  val newDirectory = IntArray(newSegments.size * 2)\n  var index = 0\n  for (s in beginSegment..endSegment) {\n    newDirectory[index] = minOf(directory[s] - beginIndex, subLen)\n    newDirectory[index++ + newSegments.size] = directory[s + segments.size]\n  }\n\n  // Set the new position of the first segment\n  val segmentOffset = if (beginSegment == 0) 0 else directory[beginSegment - 1]\n  newDirectory[newSegments.size] += beginIndex - segmentOffset\n\n  return SegmentedByteString(newSegments, newDirectory)\n}\n\ninternal inline fun SegmentedByteString.commonInternalGet(pos: Int): Byte {\n  checkOffsetAndCount(directory[segments.size - 1].toLong(), pos.toLong(), 1)\n  val segment = segment(pos)\n  val segmentOffset = if (segment == 0) 0 else directory[segment - 1]\n  val segmentPos = directory[segment + segments.size]\n  return segments[segment][pos - segmentOffset + segmentPos]\n}\n\ninternal inline fun SegmentedByteString.commonGetSize() = directory[segments.size - 1]\n\ninternal inline fun SegmentedByteString.commonToByteArray(): ByteArray {\n  val result = ByteArray(size)\n  var resultPos = 0\n  forEachSegment { data, offset, byteCount ->\n    data.copyInto(\n      result,\n      destinationOffset = resultPos,\n      startIndex = offset,\n      endIndex = offset + byteCount,\n    )\n    resultPos += byteCount\n  }\n  return result\n}\n\ninternal inline fun SegmentedByteString.commonWrite(buffer: Buffer, offset: Int, byteCount: Int) {\n  forEachSegment(offset, offset + byteCount) { data, offset, byteCount ->\n    val segment = Segment(data, offset, offset + byteCount, true, false)\n    if (buffer.head == null) {\n      segment.prev = segment\n      segment.next = segment.prev\n      buffer.head = segment.next\n    } else {\n      buffer.head!!.prev!!.push(segment)\n    }\n  }\n  buffer.size += byteCount\n}\n\ninternal inline fun SegmentedByteString.commonRangeEquals(\n  offset: Int,\n  other: ByteString,\n  otherOffset: Int,\n  byteCount: Int,\n): Boolean {\n  if (offset < 0 || offset > size - byteCount) return false\n  // Go segment-by-segment through this, passing arrays to other's rangeEquals().\n  var otherOffset = otherOffset\n  forEachSegment(offset, offset + byteCount) { data, offset, byteCount ->\n    if (!other.rangeEquals(otherOffset, data, offset, byteCount)) return false\n    otherOffset += byteCount\n  }\n  return true\n}\n\ninternal inline fun SegmentedByteString.commonRangeEquals(\n  offset: Int,\n  other: ByteArray,\n  otherOffset: Int,\n  byteCount: Int,\n): Boolean {\n  if (offset < 0 || offset > size - byteCount ||\n    otherOffset < 0 || otherOffset > other.size - byteCount\n  ) {\n    return false\n  }\n  // Go segment-by-segment through this, comparing ranges of arrays.\n  var otherOffset = otherOffset\n  forEachSegment(offset, offset + byteCount) { data, offset, byteCount ->\n    if (!arrayRangeEquals(data, offset, other, otherOffset, byteCount)) return false\n    otherOffset += byteCount\n  }\n  return true\n}\n\ninternal inline fun SegmentedByteString.commonCopyInto(\n  offset: Int,\n  target: ByteArray,\n  targetOffset: Int,\n  byteCount: Int,\n) {\n  checkOffsetAndCount(size.toLong(), offset.toLong(), byteCount.toLong())\n  checkOffsetAndCount(target.size.toLong(), targetOffset.toLong(), byteCount.toLong())\n  // Go segment-by-segment through this, copying ranges of arrays.\n  var targetOffset = targetOffset\n  forEachSegment(offset, offset + byteCount) { data, offset, byteCount ->\n    data.copyInto(target, targetOffset, offset, offset + byteCount)\n    targetOffset += byteCount\n  }\n}\n\ninternal inline fun SegmentedByteString.commonEquals(other: Any?): Boolean {\n  return when {\n    other === this -> true\n    other is ByteString -> other.size == size && rangeEquals(0, other, 0, size)\n    else -> false\n  }\n}\n\ninternal inline fun SegmentedByteString.commonHashCode(): Int {\n  var result = hashCode\n  if (result != 0) return result\n\n  // Equivalent to Arrays.hashCode(toByteArray()).\n  result = 1\n  forEachSegment { data, offset, byteCount ->\n    var i = offset\n    val limit = offset + byteCount\n    while (i < limit) {\n      result = 31 * result + data[i]\n      i++\n    }\n  }\n  hashCode = result\n  return result\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/BufferCommonTest.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport okio.ByteString.Companion.encodeUtf8\n\nclass BufferCommonTest {\n\n  @Test fun copyToBuffer() {\n    val source = Buffer()\n    source.write(\"party\".encodeUtf8())\n\n    val target = Buffer()\n    source.copyTo(target)\n    assertEquals(\"party\", target.readByteString().utf8())\n    assertEquals(\"party\", source.readByteString().utf8())\n  }\n\n  @Test fun copyToBufferWithOffset() {\n    val source = Buffer()\n    source.write(\"party\".encodeUtf8())\n\n    val target = Buffer()\n    source.copyTo(target, 2)\n    assertEquals(\"rty\", target.readByteString().utf8())\n    assertEquals(\"party\", source.readByteString().utf8())\n  }\n\n  @Test fun copyToBufferWithByteCount() {\n    val source = Buffer()\n    source.write(\"party\".encodeUtf8())\n\n    val target = Buffer()\n    source.copyTo(target, 0, 3)\n    assertEquals(\"par\", target.readByteString().utf8())\n    assertEquals(\"party\", source.readByteString().utf8())\n  }\n\n  @Test fun copyToBufferWithOffsetAndByteCount() {\n    val source = Buffer()\n    source.write(\"party\".encodeUtf8())\n\n    val target = Buffer()\n    source.copyTo(target, 1, 3)\n    assertEquals(\"art\", target.readByteString().utf8())\n    assertEquals(\"party\", source.readByteString().utf8())\n  }\n\n  @Test fun completeSegmentByteCountOnEmptyBuffer() {\n    val buffer = Buffer()\n    assertEquals(0, buffer.completeSegmentByteCount())\n  }\n\n  @Test fun completeSegmentByteCountOnBufferWithFullSegments() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"a\".repeat(Segment.SIZE * 4))\n    assertEquals((Segment.SIZE * 4).toLong(), buffer.completeSegmentByteCount())\n  }\n\n  @Test fun completeSegmentByteCountOnBufferWithIncompleteTailSegment() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"a\".repeat(Segment.SIZE * 4 - 10))\n    assertEquals((Segment.SIZE * 3).toLong(), buffer.completeSegmentByteCount())\n  }\n\n  @Test fun testHash() {\n    val buffer = Buffer().apply { write(\"Kevin\".encodeUtf8()) }\n    with(buffer) {\n      assertEquals(\"e043899daa0c7add37bc99792b2c045d6abbc6dc\", sha1().hex())\n      assertEquals(\"f1cd318e412b5f7226e5f377a9544ff7\", md5().hex())\n      assertEquals(\"0e4dd66217fc8d2e298b78c8cd9392870dcd065d0ff675d0edff5bcd227837e9\", sha256().hex())\n      assertEquals(\"483676b93c4417198b465083d196ec6a9fab8d004515874b8ff47e041f5f56303cc08179625030b8b5b721c09149a18f0f59e64e7ae099518cea78d3d83167e1\", sha512().hex())\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/BufferedSinkFactory.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nenum class BufferedSinkFactory {\n  BasicBuffer {\n    override fun create(data: Buffer): BufferedSink {\n      return data\n    }\n  },\n\n  SinkBuffer {\n    override fun create(data: Buffer): BufferedSink {\n      return (data as Sink).buffer()\n    }\n  },\n  ;\n\n  abstract fun create(data: Buffer): BufferedSink\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/BufferedSourceFactory.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nenum class BufferedSourceFactory {\n  NewBuffer {\n    override val isOneByteAtATime: Boolean\n      get() = false\n\n    override fun pipe(): Pipe {\n      val buffer = Buffer()\n      return Pipe(\n        buffer,\n        buffer,\n      )\n    }\n  },\n\n  SourceBuffer {\n    override val isOneByteAtATime: Boolean\n      get() = false\n\n    override fun pipe(): Pipe {\n      val buffer = Buffer()\n      return Pipe(\n        buffer,\n        (buffer as Source).buffer(),\n      )\n    }\n  },\n\n  /**\n   * A factory deliberately written to create buffers whose internal segments are always 1 byte\n   * long. We like testing with these segments because are likely to trigger bugs!\n   */\n  OneByteAtATimeSource {\n    override val isOneByteAtATime: Boolean\n      get() = true\n\n    override fun pipe(): Pipe {\n      val buffer = Buffer()\n      return Pipe(\n        buffer,\n        object : Source by buffer {\n          override fun read(sink: Buffer, byteCount: Long): Long {\n            // Read one byte into a new buffer, then clone it so that the segment is shared.\n            // Shared segments cannot be compacted so we'll get a long chain of short segments.\n            val box = Buffer()\n            val result = buffer.read(box, minOf(byteCount, 1L))\n            if (result > 0L) sink.write(box.copy(), result)\n            return result\n          }\n        }.buffer(),\n      )\n    }\n  },\n\n  OneByteAtATimeSink {\n    override val isOneByteAtATime: Boolean\n      get() = true\n\n    override fun pipe(): Pipe {\n      val buffer = Buffer()\n      return Pipe(\n        object : Sink by buffer {\n          override fun write(source: Buffer, byteCount: Long) {\n            // Write each byte into a new buffer, then clone it so that the segments are shared.\n            // Shared segments cannot be compacted so we'll get a long chain of short segments.\n            for (i in 0 until byteCount) {\n              val box = Buffer()\n              box.write(source, 1)\n              buffer.write(box.copy(), 1)\n            }\n          }\n        }.buffer(),\n        buffer,\n      )\n    }\n  },\n\n  PeekBuffer {\n    override val isOneByteAtATime: Boolean\n      get() = false\n\n    override fun pipe(): Pipe {\n      val buffer = Buffer()\n      return Pipe(\n        buffer,\n        buffer.peek(),\n      )\n    }\n  },\n\n  PeekBufferedSource {\n    override val isOneByteAtATime: Boolean\n      get() = false\n\n    override fun pipe(): Pipe {\n      val buffer = Buffer()\n      return Pipe(\n        buffer,\n        (buffer as Source).buffer().peek(),\n      )\n    }\n  },\n  ;\n\n  abstract val isOneByteAtATime: Boolean\n\n  abstract fun pipe(): Pipe\n\n  class Pipe(\n    var sink: BufferedSink,\n    var source: BufferedSource,\n  )\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/ByteStringFactory.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.internal.commonAsUtf8ToByteArray\n\nenum class ByteStringFactory {\n  BasicByteString {\n    override fun decodeHex(hex: String) = hex.decodeHex()\n    override fun encodeUtf8(s: String) = s.encodeUtf8()\n  },\n\n  SegmentedByteString {\n    override fun decodeHex(hex: String) = Buffer().apply { write(hex.decodeHex()) }.snapshot()\n    override fun encodeUtf8(s: String) = Buffer().apply { writeUtf8(s) }.snapshot()\n  },\n\n  OneBytePerSegment {\n    override fun decodeHex(hex: String) = makeSegments(hex.decodeHex())\n    override fun encodeUtf8(s: String) = makeSegments(s.encodeUtf8())\n  },\n\n  // For Kotlin/JVM, the native Java UTF-8 encoder is used. This forces\n  // testing of the Okio encoder used for Kotlin/JS and Kotlin/Native to be\n  // tested on JVM as well.\n  OkioUtf8Encoder {\n    override fun decodeHex(hex: String) = hex.decodeHex()\n    override fun encodeUtf8(s: String) = ByteString.of(*s.commonAsUtf8ToByteArray())\n  },\n  ;\n\n  abstract fun decodeHex(hex: String): ByteString\n\n  abstract fun encodeUtf8(s: String): ByteString\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/ByteStringMoreTests.kt",
    "content": "/*\n * Copyright (C) 2022 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport okio.ByteString.Companion.toByteString\n\nclass ByteStringMoreTests {\n  @Test fun arrayToByteString() {\n    val actual = byteArrayOf(1, 2, 3, 4).toByteString()\n    val expected = ByteString.of(1, 2, 3, 4)\n    assertEquals(actual, expected)\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/ByteStringTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport app.cash.burst.Burst\nimport kotlin.random.Random\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNotEquals\nimport kotlin.test.assertSame\nimport kotlin.test.assertTrue\nimport kotlin.test.fail\nimport okio.ByteString.Companion.decodeBase64\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.ByteString.Companion.toByteString\nimport okio.internal.commonAsUtf8ToByteArray\n\n@Burst\nclass ByteStringTest(\n  private val factory: ByteStringFactory,\n) {\n  @Test fun get() {\n    val actual = factory.encodeUtf8(\"abc\")\n    assertEquals(3, actual.size)\n    assertEquals(actual[0], 'a'.code.toByte())\n    assertEquals(actual[1], 'b'.code.toByte())\n    assertEquals(actual[2], 'c'.code.toByte())\n    try {\n      actual[-1]\n      fail(\"no index out of bounds: -1\")\n    } catch (expected: IndexOutOfBoundsException) {\n    }\n    try {\n      actual[3]\n      fail(\"no index out of bounds: 3\")\n    } catch (expected: IndexOutOfBoundsException) {\n    }\n  }\n\n  @Test fun getByte() {\n    val byteString = factory.decodeHex(\"ab12\")\n    assertEquals(-85, byteString[0].toLong())\n    assertEquals(18, byteString[1].toLong())\n  }\n\n  @Test fun startsWithByteString() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertTrue(byteString.startsWith(\"\".decodeHex()))\n    assertTrue(byteString.startsWith(\"11\".decodeHex()))\n    assertTrue(byteString.startsWith(\"1122\".decodeHex()))\n    assertTrue(byteString.startsWith(\"112233\".decodeHex()))\n    assertFalse(byteString.startsWith(\"2233\".decodeHex()))\n    assertFalse(byteString.startsWith(\"11223344\".decodeHex()))\n    assertFalse(byteString.startsWith(\"112244\".decodeHex()))\n  }\n\n  @Test fun endsWithByteString() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertTrue(byteString.endsWith(\"\".decodeHex()))\n    assertTrue(byteString.endsWith(\"33\".decodeHex()))\n    assertTrue(byteString.endsWith(\"2233\".decodeHex()))\n    assertTrue(byteString.endsWith(\"112233\".decodeHex()))\n    assertFalse(byteString.endsWith(\"1122\".decodeHex()))\n    assertFalse(byteString.endsWith(\"00112233\".decodeHex()))\n    assertFalse(byteString.endsWith(\"002233\".decodeHex()))\n  }\n\n  @Test fun startsWithByteArray() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertTrue(byteString.startsWith(\"\".decodeHex().toByteArray()))\n    assertTrue(byteString.startsWith(\"11\".decodeHex().toByteArray()))\n    assertTrue(byteString.startsWith(\"1122\".decodeHex().toByteArray()))\n    assertTrue(byteString.startsWith(\"112233\".decodeHex().toByteArray()))\n    assertFalse(byteString.startsWith(\"2233\".decodeHex().toByteArray()))\n    assertFalse(byteString.startsWith(\"11223344\".decodeHex().toByteArray()))\n    assertFalse(byteString.startsWith(\"112244\".decodeHex().toByteArray()))\n  }\n\n  @Test fun endsWithByteArray() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertTrue(byteString.endsWith(\"\".decodeHex().toByteArray()))\n    assertTrue(byteString.endsWith(\"33\".decodeHex().toByteArray()))\n    assertTrue(byteString.endsWith(\"2233\".decodeHex().toByteArray()))\n    assertTrue(byteString.endsWith(\"112233\".decodeHex().toByteArray()))\n    assertFalse(byteString.endsWith(\"1122\".decodeHex().toByteArray()))\n    assertFalse(byteString.endsWith(\"00112233\".decodeHex().toByteArray()))\n    assertFalse(byteString.endsWith(\"002233\".decodeHex().toByteArray()))\n  }\n\n  @Test fun indexOfByteString() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertEquals(0, byteString.indexOf(\"112233\".decodeHex()).toLong())\n    assertEquals(0, byteString.indexOf(\"1122\".decodeHex()).toLong())\n    assertEquals(0, byteString.indexOf(\"11\".decodeHex()).toLong())\n    assertEquals(0, byteString.indexOf(\"11\".decodeHex(), 0).toLong())\n    assertEquals(0, byteString.indexOf(\"\".decodeHex()).toLong())\n    assertEquals(0, byteString.indexOf(\"\".decodeHex(), 0).toLong())\n    assertEquals(1, byteString.indexOf(\"2233\".decodeHex()).toLong())\n    assertEquals(1, byteString.indexOf(\"22\".decodeHex()).toLong())\n    assertEquals(1, byteString.indexOf(\"22\".decodeHex(), 1).toLong())\n    assertEquals(1, byteString.indexOf(\"\".decodeHex(), 1).toLong())\n    assertEquals(2, byteString.indexOf(\"33\".decodeHex()).toLong())\n    assertEquals(2, byteString.indexOf(\"33\".decodeHex(), 2).toLong())\n    assertEquals(2, byteString.indexOf(\"\".decodeHex(), 2).toLong())\n    assertEquals(3, byteString.indexOf(\"\".decodeHex(), 3).toLong())\n    assertEquals(-1, byteString.indexOf(\"112233\".decodeHex(), 1).toLong())\n    assertEquals(-1, byteString.indexOf(\"44\".decodeHex()).toLong())\n    assertEquals(-1, byteString.indexOf(\"11223344\".decodeHex()).toLong())\n    assertEquals(-1, byteString.indexOf(\"112244\".decodeHex()).toLong())\n    assertEquals(-1, byteString.indexOf(\"112233\".decodeHex(), 1).toLong())\n    assertEquals(-1, byteString.indexOf(\"2233\".decodeHex(), 2).toLong())\n    assertEquals(-1, byteString.indexOf(\"33\".decodeHex(), 3).toLong())\n    assertEquals(-1, byteString.indexOf(\"\".decodeHex(), 4).toLong())\n  }\n\n  @Test fun indexOfWithOffset() {\n    val byteString = factory.decodeHex(\"112233112233\")\n    assertEquals(0, byteString.indexOf(\"112233\".decodeHex(), -1).toLong())\n    assertEquals(0, byteString.indexOf(\"112233\".decodeHex(), 0).toLong())\n    assertEquals(0, byteString.indexOf(\"112233\".decodeHex()).toLong())\n    assertEquals(3, byteString.indexOf(\"112233\".decodeHex(), 1).toLong())\n    assertEquals(3, byteString.indexOf(\"112233\".decodeHex(), 2).toLong())\n    assertEquals(3, byteString.indexOf(\"112233\".decodeHex(), 3).toLong())\n    assertEquals(-1, byteString.indexOf(\"112233\".decodeHex(), 4).toLong())\n  }\n\n  @Test fun indexOfByteArray() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertEquals(0, byteString.indexOf(\"112233\".decodeHex().toByteArray()).toLong())\n    assertEquals(1, byteString.indexOf(\"2233\".decodeHex().toByteArray()).toLong())\n    assertEquals(2, byteString.indexOf(\"33\".decodeHex().toByteArray()).toLong())\n    assertEquals(-1, byteString.indexOf(\"112244\".decodeHex().toByteArray()).toLong())\n  }\n\n  @Test fun lastIndexOfByteString() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertEquals(0, byteString.lastIndexOf(\"112233\".decodeHex()).toLong())\n    assertEquals(0, byteString.lastIndexOf(\"1122\".decodeHex()).toLong())\n    assertEquals(0, byteString.lastIndexOf(\"11\".decodeHex()).toLong())\n    assertEquals(0, byteString.lastIndexOf(\"11\".decodeHex(), 3).toLong())\n    assertEquals(0, byteString.lastIndexOf(\"11\".decodeHex(), 0).toLong())\n    assertEquals(0, byteString.lastIndexOf(\"\".decodeHex(), 0).toLong())\n    assertEquals(1, byteString.lastIndexOf(\"2233\".decodeHex()).toLong())\n    assertEquals(1, byteString.lastIndexOf(\"22\".decodeHex()).toLong())\n    assertEquals(1, byteString.lastIndexOf(\"22\".decodeHex(), 3).toLong())\n    assertEquals(1, byteString.lastIndexOf(\"22\".decodeHex(), 1).toLong())\n    assertEquals(1, byteString.lastIndexOf(\"\".decodeHex(), 1).toLong())\n    assertEquals(2, byteString.lastIndexOf(\"33\".decodeHex()).toLong())\n    assertEquals(2, byteString.lastIndexOf(\"33\".decodeHex(), 3).toLong())\n    assertEquals(2, byteString.lastIndexOf(\"33\".decodeHex(), 2).toLong())\n    assertEquals(2, byteString.lastIndexOf(\"\".decodeHex(), 2).toLong())\n    assertEquals(3, byteString.lastIndexOf(\"\".decodeHex(), 3).toLong())\n    assertEquals(3, byteString.lastIndexOf(\"\".decodeHex()).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"112233\".decodeHex(), -1).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"112233\".decodeHex(), -2).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"44\".decodeHex()).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"11223344\".decodeHex()).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"112244\".decodeHex()).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"2233\".decodeHex(), 0).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"33\".decodeHex(), 1).toLong())\n    assertEquals(-1, byteString.lastIndexOf(\"\".decodeHex(), -1).toLong())\n  }\n\n  @Test fun lastIndexOfByteArray() {\n    val byteString = factory.decodeHex(\"112233\")\n    assertEquals(0, byteString.lastIndexOf(\"112233\".decodeHex().toByteArray()).toLong())\n    assertEquals(1, byteString.lastIndexOf(\"2233\".decodeHex().toByteArray()).toLong())\n    assertEquals(2, byteString.lastIndexOf(\"33\".decodeHex().toByteArray()).toLong())\n    assertEquals(3, byteString.lastIndexOf(\"\".decodeHex().toByteArray()).toLong())\n  }\n\n  @Test fun equalsTest() {\n    val byteString = factory.decodeHex(\"000102\")\n    assertEquals(byteString, byteString)\n    assertEquals(byteString, \"000102\".decodeHex())\n    assertNotEquals(byteString, Any())\n    assertNotEquals(byteString, \"000201\".decodeHex())\n  }\n\n  @Test fun equalsEmptyTest() {\n    assertEquals(factory.decodeHex(\"\"), ByteString.EMPTY)\n    assertEquals(factory.decodeHex(\"\"), ByteString.of())\n    assertEquals(ByteString.EMPTY, factory.decodeHex(\"\"))\n    assertEquals(ByteString.of(), factory.decodeHex(\"\"))\n  }\n\n  private val bronzeHorseman = \"На берегу пустынных волн\"\n\n  @Test fun utf8() {\n    val byteString = factory.encodeUtf8(bronzeHorseman)\n    assertEquals(byteString.toByteArray().toList(), bronzeHorseman.commonAsUtf8ToByteArray().toList())\n    assertTrue(byteString == ByteString.of(*bronzeHorseman.commonAsUtf8ToByteArray()))\n    assertEquals(\n      byteString,\n      (\n        \"d09dd0b020d0b1d0b5d180d0b5d0b3d18320d0bfd183d181\" +\n          \"d182d18bd0bdd0bdd18bd18520d0b2d0bed0bbd0bd\"\n        ).decodeHex(),\n    )\n    assertEquals(byteString.utf8(), bronzeHorseman)\n  }\n\n  @Test fun testHashCode() {\n    val byteString = factory.decodeHex(\"0102\")\n    assertEquals(byteString.hashCode().toLong(), byteString.hashCode().toLong())\n    assertEquals(byteString.hashCode().toLong(), \"0102\".decodeHex().hashCode().toLong())\n  }\n\n  @Test fun toAsciiLowerCaseNoUppercase() {\n    val s = factory.encodeUtf8(\"a1_+\")\n    assertEquals(s, s.toAsciiLowercase())\n    if (factory === ByteStringFactory.BasicByteString) {\n      assertSame(s, s.toAsciiLowercase())\n    }\n  }\n\n  @Test fun toAsciiAllUppercase() {\n    assertEquals(\"ab\".encodeUtf8(), factory.encodeUtf8(\"AB\").toAsciiLowercase())\n  }\n\n  @Test fun toAsciiStartsLowercaseEndsUppercase() {\n    assertEquals(\"abcd\".encodeUtf8(), factory.encodeUtf8(\"abCD\").toAsciiLowercase())\n  }\n\n  @Test fun toAsciiStartsUppercaseEndsLowercase() {\n    assertEquals(\"ABCD\".encodeUtf8(), factory.encodeUtf8(\"ABcd\").toAsciiUppercase())\n  }\n\n  @Test fun substring() {\n    val byteString = factory.encodeUtf8(\"Hello, World!\")\n\n    assertEquals(byteString.substring(0), byteString)\n    assertEquals(byteString.substring(0, 5), \"Hello\".encodeUtf8())\n    assertEquals(byteString.substring(7), \"World!\".encodeUtf8())\n    assertEquals(byteString.substring(6, 6), \"\".encodeUtf8())\n  }\n\n  @Test fun substringWithInvalidBounds() {\n    val byteString = factory.encodeUtf8(\"Hello, World!\")\n\n    assertFailsWith<IllegalArgumentException> {\n      byteString.substring(-1)\n    }\n\n    assertFailsWith<IllegalArgumentException> {\n      byteString.substring(0, 14)\n    }\n\n    assertFailsWith<IllegalArgumentException> {\n      byteString.substring(8, 7)\n    }\n  }\n\n  @Test fun encodeBase64() {\n    assertEquals(\"\", factory.encodeUtf8(\"\").base64())\n    assertEquals(\"AA==\", factory.encodeUtf8(\"\\u0000\").base64())\n    assertEquals(\"AAA=\", factory.encodeUtf8(\"\\u0000\\u0000\").base64())\n    assertEquals(\"AAAA\", factory.encodeUtf8(\"\\u0000\\u0000\\u0000\").base64())\n    assertEquals(\n      \"SG93IG1hbnkgbGluZXMgb2YgY29kZSBhcmUgdGhlcmU/ICdib3V0IDIgbWlsbGlvbi4=\",\n      factory.encodeUtf8(\"How many lines of code are there? 'bout 2 million.\").base64(),\n    )\n  }\n\n  @Test fun encodeBase64Url() {\n    assertEquals(\"\", factory.encodeUtf8(\"\").base64Url())\n    assertEquals(\"AA==\", factory.encodeUtf8(\"\\u0000\").base64Url())\n    assertEquals(\"AAA=\", factory.encodeUtf8(\"\\u0000\\u0000\").base64Url())\n    assertEquals(\"AAAA\", factory.encodeUtf8(\"\\u0000\\u0000\\u0000\").base64Url())\n    assertEquals(\n      \"SG93IG1hbnkgbGluZXMgb2YgY29kZSBhcmUgdGhlcmU_ICdib3V0IDIgbWlsbGlvbi4=\",\n      factory.encodeUtf8(\"How many lines of code are there? 'bout 2 million.\").base64Url(),\n    )\n  }\n\n  @Test fun ignoreUnnecessaryPadding() {\n    assertEquals(\"\", \"====\".decodeBase64()!!.utf8())\n    assertEquals(\"\\u0000\\u0000\\u0000\", \"AAAA====\".decodeBase64()!!.utf8())\n  }\n\n  @Test fun decodeBase64() {\n    assertEquals(\"\", \"\".decodeBase64()!!.utf8())\n    assertEquals(null, \"/===\".decodeBase64()) // Can't do anything with 6 bits!\n    assertEquals(\"ff\".decodeHex(), \"//==\".decodeBase64())\n    assertEquals(\"ff\".decodeHex(), \"__==\".decodeBase64())\n    assertEquals(\"ffff\".decodeHex(), \"///=\".decodeBase64())\n    assertEquals(\"ffff\".decodeHex(), \"___=\".decodeBase64())\n    assertEquals(\"ffffff\".decodeHex(), \"////\".decodeBase64())\n    assertEquals(\"ffffff\".decodeHex(), \"____\".decodeBase64())\n    assertEquals(\"ffffffffffff\".decodeHex(), \"////////\".decodeBase64())\n    assertEquals(\"ffffffffffff\".decodeHex(), \"________\".decodeBase64())\n    assertEquals(\n      \"What's to be scared about? It's just a little hiccup in the power...\",\n      (\n        \"V2hhdCdzIHRvIGJlIHNjYXJlZCBhYm91dD8gSXQncyBqdXN0IGEgbGl0dGxlIGhpY2\" +\n          \"N1cCBpbiB0aGUgcG93ZXIuLi4=\"\n        ).decodeBase64()!!.utf8(),\n    )\n    // Uses two encoding styles. Malformed, but supported as a side-effect.\n    assertEquals(\"ffffff\".decodeHex(), \"__//\".decodeBase64())\n  }\n\n  @Test fun decodeBase64WithWhitespace() {\n    assertEquals(\"\\u0000\\u0000\\u0000\", \" AA AA \".decodeBase64()!!.utf8())\n    assertEquals(\"\\u0000\\u0000\\u0000\", \" AA A\\r\\nA \".decodeBase64()!!.utf8())\n    assertEquals(\"\\u0000\\u0000\\u0000\", \"AA AA\".decodeBase64()!!.utf8())\n    assertEquals(\"\\u0000\\u0000\\u0000\", \" AA AA \".decodeBase64()!!.utf8())\n    assertEquals(\"\\u0000\\u0000\\u0000\", \" AA A\\r\\nA \".decodeBase64()!!.utf8())\n    assertEquals(\"\\u0000\\u0000\\u0000\", \"A    AAA\".decodeBase64()!!.utf8())\n    assertEquals(\"\", \"    \".decodeBase64()!!.utf8())\n  }\n\n  @Test fun encodeHex() {\n    assertEquals(\"000102\", ByteString.of(0x0, 0x1, 0x2).hex())\n  }\n\n  @Test fun decodeHex() {\n    val actual = \"CAFEBABE\".decodeHex()\n    val expected = ByteString.of(-54, -2, -70, -66)\n    assertEquals(expected, actual)\n  }\n\n  @Test fun decodeHexOddNumberOfChars() {\n    assertFailsWith<IllegalArgumentException> {\n      \"aaa\".decodeHex()\n    }\n  }\n\n  @Test fun decodeHexInvalidChar() {\n    assertFailsWith<IllegalArgumentException> {\n      \"a\\u0000\".decodeHex()\n    }\n  }\n\n  @Test fun toStringOnEmpty() {\n    assertEquals(\"[size=0]\", factory.decodeHex(\"\").toString())\n  }\n\n  @Test fun toStringOnShortText() {\n    assertEquals(\n      \"[text=Tyrannosaur]\",\n      factory.encodeUtf8(\"Tyrannosaur\").toString(),\n    )\n    assertEquals(\n      \"[text=təˈranəˌsôr]\",\n      factory.decodeHex(\"74c999cb8872616ec999cb8c73c3b472\").toString(),\n    )\n  }\n\n  @Test fun toStringOnLongTextIsTruncated() {\n    val raw = (\n      \"Um, I'll tell you the problem with the scientific power that you're using here, \" +\n        \"it didn't require any discipline to attain it. You read what others had done and you \" +\n        \"took the next step. You didn't earn the knowledge for yourselves, so you don't take any \" +\n        \"responsibility for it. You stood on the shoulders of geniuses to accomplish something \" +\n        \"as fast as you could, and before you even knew what you had, you patented it, and \" +\n        \"packaged it, and slapped it on a plastic lunchbox, and now you're selling it, you wanna \" +\n        \"sell it.\"\n      )\n    assertEquals(\n      \"[size=517 text=Um, I'll tell you the problem with the scientific power that \" +\n        \"you…]\",\n      factory.encodeUtf8(raw).toString(),\n    )\n    val war = (\n      \"Սｍ, I'll 𝓽𝖾ll ᶌօ𝘂 ᴛℎ℮ 𝜚𝕣०ｂl𝖾ｍ ｗі𝕥𝒽 𝘵𝘩𝐞 𝓼𝙘𝐢𝔢𝓷𝗍𝜄𝚏𝑖ｃ 𝛠𝝾ｗ𝚎𝑟 𝕥ｈ⍺𝞃 𝛄𝓸𝘂'𝒓𝗲 υ𝖘𝓲𝗇ɡ 𝕙𝚎𝑟ｅ, \" +\n        \"𝛊𝓽 ⅆ𝕚𝐝𝝿'𝗍 𝔯𝙚𝙦ᴜ𝜾𝒓𝘦 𝔞𝘯𝐲 ԁ𝜄𝑠𝚌ι𝘱lι𝒏ｅ 𝑡𝜎 𝕒𝚝𝖙𝓪і𝞹 𝔦𝚝. 𝒀ο𝗎 𝔯𝑒⍺𝖉 ｗ𝐡𝝰𝔱 𝞂𝞽һ𝓮𝓇ƽ հ𝖺𝖉 ⅾ𝛐𝝅ⅇ 𝝰πԁ 𝔂ᴑᴜ 𝓉ﮨ၀𝚔 \" +\n        \"т𝒽𝑒 𝗇𝕖ⅹ𝚝 𝔰𝒕е𝓅. 𝘠ⲟ𝖚 𝖉ⅰԁ𝝕'τ 𝙚𝚊ｒ𝞹 𝘵Ꮒ𝖾 𝝒𝐧هｗl𝑒𝖉ƍ𝙚 𝓯૦ｒ 𝔂𝞼𝒖𝕣𝑠𝕖l𝙫𝖊𝓼, 𐑈о ｙ𝘰𝒖 ⅆە𝗇'ｔ 𝜏α𝒌𝕖 𝛂𝟉ℽ \" +\n        \"𝐫ⅇ𝗌ⲣ๐ϖ𝖘ꙇᖯ𝓲l𝓲𝒕𝘆 𝐟𝞼𝘳 𝚤𝑡. 𝛶𝛔𝔲 ｓ𝕥σσ𝐝 ﮩ𝕟 𝒕𝗁𝔢 𝘴𝐡𝜎ᴜlⅾ𝓮𝔯𝚜 𝛐𝙛 ᶃ𝚎ᴨᎥս𝚜𝘦𝓈 𝓽𝞸 ａ𝒄𝚌𝞸ｍρl𝛊ꜱ𝐡 𝓈𝚘ｍ𝚎𝞃𝔥⍳𝞹𝔤 𝐚𝗌 𝖋ａ𝐬𝒕 \" +\n        \"αｓ γ𝛐𝕦 𝔠ﻫ𝛖lԁ, 𝚊π𝑑 Ь𝑒𝙛૦𝓇𝘦 𝓎٥𝖚 ⅇｖℯ𝝅 𝜅ո𝒆ｗ ｗ𝗵𝒂𝘁 ᶌ੦𝗎 ｈ𝐚𝗱, 𝜸ﮨ𝒖 𝓹𝝰𝔱𝖾𝗇𝓽𝔢ⅆ і𝕥, 𝚊𝜛𝓭 𝓹𝖺ⅽϰ𝘢ℊеᏧ 𝑖𝞃, \" +\n        \"𝐚𝛑ꓒ 𝙨l𝔞р𝘱𝔢𝓭 ɩ𝗍 ہ𝛑 𝕒 ｐl𝛂ѕᴛ𝗂𝐜 l𝞄ℼ𝔠𝒽𝑏ﮪ⨯, 𝔞ϖ𝒹 ｎ𝛔ｗ 𝛾𝐨𝞄'𝗿𝔢 ꜱ℮ll𝙞ｎɡ ɩ𝘁, 𝙮𝕠𝛖 ｗ𝑎ℼ𝚗𝛂 𝕤𝓮ll 𝙞𝓉.\"\n      )\n    assertEquals(\n      \"[size=1496 text=Սｍ, I'll 𝓽𝖾ll ᶌօ𝘂 ᴛℎ℮ 𝜚𝕣०ｂl𝖾ｍ ｗі𝕥𝒽 𝘵𝘩𝐞 𝓼𝙘𝐢𝔢𝓷𝗍𝜄𝚏𝑖ｃ 𝛠𝝾ｗ𝚎𝑟 𝕥ｈ⍺𝞃 \" +\n        \"𝛄𝓸𝘂…]\",\n      factory.encodeUtf8(war).toString(),\n    )\n  }\n\n  @Test fun toStringOnTextWithNewlines() {\n    // Instead of emitting a literal newline in the toString(), these are escaped as \"\\n\".\n    assertEquals(\n      \"[text=a\\\\r\\\\nb\\\\nc\\\\rd\\\\\\\\e]\",\n      factory.encodeUtf8(\"a\\r\\nb\\nc\\rd\\\\e\").toString(),\n    )\n  }\n\n  @Test fun toStringOnData() {\n    val byteString = factory.decodeHex(\n      \"\" +\n        \"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55\" +\n        \"4bf0b54023c29b624de9ef9c2f931efc580f9afb\",\n    )\n    assertEquals(\n      \"[hex=\" +\n        \"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55\" +\n        \"4bf0b54023c29b624de9ef9c2f931efc580f9afb]\",\n      byteString.toString(),\n    )\n  }\n\n  @Test fun toStringOnLongDataIsTruncated() {\n    val byteString = factory.decodeHex(\n      \"\" +\n        \"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55\" +\n        \"4bf0b54023c29b624de9ef9c2f931efc580f9afba1\",\n    )\n    assertEquals(\n      \"[size=65 hex=\" +\n        \"60b420bb3851d9d47acb933dbe70399bf6c92da33af01d4fb770e98c0325f41d3ebaf8986da712c82bcd4d55\" +\n        \"4bf0b54023c29b624de9ef9c2f931efc580f9afb…]\",\n      byteString.toString(),\n    )\n  }\n\n  @Test fun compareToSingleBytes() {\n    val originalByteStrings = listOf(\n      factory.decodeHex(\"00\"),\n      factory.decodeHex(\"01\"),\n      factory.decodeHex(\"7e\"),\n      factory.decodeHex(\"7f\"),\n      factory.decodeHex(\"80\"),\n      factory.decodeHex(\"81\"),\n      factory.decodeHex(\"fe\"),\n      factory.decodeHex(\"ff\"),\n    )\n\n    val sortedByteStrings = originalByteStrings.toMutableList()\n    sortedByteStrings.shuffle(Random(0))\n    assertNotEquals(originalByteStrings, sortedByteStrings)\n\n    sortedByteStrings.sort()\n    assertEquals(originalByteStrings, sortedByteStrings)\n  }\n\n  @Test fun compareToMultipleBytes() {\n    val originalByteStrings = listOf(\n      factory.decodeHex(\"\"),\n      factory.decodeHex(\"00\"),\n      factory.decodeHex(\"0000\"),\n      factory.decodeHex(\"000000\"),\n      factory.decodeHex(\"00000000\"),\n      factory.decodeHex(\"0000000000\"),\n      factory.decodeHex(\"0000000001\"),\n      factory.decodeHex(\"000001\"),\n      factory.decodeHex(\"00007f\"),\n      factory.decodeHex(\"0000ff\"),\n      factory.decodeHex(\"000100\"),\n      factory.decodeHex(\"000101\"),\n      factory.decodeHex(\"007f00\"),\n      factory.decodeHex(\"00ff00\"),\n      factory.decodeHex(\"010000\"),\n      factory.decodeHex(\"010001\"),\n      factory.decodeHex(\"01007f\"),\n      factory.decodeHex(\"0100ff\"),\n      factory.decodeHex(\"010100\"),\n      factory.decodeHex(\"01010000\"),\n      factory.decodeHex(\"0101000000\"),\n      factory.decodeHex(\"0101000001\"),\n      factory.decodeHex(\"010101\"),\n      factory.decodeHex(\"7f0000\"),\n      factory.decodeHex(\"7f0000ffff\"),\n      factory.decodeHex(\"ffffff\"),\n    )\n\n    val sortedByteStrings = originalByteStrings.toMutableList()\n    sortedByteStrings.shuffle(Random(0))\n    assertNotEquals(originalByteStrings, sortedByteStrings)\n\n    sortedByteStrings.sort()\n    assertEquals(originalByteStrings, sortedByteStrings)\n  }\n\n  @Test fun testHash() = with(factory.encodeUtf8(\"Kevin\")) {\n    assertEquals(\"e043899daa0c7add37bc99792b2c045d6abbc6dc\", sha1().hex())\n    assertEquals(\"f1cd318e412b5f7226e5f377a9544ff7\", md5().hex())\n    assertEquals(\"0e4dd66217fc8d2e298b78c8cd9392870dcd065d0ff675d0edff5bcd227837e9\", sha256().hex())\n    assertEquals(\"483676b93c4417198b465083d196ec6a9fab8d004515874b8ff47e041f5f56303cc08179625030b8b5b721c09149a18f0f59e64e7ae099518cea78d3d83167e1\", sha512().hex())\n  }\n\n  @Test fun copyInto() {\n    val byteString = factory.encodeUtf8(\"abcdefgh\")\n    val byteArray = \"WwwwXxxxYyyyZzzz\".encodeToByteArray()\n    byteString.copyInto(target = byteArray, byteCount = 5)\n    assertEquals(\"abcdexxxYyyyZzzz\", byteArray.decodeToString())\n  }\n\n  @Test fun copyIntoFullRange() {\n    val byteString = factory.encodeUtf8(\"abcdefghijklmnop\")\n    val byteArray = \"WwwwXxxxYyyyZzzz\".encodeToByteArray()\n    byteString.copyInto(target = byteArray, byteCount = 16)\n    assertEquals(\"abcdefghijklmnop\", byteArray.decodeToString())\n  }\n\n  @Test fun copyIntoWithTargetOffset() {\n    val byteString = factory.encodeUtf8(\"abcdefgh\")\n    val byteArray = \"WwwwXxxxYyyyZzzz\".encodeToByteArray()\n    byteString.copyInto(target = byteArray, targetOffset = 11, byteCount = 5)\n    assertEquals(\"WwwwXxxxYyyabcde\", byteArray.decodeToString())\n  }\n\n  @Test fun copyIntoWithSourceOffset() {\n    val byteString = factory.encodeUtf8(\"abcdefgh\")\n    val byteArray = \"WwwwXxxxYyyyZzzz\".encodeToByteArray()\n    byteString.copyInto(offset = 3, target = byteArray, byteCount = 5)\n    assertEquals(\"defghxxxYyyyZzzz\", byteArray.decodeToString())\n  }\n\n  @Test fun copyIntoWithAllParameters() {\n    val byteString = factory.encodeUtf8(\"abcdefgh\")\n    val byteArray = \"WwwwXxxxYyyyZzzz\".encodeToByteArray()\n    byteString.copyInto(offset = 3, target = byteArray, targetOffset = 11, byteCount = 5)\n    assertEquals(\"WwwwXxxxYyydefgh\", byteArray.decodeToString())\n  }\n\n  @Test fun copyIntoBoundsChecks() {\n    val byteString = factory.encodeUtf8(\"abcdefgh\")\n    val byteArray = \"WwwwXxxxYyyyZzzz\".encodeToByteArray()\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString.copyInto(offset = -1, target = byteArray, targetOffset = 1, byteCount = 1)\n    }\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString.copyInto(offset = 9, target = byteArray, targetOffset = 0, byteCount = 0)\n    }\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString.copyInto(offset = 1, target = byteArray, targetOffset = -1, byteCount = 1)\n    }\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString.copyInto(offset = 1, target = byteArray, targetOffset = 17, byteCount = 1)\n    }\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString.copyInto(offset = 7, target = byteArray, targetOffset = 1, byteCount = 2)\n    }\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString.copyInto(offset = 1, target = byteArray, targetOffset = 15, byteCount = 2)\n    }\n  }\n\n  @Test fun copyEmptyAtBounds() {\n    val byteString = factory.encodeUtf8(\"abcdefgh\")\n    val byteArray = \"WwwwXxxxYyyyZzzz\".encodeToByteArray()\n    byteString.copyInto(offset = 0, target = byteArray, targetOffset = 0, byteCount = 0)\n    assertEquals(\"WwwwXxxxYyyyZzzz\", byteArray.decodeToString())\n    byteString.copyInto(offset = 0, target = byteArray, targetOffset = 16, byteCount = 0)\n    assertEquals(\"WwwwXxxxYyyyZzzz\", byteArray.decodeToString())\n    byteString.copyInto(offset = 8, target = byteArray, targetOffset = 0, byteCount = 0)\n    assertEquals(\"WwwwXxxxYyyyZzzz\", byteArray.decodeToString())\n  }\n\n  @Test\n  fun ofCopy() {\n    val bytes = \"Hello, World!\".encodeToByteArray()\n    val byteString = ByteString.of(*bytes)\n    // Verify that the bytes were copied out.\n    bytes[4] = 'a'.code.toByte()\n    assertEquals(\"Hello, World!\", byteString.utf8())\n  }\n\n  @Test\n  fun ofCopyRange() {\n    val bytes = \"Hello, World!\".encodeToByteArray()\n    val byteString: ByteString = bytes.toByteString(2, 9)\n    // Verify that the bytes were copied out.\n    bytes[4] = 'a'.code.toByte()\n    assertEquals(\"llo, Worl\", byteString.utf8())\n  }\n\n  @Test\n  fun getByteOutOfBounds() {\n    val byteString = factory.decodeHex(\"ab12\")\n    try {\n      byteString[2]\n      fail()\n    } catch (expected: IndexOutOfBoundsException) {\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/CommonBufferTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport kotlin.random.Random\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.decodeHex\n\n/**\n * Tests solely for the behavior of Buffer's implementation. For generic BufferedSink or\n * BufferedSource behavior use BufferedSinkTest or BufferedSourceTest, respectively.\n */\nclass CommonBufferTest {\n  @Test fun readAndWriteUtf8() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"ab\")\n    assertEquals(2, buffer.size)\n    buffer.writeUtf8(\"cdef\")\n    assertEquals(6, buffer.size)\n    assertEquals(\"abcd\", buffer.readUtf8(4))\n    assertEquals(2, buffer.size)\n    assertEquals(\"ef\", buffer.readUtf8(2))\n    assertEquals(0, buffer.size)\n    assertFailsWith<EOFException> {\n      buffer.readUtf8(1)\n    }\n  }\n\n  /** Buffer's toString is the same as ByteString's.  */\n  @Test fun bufferToString() {\n    assertEquals(\"[size=0]\", Buffer().toString())\n    assertEquals(\n      \"[text=a\\\\r\\\\nb\\\\nc\\\\rd\\\\\\\\e]\",\n      Buffer().writeUtf8(\"a\\r\\nb\\nc\\rd\\\\e\").toString(),\n    )\n    assertEquals(\n      \"[text=Tyrannosaur]\",\n      Buffer().writeUtf8(\"Tyrannosaur\").toString(),\n    )\n    assertEquals(\n      \"[text=təˈranəˌsôr]\",\n      Buffer()\n        .write(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex())\n        .toString(),\n    )\n    assertEquals(\n      \"[hex=0000000000000000000000000000000000000000000000000000000000000000000000000000\" +\n        \"0000000000000000000000000000000000000000000000000000]\",\n      Buffer().write(ByteArray(64)).toString(),\n    )\n  }\n\n  @Test fun multipleSegmentBuffers() {\n    val buffer = Buffer()\n    buffer.writeUtf8('a'.repeat(1000))\n    buffer.writeUtf8('b'.repeat(2500))\n    buffer.writeUtf8('c'.repeat(5000))\n    buffer.writeUtf8('d'.repeat(10000))\n    buffer.writeUtf8('e'.repeat(25000))\n    buffer.writeUtf8('f'.repeat(50000))\n\n    assertEquals('a'.repeat(999), buffer.readUtf8(999)) // a...a\n    assertEquals(\"a\" + 'b'.repeat(2500) + \"c\", buffer.readUtf8(2502)) // ab...bc\n    assertEquals('c'.repeat(4998), buffer.readUtf8(4998)) // c...c\n    assertEquals(\"c\" + 'd'.repeat(10000) + \"e\", buffer.readUtf8(10002)) // cd...de\n    assertEquals('e'.repeat(24998), buffer.readUtf8(24998)) // e...e\n    assertEquals(\"e\" + 'f'.repeat(50000), buffer.readUtf8(50001)) // ef...f\n    assertEquals(0, buffer.size)\n  }\n\n  @Test fun fillAndDrainPool() {\n    val buffer = Buffer()\n\n    // Take 2 * MAX_SIZE segments. This will drain the pool, even if other tests filled it.\n    buffer.write(ByteArray(SegmentPool.MAX_SIZE))\n    buffer.write(ByteArray(SegmentPool.MAX_SIZE))\n    assertEquals(0, SegmentPool.byteCount)\n\n    // Recycle MAX_SIZE segments. They're all in the pool.\n    buffer.skip(SegmentPool.MAX_SIZE.toLong())\n    assertEquals(SegmentPool.MAX_SIZE, SegmentPool.byteCount)\n\n    // Recycle MAX_SIZE more segments. The pool is full so they get garbage collected.\n    buffer.skip(SegmentPool.MAX_SIZE.toLong())\n    assertEquals(SegmentPool.MAX_SIZE, SegmentPool.byteCount)\n\n    // Take MAX_SIZE segments to drain the pool.\n    buffer.write(ByteArray(SegmentPool.MAX_SIZE))\n    assertEquals(0, SegmentPool.byteCount)\n\n    // Take MAX_SIZE more segments. The pool is drained so these will need to be allocated.\n    buffer.write(ByteArray(SegmentPool.MAX_SIZE))\n    assertEquals(0, SegmentPool.byteCount)\n  }\n\n  @Test fun moveBytesBetweenBuffersShareSegment() {\n    val size = Segment.SIZE / 2 - 1\n    val segmentSizes = moveBytesBetweenBuffers('a'.repeat(size), 'b'.repeat(size))\n    assertEquals(listOf(size * 2), segmentSizes)\n  }\n\n  @Test fun moveBytesBetweenBuffersReassignSegment() {\n    val size = Segment.SIZE / 2 + 1\n    val segmentSizes = moveBytesBetweenBuffers('a'.repeat(size), 'b'.repeat(size))\n    assertEquals(listOf(size, size), segmentSizes)\n  }\n\n  @Test fun moveBytesBetweenBuffersMultipleSegments() {\n    val size = 3 * Segment.SIZE + 1\n    val segmentSizes = moveBytesBetweenBuffers('a'.repeat(size), 'b'.repeat(size))\n    assertEquals(\n      listOf(\n        Segment.SIZE,\n        Segment.SIZE,\n        Segment.SIZE,\n        1,\n        Segment.SIZE,\n        Segment.SIZE,\n        Segment.SIZE,\n        1,\n      ),\n      segmentSizes,\n    )\n  }\n\n  private fun moveBytesBetweenBuffers(vararg contents: String): List<Int> {\n    val expected = StringBuilder()\n    val buffer = Buffer()\n    for (s in contents) {\n      val source = Buffer()\n      source.writeUtf8(s)\n      buffer.writeAll(source)\n      expected.append(s)\n    }\n    val segmentSizes = segmentSizes(buffer)\n    assertEquals(expected.toString(), buffer.readUtf8(expected.length.toLong()))\n    return segmentSizes\n  }\n\n  /** The big part of source's first segment is being moved.  */\n  @Test fun writeSplitSourceBufferLeft() {\n    val writeSize = Segment.SIZE / 2 + 1\n\n    val sink = Buffer()\n    sink.writeUtf8('b'.repeat(Segment.SIZE - 10))\n\n    val source = Buffer()\n    source.writeUtf8('a'.repeat(Segment.SIZE * 2))\n    sink.write(source, writeSize.toLong())\n\n    assertEquals(listOf(Segment.SIZE - 10, writeSize), segmentSizes(sink))\n    assertEquals(listOf(Segment.SIZE - writeSize, Segment.SIZE), segmentSizes(source))\n  }\n\n  /** The big part of source's first segment is staying put.  */\n  @Test fun writeSplitSourceBufferRight() {\n    val writeSize = Segment.SIZE / 2 - 1\n\n    val sink = Buffer()\n    sink.writeUtf8('b'.repeat(Segment.SIZE - 10))\n\n    val source = Buffer()\n    source.writeUtf8('a'.repeat(Segment.SIZE * 2))\n    sink.write(source, writeSize.toLong())\n\n    assertEquals(listOf(Segment.SIZE - 10, writeSize), segmentSizes(sink))\n    assertEquals(listOf(Segment.SIZE - writeSize, Segment.SIZE), segmentSizes(source))\n  }\n\n  @Test fun writePrefixDoesntSplit() {\n    val sink = Buffer()\n    sink.writeUtf8('b'.repeat(10))\n\n    val source = Buffer()\n    source.writeUtf8('a'.repeat(Segment.SIZE * 2))\n    sink.write(source, 20)\n\n    assertEquals(listOf(30), segmentSizes(sink))\n    assertEquals(listOf(Segment.SIZE - 20, Segment.SIZE), segmentSizes(source))\n    assertEquals(30, sink.size)\n    assertEquals((Segment.SIZE * 2 - 20).toLong(), source.size)\n  }\n\n  @Test fun writePrefixDoesntSplitButRequiresCompact() {\n    val sink = Buffer()\n    sink.writeUtf8('b'.repeat(Segment.SIZE - 10)) // limit = size - 10\n    sink.readUtf8((Segment.SIZE - 20).toLong()) // pos = size = 20\n\n    val source = Buffer()\n    source.writeUtf8('a'.repeat(Segment.SIZE * 2))\n    sink.write(source, 20)\n\n    assertEquals(listOf(30), segmentSizes(sink))\n    assertEquals(listOf(Segment.SIZE - 20, Segment.SIZE), segmentSizes(source))\n    assertEquals(30, sink.size)\n    assertEquals((Segment.SIZE * 2 - 20).toLong(), source.size)\n  }\n\n  @Test fun moveAllRequestedBytesWithRead() {\n    val sink = Buffer()\n    sink.writeUtf8('a'.repeat(10))\n\n    val source = Buffer()\n    source.writeUtf8('b'.repeat(15))\n\n    assertEquals(10, source.read(sink, 10))\n    assertEquals(20, sink.size)\n    assertEquals(5, source.size)\n    assertEquals('a'.repeat(10) + 'b'.repeat(10), sink.readUtf8(20))\n  }\n\n  @Test fun moveFewerThanRequestedBytesWithRead() {\n    val sink = Buffer()\n    sink.writeUtf8('a'.repeat(10))\n\n    val source = Buffer()\n    source.writeUtf8('b'.repeat(20))\n\n    assertEquals(20, source.read(sink, 25))\n    assertEquals(30, sink.size)\n    assertEquals(0, source.size)\n    assertEquals('a'.repeat(10) + 'b'.repeat(20), sink.readUtf8(30))\n  }\n\n  @Test fun indexOfWithOffset() {\n    val buffer = Buffer()\n    val halfSegment = Segment.SIZE / 2\n    buffer.writeUtf8('a'.repeat(halfSegment))\n    buffer.writeUtf8('b'.repeat(halfSegment))\n    buffer.writeUtf8('c'.repeat(halfSegment))\n    buffer.writeUtf8('d'.repeat(halfSegment))\n    assertEquals(0, buffer.indexOf('a'.code.toByte(), 0))\n    assertEquals((halfSegment - 1).toLong(), buffer.indexOf('a'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals(halfSegment.toLong(), buffer.indexOf('b'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals((halfSegment * 2).toLong(), buffer.indexOf('c'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 2).toLong()))\n    assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 3).toLong()))\n    assertEquals((halfSegment * 4 - 1).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 4 - 1).toLong()))\n  }\n\n  @Test fun byteAt() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"a\")\n    buffer.writeUtf8('b'.repeat(Segment.SIZE))\n    buffer.writeUtf8(\"c\")\n    assertEquals('a'.code.toLong(), buffer[0].toLong())\n    assertEquals('a'.code.toLong(), buffer[0].toLong()) // getByte doesn't mutate!\n    assertEquals('c'.code.toLong(), buffer[buffer.size - 1].toLong())\n    assertEquals('b'.code.toLong(), buffer[buffer.size - 2].toLong())\n    assertEquals('b'.code.toLong(), buffer[buffer.size - 3].toLong())\n  }\n\n  @Test fun getByteOfEmptyBuffer() {\n    val buffer = Buffer()\n    assertFailsWith<IndexOutOfBoundsException> {\n      buffer[0]\n    }\n  }\n\n  @Test\n  fun writePrefixToEmptyBuffer() {\n    val sink = Buffer()\n    val source = Buffer()\n    source.writeUtf8(\"abcd\")\n    sink.write(source, 2)\n    assertEquals(\"ab\", sink.readUtf8(2))\n  }\n\n  @Suppress(\"ReplaceAssertBooleanWithAssertEquality\")\n  @Test\n  fun equalsAndHashCodeEmpty() {\n    val a = Buffer()\n    val b = Buffer()\n    assertTrue(a == b)\n    assertTrue(a.hashCode() == b.hashCode())\n  }\n\n  @Suppress(\"ReplaceAssertBooleanWithAssertEquality\")\n  @Test\n  fun equalsAndHashCode() {\n    val a = Buffer().writeUtf8(\"dog\")\n    val b = Buffer().writeUtf8(\"hotdog\")\n    assertFalse(a == b)\n    assertFalse(a.hashCode() == b.hashCode())\n\n    b.readUtf8(3) // Leaves b containing 'dog'.\n    assertTrue(a == b)\n    assertTrue(a.hashCode() == b.hashCode())\n  }\n\n  @Suppress(\"ReplaceAssertBooleanWithAssertEquality\")\n  @Test\n  fun equalsAndHashCodeSpanningSegments() {\n    val data = ByteArray(1024 * 1024)\n    val dice = Random(0)\n    dice.nextBytes(data)\n\n    val a = bufferWithRandomSegmentLayout(dice, data)\n    val b = bufferWithRandomSegmentLayout(dice, data)\n    assertTrue(a == b)\n    assertTrue(a.hashCode() == b.hashCode())\n\n    data[data.size / 2]++ // Change a single byte.\n    val c = bufferWithRandomSegmentLayout(dice, data)\n    assertFalse(a == c)\n    assertFalse(a.hashCode() == c.hashCode())\n  }\n\n  /**\n   * When writing data that's already buffered, there's no reason to page the\n   * data by segment.\n   */\n  @Test fun readAllWritesAllSegmentsAtOnce() {\n    val write1 = Buffer().writeUtf8(\n      'a'.repeat(Segment.SIZE) +\n        'b'.repeat(Segment.SIZE) +\n        'c'.repeat(Segment.SIZE),\n    )\n\n    val source = Buffer().writeUtf8(\n      'a'.repeat(Segment.SIZE) +\n        'b'.repeat(Segment.SIZE) +\n        'c'.repeat(Segment.SIZE),\n    )\n\n    val mockSink = MockSink()\n\n    assertEquals((Segment.SIZE * 3).toLong(), source.readAll(mockSink))\n    assertEquals(0, source.size)\n    mockSink.assertLog(\"write($write1, ${write1.size})\")\n  }\n\n  @Test fun writeAllMultipleSegments() {\n    val source = Buffer().writeUtf8('a'.repeat(Segment.SIZE * 3))\n    val sink = Buffer()\n\n    assertEquals((Segment.SIZE * 3).toLong(), sink.writeAll(source))\n    assertEquals(0, source.size)\n    assertEquals('a'.repeat(Segment.SIZE * 3), sink.readUtf8())\n  }\n\n  @Test fun copyTo() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n\n    val target = Buffer()\n    source.copyTo(target, 1, 3)\n\n    assertEquals(\"art\", target.readUtf8())\n    assertEquals(\"party\", source.readUtf8())\n  }\n\n  @Test fun copyToOnSegmentBoundary() {\n    val `as` = 'a'.repeat(Segment.SIZE)\n    val bs = 'b'.repeat(Segment.SIZE)\n    val cs = 'c'.repeat(Segment.SIZE)\n    val ds = 'd'.repeat(Segment.SIZE)\n\n    val source = Buffer()\n    source.writeUtf8(`as`)\n    source.writeUtf8(bs)\n    source.writeUtf8(cs)\n\n    val target = Buffer()\n    target.writeUtf8(ds)\n\n    source.copyTo(target, `as`.length.toLong(), (bs.length + cs.length).toLong())\n    assertEquals(ds + bs + cs, target.readUtf8())\n  }\n\n  @Test fun copyToOffSegmentBoundary() {\n    val `as` = 'a'.repeat(Segment.SIZE - 1)\n    val bs = 'b'.repeat(Segment.SIZE + 2)\n    val cs = 'c'.repeat(Segment.SIZE - 4)\n    val ds = 'd'.repeat(Segment.SIZE + 8)\n\n    val source = Buffer()\n    source.writeUtf8(`as`)\n    source.writeUtf8(bs)\n    source.writeUtf8(cs)\n\n    val target = Buffer()\n    target.writeUtf8(ds)\n\n    source.copyTo(target, `as`.length.toLong(), (bs.length + cs.length).toLong())\n    assertEquals(ds + bs + cs, target.readUtf8())\n  }\n\n  @Test fun copyToSourceAndTargetCanBeTheSame() {\n    val `as` = 'a'.repeat(Segment.SIZE)\n    val bs = 'b'.repeat(Segment.SIZE)\n\n    val source = Buffer()\n    source.writeUtf8(`as`)\n    source.writeUtf8(bs)\n\n    source.copyTo(source, 0, source.size)\n    assertEquals(`as` + bs + `as` + bs, source.readUtf8())\n  }\n\n  @Test fun copyToEmptySource() {\n    val source = Buffer()\n    val target = Buffer().writeUtf8(\"aaa\")\n    source.copyTo(target, 0L, 0L)\n    assertEquals(\"\", source.readUtf8())\n    assertEquals(\"aaa\", target.readUtf8())\n  }\n\n  @Test fun copyToEmptyTarget() {\n    val source = Buffer().writeUtf8(\"aaa\")\n    val target = Buffer()\n    source.copyTo(target, 0L, 3L)\n    assertEquals(\"aaa\", source.readUtf8())\n    assertEquals(\"aaa\", target.readUtf8())\n  }\n\n  @Test fun snapshotReportsAccurateSize() {\n    val buf = Buffer().write(byteArrayOf(0, 1, 2, 3))\n    assertEquals(1, buf.snapshot(1).size)\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/CommonBufferedSinkTest.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nimport app.cash.burst.Burst\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\n\n@Burst\nclass CommonBufferedSinkTest(\n  factory: BufferedSinkFactory,\n) {\n  private val data: Buffer = Buffer()\n  private val sink: BufferedSink = factory.create(data)\n\n  @Test fun writeNothing() {\n    sink.writeUtf8(\"\")\n    sink.flush()\n    assertEquals(0, data.size)\n  }\n\n  @Test fun writeBytes() {\n    sink.writeByte(0xab)\n    sink.writeByte(0xcd)\n    sink.flush()\n    assertEquals(\"[hex=abcd]\", data.toString())\n  }\n\n  @Test fun writeLastByteInSegment() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 1))\n    sink.writeByte(0x20)\n    sink.writeByte(0x21)\n    sink.flush()\n    assertEquals(listOf(Segment.SIZE, 1), segmentSizes(data))\n    assertEquals(\"a\".repeat(Segment.SIZE - 1), data.readUtf8(Segment.SIZE - 1L))\n    assertEquals(\"[text= !]\", data.toString())\n  }\n\n  @Test fun writeShort() {\n    sink.writeShort(0xabcd)\n    sink.writeShort(0x4321)\n    sink.flush()\n    assertEquals(\"[hex=abcd4321]\", data.toString())\n  }\n\n  @Test fun writeShortLe() {\n    sink.writeShortLe(0xcdab)\n    sink.writeShortLe(0x2143)\n    sink.flush()\n    assertEquals(\"[hex=abcd4321]\", data.toString())\n  }\n\n  @Test fun writeInt() {\n    sink.writeInt(-0x543210ff)\n    sink.writeInt(-0x789abcdf)\n    sink.flush()\n    assertEquals(\"[hex=abcdef0187654321]\", data.toString())\n  }\n\n  @Test fun writeLastIntegerInSegment() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 4))\n    sink.writeInt(-0x543210ff)\n    sink.writeInt(-0x789abcdf)\n    sink.flush()\n    assertEquals(listOf(Segment.SIZE, 4), segmentSizes(data))\n    assertEquals(\"a\".repeat(Segment.SIZE - 4), data.readUtf8(Segment.SIZE - 4L))\n    assertEquals(\"[hex=abcdef0187654321]\", data.toString())\n  }\n\n  @Test fun writeIntegerDoesNotQuiteFitInSegment() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 3))\n    sink.writeInt(-0x543210ff)\n    sink.writeInt(-0x789abcdf)\n    sink.flush()\n    assertEquals(listOf(Segment.SIZE - 3, 8), segmentSizes(data))\n    assertEquals(\"a\".repeat(Segment.SIZE - 3), data.readUtf8(Segment.SIZE - 3L))\n    assertEquals(\"[hex=abcdef0187654321]\", data.toString())\n  }\n\n  @Test fun writeIntLe() {\n    sink.writeIntLe(-0x543210ff)\n    sink.writeIntLe(-0x789abcdf)\n    sink.flush()\n    assertEquals(\"[hex=01efcdab21436587]\", data.toString())\n  }\n\n  @Test fun writeLong() {\n    sink.writeLong(-0x543210fe789abcdfL)\n    sink.writeLong(-0x350145414f4ea400L)\n    sink.flush()\n    assertEquals(\"[hex=abcdef0187654321cafebabeb0b15c00]\", data.toString())\n  }\n\n  @Test fun writeLongLe() {\n    sink.writeLongLe(-0x543210fe789abcdfL)\n    sink.writeLongLe(-0x350145414f4ea400L)\n    sink.flush()\n    assertEquals(\"[hex=2143658701efcdab005cb1b0bebafeca]\", data.toString())\n  }\n\n  @Test fun writeByteString() {\n    sink.write(\"təˈranəˌsôr\".encodeUtf8())\n    sink.flush()\n    assertEquals(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex(), data.readByteString())\n  }\n\n  @Test fun writeByteStringOffset() {\n    sink.write(\"təˈranəˌsôr\".encodeUtf8(), 5, 5)\n    sink.flush()\n    assertEquals(\"72616ec999\".decodeHex(), data.readByteString())\n  }\n\n  @Test fun writeSegmentedByteString() {\n    sink.write(Buffer().write(\"təˈranəˌsôr\".encodeUtf8()).snapshot())\n    sink.flush()\n    assertEquals(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex(), data.readByteString())\n  }\n\n  @Test fun writeSegmentedByteStringOffset() {\n    sink.write(Buffer().write(\"təˈranəˌsôr\".encodeUtf8()).snapshot(), 5, 5)\n    sink.flush()\n    assertEquals(\"72616ec999\".decodeHex(), data.readByteString())\n  }\n\n  @Test fun writeStringUtf8() {\n    sink.writeUtf8(\"təˈranəˌsôr\")\n    sink.flush()\n    assertEquals(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex(), data.readByteString())\n  }\n\n  @Test fun writeSubstringUtf8() {\n    sink.writeUtf8(\"təˈranəˌsôr\", 3, 7)\n    sink.flush()\n    assertEquals(\"72616ec999\".decodeHex(), data.readByteString())\n  }\n\n  @Test fun writeAll() {\n    val source = Buffer().writeUtf8(\"abcdef\")\n\n    assertEquals(6, sink.writeAll(source))\n    assertEquals(0, source.size)\n    sink.flush()\n    assertEquals(\"abcdef\", data.readUtf8())\n  }\n\n  @Test fun writeSource() {\n    val source = Buffer().writeUtf8(\"abcdef\")\n\n    // Force resolution of the Source method overload.\n    sink.write(source as Source, 4)\n    sink.flush()\n    assertEquals(\"abcd\", data.readUtf8())\n    assertEquals(\"ef\", source.readUtf8())\n  }\n\n  @Test fun writeSourceReadsFully() {\n    val source = object : Source by Buffer() {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        sink.writeUtf8(\"abcd\")\n        return 4\n      }\n    }\n\n    sink.write(source, 8)\n    sink.flush()\n    assertEquals(\"abcdabcd\", data.readUtf8())\n  }\n\n  @Test fun writeSourcePropagatesEof() {\n    val source: Source = Buffer().writeUtf8(\"abcd\")\n\n    assertFailsWith<EOFException> {\n      sink.write(source, 8)\n    }\n\n    // Ensure that whatever was available was correctly written.\n    sink.flush()\n    assertEquals(\"abcd\", data.readUtf8())\n  }\n\n  @Test fun writeSourceWithZeroIsNoOp() {\n    // This test ensures that a zero byte count never calls through to read the source. It may be\n    // tied to something like a socket which will potentially block trying to read a segment when\n    // ultimately we don't want any data.\n    val source = object : Source by Buffer() {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        throw AssertionError()\n      }\n    }\n    sink.write(source, 0)\n    assertEquals(0, data.size)\n  }\n\n  @Test fun writeAllExhausted() {\n    val source = Buffer()\n    assertEquals(0, sink.writeAll(source))\n    assertEquals(0, source.size)\n  }\n\n  @Test fun closeEmitsBufferedBytes() {\n    sink.writeByte('a'.code)\n    sink.close()\n    assertEquals('a', data.readByte().toInt().toChar())\n  }\n\n  /**\n   * This test hard codes the results of Long.toString() because that function rounds large values\n   * when using Kotlin/JS IR. https://youtrack.jetbrains.com/issue/KT-39891\n   */\n  @Test fun longDecimalString() {\n    assertLongDecimalString(\"0\", 0)\n    assertLongDecimalString(\"-9223372036854775808\", Long.MIN_VALUE)\n    assertLongDecimalString(\"9223372036854775807\", Long.MAX_VALUE)\n    assertLongDecimalString(\"9\", 9L)\n    assertLongDecimalString(\"99\", 99L)\n    assertLongDecimalString(\"999\", 999L)\n    assertLongDecimalString(\"9999\", 9999L)\n    assertLongDecimalString(\"99999\", 99999L)\n    assertLongDecimalString(\"999999\", 999999L)\n    assertLongDecimalString(\"9999999\", 9999999L)\n    assertLongDecimalString(\"99999999\", 99999999L)\n    assertLongDecimalString(\"999999999\", 999999999L)\n    assertLongDecimalString(\"9999999999\", 9999999999L)\n    assertLongDecimalString(\"99999999999\", 99999999999L)\n    assertLongDecimalString(\"999999999999\", 999999999999L)\n    assertLongDecimalString(\"9999999999999\", 9999999999999L)\n    assertLongDecimalString(\"99999999999999\", 99999999999999L)\n    assertLongDecimalString(\"999999999999999\", 999999999999999L)\n    assertLongDecimalString(\"9999999999999999\", 9999999999999999L)\n    assertLongDecimalString(\"99999999999999999\", 99999999999999999L)\n    assertLongDecimalString(\"999999999999999999\", 999999999999999999L)\n    assertLongDecimalString(\"10\", 10L)\n    assertLongDecimalString(\"100\", 100L)\n    assertLongDecimalString(\"1000\", 1000L)\n    assertLongDecimalString(\"10000\", 10000L)\n    assertLongDecimalString(\"100000\", 100000L)\n    assertLongDecimalString(\"1000000\", 1000000L)\n    assertLongDecimalString(\"10000000\", 10000000L)\n    assertLongDecimalString(\"100000000\", 100000000L)\n    assertLongDecimalString(\"1000000000\", 1000000000L)\n    assertLongDecimalString(\"10000000000\", 10000000000L)\n    assertLongDecimalString(\"100000000000\", 100000000000L)\n    assertLongDecimalString(\"1000000000000\", 1000000000000L)\n    assertLongDecimalString(\"10000000000000\", 10000000000000L)\n    assertLongDecimalString(\"100000000000000\", 100000000000000L)\n    assertLongDecimalString(\"1000000000000000\", 1000000000000000L)\n    assertLongDecimalString(\"10000000000000000\", 10000000000000000L)\n    assertLongDecimalString(\"100000000000000000\", 100000000000000000L)\n    assertLongDecimalString(\"1000000000000000000\", 1000000000000000000L)\n    assertLongDecimalString(\"-9\", -9L)\n    assertLongDecimalString(\"-99\", -99L)\n    assertLongDecimalString(\"-999\", -999L)\n    assertLongDecimalString(\"-9999\", -9999L)\n    assertLongDecimalString(\"-99999\", -99999L)\n    assertLongDecimalString(\"-999999\", -999999L)\n    assertLongDecimalString(\"-9999999\", -9999999L)\n    assertLongDecimalString(\"-99999999\", -99999999L)\n    assertLongDecimalString(\"-999999999\", -999999999L)\n    assertLongDecimalString(\"-9999999999\", -9999999999L)\n    assertLongDecimalString(\"-99999999999\", -99999999999L)\n    assertLongDecimalString(\"-999999999999\", -999999999999L)\n    assertLongDecimalString(\"-9999999999999\", -9999999999999L)\n    assertLongDecimalString(\"-99999999999999\", -99999999999999L)\n    assertLongDecimalString(\"-999999999999999\", -999999999999999L)\n    assertLongDecimalString(\"-9999999999999999\", -9999999999999999L)\n    assertLongDecimalString(\"-99999999999999999\", -99999999999999999L)\n    assertLongDecimalString(\"-999999999999999999\", -999999999999999999L)\n    assertLongDecimalString(\"-10\", -10L)\n    assertLongDecimalString(\"-100\", -100L)\n    assertLongDecimalString(\"-1000\", -1000L)\n    assertLongDecimalString(\"-10000\", -10000L)\n    assertLongDecimalString(\"-100000\", -100000L)\n    assertLongDecimalString(\"-1000000\", -1000000L)\n    assertLongDecimalString(\"-10000000\", -10000000L)\n    assertLongDecimalString(\"-100000000\", -100000000L)\n    assertLongDecimalString(\"-1000000000\", -1000000000L)\n    assertLongDecimalString(\"-10000000000\", -10000000000L)\n    assertLongDecimalString(\"-100000000000\", -100000000000L)\n    assertLongDecimalString(\"-1000000000000\", -1000000000000L)\n    assertLongDecimalString(\"-10000000000000\", -10000000000000L)\n    assertLongDecimalString(\"-100000000000000\", -100000000000000L)\n    assertLongDecimalString(\"-1000000000000000\", -1000000000000000L)\n    assertLongDecimalString(\"-10000000000000000\", -10000000000000000L)\n    assertLongDecimalString(\"-100000000000000000\", -100000000000000000L)\n    assertLongDecimalString(\"-1000000000000000000\", -1000000000000000000L)\n  }\n\n  private fun assertLongDecimalString(string: String, value: Long) {\n    sink.writeDecimalLong(value).writeUtf8(\"zzz\").flush()\n    val expected = \"${string}zzz\"\n    val actual = data.readUtf8()\n    assertEquals(expected, actual, \"$value expected $expected but was $actual\")\n  }\n\n  @Test fun longHexString() {\n    assertLongHexString(0)\n    assertLongHexString(Long.MIN_VALUE)\n    assertLongHexString(Long.MAX_VALUE)\n\n    for (i in 0..62) {\n      assertLongHexString((1L shl i) - 1)\n      assertLongHexString(1L shl i)\n    }\n  }\n\n  private fun assertLongHexString(value: Long) {\n    sink.writeHexadecimalUnsignedLong(value).writeUtf8(\"zzz\").flush()\n    val expected = \"${value.toHexString()}zzz\"\n    val actual = data.readUtf8()\n    assertEquals(expected, actual, \"$value expected $expected but was $actual\")\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/CommonBufferedSourceTest.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nimport app.cash.burst.Burst\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\n\n@Burst\nclass CommonBufferedSourceTest(\n  private val factory: BufferedSourceFactory,\n) {\n  private val sink: BufferedSink\n  private val source: BufferedSource\n\n  init {\n    val pipe = factory.pipe()\n    sink = pipe.sink\n    source = pipe.source\n  }\n\n  @Test fun readBytes() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte()))\n    sink.emit()\n    assertEquals(0xab, (source.readByte() and 0xff).toLong())\n    assertEquals(0xcd, (source.readByte() and 0xff).toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readByteTooShortThrows() {\n    assertFailsWith<EOFException> {\n      source.readByte()\n    }\n  }\n\n  @Test fun readShort() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x01.toByte()))\n    sink.emit()\n    assertEquals(0xabcd.toShort().toLong(), source.readShort().toLong())\n    assertEquals(0xef01.toShort().toLong(), source.readShort().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readShortLe() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x10.toByte()))\n    sink.emit()\n    assertEquals(0xcdab.toShort().toLong(), source.readShortLe().toLong())\n    assertEquals(0x10ef.toShort().toLong(), source.readShortLe().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readShortSplitAcrossMultipleSegments() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 1))\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte()))\n    sink.emit()\n    source.skip((Segment.SIZE - 1).toLong())\n    assertEquals(0xabcd.toShort().toLong(), source.readShort().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readShortTooShortThrows() {\n    sink.writeShort(Short.MAX_VALUE.toInt())\n    sink.emit()\n    source.readByte()\n    assertFailsWith<EOFException> {\n      source.readShort()\n    }\n  }\n\n  @Test fun readShortLeTooShortThrows() {\n    sink.writeShortLe(Short.MAX_VALUE.toInt())\n    sink.emit()\n    source.readByte()\n    assertFailsWith<EOFException> {\n      source.readShortLe()\n    }\n  }\n\n  @Test fun readInt() {\n    sink.write(\n      byteArrayOf(\n        0xab.toByte(),\n        0xcd.toByte(),\n        0xef.toByte(),\n        0x01.toByte(),\n        0x87.toByte(),\n        0x65.toByte(),\n        0x43.toByte(),\n        0x21.toByte(),\n      ),\n    )\n    sink.emit()\n    assertEquals(-0x543210ff, source.readInt().toLong())\n    assertEquals(-0x789abcdf, source.readInt().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readIntLe() {\n    sink.write(\n      byteArrayOf(\n        0xab.toByte(),\n        0xcd.toByte(),\n        0xef.toByte(),\n        0x10.toByte(),\n        0x87.toByte(),\n        0x65.toByte(),\n        0x43.toByte(),\n        0x21.toByte(),\n      ),\n    )\n    sink.emit()\n    assertEquals(0x10efcdab, source.readIntLe().toLong())\n    assertEquals(0x21436587, source.readIntLe().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readIntSplitAcrossMultipleSegments() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 3))\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x01.toByte()))\n    sink.emit()\n    source.skip((Segment.SIZE - 3).toLong())\n    assertEquals(-0x543210ff, source.readInt().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readIntTooShortThrows() {\n    sink.writeInt(Int.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    assertFailsWith<EOFException> {\n      source.readInt()\n    }\n  }\n\n  @Test fun readIntLeTooShortThrows() {\n    sink.writeIntLe(Int.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    assertFailsWith<EOFException> {\n      source.readIntLe()\n    }\n  }\n\n  @Test fun readLong() {\n    sink.write(\n      byteArrayOf(\n        0xab.toByte(),\n        0xcd.toByte(),\n        0xef.toByte(),\n        0x10.toByte(),\n        0x87.toByte(),\n        0x65.toByte(),\n        0x43.toByte(),\n        0x21.toByte(),\n        0x36.toByte(),\n        0x47.toByte(),\n        0x58.toByte(),\n        0x69.toByte(),\n        0x12.toByte(),\n        0x23.toByte(),\n        0x34.toByte(),\n        0x45.toByte(),\n      ),\n    )\n    sink.emit()\n    assertEquals(-0x543210ef789abcdfL, source.readLong())\n    assertEquals(0x3647586912233445L, source.readLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readLongLe() {\n    sink.write(\n      byteArrayOf(\n        0xab.toByte(),\n        0xcd.toByte(),\n        0xef.toByte(),\n        0x10.toByte(),\n        0x87.toByte(),\n        0x65.toByte(),\n        0x43.toByte(),\n        0x21.toByte(),\n        0x36.toByte(),\n        0x47.toByte(),\n        0x58.toByte(),\n        0x69.toByte(),\n        0x12.toByte(),\n        0x23.toByte(),\n        0x34.toByte(),\n        0x45.toByte(),\n      ),\n    )\n    sink.emit()\n    assertEquals(0x2143658710efcdabL, source.readLongLe())\n    assertEquals(0x4534231269584736L, source.readLongLe())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readLongSplitAcrossMultipleSegments() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 7))\n    sink.write(\n      byteArrayOf(\n        0xab.toByte(),\n        0xcd.toByte(),\n        0xef.toByte(),\n        0x01.toByte(),\n        0x87.toByte(),\n        0x65.toByte(),\n        0x43.toByte(),\n        0x21.toByte(),\n      ),\n    )\n    sink.emit()\n    source.skip((Segment.SIZE - 7).toLong())\n    assertEquals(-0x543210fe789abcdfL, source.readLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readLongTooShortThrows() {\n    sink.writeLong(Long.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    assertFailsWith<EOFException> {\n      source.readLong()\n    }\n  }\n\n  @Test fun readLongLeTooShortThrows() {\n    sink.writeLongLe(Long.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    assertFailsWith<EOFException> {\n      source.readLongLe()\n    }\n  }\n\n  @Test fun readAll() {\n    source.buffer.writeUtf8(\"abc\")\n    sink.writeUtf8(\"def\")\n    sink.emit()\n\n    val sink = Buffer()\n    assertEquals(6, source.readAll(sink))\n    assertEquals(\"abcdef\", sink.readUtf8())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readAllExhausted() {\n    val mockSink = MockSink()\n    assertEquals(0, source.readAll(mockSink))\n    assertTrue(source.exhausted())\n    mockSink.assertLog()\n  }\n\n  @Test fun readExhaustedSource() {\n    val sink = Buffer()\n    sink.writeUtf8(\"a\".repeat(10))\n    assertEquals(-1, source.read(sink, 10))\n    assertEquals(10, sink.size)\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readZeroBytesFromSource() {\n    val sink = Buffer()\n    sink.writeUtf8(\"a\".repeat(10))\n\n    // Either 0 or -1 is reasonable here. For consistency with Android's\n    // ByteArrayInputStream we return 0.\n    val readResult = source.read(sink, 0)\n    assertTrue(readResult == 0L || readResult == -1L)\n    assertEquals(10, sink.size)\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun readFully() {\n    sink.writeUtf8(\"a\".repeat(10000))\n    sink.emit()\n    val sink = Buffer()\n    source.readFully(sink, 9999)\n    assertEquals(\"a\".repeat(9999), sink.readUtf8())\n    assertEquals(\"a\", source.readUtf8())\n  }\n\n  @Test fun readFullyTooShortThrows() {\n    sink.writeUtf8(\"Hi\")\n    sink.emit()\n    val sink = Buffer()\n    assertFailsWith<EOFException> {\n      source.readFully(sink, 5)\n    }\n\n    // Verify we read all that we could from the source.\n    assertEquals(\"Hi\", sink.readUtf8())\n  }\n\n  @Test fun readFullyByteArray() {\n    val data = Buffer()\n    data.writeUtf8(\"Hello\").writeUtf8(\"e\".repeat(Segment.SIZE))\n\n    val expected = data.copy().readByteArray()\n    sink.write(data, data.size)\n    sink.emit()\n\n    val sink = ByteArray(Segment.SIZE + 5)\n    source.readFully(sink)\n    assertArrayEquals(expected, sink)\n  }\n\n  @Test fun readFullyByteArrayTooShortThrows() {\n    sink.writeUtf8(\"Hello\")\n    sink.emit()\n\n    val array = ByteArray(6)\n    assertFailsWith<EOFException> {\n      source.readFully(array)\n    }\n\n    // Verify we read all that we could from the source.\n    assertArrayEquals(\n      byteArrayOf(\n        'H'.code.toByte(),\n        'e'.code.toByte(),\n        'l'.code.toByte(),\n        'l'.code.toByte(),\n        'o'.code.toByte(),\n        0,\n      ),\n      array,\n    )\n  }\n\n  @Test fun readIntoByteArray() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n\n    val sink = ByteArray(3)\n    val read = source.read(sink)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      val expected = byteArrayOf('a'.code.toByte(), 0, 0)\n      assertArrayEquals(expected, sink)\n    } else {\n      assertEquals(3, read.toLong())\n      val expected = byteArrayOf('a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte())\n      assertArrayEquals(expected, sink)\n    }\n  }\n\n  @Test fun readIntoByteArrayNotEnough() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n\n    val sink = ByteArray(5)\n    val read = source.read(sink)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      val expected = byteArrayOf('a'.code.toByte(), 0, 0, 0, 0)\n      assertArrayEquals(expected, sink)\n    } else {\n      assertEquals(4, read.toLong())\n      val expected =\n        byteArrayOf('a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte(), 'd'.code.toByte(), 0)\n      assertArrayEquals(expected, sink)\n    }\n  }\n\n  @Test fun readIntoByteArrayOffsetAndCount() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n\n    val sink = ByteArray(7)\n    val read = source.read(sink, 2, 3)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      val expected = byteArrayOf(0, 0, 'a'.code.toByte(), 0, 0, 0, 0)\n      assertArrayEquals(expected, sink)\n    } else {\n      assertEquals(3, read.toLong())\n      val expected =\n        byteArrayOf(0, 0, 'a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte(), 0, 0)\n      assertArrayEquals(expected, sink)\n    }\n  }\n\n  @Test fun readByteArray() {\n    val string = \"abcd\" + \"e\".repeat(Segment.SIZE)\n    sink.writeUtf8(string)\n    sink.emit()\n    assertArrayEquals(string.asUtf8ToByteArray(), source.readByteArray())\n  }\n\n  @Test fun readByteArrayPartial() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n    assertEquals(\"[97, 98, 99]\", source.readByteArray(3).contentToString())\n    assertEquals(\"d\", source.readUtf8(1))\n  }\n\n  @Test fun readByteArrayTooShortThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    assertFailsWith<EOFException> {\n      source.readByteArray(4)\n    }\n\n    assertEquals(\"abc\", source.readUtf8()) // The read shouldn't consume any data.\n  }\n\n  @Test fun readByteString() {\n    sink.writeUtf8(\"abcd\").writeUtf8(\"e\".repeat(Segment.SIZE))\n    sink.emit()\n    assertEquals(\"abcd\" + \"e\".repeat(Segment.SIZE), source.readByteString().utf8())\n  }\n\n  @Test fun readByteStringPartial() {\n    sink.writeUtf8(\"abcd\").writeUtf8(\"e\".repeat(Segment.SIZE))\n    sink.emit()\n    assertEquals(\"abc\", source.readByteString(3).utf8())\n    assertEquals(\"d\", source.readUtf8(1))\n  }\n\n  @Test fun readByteStringTooShortThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    assertFailsWith<EOFException> {\n      source.readByteString(4)\n    }\n\n    assertEquals(\"abc\", source.readUtf8()) // The read shouldn't consume any data.\n  }\n\n  @Test fun readUtf8SpansSegments() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE * 2))\n    sink.emit()\n    source.skip((Segment.SIZE - 1).toLong())\n    assertEquals(\"aa\", source.readUtf8(2))\n  }\n\n  @Test fun readUtf8Segment() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE))\n    sink.emit()\n    assertEquals(\"a\".repeat(Segment.SIZE), source.readUtf8(Segment.SIZE.toLong()))\n  }\n\n  @Test fun readUtf8PartialBuffer() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE + 20))\n    sink.emit()\n    assertEquals(\"a\".repeat(Segment.SIZE + 10), source.readUtf8((Segment.SIZE + 10).toLong()))\n  }\n\n  @Test fun readUtf8EntireBuffer() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE * 2))\n    sink.emit()\n    assertEquals(\"a\".repeat(Segment.SIZE * 2), source.readUtf8())\n  }\n\n  @Test fun readUtf8TooShortThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    assertFailsWith<EOFException> {\n      source.readUtf8(4L)\n    }\n\n    assertEquals(\"abc\", source.readUtf8()) // The read shouldn't consume any data.\n  }\n\n  @Test fun skip() {\n    sink.writeUtf8(\"a\")\n    sink.writeUtf8(\"b\".repeat(Segment.SIZE))\n    sink.writeUtf8(\"c\")\n    sink.emit()\n    source.skip(1)\n    assertEquals('b'.code.toLong(), (source.readByte() and 0xff).toLong())\n    source.skip((Segment.SIZE - 2).toLong())\n    assertEquals('b'.code.toLong(), (source.readByte() and 0xff).toLong())\n    source.skip(1)\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun skipInsufficientData() {\n    sink.writeUtf8(\"a\")\n    sink.emit()\n    assertFailsWith<EOFException> {\n      source.skip(2)\n    }\n  }\n\n  @Test fun indexOf() {\n    // The segment is empty.\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n\n    // The segment has one value.\n    sink.writeUtf8(\"a\") // a\n    sink.emit()\n    assertEquals(0, source.indexOf('a'.code.toByte()))\n    assertEquals(-1, source.indexOf('b'.code.toByte()))\n\n    // The segment has lots of data.\n    sink.writeUtf8(\"b\".repeat(Segment.SIZE - 2)) // ab...b\n    sink.emit()\n    assertEquals(0, source.indexOf('a'.code.toByte()))\n    assertEquals(1, source.indexOf('b'.code.toByte()))\n    assertEquals(-1, source.indexOf('c'.code.toByte()))\n\n    // The segment doesn't start at 0, it starts at 2.\n    source.skip(2) // b...b\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('b'.code.toByte()))\n    assertEquals(-1, source.indexOf('c'.code.toByte()))\n\n    // The segment is full.\n    sink.writeUtf8(\"c\") // b...bc\n    sink.emit()\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('b'.code.toByte()))\n    assertEquals((Segment.SIZE - 3).toLong(), source.indexOf('c'.code.toByte()))\n\n    // The segment doesn't start at 2, it starts at 4.\n    source.skip(2) // b...bc\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('b'.code.toByte()))\n    assertEquals((Segment.SIZE - 5).toLong(), source.indexOf('c'.code.toByte()))\n\n    // Two segments.\n    sink.writeUtf8(\"d\") // b...bcd, d is in the 2nd segment.\n    sink.emit()\n    assertEquals((Segment.SIZE - 4).toLong(), source.indexOf('d'.code.toByte()))\n    assertEquals(-1, source.indexOf('e'.code.toByte()))\n  }\n\n  @Test fun indexOfByteWithStartOffset() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(Segment.SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertEquals(-1, source.indexOf('a'.code.toByte(), 1))\n    assertEquals(15, source.indexOf('b'.code.toByte(), 15))\n  }\n\n  @Test fun indexOfByteWithBothOffsets() {\n    if (factory.isOneByteAtATime) {\n      // When run on CI this causes out-of-memory errors.\n      return\n    }\n    val a = 'a'.code.toByte()\n    val c = 'c'.code.toByte()\n\n    val size = Segment.SIZE * 5\n    val bytes = ByteArray(size) { a }\n\n    // These are tricky places where the buffer\n    // starts, ends, or segments come together.\n    val points = intArrayOf(\n      0,\n      1,\n      2,\n      Segment.SIZE - 1,\n      Segment.SIZE,\n      Segment.SIZE + 1,\n      size / 2 - 1,\n      size / 2,\n      size / 2 + 1,\n      size - Segment.SIZE - 1,\n      size - Segment.SIZE,\n      size - Segment.SIZE + 1,\n      size - 3,\n      size - 2,\n      size - 1,\n    )\n\n    // In each iteration, we write c to the known point and then search for it using different\n    // windows. Some of the windows don't overlap with c's position, and therefore a match shouldn't\n    // be found.\n    for (p in points) {\n      bytes[p] = c\n      sink.write(bytes)\n      sink.emit()\n\n      assertEquals(p.toLong(), source.indexOf(c, 0, size.toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, 0, (p + 1).toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, p.toLong(), size.toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, p.toLong(), (p + 1).toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, (p / 2).toLong(), (p * 2 + 1).toLong()))\n      assertEquals(-1, source.indexOf(c, 0, (p / 2).toLong()))\n      assertEquals(-1, source.indexOf(c, 0, p.toLong()))\n      assertEquals(-1, source.indexOf(c, 0, 0))\n      assertEquals(-1, source.indexOf(c, p.toLong(), p.toLong()))\n\n      // Reset.\n      source.readUtf8()\n      bytes[p] = a\n    }\n  }\n\n  @Test fun indexOfByteInvalidBoundsThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    assertFailsWith<IllegalArgumentException>(\"Expected failure: fromIndex < 0\") {\n      source.indexOf('a'.code.toByte(), -1)\n    }\n    assertFailsWith<IllegalArgumentException>(\"Expected failure: fromIndex > toIndex\") {\n      source.indexOf('a'.code.toByte(), 10, 0)\n    }\n  }\n\n  @Test fun indexOfByteString() {\n    assertEquals(-1, source.indexOf(\"flop\".encodeUtf8()))\n\n    sink.writeUtf8(\"flip flop\")\n    sink.emit()\n    assertEquals(5, source.indexOf(\"flop\".encodeUtf8()))\n    source.readUtf8() // Clear stream.\n\n    // Make sure we backtrack and resume searching after partial match.\n    sink.writeUtf8(\"hi hi hi hey\")\n    sink.emit()\n    assertEquals(3, source.indexOf(\"hi hi hey\".encodeUtf8()))\n  }\n\n  @Test fun indexOfByteStringAtSegmentBoundary() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 1))\n    sink.writeUtf8(\"bcd\")\n    sink.emit()\n    assertEquals(\n      (Segment.SIZE - 3).toLong(),\n      source.indexOf(\"aabc\".encodeUtf8(), (Segment.SIZE - 4).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 3).toLong(),\n      source.indexOf(\"aabc\".encodeUtf8(), (Segment.SIZE - 3).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 2).toLong(),\n      source.indexOf(\"abcd\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 2).toLong(),\n      source.indexOf(\"abc\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 2).toLong(),\n      source.indexOf(\"abc\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 2).toLong(),\n      source.indexOf(\"ab\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 2).toLong(),\n      source.indexOf(\"a\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 1).toLong(),\n      source.indexOf(\"bc\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE - 1).toLong(),\n      source.indexOf(\"b\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      Segment.SIZE.toLong(),\n      source.indexOf(\"c\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      Segment.SIZE.toLong(),\n      source.indexOf(\"c\".encodeUtf8(), Segment.SIZE.toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE + 1).toLong(),\n      source.indexOf(\"d\".encodeUtf8(), (Segment.SIZE - 2).toLong()),\n    )\n    assertEquals(\n      (Segment.SIZE + 1).toLong(),\n      source.indexOf(\"d\".encodeUtf8(), (Segment.SIZE + 1).toLong()),\n    )\n  }\n\n  @Test fun indexOfDoesNotWrapAround() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 1))\n    sink.writeUtf8(\"bcd\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"abcda\".encodeUtf8(), (Segment.SIZE - 3).toLong()))\n  }\n\n  @Test fun indexOfByteStringWithOffset() {\n    assertEquals(-1, source.indexOf(\"flop\".encodeUtf8(), 1))\n\n    sink.writeUtf8(\"flop flip flop\")\n    sink.emit()\n    assertEquals(10, source.indexOf(\"flop\".encodeUtf8(), 1))\n    source.readUtf8() // Clear stream\n\n    // Make sure we backtrack and resume searching after partial match.\n    sink.writeUtf8(\"hi hi hi hi hey\")\n    sink.emit()\n    assertEquals(6, source.indexOf(\"hi hi hey\".encodeUtf8(), 1))\n  }\n\n  @Test fun indexOfByteStringInvalidArgumentsThrows() {\n    var e = assertFailsWith<IllegalArgumentException> {\n      source.indexOf(ByteString.of())\n    }\n    assertEquals(\"byteCount == 0\", e.message)\n\n    e = assertFailsWith<IllegalArgumentException> {\n      source.indexOf(\"hi\".encodeUtf8(), -1)\n    }\n    assertEquals(\"fromIndex < 0: -1\", e.message)\n  }\n\n  /**\n   * With [BufferedSourceFactory.OneByteAtATimeSource], this code was extremely slow.\n   * https://github.com/square/okio/issues/171\n   */\n  @Test fun indexOfByteStringAcrossSegmentBoundaries() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE * 2 - 3))\n    sink.writeUtf8(\"bcdefg\")\n    sink.emit()\n    assertEquals((Segment.SIZE * 2 - 4).toLong(), source.indexOf(\"ab\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 4).toLong(), source.indexOf(\"abc\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 4).toLong(), source.indexOf(\"abcd\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 4).toLong(), source.indexOf(\"abcde\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 4).toLong(), source.indexOf(\"abcdef\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 4).toLong(), source.indexOf(\"abcdefg\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 3).toLong(), source.indexOf(\"bcdefg\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 2).toLong(), source.indexOf(\"cdefg\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 - 1).toLong(), source.indexOf(\"defg\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2).toLong(), source.indexOf(\"efg\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 + 1).toLong(), source.indexOf(\"fg\".encodeUtf8()))\n    assertEquals((Segment.SIZE * 2 + 2).toLong(), source.indexOf(\"g\".encodeUtf8()))\n  }\n\n  @Test fun indexOfElement() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(Segment.SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertEquals(0, source.indexOfElement(\"DEFGaHIJK\".encodeUtf8()))\n    assertEquals(1, source.indexOfElement(\"DEFGHIJKb\".encodeUtf8()))\n    assertEquals((Segment.SIZE + 1).toLong(), source.indexOfElement(\"cDEFGHIJK\".encodeUtf8()))\n    assertEquals(1, source.indexOfElement(\"DEFbGHIc\".encodeUtf8()))\n    assertEquals(-1L, source.indexOfElement(\"DEFGHIJK\".encodeUtf8()))\n    assertEquals(-1L, source.indexOfElement(\"\".encodeUtf8()))\n  }\n\n  @Test fun indexOfElementWithOffset() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(Segment.SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertEquals(-1, source.indexOfElement(\"DEFGaHIJK\".encodeUtf8(), 1))\n    assertEquals(15, source.indexOfElement(\"DEFGHIJKb\".encodeUtf8(), 15))\n  }\n\n  @Test fun indexOfByteWithFromIndex() {\n    sink.writeUtf8(\"aaa\")\n    sink.emit()\n    assertEquals(0, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('a'.code.toByte(), 0))\n    assertEquals(1, source.indexOf('a'.code.toByte(), 1))\n    assertEquals(2, source.indexOf('a'.code.toByte(), 2))\n  }\n\n  @Test fun indexOfByteStringWithFromIndex() {\n    sink.writeUtf8(\"aaa\")\n    sink.emit()\n    assertEquals(0, source.indexOf(\"a\".encodeUtf8()))\n    assertEquals(0, source.indexOf(\"a\".encodeUtf8(), 0))\n    assertEquals(1, source.indexOf(\"a\".encodeUtf8(), 1))\n    assertEquals(2, source.indexOf(\"a\".encodeUtf8(), 2))\n  }\n\n  @Test fun indexOfElementWithFromIndex() {\n    sink.writeUtf8(\"aaa\")\n    sink.emit()\n    assertEquals(0, source.indexOfElement(\"a\".encodeUtf8()))\n    assertEquals(0, source.indexOfElement(\"a\".encodeUtf8(), 0))\n    assertEquals(1, source.indexOfElement(\"a\".encodeUtf8(), 1))\n    assertEquals(2, source.indexOfElement(\"a\".encodeUtf8(), 2))\n  }\n\n  @Test fun request() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(Segment.SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertTrue(source.request((Segment.SIZE + 2).toLong()))\n    assertFalse(source.request((Segment.SIZE + 3).toLong()))\n  }\n\n  @Test fun require() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(Segment.SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    source.require((Segment.SIZE + 2).toLong())\n    assertFailsWith<EOFException> {\n      source.require((Segment.SIZE + 3).toLong())\n    }\n  }\n\n  @Test fun longHexString() {\n    assertLongHexString(\"8000000000000000\", Long.MIN_VALUE)\n    assertLongHexString(\"fffffffffffffffe\", -0x2L)\n    assertLongHexString(\"FFFFFFFFFFFFFFFe\", -0x2L)\n    assertLongHexString(\"ffffffffffffffff\", -0x1L)\n    assertLongHexString(\"FFFFFFFFFFFFFFFF\", -0x1L)\n    assertLongHexString(\"0000000000000000\", 0x0L)\n    assertLongHexString(\"0000000000000001\", 0x1L)\n    assertLongHexString(\"7999999999999999\", 0x7999999999999999L)\n\n    assertLongHexString(\"FF\", 0xFF)\n    assertLongHexString(\"0000000000000001\", 0x1)\n  }\n\n  @Test fun hexStringWithManyLeadingZeros() {\n    assertLongHexString(\"00000000000000001\", 0x1)\n    assertLongHexString(\"0000000000000000ffffffffffffffff\", -0x1L)\n    assertLongHexString(\"00000000000000007fffffffffffffff\", 0x7fffffffffffffffL)\n    assertLongHexString(\"0\".repeat(Segment.SIZE + 1) + \"1\", 0x1)\n  }\n\n  private fun assertLongHexString(s: String, expected: Long) {\n    sink.writeUtf8(s)\n    sink.emit()\n    val actual = source.readHexadecimalUnsignedLong()\n    assertEquals(expected, actual, \"$s --> $expected\")\n  }\n\n  @Test fun longHexStringAcrossSegment() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 8)).writeUtf8(\"FFFFFFFFFFFFFFFF\")\n    sink.emit()\n    source.skip((Segment.SIZE - 8).toLong())\n    assertEquals(-1, source.readHexadecimalUnsignedLong())\n  }\n\n  @Test fun longHexStringTooLongThrows() {\n    sink.writeUtf8(\"fffffffffffffffff\")\n    sink.emit()\n\n    val e = assertFailsWith<NumberFormatException> {\n      source.readHexadecimalUnsignedLong()\n    }\n    assertEquals(\"Number too large: fffffffffffffffff\", e.message)\n  }\n\n  @Test fun longHexStringTooShortThrows() {\n    sink.writeUtf8(\" \")\n    sink.emit()\n\n    val e = assertFailsWith<NumberFormatException> {\n      source.readHexadecimalUnsignedLong()\n    }\n    assertEquals(\"Expected leading [0-9a-fA-F] character but was 0x20\", e.message)\n  }\n\n  @Test fun longHexEmptySourceThrows() {\n    sink.writeUtf8(\"\")\n    sink.emit()\n    assertFailsWith<EOFException> { source.readHexadecimalUnsignedLong() }\n  }\n\n  @Test fun longDecimalString() {\n    assertLongDecimalString(\"-9223372036854775808\", Long.MIN_VALUE)\n    assertLongDecimalString(\"-1\", -1L)\n    assertLongDecimalString(\"0\", 0L)\n    assertLongDecimalString(\"1\", 1L)\n    assertLongDecimalString(\"9223372036854775807\", Long.MAX_VALUE)\n\n    assertLongDecimalString(\"00000001\", 1L)\n    assertLongDecimalString(\"-000001\", -1L)\n  }\n\n  private fun assertLongDecimalString(s: String, expected: Long) {\n    sink.writeUtf8(s)\n    sink.writeUtf8(\"zzz\")\n    sink.emit()\n    val actual = source.readDecimalLong()\n    assertEquals(expected, actual, \"$s --> $expected\")\n    assertEquals(\"zzz\", source.readUtf8())\n  }\n\n  @Test fun longDecimalStringAcrossSegment() {\n    sink.writeUtf8(\"a\".repeat(Segment.SIZE - 8)).writeUtf8(\"1234567890123456\")\n    sink.writeUtf8(\"zzz\")\n    sink.emit()\n    source.skip((Segment.SIZE - 8).toLong())\n    assertEquals(1234567890123456L, source.readDecimalLong())\n    assertEquals(\"zzz\", source.readUtf8())\n  }\n\n  @Test fun longDecimalStringTooLongThrows() {\n    sink.writeUtf8(\"12345678901234567890\") // Too many digits.\n    sink.emit()\n\n    val e = assertFailsWith<NumberFormatException> {\n      source.readDecimalLong()\n    }\n    assertEquals(\"Number too large: 12345678901234567890\", e.message)\n  }\n\n  @Test fun longDecimalStringTooHighThrows() {\n    sink.writeUtf8(\"9223372036854775808\") // Right size but cannot fit.\n    sink.emit()\n\n    val e = assertFailsWith<NumberFormatException> {\n      source.readDecimalLong()\n    }\n    assertEquals(\"Number too large: 9223372036854775808\", e.message)\n  }\n\n  @Test fun longDecimalStringTooLowThrows() {\n    sink.writeUtf8(\"-9223372036854775809\") // Right size but cannot fit.\n    sink.emit()\n\n    val e = assertFailsWith<NumberFormatException> {\n      source.readDecimalLong()\n    }\n    assertEquals(\"Number too large: -9223372036854775809\", e.message)\n  }\n\n  @Test fun longDecimalStringTooShortThrows() {\n    sink.writeUtf8(\" \")\n    sink.emit()\n\n    val e = assertFailsWith<NumberFormatException> {\n      source.readDecimalLong()\n    }\n    assertEquals(\"Expected a digit or '-' but was 0x20\", e.message)\n  }\n\n  @Test fun longDecimalEmptyThrows() {\n    sink.writeUtf8(\"\")\n    sink.emit()\n    assertFailsWith<EOFException> {\n      source.readDecimalLong()\n    }\n  }\n\n  @Test fun longDecimalLoneDashThrows() {\n    sink.writeUtf8(\"-\")\n    sink.emit()\n    assertFailsWith<EOFException> {\n      source.readDecimalLong()\n    }\n  }\n\n  @Test fun longDecimalDashFollowedByNonDigitThrows() {\n    sink.writeUtf8(\"- \")\n    sink.emit()\n    assertFailsWith<NumberFormatException> {\n      source.readDecimalLong()\n    }\n  }\n\n  @Test fun codePoints() {\n    sink.write(\"7f\".decodeHex())\n    sink.emit()\n    assertEquals(0x7f, source.readUtf8CodePoint().toLong())\n\n    sink.write(\"dfbf\".decodeHex())\n    sink.emit()\n    assertEquals(0x07ff, source.readUtf8CodePoint().toLong())\n\n    sink.write(\"efbfbf\".decodeHex())\n    sink.emit()\n    assertEquals(0xffff, source.readUtf8CodePoint().toLong())\n\n    sink.write(\"f48fbfbf\".decodeHex())\n    sink.emit()\n    assertEquals(0x10ffff, source.readUtf8CodePoint().toLong())\n  }\n\n  @Test fun decimalStringWithManyLeadingZeros() {\n    assertLongDecimalString(\"00000000000000001\", 1)\n    assertLongDecimalString(\"00000000000000009223372036854775807\", Long.MAX_VALUE)\n    assertLongDecimalString(\"-00000000000000009223372036854775808\", Long.MIN_VALUE)\n    assertLongDecimalString(\"0\".repeat(Segment.SIZE + 1) + \"1\", 1)\n  }\n\n  @Test fun select() {\n    val options = Options.of(\n      \"ROCK\".encodeUtf8(),\n      \"SCISSORS\".encodeUtf8(),\n      \"PAPER\".encodeUtf8(),\n    )\n\n    sink.writeUtf8(\"PAPER,SCISSORS,ROCK\")\n    sink.emit()\n    assertEquals(2, source.select(options).toLong())\n    assertEquals(','.code.toLong(), source.readByte().toLong())\n    assertEquals(1, source.select(options).toLong())\n    assertEquals(','.code.toLong(), source.readByte().toLong())\n    assertEquals(0, source.select(options).toLong())\n    assertTrue(source.exhausted())\n  }\n\n  /** Note that this test crashes the VM on Android. */\n  @Test fun selectSpanningMultipleSegments() {\n    if (factory.isOneByteAtATime && isBrowser()) {\n      return // This test times out on browsers.\n    }\n    val commonPrefix = randomBytes(Segment.SIZE + 10)\n    val a = Buffer().write(commonPrefix).writeUtf8(\"a\").readByteString()\n    val bc = Buffer().write(commonPrefix).writeUtf8(\"bc\").readByteString()\n    val bd = Buffer().write(commonPrefix).writeUtf8(\"bd\").readByteString()\n    val options = Options.of(a, bc, bd)\n\n    sink.write(bd)\n    sink.write(a)\n    sink.write(bc)\n    sink.emit()\n\n    assertEquals(2, source.select(options).toLong())\n    assertEquals(0, source.select(options).toLong())\n    assertEquals(1, source.select(options).toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test fun selectNotFound() {\n    val options = Options.of(\n      \"ROCK\".encodeUtf8(),\n      \"SCISSORS\".encodeUtf8(),\n      \"PAPER\".encodeUtf8(),\n    )\n\n    sink.writeUtf8(\"SPOCK\")\n    sink.emit()\n    assertEquals(-1, source.select(options).toLong())\n    assertEquals(\"SPOCK\", source.readUtf8())\n  }\n\n  @Test fun selectValuesHaveCommonPrefix() {\n    val options = Options.of(\n      \"abcd\".encodeUtf8(),\n      \"abce\".encodeUtf8(),\n      \"abcc\".encodeUtf8(),\n    )\n\n    sink.writeUtf8(\"abcc\").writeUtf8(\"abcd\").writeUtf8(\"abce\")\n    sink.emit()\n    assertEquals(2, source.select(options).toLong())\n    assertEquals(0, source.select(options).toLong())\n    assertEquals(1, source.select(options).toLong())\n  }\n\n  @Test fun selectLongerThanSource() {\n    val options = Options.of(\n      \"abcd\".encodeUtf8(),\n      \"abce\".encodeUtf8(),\n      \"abcc\".encodeUtf8(),\n    )\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    assertEquals(-1, source.select(options).toLong())\n    assertEquals(\"abc\", source.readUtf8())\n  }\n\n  @Test fun selectReturnsFirstByteStringThatMatches() {\n    val options = Options.of(\n      \"abcd\".encodeUtf8(),\n      \"abc\".encodeUtf8(),\n      \"abcde\".encodeUtf8(),\n    )\n    sink.writeUtf8(\"abcdef\")\n    sink.emit()\n    assertEquals(0, source.select(options).toLong())\n    assertEquals(\"ef\", source.readUtf8())\n  }\n\n  @Test fun selectFromEmptySource() {\n    val options = Options.of(\n      \"abc\".encodeUtf8(),\n      \"def\".encodeUtf8(),\n    )\n    assertEquals(-1, source.select(options).toLong())\n  }\n\n  @Test fun selectNoByteStringsFromEmptySource() {\n    val options = Options.of()\n    assertEquals(-1, source.select(options).toLong())\n  }\n\n  @Test fun peek() {\n    sink.writeUtf8(\"abcdefghi\")\n    sink.emit()\n\n    assertEquals(\"abc\", source.readUtf8(3))\n\n    val peek = source.peek()\n    assertEquals(\"def\", peek.readUtf8(3))\n    assertEquals(\"ghi\", peek.readUtf8(3))\n    assertFalse(peek.request(1))\n\n    assertEquals(\"def\", source.readUtf8(3))\n  }\n\n  @Test fun peekMultiple() {\n    sink.writeUtf8(\"abcdefghi\")\n    sink.emit()\n\n    assertEquals(\"abc\", source.readUtf8(3))\n\n    val peek1 = source.peek()\n    val peek2 = source.peek()\n\n    assertEquals(\"def\", peek1.readUtf8(3))\n\n    assertEquals(\"def\", peek2.readUtf8(3))\n    assertEquals(\"ghi\", peek2.readUtf8(3))\n    assertFalse(peek2.request(1))\n\n    assertEquals(\"ghi\", peek1.readUtf8(3))\n    assertFalse(peek1.request(1))\n\n    assertEquals(\"def\", source.readUtf8(3))\n  }\n\n  @Test fun peekLarge() {\n    if (factory.isOneByteAtATime) {\n      // When run on CI this causes out-of-memory errors.\n      return\n    }\n    sink.writeUtf8(\"abcdef\")\n    sink.writeUtf8(\"g\".repeat(2 * Segment.SIZE))\n    sink.writeUtf8(\"hij\")\n    sink.emit()\n\n    assertEquals(\"abc\", source.readUtf8(3))\n\n    val peek = source.peek()\n    assertEquals(\"def\", peek.readUtf8(3))\n    peek.skip((2 * Segment.SIZE).toLong())\n    assertEquals(\"hij\", peek.readUtf8(3))\n    assertFalse(peek.request(1))\n\n    assertEquals(\"def\", source.readUtf8(3))\n    source.skip((2 * Segment.SIZE).toLong())\n    assertEquals(\"hij\", source.readUtf8(3))\n  }\n\n  @Test fun peekInvalid() {\n    sink.writeUtf8(\"abcdefghi\")\n    sink.emit()\n\n    assertEquals(\"abc\", source.readUtf8(3))\n\n    val peek = source.peek()\n    assertEquals(\"def\", peek.readUtf8(3))\n    assertEquals(\"ghi\", peek.readUtf8(3))\n    assertFalse(peek.request(1))\n\n    assertEquals(\"def\", source.readUtf8(3))\n\n    val e = assertFailsWith<IllegalStateException> {\n      peek.readUtf8()\n    }\n    assertEquals(\"Peek source is invalid because upstream source was used\", e.message)\n  }\n\n  @Test fun peekSegmentThenInvalid() {\n    sink.writeUtf8(\"abc\")\n    sink.writeUtf8(\"d\".repeat(2 * Segment.SIZE))\n    sink.emit()\n\n    assertEquals(\"abc\", source.readUtf8(3))\n\n    // Peek a little data and skip the rest of the upstream source\n    val peek = source.peek()\n    assertEquals(\"ddd\", peek.readUtf8(3))\n    source.readAll(blackholeSink())\n\n    // Skip the rest of the buffered data\n    peek.skip(peek.buffer.size)\n\n    val e = assertFailsWith<IllegalStateException> {\n      peek.readByte()\n    }\n    assertEquals(\"Peek source is invalid because upstream source was used\", e.message)\n  }\n\n  @Test fun peekDoesntReadTooMuch() {\n    // 6 bytes in source's buffer plus 3 bytes upstream.\n    sink.writeUtf8(\"abcdef\")\n    sink.emit()\n    source.require(6L)\n    sink.writeUtf8(\"ghi\")\n    sink.emit()\n\n    val peek = source.peek()\n\n    // Read 3 bytes. This reads some of the buffered data.\n    assertTrue(peek.request(3))\n    if (source !is Buffer) {\n      assertEquals(6, source.buffer.size)\n      assertEquals(6, peek.buffer.size)\n    }\n    assertEquals(\"abc\", peek.readUtf8(3L))\n\n    // Read 3 more bytes. This exhausts the buffered data.\n    assertTrue(peek.request(3))\n    if (source !is Buffer) {\n      assertEquals(6, source.buffer.size)\n      assertEquals(3, peek.buffer.size)\n    }\n    assertEquals(\"def\", peek.readUtf8(3L))\n\n    // Read 3 more bytes. This draws new bytes.\n    assertTrue(peek.request(3))\n    assertEquals(9, source.buffer.size)\n    assertEquals(3, peek.buffer.size)\n    assertEquals(\"ghi\", peek.readUtf8(3L))\n  }\n\n  @Test fun rangeEquals() {\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertTrue(source.rangeEquals(7, \"a plan\".encodeUtf8()))\n    assertTrue(source.rangeEquals(0, \"A man\".encodeUtf8()))\n    assertTrue(source.rangeEquals(24, \"Panama\".encodeUtf8()))\n    assertFalse(source.rangeEquals(24, \"Panama. Panama. Panama.\".encodeUtf8()))\n  }\n\n  @Test fun rangeEqualsWithOffsetAndCount() {\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertTrue(source.rangeEquals(7, \"aaa plannn\".encodeUtf8(), 2, 6))\n    assertTrue(source.rangeEquals(0, \"AAA mannn\".encodeUtf8(), 2, 5))\n    assertTrue(source.rangeEquals(24, \"PPPanamaaa\".encodeUtf8(), 2, 6))\n  }\n\n  @Test fun rangeEqualsOnlyReadsUntilMismatch() {\n    if (factory !== BufferedSourceFactory.OneByteAtATimeSource) return // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertFalse(source.rangeEquals(0, (\"A man.\").encodeUtf8()))\n    assertEquals(\"A man,\", source.buffer.readUtf8())\n  }\n\n  @Test fun rangeEqualsArgumentValidation() {\n    // Negative source offset.\n    assertFalse(source.rangeEquals(-1, \"A\".encodeUtf8()))\n    // Negative bytes offset.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), -1, 1))\n    // Bytes offset longer than bytes length.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 2, 1))\n    // Negative byte count.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 0, -1))\n    // Byte count longer than bytes length.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 0, 2))\n    // Bytes offset plus byte count longer than bytes length.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 1, 1))\n  }\n\n  @Test fun factorySegmentSizes() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    source.require(3)\n    if (factory.isOneByteAtATime) {\n      assertEquals(listOf(1, 1, 1), segmentSizes(source.buffer))\n    } else {\n      assertEquals(listOf(3), segmentSizes(source.buffer))\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/CommonOkioKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass CommonOkioKotlinTest {\n  @Test fun sourceBuffer() {\n    val source = Buffer().writeUtf8(\"a\")\n    val buffered = (source as Source).buffer()\n    assertEquals(buffered.readUtf8(), \"a\")\n    assertEquals(source.size, 0L)\n  }\n\n  @Test fun sinkBuffer() {\n    val sink = Buffer()\n    val buffered = (sink as Sink).buffer()\n    buffered.writeUtf8(\"a\")\n    assertEquals(sink.size, 0L)\n    buffered.flush()\n    assertEquals(sink.size, 1L)\n  }\n\n  @Test fun blackhole() {\n    blackholeSink().write(Buffer().writeUtf8(\"a\"), 1L)\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/CommonOptionsTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.fail\nimport okio.ByteString.Companion.encodeUtf8\n\nclass CommonOptionsTest {\n  /** Confirm that options prefers the first-listed option, not the longest or shortest one. */\n  @Test fun optionOrderTakesPrecedence() {\n    assertSelect(\"abcdefg\", 0, \"abc\", \"abcdef\")\n    assertSelect(\"abcdefg\", 0, \"abcdef\", \"abc\")\n  }\n\n  @Test fun simpleOptionsTrie() {\n    assertEquals(\n      utf8Options(\"hotdog\", \"hoth\", \"hot\").trieString(),\n      \"\"\"\n      |hot\n      |   -> 2\n      |   d\n      |    og -> 0\n      |   h -> 1\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test fun realisticOptionsTrie() {\n    // These are the fields of OkHttpClient in 3.10.\n    val options = utf8Options(\n      \"dispatcher\",\n      \"proxy\",\n      \"protocols\",\n      \"connectionSpecs\",\n      \"interceptors\",\n      \"networkInterceptors\",\n      \"eventListenerFactory\",\n      \"proxySelector\", // No index 7 in the trie because 'proxy' is a prefix!\n      \"cookieJar\",\n      \"cache\",\n      \"internalCache\",\n      \"socketFactory\",\n      \"sslSocketFactory\",\n      \"certificateChainCleaner\",\n      \"hostnameVerifier\",\n      \"certificatePinner\",\n      \"proxyAuthenticator\", // No index 16 in the trie because 'proxy' is a prefix!\n      \"authenticator\",\n      \"connectionPool\",\n      \"dns\",\n      \"followSslRedirects\",\n      \"followRedirects\",\n      \"retryOnConnectionFailure\",\n      \"connectTimeout\",\n      \"readTimeout\",\n      \"writeTimeout\",\n      \"pingInterval\",\n    )\n    assertEquals(\n      options.trieString(),\n      \"\"\"\n      |a\n      | uthenticator -> 17\n      |c\n      | a\n      |  che -> 9\n      | e\n      |  rtificate\n      |           C\n      |            hainCleaner -> 13\n      |           P\n      |            inner -> 15\n      | o\n      |  n\n      |   nect\n      |       T\n      |        imeout -> 23\n      |       i\n      |        on\n      |          P\n      |           ool -> 18\n      |          S\n      |           pecs -> 3\n      |  o\n      |   kieJar -> 8\n      |d\n      | i\n      |  spatcher -> 0\n      | n\n      |  s -> 19\n      |e\n      | ventListenerFactory -> 6\n      |f\n      | ollow\n      |      R\n      |       edirects -> 21\n      |      S\n      |       slRedirects -> 20\n      |h\n      | ostnameVerifier -> 14\n      |i\n      | nter\n      |     c\n      |      eptors -> 4\n      |     n\n      |      alCache -> 10\n      |n\n      | etworkInterceptors -> 5\n      |p\n      | i\n      |  ngInterval -> 26\n      | r\n      |  o\n      |   t\n      |    ocols -> 2\n      |   x\n      |    y -> 1\n      |r\n      | e\n      |  a\n      |   dTimeout -> 24\n      |  t\n      |   ryOnConnectionFailure -> 22\n      |s\n      | o\n      |  cketFactory -> 11\n      | s\n      |  lSocketFactory -> 12\n      |w\n      | riteTimeout -> 25\n      |\n      \"\"\".trimMargin(),\n    )\n    assertSelect(\"\", -1, options)\n    assertSelect(\"a\", -1, options)\n    assertSelect(\"eventListenerFactor\", -1, options)\n    assertSelect(\"dnst\", 19, options)\n    assertSelect(\"proxyproxy\", 1, options)\n    assertSelect(\"prox\", -1, options)\n\n    assertSelect(\"dispatcher\", 0, options)\n    assertSelect(\"proxy\", 1, options)\n    assertSelect(\"protocols\", 2, options)\n    assertSelect(\"connectionSpecs\", 3, options)\n    assertSelect(\"interceptors\", 4, options)\n    assertSelect(\"networkInterceptors\", 5, options)\n    assertSelect(\"eventListenerFactory\", 6, options)\n    assertSelect(\"proxySelector\", 1, options) // 'proxy' is a prefix.\n    assertSelect(\"cookieJar\", 8, options)\n    assertSelect(\"cache\", 9, options)\n    assertSelect(\"internalCache\", 10, options)\n    assertSelect(\"socketFactory\", 11, options)\n    assertSelect(\"sslSocketFactory\", 12, options)\n    assertSelect(\"certificateChainCleaner\", 13, options)\n    assertSelect(\"hostnameVerifier\", 14, options)\n    assertSelect(\"certificatePinner\", 15, options)\n    assertSelect(\"proxyAuthenticator\", 1, options) // 'proxy' is a prefix.\n    assertSelect(\"authenticator\", 17, options)\n    assertSelect(\"connectionPool\", 18, options)\n    assertSelect(\"dns\", 19, options)\n    assertSelect(\"followSslRedirects\", 20, options)\n    assertSelect(\"followRedirects\", 21, options)\n    assertSelect(\"retryOnConnectionFailure\", 22, options)\n    assertSelect(\"connectTimeout\", 23, options)\n    assertSelect(\"readTimeout\", 24, options)\n    assertSelect(\"writeTimeout\", 25, options)\n    assertSelect(\"pingInterval\", 26, options)\n  }\n\n  @Test fun emptyOptions() {\n    val options = utf8Options()\n    assertSelect(\"\", -1, options)\n    assertSelect(\"a\", -1, options)\n    assertSelect(\"abc\", -1, options)\n  }\n\n  @Test fun emptyStringInOptionsTrie() {\n    assertFailsWith<IllegalArgumentException> {\n      utf8Options(\"\")\n    }\n    assertFailsWith<IllegalArgumentException> {\n      utf8Options(\"abc\", \"\")\n    }\n  }\n\n  @Test fun multipleIdenticalValues() {\n    try {\n      utf8Options(\"abc\", \"abc\")\n      fail()\n    } catch (expected: IllegalArgumentException) {\n      assertEquals(expected.message, \"duplicate option: [text=abc]\")\n    }\n  }\n\n  @Test fun prefixesAreStripped() {\n    val options = utf8Options(\"abcA\", \"abc\", \"abcB\")\n    assertEquals(\n      options.trieString(),\n      \"\"\"\n      |abc\n      |   -> 1\n      |   A -> 0\n      |\n      \"\"\".trimMargin(),\n    )\n    assertSelect(\"abc\", 1, options)\n    assertSelect(\"abcA\", 0, options)\n    assertSelect(\"abcB\", 1, options)\n    assertSelect(\"abcC\", 1, options)\n    assertSelect(\"ab\", -1, options)\n  }\n\n  @Test fun multiplePrefixesAreStripped() {\n    assertEquals(\n      utf8Options(\"a\", \"ab\", \"abc\", \"abcd\", \"abcde\").trieString(),\n      \"\"\"\n      |a -> 0\n      |\n      \"\"\".trimMargin(),\n    )\n    assertEquals(\n      utf8Options(\"abc\", \"a\", \"ab\", \"abe\", \"abcd\", \"abcf\").trieString(),\n      \"\"\"\n      |a\n      | -> 1\n      | bc -> 0\n      |\n      \"\"\".trimMargin(),\n    )\n    assertEquals(\n      utf8Options(\"abc\", \"ab\", \"a\").trieString(),\n      \"\"\"\n      |a\n      | -> 2\n      | b\n      |  -> 1\n      |  c -> 0\n      |\n      \"\"\".trimMargin(),\n    )\n    assertEquals(\n      utf8Options(\"abcd\", \"abce\", \"abc\", \"abcf\", \"abcg\").trieString(),\n      \"\"\"\n      |abc\n      |   -> 2\n      |   d -> 0\n      |   e -> 1\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test fun scan() {\n    val options = utf8Options(\"abc\")\n    assertSelect(\"abcde\", 0, options)\n  }\n\n  @Test fun scanReturnsPrefix() {\n    val options = utf8Options(\"abcdefg\", \"ab\")\n    assertSelect(\"ab\", 1, options)\n    assertSelect(\"abcd\", 1, options)\n    assertSelect(\"abcdefg\", 0, options)\n    assertSelect(\"abcdefghi\", 0, options)\n    assertSelect(\"abcdhi\", 1, options)\n  }\n\n  @Test fun select() {\n    val options = utf8Options(\"a\", \"b\", \"c\")\n    assertSelect(\"a\", 0, options)\n    assertSelect(\"b\", 1, options)\n    assertSelect(\"c\", 2, options)\n    assertSelect(\"d\", -1, options)\n    assertSelect(\"aa\", 0, options)\n    assertSelect(\"bb\", 1, options)\n    assertSelect(\"cc\", 2, options)\n    assertSelect(\"dd\", -1, options)\n  }\n\n  @Test fun selectSelect() {\n    val options = utf8Options(\"aa\", \"ab\", \"ba\", \"bb\")\n    assertSelect(\"a\", -1, options)\n    assertSelect(\"b\", -1, options)\n    assertSelect(\"c\", -1, options)\n    assertSelect(\"aa\", 0, options)\n    assertSelect(\"ab\", 1, options)\n    assertSelect(\"ac\", -1, options)\n    assertSelect(\"ba\", 2, options)\n    assertSelect(\"bb\", 3, options)\n    assertSelect(\"bc\", -1, options)\n    assertSelect(\"ca\", -1, options)\n    assertSelect(\"cb\", -1, options)\n    assertSelect(\"cc\", -1, options)\n  }\n\n  @Test fun selectScan() {\n    val options = utf8Options(\"abcd\", \"defg\")\n    assertSelect(\"a\", -1, options)\n    assertSelect(\"d\", -1, options)\n    assertSelect(\"h\", -1, options)\n    assertSelect(\"ab\", -1, options)\n    assertSelect(\"ae\", -1, options)\n    assertSelect(\"de\", -1, options)\n    assertSelect(\"db\", -1, options)\n    assertSelect(\"hi\", -1, options)\n    assertSelect(\"abcd\", 0, options)\n    assertSelect(\"aefg\", -1, options)\n    assertSelect(\"defg\", 1, options)\n    assertSelect(\"dbcd\", -1, options)\n    assertSelect(\"hijk\", -1, options)\n    assertSelect(\"abcdh\", 0, options)\n    assertSelect(\"defgh\", 1, options)\n    assertSelect(\"hijkl\", -1, options)\n  }\n\n  @Test fun scanSelect() {\n    val options = utf8Options(\"abcd\", \"abce\")\n    assertSelect(\"a\", -1, options)\n    assertSelect(\"f\", -1, options)\n    assertSelect(\"abc\", -1, options)\n    assertSelect(\"abf\", -1, options)\n    assertSelect(\"abcd\", 0, options)\n    assertSelect(\"abce\", 1, options)\n    assertSelect(\"abcf\", -1, options)\n    assertSelect(\"abcdf\", 0, options)\n    assertSelect(\"abcef\", 1, options)\n  }\n\n  @Test fun scanSpansSegments() {\n    val options = utf8Options(\"abcd\")\n    assertSelect(bufferWithSegments(\"a\", \"bcd\"), 0, options)\n    assertSelect(bufferWithSegments(\"a\", \"bcde\"), 0, options)\n    assertSelect(bufferWithSegments(\"ab\", \"cd\"), 0, options)\n    assertSelect(bufferWithSegments(\"ab\", \"cde\"), 0, options)\n    assertSelect(bufferWithSegments(\"abc\", \"d\"), 0, options)\n    assertSelect(bufferWithSegments(\"abc\", \"de\"), 0, options)\n    assertSelect(bufferWithSegments(\"abcd\", \"e\"), 0, options)\n    assertSelect(bufferWithSegments(\"a\", \"bce\"), -1, options)\n    assertSelect(bufferWithSegments(\"a\", \"bce\"), -1, options)\n    assertSelect(bufferWithSegments(\"ab\", \"ce\"), -1, options)\n    assertSelect(bufferWithSegments(\"ab\", \"ce\"), -1, options)\n    assertSelect(bufferWithSegments(\"abc\", \"e\"), -1, options)\n    assertSelect(bufferWithSegments(\"abc\", \"ef\"), -1, options)\n    assertSelect(bufferWithSegments(\"abce\", \"f\"), -1, options)\n  }\n\n  @Test fun selectSpansSegments() {\n    val options = utf8Options(\"aa\", \"ab\", \"ba\", \"bb\")\n    assertSelect(bufferWithSegments(\"a\", \"a\"), 0, options)\n    assertSelect(bufferWithSegments(\"a\", \"b\"), 1, options)\n    assertSelect(bufferWithSegments(\"a\", \"c\"), -1, options)\n    assertSelect(bufferWithSegments(\"b\", \"a\"), 2, options)\n    assertSelect(bufferWithSegments(\"b\", \"b\"), 3, options)\n    assertSelect(bufferWithSegments(\"b\", \"c\"), -1, options)\n    assertSelect(bufferWithSegments(\"c\", \"a\"), -1, options)\n    assertSelect(bufferWithSegments(\"c\", \"b\"), -1, options)\n    assertSelect(bufferWithSegments(\"c\", \"c\"), -1, options)\n    assertSelect(bufferWithSegments(\"a\", \"ad\"), 0, options)\n    assertSelect(bufferWithSegments(\"a\", \"bd\"), 1, options)\n    assertSelect(bufferWithSegments(\"a\", \"cd\"), -1, options)\n    assertSelect(bufferWithSegments(\"b\", \"ad\"), 2, options)\n    assertSelect(bufferWithSegments(\"b\", \"bd\"), 3, options)\n    assertSelect(bufferWithSegments(\"b\", \"cd\"), -1, options)\n    assertSelect(bufferWithSegments(\"c\", \"ad\"), -1, options)\n    assertSelect(bufferWithSegments(\"c\", \"bd\"), -1, options)\n    assertSelect(bufferWithSegments(\"c\", \"cd\"), -1, options)\n  }\n\n  private fun utf8Options(vararg options: String): Options {\n    return Options.of(*options.map { it.encodeUtf8() }.toTypedArray())\n  }\n\n  private fun assertSelect(data: String, expected: Int, options: Options) {\n    assertSelect(Buffer().writeUtf8(data), expected, options)\n  }\n\n  private fun assertSelect(data: String, expected: Int, vararg options: String) {\n    assertSelect(data, expected, utf8Options(*options))\n  }\n\n  private fun assertSelect(data: Buffer, expected: Int, options: Options) {\n    val initialSize = data.size\n    val actual = data.select(options)\n\n    assertEquals(actual, expected)\n    if (expected == -1) {\n      assertEquals(data.size, initialSize)\n    } else {\n      assertEquals(data.size + options[expected].size, initialSize)\n    }\n  }\n\n  private fun Options.trieString(): String {\n    val result = StringBuilder()\n    printTrieNode(result, 0)\n    return result.toString()\n  }\n\n  private fun Options.printTrieNode(out: StringBuilder, offset: Int = 0, indent: String = \"\") {\n    if (trie[offset + 1] != -1) {\n      // Print the prefix.\n      out.append(\"$indent-> ${trie[offset + 1]}\\n\")\n    }\n\n    if (trie[offset] > 0) {\n      // Print the select.\n      val selectChoiceCount = trie[offset]\n      for (i in 0 until selectChoiceCount) {\n        out.append(\"$indent${trie[offset + 2 + i].toChar()}\")\n        printTrieResult(out, trie[offset + 2 + selectChoiceCount + i], \"$indent \")\n      }\n    } else {\n      // Print the scan.\n      val scanByteCount = -1 * trie[offset]\n      out.append(indent)\n      for (i in 0 until scanByteCount) {\n        out.append(trie[offset + 2 + i].toChar())\n      }\n      printTrieResult(out, trie[offset + 2 + scanByteCount], \"$indent${\" \".repeat(scanByteCount)}\")\n    }\n  }\n\n  private fun Options.printTrieResult(out: StringBuilder, result: Int, indent: String) {\n    if (result >= 0) {\n      out.append(\" -> $result\\n\")\n    } else {\n      out.append(\"\\n\")\n      printTrieNode(out, -1 * result, indent)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/CommonRealBufferedSinkTest.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.fail\n\n/**\n * Tests solely for the behavior of RealBufferedSink's implementation. For generic\n * BufferedSink behavior use BufferedSinkTest.\n */\nclass CommonRealBufferedSinkTest {\n  @Test fun bufferedSinkEmitsTailWhenItIsComplete() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(Segment.SIZE - 1))\n    assertEquals(0, sink.size)\n    bufferedSink.writeByte(0)\n    assertEquals(Segment.SIZE.toLong(), sink.size)\n    assertEquals(0, bufferedSink.buffer.size)\n  }\n\n  @Test fun bufferedSinkEmitMultipleSegments() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(Segment.SIZE * 4 - 1))\n    assertEquals(Segment.SIZE.toLong() * 3L, sink.size)\n    assertEquals(Segment.SIZE.toLong() - 1L, bufferedSink.buffer.size)\n  }\n\n  @Test fun bufferedSinkFlush() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeByte('a'.code)\n    assertEquals(0, sink.size)\n    bufferedSink.flush()\n    assertEquals(0, bufferedSink.buffer.size)\n    assertEquals(1, sink.size)\n  }\n\n  @Test fun bytesEmittedToSinkWithFlush() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"abc\")\n    bufferedSink.flush()\n    assertEquals(3, sink.size)\n  }\n\n  @Test fun bytesNotEmittedToSinkWithoutFlush() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"abc\")\n    assertEquals(0, sink.size)\n  }\n\n  @Test fun bytesEmittedToSinkWithEmit() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"abc\")\n    bufferedSink.emit()\n    assertEquals(3, sink.size)\n  }\n\n  @Test fun completeSegmentsEmitted() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(Segment.SIZE * 3))\n    assertEquals(Segment.SIZE.toLong() * 3L, sink.size)\n  }\n\n  @Test fun incompleteSegmentsNotEmitted() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(Segment.SIZE * 3 - 1))\n    assertEquals(Segment.SIZE.toLong() * 2L, sink.size)\n  }\n\n  @Test fun closeWithExceptionWhenWriting() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(0, IOException(\"boom\"))\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    assertFailsWith<IOException> {\n      bufferedSink.close()\n    }\n\n    mockSink.assertLog(\"write([text=a], 1)\", \"close()\")\n  }\n\n  @Test fun closeWithExceptionWhenClosing() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(1, IOException(\"boom\"))\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    assertFailsWith<IOException> {\n      bufferedSink.close()\n    }\n\n    mockSink.assertLog(\"write([text=a], 1)\", \"close()\")\n  }\n\n  @Test fun closeWithExceptionWhenWritingAndClosing() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(0, IOException(\"first\"))\n    mockSink.scheduleThrow(1, IOException(\"second\"))\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    try {\n      bufferedSink.close()\n      fail()\n    } catch (expected: IOException) {\n      assertEquals(\"first\", expected.message)\n    }\n\n    mockSink.assertLog(\"write([text=a], 1)\", \"close()\")\n  }\n\n  @Test fun operationsAfterClose() {\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    bufferedSink.close()\n\n    // Test a sample set of methods.\n    assertFailsWith<IllegalStateException> {\n      bufferedSink.writeByte('a'.code)\n    }\n\n    assertFailsWith<IllegalStateException> {\n      bufferedSink.write(ByteArray(10))\n    }\n\n    assertFailsWith<IllegalStateException> {\n      bufferedSink.emitCompleteSegments()\n    }\n\n    assertFailsWith<IllegalStateException> {\n      bufferedSink.emit()\n    }\n\n    assertFailsWith<IllegalStateException> {\n      bufferedSink.flush()\n    }\n  }\n\n  @Test fun writeAll() {\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n\n    bufferedSink.buffer.writeUtf8(\"abc\")\n    assertEquals(3, bufferedSink.writeAll(Buffer().writeUtf8(\"def\")))\n\n    assertEquals(6, bufferedSink.buffer.size)\n    assertEquals(\"abcdef\", bufferedSink.buffer.readUtf8(6))\n    mockSink.assertLog() // No writes.\n  }\n\n  @Test fun writeAllExhausted() {\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n\n    assertEquals(0, bufferedSink.writeAll(Buffer()))\n    assertEquals(0, bufferedSink.buffer.size)\n    mockSink.assertLog() // No writes.\n  }\n\n  @Test fun writeAllWritesOneSegmentAtATime() {\n    val write1 = Buffer().writeUtf8(\"a\".repeat(Segment.SIZE))\n    val write2 = Buffer().writeUtf8(\"b\".repeat(Segment.SIZE))\n    val write3 = Buffer().writeUtf8(\"c\".repeat(Segment.SIZE))\n\n    val source = Buffer().writeUtf8(\n      \"${\"a\".repeat(Segment.SIZE)}${\"b\".repeat(Segment.SIZE)}${\"c\".repeat(Segment.SIZE)}\",\n    )\n\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n    assertEquals(Segment.SIZE.toLong() * 3L, bufferedSink.writeAll(source))\n\n    mockSink.assertLog(\n      \"write($write1, ${write1.size})\",\n      \"write($write2, ${write2.size})\",\n      \"write($write3, ${write3.size})\",\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/CommonRealBufferedSourceTest.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\n/**\n * Tests solely for the behavior of RealBufferedSource's implementation. For generic\n * BufferedSource behavior use BufferedSourceTest.\n */\nclass CommonRealBufferedSourceTest {\n  @Test fun indexOfStopsReadingAtLimit() {\n    val buffer = Buffer().writeUtf8(\"abcdef\")\n    val bufferedSource = (\n      object : Source by buffer {\n        override fun read(sink: Buffer, byteCount: Long): Long {\n          return buffer.read(sink, minOf(1, byteCount))\n        }\n      }\n      ).buffer()\n\n    assertEquals(6, buffer.size)\n    assertEquals(-1, bufferedSource.indexOf('e'.code.toByte(), 0, 4))\n    assertEquals(2, buffer.size)\n  }\n\n  @Test fun requireTracksBufferFirst() {\n    val source = Buffer()\n    source.writeUtf8(\"bb\")\n\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.buffer.writeUtf8(\"aa\")\n\n    bufferedSource.require(2)\n    assertEquals(2, bufferedSource.buffer.size)\n    assertEquals(2, source.size)\n  }\n\n  @Test fun requireIncludesBufferBytes() {\n    val source = Buffer()\n    source.writeUtf8(\"b\")\n\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.buffer.writeUtf8(\"a\")\n\n    bufferedSource.require(2)\n    assertEquals(\"ab\", bufferedSource.buffer.readUtf8(2))\n  }\n\n  @Test fun requireInsufficientData() {\n    val source = Buffer()\n    source.writeUtf8(\"a\")\n\n    val bufferedSource = (source as Source).buffer()\n\n    assertFailsWith<EOFException> {\n      bufferedSource.require(2)\n    }\n  }\n\n  @Test fun requireReadsOneSegmentAtATime() {\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(Segment.SIZE))\n    source.writeUtf8(\"b\".repeat(Segment.SIZE))\n\n    val bufferedSource = (source as Source).buffer()\n\n    bufferedSource.require(2)\n    assertEquals(Segment.SIZE.toLong(), source.size)\n    assertEquals(Segment.SIZE.toLong(), bufferedSource.buffer.size)\n  }\n\n  @Test fun skipReadsOneSegmentAtATime() {\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(Segment.SIZE))\n    source.writeUtf8(\"b\".repeat(Segment.SIZE))\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.skip(2)\n    assertEquals(Segment.SIZE.toLong(), source.size)\n    assertEquals(Segment.SIZE.toLong() - 2L, bufferedSource.buffer.size)\n  }\n\n  @Test fun skipTracksBufferFirst() {\n    val source = Buffer()\n    source.writeUtf8(\"bb\")\n\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.buffer.writeUtf8(\"aa\")\n\n    bufferedSource.skip(2)\n    assertEquals(0, bufferedSource.buffer.size)\n    assertEquals(2, source.size)\n  }\n\n  @Test fun operationsAfterClose() {\n    val source = Buffer()\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.close()\n\n    // Test a sample set of methods.\n    assertFailsWith<IllegalStateException> {\n      bufferedSource.indexOf(1.toByte())\n    }\n\n    assertFailsWith<IllegalStateException> {\n      bufferedSource.skip(1)\n    }\n\n    assertFailsWith<IllegalStateException> {\n      bufferedSource.readByte()\n    }\n\n    assertFailsWith<IllegalStateException> {\n      bufferedSource.readByteString(10)\n    }\n  }\n\n  /**\n   * We don't want readAll to buffer an unbounded amount of data. Instead it\n   * should buffer a segment, write it, and repeat.\n   */\n  @Test fun readAllReadsOneSegmentAtATime() {\n    val write1 = Buffer().writeUtf8(\"a\".repeat(Segment.SIZE))\n    val write2 = Buffer().writeUtf8(\"b\".repeat(Segment.SIZE))\n    val write3 = Buffer().writeUtf8(\"c\".repeat(Segment.SIZE))\n\n    val source = Buffer().writeUtf8(\n      \"${\"a\".repeat(Segment.SIZE)}${\"b\".repeat(Segment.SIZE)}${\"c\".repeat(Segment.SIZE)}\",\n    )\n\n    val mockSink = MockSink()\n    val bufferedSource = (source as Source).buffer()\n    assertEquals(Segment.SIZE.toLong() * 3L, bufferedSource.readAll(mockSink))\n    mockSink.assertLog(\n      \"write($write1, ${write1.size})\",\n      \"write($write2, ${write2.size})\",\n      \"write($write3, ${write3.size})\",\n    )\n  }\n\n  @Test fun readZeroBytesIntoBufferDoesNotRefillBuffer() {\n    val source = Buffer()\n    source.writeUtf8(\"abc\")\n\n    val sink = Buffer()\n\n    val bufferedSource = (source as Source).buffer()\n    assertEquals(0L, bufferedSource.read(sink, 0L))\n\n    assertEquals(0, sink.size)\n    assertEquals(0, bufferedSource.buffer.size)\n    assertEquals(3, source.size)\n  }\n\n  @Test fun readZeroBytesIntoByteArrayDoesNotRefillBuffer() {\n    val source = Buffer()\n    source.writeUtf8(\"abc\")\n\n    val sink = ByteArray(1024)\n\n    val bufferedSource = (source as Source).buffer()\n    assertEquals(0, bufferedSource.read(sink, 0, 0))\n\n    assertEquals(0, bufferedSource.buffer.size)\n    assertEquals(3, source.size)\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/ForwardingSourceTest.kt",
    "content": "/*\n * Copyright (C) 2022 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\nclass ForwardingSourceTest {\n  val source = Buffer().writeUtf8(\"Delegate\")\n\n  @Test\n  fun testForwardingSourceOverrides() {\n    val forwarder = \"Forwarder\"\n    val newSource = Buffer().writeUtf8(forwarder)\n    val forwardingSource = object : ForwardingSource(source) {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        return newSource.read(sink, byteCount)\n      }\n    }\n\n    assertEquals(\"Forwarder\", forwardingSource.buffer().readUtf8())\n  }\n\n  @Test\n  fun testForwardingSourceDelegates() {\n    val forwardingSource = object : ForwardingSource(source) {\n    }\n\n    assertEquals(\"Delegate\", forwardingSource.buffer().readUtf8())\n  }\n\n  @Test\n  fun testToString() {\n    val forwardingSource = object : ForwardingSource(source) {\n    }\n\n    assertTrue(forwardingSource.toString().endsWith(\"([text=Delegate])\"))\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/HashingSinkTest.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport okio.HashingSink.Companion.hmacSha1\nimport okio.HashingSink.Companion.hmacSha256\nimport okio.HashingSink.Companion.hmacSha512\nimport okio.HashingSink.Companion.sha1\nimport okio.HashingSink.Companion.sha256\nimport okio.HashingSink.Companion.sha512\n\nclass HashingSinkTest {\n  private val source = Buffer()\n  private val sink = Buffer()\n\n  @Test fun md5() {\n    val hashingSink: HashingSink = HashingSink.md5(sink)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.MD5_abc, hashingSink.hash)\n  }\n\n  @Test fun sha1() {\n    val hashingSink = sha1(sink)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.SHA1_abc, hashingSink.hash)\n  }\n\n  @Test fun sha256() {\n    val hashingSink = sha256(sink)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.SHA256_abc, hashingSink.hash)\n  }\n\n  @Test fun sha512() {\n    val hashingSink = sha512(sink)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.SHA512_abc, hashingSink.hash)\n  }\n\n  @Test fun hmacSha1() {\n    val hashingSink = hmacSha1(sink, HashingTest.HMAC_KEY)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.HMAC_SHA1_abc, hashingSink.hash)\n  }\n\n  @Test fun hmacSha256() {\n    val hashingSink = hmacSha256(sink, HashingTest.HMAC_KEY)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.HMAC_SHA256_abc, hashingSink.hash)\n  }\n\n  @Test fun hmacSha512() {\n    val hashingSink = hmacSha512(sink, HashingTest.HMAC_KEY)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.HMAC_SHA512_abc, hashingSink.hash)\n  }\n\n  @Test fun multipleWrites() {\n    val hashingSink = sha256(sink)\n    source.writeUtf8(\"a\")\n    hashingSink.write(source, 1L)\n    source.writeUtf8(\"b\")\n    hashingSink.write(source, 1L)\n    source.writeUtf8(\"c\")\n    hashingSink.write(source, 1L)\n    assertEquals(HashingTest.SHA256_abc, hashingSink.hash)\n  }\n\n  @Test fun multipleHashes() {\n    val hashingSink = sha256(sink)\n    source.writeUtf8(\"abc\")\n    hashingSink.write(source, 3L)\n    val hash_abc = hashingSink.hash\n    assertEquals(HashingTest.SHA256_abc, hash_abc)\n    source.writeUtf8(\"def\")\n    hashingSink.write(source, 3L)\n    assertEquals(HashingTest.SHA256_def, hashingSink.hash)\n    assertEquals(HashingTest.SHA256_abc, hash_abc)\n  }\n\n  @Test fun multipleSegments() {\n    val hashingSink = sha256(sink)\n    source.write(HashingTest.r32k)\n    hashingSink.write(source, HashingTest.r32k.size.toLong())\n    assertEquals(HashingTest.SHA256_r32k, hashingSink.hash)\n  }\n\n  @Test fun readFromPrefixOfBuffer() {\n    source.writeUtf8(\"z\")\n    source.write(HashingTest.r32k)\n    source.skip(1)\n    source.writeUtf8(\"z\".repeat(Segment.SIZE * 2 - 1))\n    val hashingSink = sha256(sink)\n    hashingSink.write(source, HashingTest.r32k.size.toLong())\n    assertEquals(HashingTest.SHA256_r32k, hashingSink.hash)\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/HashingSourceTest.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.fail\nimport okio.HashingSource.Companion.hmacSha1\nimport okio.HashingSource.Companion.hmacSha256\nimport okio.HashingSource.Companion.hmacSha512\nimport okio.HashingSource.Companion.md5\nimport okio.HashingSource.Companion.sha1\nimport okio.HashingSource.Companion.sha256\n\nclass HashingSourceTest {\n  private val source = Buffer()\n  private val sink = Buffer()\n\n  @Test fun md5() {\n    val hashingSource = md5(source)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.MD5_abc, hashingSource.hash)\n  }\n\n  @Test fun sha1() {\n    val hashingSource = sha1(source)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.SHA1_abc, hashingSource.hash)\n  }\n\n  @Test fun sha256() {\n    val hashingSource = sha256(source)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.SHA256_abc, hashingSource.hash)\n  }\n\n  @Test fun sha512() {\n    val hashingSource: HashingSource = HashingSource.sha512(source)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.SHA512_abc, hashingSource.hash)\n  }\n\n  @Test fun hmacSha1() {\n    val hashingSource = hmacSha1(source, HashingTest.HMAC_KEY)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.HMAC_SHA1_abc, hashingSource.hash)\n  }\n\n  @Test fun hmacSha256() {\n    val hashingSource = hmacSha256(source, HashingTest.HMAC_KEY)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.HMAC_SHA256_abc, hashingSource.hash)\n  }\n\n  @Test fun hmacSha512() {\n    val hashingSource = hmacSha512(source, HashingTest.HMAC_KEY)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.HMAC_SHA512_abc, hashingSource.hash)\n  }\n\n  @Test fun multipleReads() {\n    val hashingSource = sha256(source)\n    val bufferedSource = hashingSource.buffer()\n    source.writeUtf8(\"a\")\n    assertEquals('a'.code.toLong(), bufferedSource.readUtf8CodePoint().toLong())\n    source.writeUtf8(\"b\")\n    assertEquals('b'.code.toLong(), bufferedSource.readUtf8CodePoint().toLong())\n    source.writeUtf8(\"c\")\n    assertEquals('c'.code.toLong(), bufferedSource.readUtf8CodePoint().toLong())\n    assertEquals(HashingTest.SHA256_abc, hashingSource.hash)\n  }\n\n  @Test fun multipleHashes() {\n    val hashingSource = sha256(source)\n    source.writeUtf8(\"abc\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    val hash_abc = hashingSource.hash\n    assertEquals(HashingTest.SHA256_abc, hash_abc)\n    source.writeUtf8(\"def\")\n    assertEquals(3L, hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.SHA256_def, hashingSource.hash)\n    assertEquals(HashingTest.SHA256_abc, hash_abc)\n  }\n\n  @Test fun multipleSegments() {\n    val hashingSource = sha256(source)\n    val bufferedSource = hashingSource.buffer()\n    source.write(HashingTest.r32k)\n    assertEquals(HashingTest.r32k, bufferedSource.readByteString())\n    assertEquals(HashingTest.SHA256_r32k, hashingSource.hash)\n  }\n\n  @Test fun readIntoSuffixOfBuffer() {\n    val hashingSource = sha256(source)\n    source.write(HashingTest.r32k)\n    sink.writeUtf8(\"z\".repeat(Segment.SIZE * 2 - 1))\n    assertEquals(HashingTest.r32k.size.toLong(), hashingSource.read(sink, Long.MAX_VALUE))\n    assertEquals(HashingTest.SHA256_r32k, hashingSource.hash)\n  }\n\n  @Test fun hmacEmptyKey() {\n    try {\n      hmacSha256(source, ByteString.EMPTY)\n      fail()\n    } catch (expected: IllegalArgumentException) {\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/HashingTest.kt",
    "content": "/*\n * Copyright 2014 Square Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\n\nclass HashingTest {\n  @Test fun byteStringMd5() {\n    assertEquals(MD5_abc, \"abc\".encodeUtf8().md5())\n  }\n\n  @Test fun byteStringSha1() {\n    assertEquals(SHA1_abc, \"abc\".encodeUtf8().sha1())\n  }\n\n  @Test fun byteStringSha256() {\n    assertEquals(SHA256_abc, \"abc\".encodeUtf8().sha256())\n  }\n\n  @Test fun byteStringSha512() {\n    assertEquals(SHA512_abc, \"abc\".encodeUtf8().sha512())\n  }\n\n  @Test fun byteStringHmacSha1() {\n    assertEquals(HMAC_SHA1_abc, \"abc\".encodeUtf8().hmacSha1(HMAC_KEY))\n  }\n\n  @Test fun byteStringHmacSha256() {\n    assertEquals(HMAC_SHA256_abc, \"abc\".encodeUtf8().hmacSha256(HMAC_KEY))\n  }\n\n  @Test fun byteStringHmacSha512() {\n    assertEquals(HMAC_SHA512_abc, \"abc\".encodeUtf8().hmacSha512(HMAC_KEY))\n  }\n\n  @Test fun bufferMd5() {\n    assertEquals(MD5_abc, Buffer().writeUtf8(\"abc\").md5())\n  }\n\n  @Test fun bufferSha1() {\n    assertEquals(SHA1_abc, Buffer().writeUtf8(\"abc\").sha1())\n  }\n\n  @Test fun bufferSha256() {\n    assertEquals(SHA256_abc, Buffer().writeUtf8(\"abc\").sha256())\n  }\n\n  @Test fun bufferSha512() {\n    assertEquals(SHA512_abc, Buffer().writeUtf8(\"abc\").sha512())\n  }\n\n  @Test fun hashEmptySha256Buffer() {\n    assertEquals(SHA256_empty, Buffer().sha256())\n  }\n\n  @Test fun hashEmptySha512Buffer() {\n    assertEquals(SHA512_empty, Buffer().sha512())\n  }\n\n  @Test fun bufferHmacSha1() {\n    assertEquals(HMAC_SHA1_abc, Buffer().writeUtf8(\"abc\").hmacSha1(HMAC_KEY))\n  }\n\n  @Test fun bufferHmacSha256() {\n    assertEquals(HMAC_SHA256_abc, Buffer().writeUtf8(\"abc\").hmacSha256(HMAC_KEY))\n  }\n\n  @Test fun bufferHmacSha512() {\n    assertEquals(HMAC_SHA512_abc, Buffer().writeUtf8(\"abc\").hmacSha512(HMAC_KEY))\n  }\n\n  @Test fun hmacSha256EmptyBuffer() {\n    assertEquals(HMAC_SHA256_empty, Buffer().hmacSha256(HMAC_KEY))\n  }\n\n  @Test fun hmacSha512EmptyBuffer() {\n    assertEquals(HMAC_SHA512_empty, Buffer().hmacSha512(HMAC_KEY))\n  }\n\n  @Test fun bufferHashIsNotDestructive() {\n    val buffer = Buffer()\n\n    buffer.writeUtf8(\"abc\")\n    assertEquals(SHA256_abc, buffer.sha256())\n    assertEquals(\"abc\", buffer.readUtf8())\n\n    buffer.writeUtf8(\"def\")\n    assertEquals(SHA256_def, buffer.sha256())\n    assertEquals(\"def\", buffer.readUtf8())\n\n    buffer.write(r32k)\n    assertEquals(SHA256_r32k, buffer.sha256())\n    assertEquals(r32k, buffer.readByteString())\n  }\n\n  companion object {\n    val HMAC_KEY =\n      \"0102030405060708\".decodeHex()\n    val MD5_abc =\n      \"900150983cd24fb0d6963f7d28e17f72\".decodeHex()\n    val SHA1_abc =\n      \"a9993e364706816aba3e25717850c26c9cd0d89d\".decodeHex()\n    val HMAC_SHA1_abc =\n      \"987af8649982ff7d9fbb1b8aa35099146997af51\".decodeHex()\n    val SHA256_abc =\n      \"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad\".decodeHex()\n    val SHA256_empty =\n      \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\".decodeHex()\n    val SHA256_def =\n      \"cb8379ac2098aa165029e3938a51da0bcecfc008fd6795f401178647f96c5b34\".decodeHex()\n    val SHA256_r32k =\n      \"dadec7297f49bdf219895bd9942454047d394e1f20f247fbdc591080b4e8731e\".decodeHex()\n    val SHA512_abc =\n      \"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f\".decodeHex()\n    val SHA512_empty =\n      \"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e\".decodeHex()\n    val HMAC_SHA256_empty =\n      \"9eeecd4a51b7e5cbfcd63bfa89130944d314c20b5c79979b124143fea006452a\".decodeHex()\n    val HMAC_SHA256_abc =\n      \"446d1715583cf1c30dfffbec0df4ff1f9d39d493211ab4c97ed6f3f0eb579b47\".decodeHex()\n    val HMAC_SHA512_empty =\n      \"c0bd671885fa6f2eade99e9b81bbc74b8c6aa9ee9e58d7e5c356022d2f0c1cd7a0c75124b88a1a021e4323ce781846d246a379df78c3b955461d1688cc873335\".decodeHex()\n    val HMAC_SHA512_abc =\n      \"24391790e7131050b05b606f2079a8983313894a1642a5ed97d094e7cabd00cfaa857d92c1f320ca3b6aaabb84c7155d6f1b10940dc133ded1b40baee8900be6\".decodeHex()\n    val r32k = randomBytes(32768)\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/MockSink.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\n/** A scriptable sink. Like Mockito, but worse and requiring less configuration.  */\nclass MockSink : Sink {\n  private val log = mutableListOf<String>()\n  private val callThrows = mutableMapOf<Int, IOException>()\n\n  fun assertLog(vararg messages: String) {\n    assertEquals(messages.toList(), log)\n  }\n\n  fun assertLogContains(message: String) {\n    assertTrue(message in log)\n  }\n\n  fun scheduleThrow(call: Int, e: IOException) {\n    callThrows[call] = e\n  }\n\n  private fun throwIfScheduled() {\n    val exception = callThrows[log.size - 1]\n    if (exception != null) throw exception\n  }\n\n  override fun write(source: Buffer, byteCount: Long) {\n    log.add(\"write($source, $byteCount)\")\n    source.skip(byteCount)\n    throwIfScheduled()\n  }\n\n  override fun flush() {\n    log.add(\"flush()\")\n    throwIfScheduled()\n  }\n\n  override fun timeout(): Timeout {\n    log.add(\"timeout()\")\n    return Timeout.NONE\n  }\n\n  override fun close() {\n    log.add(\"close()\")\n    throwIfScheduled()\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/OkioTesting.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nimport kotlin.random.Random\nimport kotlin.test.assertTrue\n\nfun assertNoEmptySegments(buffer: Buffer) {\n  assertTrue(segmentSizes(buffer).all { it != 0 }, \"Expected all segments to be non-empty\")\n}\n\nfun segmentSizes(buffer: Buffer): List<Int> {\n  var segment = buffer.head ?: return emptyList()\n\n  val sizes = mutableListOf(segment.limit - segment.pos)\n  segment = segment.next!!\n  while (segment !== buffer.head) {\n    sizes.add(segment.limit - segment.pos)\n    segment = segment.next!!\n  }\n  return sizes\n}\n\nfun bufferWithRandomSegmentLayout(dice: Random, data: ByteArray): Buffer {\n  val result = Buffer()\n\n  // Writing to result directly will yield packed segments. Instead, write to\n  // other buffers, then write those buffers to result.\n  var pos = 0\n  var byteCount: Int\n  while (pos < data.size) {\n    byteCount = Segment.SIZE / 2 + dice.nextInt(Segment.SIZE / 2)\n    if (byteCount > data.size - pos) byteCount = data.size - pos\n    val offset = dice.nextInt(Segment.SIZE - byteCount)\n\n    val segment = Buffer()\n    segment.write(ByteArray(offset))\n    segment.write(data, pos, byteCount)\n    segment.skip(offset.toLong())\n\n    result.write(segment, byteCount.toLong())\n    pos += byteCount\n  }\n\n  return result\n}\n\nfun bufferWithSegments(vararg segments: String): Buffer {\n  val result = Buffer()\n  for (s in segments) {\n    val offsetInSegment = if (s.length < Segment.SIZE) (Segment.SIZE - s.length) / 2 else 0\n    val buffer = Buffer()\n    buffer.writeUtf8('_'.repeat(offsetInSegment))\n    buffer.writeUtf8(s)\n    buffer.skip(offsetInSegment.toLong())\n    result.write(buffer.copyTo(Buffer()), buffer.size)\n  }\n  return result\n}\n\nfun makeSegments(source: ByteString): ByteString {\n  val buffer = Buffer()\n  for (i in 0 until source.size) {\n    val segment = buffer.writableSegment(Segment.SIZE)\n    segment.data[segment.pos] = source[i]\n    segment.limit++\n    buffer.size++\n  }\n  return buffer.snapshot()\n}\n\n/**\n * Returns a string with all '\\' slashes replaced with '/' slashes. This is useful for test\n * assertions that intend to ignore slashes.\n */\nfun Path.withUnixSlashes(): String {\n  return toString().replace('\\\\', '/')\n}\n\nexpect fun assertRelativeTo(\n  a: Path,\n  b: Path,\n  bRelativeToA: Path,\n  sameAsNio: Boolean = true,\n)\n\nexpect fun assertRelativeToFails(\n  a: Path,\n  b: Path,\n  sameAsNio: Boolean = true,\n): IllegalArgumentException\n\nexpect fun <T> withUtc(block: () -> T): T\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/PathTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNotEquals\nimport kotlin.test.assertNull\nimport kotlin.test.assertTrue\nimport okio.Path.Companion.toPath\n\nclass PathTest {\n  @Test\n  fun unixRoot() {\n    val path = \"/\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(path, path.root)\n    assertEquals(listOf(), path.segments)\n    assertEquals(\"/\", path.toString())\n    assertNull(path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"\", path.name)\n    assertTrue(path.isAbsolute)\n    assertTrue(path.isRoot)\n  }\n\n  @Test\n  fun unixAbsolutePath() {\n    val path = \"/home/jesse/todo.txt\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"/\".toPath(), path.root)\n    assertEquals(listOf(\"home\", \"jesse\", \"todo.txt\"), path.segments)\n    assertEquals(\"/home/jesse/todo.txt\", path.toString())\n    assertEquals(\"/home/jesse\".toPath(), path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"todo.txt\", path.name)\n    assertTrue(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun unixRelativePath() {\n    val path = \"project/todo.txt\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\"project\", \"todo.txt\"), path.segments)\n    assertEquals(\"project/todo.txt\", path.toString())\n    assertEquals(\"project\".toPath(), path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"todo.txt\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun unixRelativePathWithDots() {\n    val path = \"../../project/todo.txt\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\"..\", \"..\", \"project\", \"todo.txt\"), path.segments)\n    assertEquals(\"../../project/todo.txt\", path.toString())\n    assertEquals(\"../../project\".toPath(), path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"todo.txt\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun unixRelativeSeriesOfDotDots() {\n    val path = \"../../..\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\"..\", \"..\", \"..\"), path.segments)\n    assertEquals(\"../../..\", path.toString())\n    assertNull(path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"..\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun unixAbsoluteSeriesOfDotDots() {\n    val path = \"/../../..\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"/\".toPath(), path.root)\n    assertEquals(listOf(), path.segments)\n    assertEquals(\"/\", path.toString())\n    assertNull(path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"\", path.name)\n    assertTrue(path.isAbsolute)\n    assertTrue(path.isRoot)\n  }\n\n  @Test\n  fun unixAbsoluteSingleDot() {\n    val path = \"/.\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"/\".toPath(), path.root)\n    assertEquals(listOf(), path.segments)\n    assertEquals(\"/\", path.toString())\n    assertNull(path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"\", path.name)\n    assertTrue(path.isAbsolute)\n    assertTrue(path.isRoot)\n  }\n\n  @Test\n  fun unixRelativeDoubleDots() {\n    val path = \"..\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\"..\"), path.segments)\n    assertEquals(\"..\", path.toString())\n    assertNull(path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"..\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun unixRelativeSingleDot() {\n    val path = \".\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\".\"), path.segments)\n    assertEquals(\".\", path.toString())\n    assertNull(path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\".\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun windowsVolumeLetter() {\n    val path = \"C:\\\\\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"C:\\\\\".toPath(), path.root)\n    assertEquals(listOf(), path.segments)\n    assertEquals(\"C:\\\\\", path.toString())\n    assertNull(path.parent)\n    assertEquals('C', path.volumeLetter)\n    assertEquals(\"\", path.name)\n    assertTrue(path.isAbsolute)\n    assertTrue(path.isRoot)\n  }\n\n  @Test\n  fun windowsAbsolutePathWithVolumeLetter() {\n    val path = \"C:\\\\Windows\\\\notepad.exe\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"C:\\\\\".toPath(), path.root)\n    assertEquals(listOf(\"Windows\", \"notepad.exe\"), path.segments)\n    assertEquals(\"C:\\\\Windows\\\\notepad.exe\", path.toString())\n    assertEquals(\"C:\\\\Windows\".toPath(), path.parent)\n    assertEquals('C', path.volumeLetter)\n    assertEquals(\"notepad.exe\", path.name)\n    assertTrue(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun windowsAbsolutePath() {\n    val path = \"\\\\\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"\\\\\".toPath(), path.root)\n    assertEquals(listOf(), path.segments)\n    assertEquals(\"\\\\\", path.toString())\n    assertEquals(null, path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"\", path.name)\n    assertTrue(path.isAbsolute)\n    assertTrue(path.isRoot)\n  }\n\n  @Test\n  fun windowsAbsolutePathWithoutVolumeLetter() {\n    val path = \"\\\\Windows\\\\notepad.exe\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"\\\\\".toPath(), path.root)\n    assertEquals(listOf(\"Windows\", \"notepad.exe\"), path.segments)\n    assertEquals(\"\\\\Windows\\\\notepad.exe\", path.toString())\n    assertEquals(\"\\\\Windows\".toPath(), path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"notepad.exe\", path.name)\n    assertTrue(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun windowsRelativePathWithVolumeLetter() {\n    val path = \"C:Windows\\\\notepad.exe\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\"C:Windows\", \"notepad.exe\"), path.segments)\n    assertEquals(\"C:Windows\\\\notepad.exe\", path.toString())\n    assertEquals(\"C:Windows\".toPath(), path.parent)\n    assertEquals('C', path.volumeLetter)\n    assertEquals(\"notepad.exe\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun windowsVolumeLetterRelative() {\n    val path = \"C:\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\"C:\"), path.segments)\n    assertEquals(\"C:\", path.toString())\n    assertNull(path.parent)\n    assertEquals('C', path.volumeLetter)\n    assertEquals(\"\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun windowsRelativePath() {\n    val path = \"Windows\\\\notepad.exe\".toPath()\n    assertEquals(path, path.normalized())\n    assertNull(path.root)\n    assertEquals(listOf(\"Windows\", \"notepad.exe\"), path.segments)\n    assertEquals(\"Windows\\\\notepad.exe\", path.toString())\n    assertEquals(\"Windows\".toPath(), path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"notepad.exe\", path.name)\n    assertFalse(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun windowsUncServer() {\n    val path = \"\\\\\\\\server\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"\\\\\\\\server\".toPath(), path.root)\n    assertEquals(listOf(), path.segments)\n    assertEquals(\"\\\\\\\\server\", path.toString())\n    assertNull(path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"server\", path.name)\n    assertTrue(path.isAbsolute)\n    assertTrue(path.isRoot)\n  }\n\n  @Test\n  fun windowsUncAbsolutePath() {\n    val path = \"\\\\\\\\server\\\\project\\\\notes.txt\".toPath()\n    assertEquals(path, path.normalized())\n    assertEquals(\"\\\\\\\\server\".toPath(), path.root)\n    assertEquals(listOf(\"project\", \"notes.txt\"), path.segments)\n    assertEquals(\"\\\\\\\\server\\\\project\\\\notes.txt\", path.toString())\n    assertEquals(\"\\\\\\\\server\\\\project\".toPath(), path.parent)\n    assertNull(path.volumeLetter)\n    assertEquals(\"notes.txt\", path.name)\n    assertTrue(path.isAbsolute)\n    assertFalse(path.isRoot)\n  }\n\n  @Test\n  fun absolutePathTraversalWithDivOperator() {\n    val root = \"/\".toPath()\n    assertEquals(\"/home\".toPath(), root / \"home\")\n    assertEquals(\"/home/jesse\".toPath(), root / \"home\" / \"jesse\")\n    assertEquals(\"/home/jesse/..\".toPath(), root / \"home\" / \"jesse\" / \"..\")\n    assertEquals(\"/home/jesse/../jake\".toPath(), root / \"home\" / \"jesse\" / \"..\" / \"jake\")\n  }\n\n  @Test\n  fun relativePathTraversalWithDivOperator() {\n    val slash = Path.DIRECTORY_SEPARATOR\n    val cwd = \".\".toPath()\n    assertEquals(\"home\".toPath(), cwd / \"home\")\n    assertEquals(\"home${slash}jesse\".toPath(), cwd / \"home\" / \"jesse\")\n    assertEquals(\"home${slash}jesse$slash..\".toPath(), cwd / \"home\" / \"jesse\" / \"..\")\n    assertEquals(\n      \"home${slash}jesse$slash..${slash}jake\".toPath(),\n      cwd / \"home\" / \"jesse\" / \"..\" / \"jake\",\n    )\n  }\n\n  @Test\n  fun relativePathTraversalWithDots() {\n    val slash = Path.DIRECTORY_SEPARATOR\n    val cwd = \".\".toPath()\n    assertEquals(\"..\".toPath(), cwd / \"..\")\n    assertEquals(\"..$slash..\".toPath(), cwd / \"..\" / \"..\")\n    assertEquals(\"..$slash..${slash}etc\".toPath(), cwd / \"..\" / \"..\" / \"etc\")\n    assertEquals(\n      \"..$slash..${slash}etc${slash}passwd\".toPath(),\n      cwd / \"..\" / \"..\" / \"etc\" / \"passwd\",\n    )\n  }\n\n  @Test\n  fun pathTraversalBaseIgnoredIfChildIsAnAbsolutePath() {\n    assertEquals(\"/home\".toPath(), \"\".toPath() / \"/home\")\n    assertEquals(\"/home\".toPath(), \"relative\".toPath() / \"/home\")\n    assertEquals(\"/home\".toPath(), \"/base\".toPath() / \"/home\")\n    assertEquals(\"/home\".toPath(), \"/\".toPath() / \"/home\")\n  }\n\n  @Test\n  fun stringToAbsolutePath() {\n    assertEquals(\"/\", \"/\".toPath().toString())\n    assertEquals(\"/a\", \"/a\".toPath().toString())\n    assertEquals(\"/a\", \"/a/\".toPath().toString())\n    assertEquals(\"/a/b/c\", \"/a/b/c\".toPath().toString())\n    assertEquals(\"/a/b/c\", \"/a/b/c/\".toPath().toString())\n    assertEquals(\"/\", \"/\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/a\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/a/\".toPath(normalize = true).toString())\n    assertEquals(\"/a/b/c\", \"/a/b/c\".toPath(normalize = true).toString())\n    assertEquals(\"/a/b/c\", \"/a/b/c/\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun stringToAbsolutePathWithTraversal() {\n    assertEquals(\"/\", \"/..\".toPath().toString())\n    assertEquals(\"/\", \"/../\".toPath().toString())\n    assertEquals(\"/\", \"/../..\".toPath().toString())\n    assertEquals(\"/\", \"/../../\".toPath().toString())\n    assertEquals(\"/\", \"/..\".toPath(normalize = true).toString())\n    assertEquals(\"/\", \"/../\".toPath(normalize = true).toString())\n    assertEquals(\"/\", \"/../..\".toPath(normalize = true).toString())\n    assertEquals(\"/\", \"/../../\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun stringToAbsolutePathWithEmptySegments() {\n    assertEquals(\"/\", \"//\".toPath().toString())\n    assertEquals(\"/a\", \"//a\".toPath().toString())\n    assertEquals(\"/a\", \"/a//\".toPath().toString())\n    assertEquals(\"/a\", \"//a//\".toPath().toString())\n    assertEquals(\"/a/b\", \"/a/b//\".toPath().toString())\n    assertEquals(\"/\", \"//\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"//a\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/a//\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"//a//\".toPath(normalize = true).toString())\n    assertEquals(\"/a/b\", \"/a/b//\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun stringToAbsolutePathWithDots() {\n    assertEquals(\"/\", \"/./\".toPath().toString())\n    assertEquals(\"/a\", \"/./a\".toPath().toString())\n    assertEquals(\"/a\", \"/a/./\".toPath().toString())\n    assertEquals(\"/a\", \"/a//.\".toPath().toString())\n    assertEquals(\"/a\", \"/./a//\".toPath().toString())\n    assertEquals(\"/a\", \"/a/.\".toPath().toString())\n    assertEquals(\"/a\", \"//a/./\".toPath().toString())\n    assertEquals(\"/a\", \"//a/./.\".toPath().toString())\n    assertEquals(\"/a/b\", \"/a/./b/\".toPath().toString())\n    assertEquals(\"/\", \"/./\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/./a\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/a/./\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/a//.\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/./a//\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"/a/.\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"//a/./\".toPath(normalize = true).toString())\n    assertEquals(\"/a\", \"//a/./.\".toPath(normalize = true).toString())\n    assertEquals(\"/a/b\", \"/a/./b/\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun stringToRelativePath() {\n    assertEquals(\".\", \"\".toPath().toString())\n    assertEquals(\".\", \".\".toPath().toString())\n    assertEquals(\"a\", \"a/\".toPath().toString())\n    assertEquals(\"a/b\", \"a/b\".toPath().toString())\n    assertEquals(\"a/b\", \"a/b/\".toPath().toString())\n    assertEquals(\"a/b/c/d\", \"a/b/c/d\".toPath().toString())\n    assertEquals(\"a/b/c/d\", \"a/b/c/d/\".toPath().toString())\n    assertEquals(\".\", \"\".toPath(normalize = true).toString())\n    assertEquals(\".\", \".\".toPath(normalize = true).toString())\n    assertEquals(\"a\", \"a/\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/b\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/b/\".toPath(normalize = true).toString())\n    assertEquals(\"a/b/c/d\", \"a/b/c/d\".toPath(normalize = true).toString())\n    assertEquals(\"a/b/c/d\", \"a/b/c/d/\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun stringToRelativePathWithTraversal() {\n    assertEquals(\"..\", \"..\".toPath().toString())\n    assertEquals(\"..\", \"../\".toPath().toString())\n    assertEquals(\"a/..\", \"a/..\".toPath().toString())\n    assertEquals(\"a/..\", \"a/../\".toPath().toString())\n    assertEquals(\"a/../..\", \"a/../..\".toPath().toString())\n    assertEquals(\"a/../..\", \"a/../../\".toPath().toString())\n    assertEquals(\"a/../../..\", \"a/../../..\".toPath().toString())\n    assertEquals(\"../../b\", \"../../b\".toPath().toString())\n    assertEquals(\"a/../../../b\", \"a/../../../b\".toPath().toString())\n    assertEquals(\"a/../../../b/../c\", \"a/../../../b/../c\".toPath().toString())\n    assertEquals(\"..\", \"..\".toPath(normalize = true).toString())\n    assertEquals(\"..\", \"../\".toPath(normalize = true).toString())\n    assertEquals(\".\", \"a/..\".toPath(normalize = true).toString())\n    assertEquals(\".\", \"a/../\".toPath(normalize = true).toString())\n    assertEquals(\"..\", \"a/../..\".toPath(normalize = true).toString())\n    assertEquals(\"..\", \"a/../../\".toPath(normalize = true).toString())\n    assertEquals(\"../..\", \"a/../../..\".toPath(normalize = true).toString())\n    assertEquals(\"../../b\", \"../../b\".toPath(normalize = true).toString())\n    assertEquals(\"../../b\", \"a/../../../b\".toPath(normalize = true).toString())\n    assertEquals(\"../../c\", \"a/../../../b/../c\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun stringToRelativePathWithEmptySegments() {\n    assertEquals(\"a\", \"a//\".toPath().toString())\n    assertEquals(\"a/b\", \"a//b\".toPath().toString())\n    assertEquals(\"a/b\", \"a/b//\".toPath().toString())\n    assertEquals(\"a/b\", \"a//b//\".toPath().toString())\n    assertEquals(\"a/b/c\", \"a/b/c//\".toPath().toString())\n    assertEquals(\"a\", \"a//\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a//b\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/b//\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a//b//\".toPath(normalize = true).toString())\n    assertEquals(\"a/b/c\", \"a/b/c//\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun stringToRelativePathWithDots() {\n    assertEquals(\".\", \".\".toPath().toString())\n    assertEquals(\".\", \"./\".toPath().toString())\n    assertEquals(\".\", \"././\".toPath().toString())\n    assertEquals(\"a/..\", \"././a/..\".toPath().toString())\n    assertEquals(\"a\", \"a/./\".toPath().toString())\n    assertEquals(\"a/b\", \"a/./b\".toPath().toString())\n    assertEquals(\"a/b\", \"a/b/./\".toPath().toString())\n    assertEquals(\"a/b\", \"a/b//.\".toPath().toString())\n    assertEquals(\"a/b\", \"a/./b//\".toPath().toString())\n    assertEquals(\"a/b\", \"a/b/.\".toPath().toString())\n    assertEquals(\"a/b\", \"a//b/./\".toPath().toString())\n    assertEquals(\"a/b\", \"a//b/./.\".toPath().toString())\n    assertEquals(\"a/b/c\", \"a/b/./c/\".toPath().toString())\n    assertEquals(\".\", \".\".toPath(normalize = true).toString())\n    assertEquals(\".\", \"./\".toPath(normalize = true).toString())\n    assertEquals(\".\", \"././\".toPath(normalize = true).toString())\n    assertEquals(\".\", \"././a/..\".toPath(normalize = true).toString())\n    assertEquals(\"a\", \"a/./\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/./b\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/b/./\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/b//.\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/./b//\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/b/.\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a//b/./\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a//b/./.\".toPath(normalize = true).toString())\n    assertEquals(\"a/b/c\", \"a/b/./c/\".toPath(normalize = true).toString())\n  }\n\n  @Test\n  fun composingWindowsPath() {\n    assertEquals(\"C:\\\\Windows\\\\notepad.exe\".toPath(), \"C:\\\\\".toPath() / \"Windows\" / \"notepad.exe\")\n  }\n\n  @Test\n  fun windowsResolveAbsolutePath() {\n    assertEquals(\"\\\\Users\".toPath(), \"C:\\\\Windows\".toPath() / \"\\\\Users\")\n  }\n\n  @Test\n  fun windowsPathTraversalUp() {\n    assertEquals(\"C:\\\\x\\\\y\\\\..\\\\..\\\\..\\\\z\".toPath(), \"C:\\\\x\\\\y\\\\..\\\\..\\\\..\\\\z\".toPath())\n    assertEquals(\"C:x\\\\y\\\\..\\\\..\\\\..\\\\z\".toPath(), \"C:x\\\\y\\\\..\\\\..\\\\..\\\\z\".toPath())\n    assertEquals(\"C:\\\\z\".toPath(), \"C:\\\\x\\\\y\\\\..\\\\..\\\\..\\\\z\".toPath(normalize = true))\n    assertEquals(\"C:..\\\\z\".toPath(), \"C:x\\\\y\\\\..\\\\..\\\\..\\\\z\".toPath(normalize = true))\n  }\n\n  @Test\n  fun samePathDifferentSlashesAreNotEqual() {\n    assertNotEquals(\"/a\".toPath(), \"\\\\b\".toPath())\n    assertNotEquals(\"a/b\".toPath(), \"a\\\\b\".toPath())\n  }\n\n  @Test\n  fun samePathNoSlashesAreEqual() {\n    assertEquals(\"a\".toPath().parent!!, \"a\".toPath().parent!!)\n    assertEquals(\"a/b\".toPath().parent!!, \"a\\\\b\".toPath().parent!!)\n  }\n\n  @Test\n  fun relativeToWindowsPaths() {\n    val a = \"C:\\\\Windows\\\\notepad.exe\".toPath()\n    val b = \"C:\\\\\".toPath()\n    assertRelativeTo(a, b, \"..\\\\..\".toPath(), sameAsNio = false)\n    assertRelativeTo(b, a, \"Windows\\\\notepad.exe\".toPath(), sameAsNio = false)\n\n    val c = \"C:\\\\Windows\\\\\".toPath()\n    val d = \"C:\\\\Windows\".toPath()\n    assertRelativeTo(c, d, \".\".toPath())\n    assertRelativeTo(d, c, \".\".toPath())\n\n    val e = \"C:\\\\Windows\\\\Downloads\\\\\".toPath()\n    val f = \"C:\\\\Windows\\\\Documents\\\\Hello.txt\".toPath()\n    assertRelativeTo(e, f, \"..\\\\Documents\\\\Hello.txt\".toPath(), sameAsNio = false)\n    assertRelativeTo(f, e, \"..\\\\..\\\\Downloads\".toPath(), sameAsNio = false)\n\n    val g = \"C:\\\\Windows\\\\\".toPath()\n    val h = \"D:\\\\Windows\\\\\".toPath()\n    assertRelativeToFails(g, h, sameAsNio = false)\n    assertRelativeToFails(h, g, sameAsNio = false)\n  }\n\n  @Test\n  fun relativeToWindowsUncPaths() {\n    val a = \"\\\\\\\\localhost\\\\c$\\\\development\\\\schema.proto\".toPath()\n    val b = \"\\\\\\\\localhost\\\\c$\\\\project\\\\notes.txt\".toPath()\n    assertRelativeTo(a, b, \"..\\\\..\\\\project\\\\notes.txt\".toPath(), sameAsNio = false)\n    assertRelativeTo(b, a, \"..\\\\..\\\\development\\\\schema.proto\".toPath(), sameAsNio = false)\n\n    val c = \"C:\\\\Windows\\\\\".toPath()\n    val d = \"\\\\\\\\localhost\\\\c$\\\\project\\\\notes.txt\".toPath()\n    assertRelativeToFails(c, d, sameAsNio = false)\n    assertRelativeToFails(d, c, sameAsNio = false)\n  }\n\n  @Test\n  fun absoluteUnixRoot() {\n    val a = \"/Users/jesse/hello.txt\".toPath()\n    val b = \"/\".toPath()\n    assertRelativeTo(a, b, \"../../..\".toPath())\n    assertRelativeTo(b, a, \"Users/jesse/hello.txt\".toPath())\n\n    val c = \"/Users/jesse/hello.txt\".toPath()\n    val d = \"/Admin/Secret\".toPath()\n    assertRelativeTo(c, d, \"../../../Admin/Secret\".toPath())\n    assertRelativeTo(d, c, \"../../Users/jesse/hello.txt\".toPath())\n\n    val e = \"/Users/\".toPath()\n    val f = \"/Users\".toPath()\n    assertRelativeTo(e, f, \".\".toPath())\n    assertRelativeTo(f, e, \".\".toPath())\n  }\n\n  @Test\n  fun relativeUnixDot() {\n    val a = \"Users/jesse/hello.txt\".toPath()\n    val b = \".\".toPath()\n    assertRelativeTo(a, b, \"../../..\".toPath(), sameAsNio = false)\n    assertRelativeTo(b, a, \"Users/jesse/hello.txt\".toPath(), sameAsNio = false)\n\n    val c = \"Users/./jesse/hello.txt\".toPath()\n    val d = \"Admin/Secret\".toPath()\n    assertRelativeTo(c, d, \"../../../Admin/Secret\".toPath())\n    assertRelativeTo(d, c, \"../../Users/jesse/hello.txt\".toPath())\n\n    val e = \"Users/\".toPath()\n    val f = \"Users/.\".toPath()\n    assertRelativeTo(e, f, \".\".toPath())\n    assertRelativeTo(f, e, \".\".toPath())\n  }\n\n  // Note that we handle the normalized version of the paths when computing relative paths.\n  @Test\n  fun relativeToUnnormalizedPath() {\n    val a = \"Users/../a\".toPath() // `a` if normalized.\n    val b = \"Users/b/../c\".toPath() // `Users/c` if normalized.\n    assertRelativeToFails(a, b, sameAsNio = false)\n    assertRelativeToFails(b, a, sameAsNio = false)\n    assertRelativeTo(a.normalized(), b.normalized(), \"../Users/c\".toPath())\n    assertRelativeTo(b.normalized(), a.normalized(), \"../../a\".toPath())\n  }\n\n  @Test\n  fun relativeToNormalizedPath() {\n    val a = \"Users/../a\".toPath(normalize = true) // results to `a`.\n    val b = \"Users/b/../c\".toPath(normalize = true) // results to `Users/c`.\n    assertRelativeTo(a, b, \"../Users/c\".toPath())\n    assertRelativeTo(b, a, \"../../a\".toPath())\n  }\n\n  @Test\n  fun absoluteToRelative() {\n    val a = \"/Users/jesse/hello.txt\".toPath()\n    val b = \"Desktop/goodbye.txt\".toPath()\n\n    var exception = assertRelativeToFails(a, b)\n    assertEquals(\n      \"Paths of different roots cannot be relative to each other: \" +\n        \"Desktop/goodbye.txt and /Users/jesse/hello.txt\",\n      exception.message,\n    )\n\n    exception = assertRelativeToFails(b, a)\n    assertEquals(\n      \"Paths of different roots cannot be relative to each other: \" +\n        \"/Users/jesse/hello.txt and Desktop/goodbye.txt\",\n      exception.message,\n    )\n  }\n\n  @Test\n  fun absoluteToAbsolute() {\n    val a = \"/Users/jesse/hello.txt\".toPath()\n    val b = \"/Users/benoit/Desktop/goodbye.txt\".toPath()\n    assertRelativeTo(a, b, \"../../benoit/Desktop/goodbye.txt\".toPath())\n    assertRelativeTo(b, a, \"../../../jesse/hello.txt\".toPath())\n  }\n\n  @Test\n  fun absoluteToSelf() {\n    val a = \"/Users/jesse/hello.txt\".toPath()\n    assertRelativeTo(a, a, \".\".toPath())\n\n    val b = \"/Users/benoit/../jesse/hello.txt\".toPath()\n    // NIO normalizes.\n    assertRelativeTo(a, b, \"../../benoit/../jesse/hello.txt\".toPath(), sameAsNio = false)\n    assertRelativeToFails(b, a, sameAsNio = false)\n    assertRelativeTo(b.normalized(), a, \".\".toPath())\n    assertRelativeTo(a, b.normalized(), \".\".toPath())\n  }\n\n  @Test\n  fun relativeToSelf() {\n    val a = \"Desktop/hello.txt\".toPath()\n    assertRelativeTo(a, a, \".\".toPath())\n\n    val b = \"Documents/../Desktop/hello.txt\".toPath()\n    // NIO normalizes.\n    assertRelativeTo(a, b, \"../../Documents/../Desktop/hello.txt\".toPath(), sameAsNio = false)\n    assertRelativeToFails(b, a, sameAsNio = false)\n    assertRelativeTo(a, b.normalized(), \".\".toPath())\n    assertRelativeTo(b.normalized(), a, \".\".toPath())\n  }\n\n  @Test\n  fun relativeToRelative() {\n    val a = \"Desktop/documents/resume.txt\".toPath()\n    val b = \"Desktop/documents/2021/taxes.txt\".toPath()\n    assertRelativeTo(a, b, \"../2021/taxes.txt\".toPath(), sameAsNio = false)\n    assertRelativeTo(b, a, \"../../resume.txt\".toPath(), sameAsNio = false)\n\n    val c = \"documents/resume.txt\".toPath()\n    val d = \"downloads/2021/taxes.txt\".toPath()\n    assertRelativeTo(c, d, \"../../downloads/2021/taxes.txt\".toPath(), sameAsNio = false)\n    assertRelativeTo(d, c, \"../../../documents/resume.txt\".toPath(), sameAsNio = false)\n  }\n\n  @Test\n  fun relativeToRelativeWithMiddleDots() {\n    val a = \"Desktop/documents/a...n\".toPath()\n    val b = \"Desktop/documents/m...z\".toPath()\n    assertRelativeTo(a, b, \"../m...z\".toPath())\n    assertRelativeTo(b, a, \"../a...n\".toPath())\n  }\n\n  @Test\n  fun relativeToRelativeWithMiddleDotsInCommonPrefix() {\n    val a = \"Desktop/documents/a...n/red\".toPath()\n    val b = \"Desktop/documents/a...m/blue\".toPath()\n    assertRelativeTo(a, b, \"../../a...m/blue\".toPath())\n    assertRelativeTo(b, a, \"../../a...n/red\".toPath())\n  }\n\n  @Test\n  fun relativeToRelativeWithUpNavigationPrefix() {\n    // We can't navigate from 'taxes' to 'resumes' because we don't know the name of 'Documents'.\n    //   /Users/jwilson/Documents/2021/Current\n    //   /Users/jwilson/Documents/resumes\n    //   /Users/jwilson/taxes\n    val a = \"../../resumes\".toPath()\n    val b = \"../../../taxes\".toPath()\n    assertRelativeTo(a, b, \"../../taxes\".toPath())\n    assertRelativeToFails(b, a, sameAsNio = false)\n  }\n\n  @Test\n  fun relativeToRelativeDifferentSlashes() {\n    val a = \"Desktop/documents/resume.txt\".toPath()\n    val b = \"Desktop\\\\documents\\\\2021\\\\taxes.txt\".toPath()\n    assertRelativeTo(a, b, \"../2021/taxes.txt\".toPath(), sameAsNio = false)\n    assertRelativeTo(b, a, \"..\\\\..\\\\resume.txt\".toPath(), sameAsNio = false)\n\n    val c = \"documents/resume.txt\".toPath()\n    val d = \"downloads\\\\2021\\\\taxes.txt\".toPath()\n    assertRelativeTo(c, d, \"../../downloads/2021/taxes.txt\".toPath(), sameAsNio = false)\n    assertRelativeTo(d, c, \"..\\\\..\\\\..\\\\documents\\\\resume.txt\".toPath(), sameAsNio = false)\n  }\n\n  @Test\n  fun windowsUncPathsDoNotDotDot() {\n    assertEquals(\n      \"\"\"\\\\localhost\\c$\\Windows\"\"\",\n      \"\"\"\\\\localhost\\c$\\Windows\"\"\".toPath().toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\"\"\",\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\"\"\".toPath().toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\\..\\Windows\"\"\",\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\\..\\Windows\"\"\".toPath().toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\..\\localhost\\c$\\Windows\"\"\",\n      \"\"\"\\\\127.0.0.1\\..\\localhost\\c$\\Windows\"\"\".toPath().toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\c$\\..\\d$\"\"\",\n      \"\"\"\\\\127.0.0.1\\c$\\..\\d$\"\"\".toPath().toString(),\n    )\n\n    assertEquals(\n      \"\"\"\\\\localhost\\c$\\Windows\"\"\",\n      \"\"\"\\\\localhost\\c$\\Windows\"\"\".toPath(normalize = true).toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\"\"\",\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\"\"\".toPath(normalize = true).toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\"\"\",\n      \"\"\"\\\\127.0.0.1\\c$\\Windows\\..\\Windows\"\"\".toPath(normalize = true).toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\localhost\\c$\\Windows\"\"\",\n      \"\"\"\\\\127.0.0.1\\..\\localhost\\c$\\Windows\"\"\".toPath(normalize = true).toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\d$\"\"\",\n      \"\"\"\\\\127.0.0.1\\c$\\..\\d$\"\"\".toPath(normalize = true).toString(),\n    )\n    assertEquals(\n      \"\"\"\\\\127.0.0.1\\c$\"\"\",\n      \"\"\"\\\\..\\127.0.0.1\\..\\c$\"\"\".toPath(normalize = true).toString(),\n    )\n  }\n\n  @Test fun normalizeAbsolute() {\n    assertEquals(\"/\", \"/.\".toPath(normalize = true).toString())\n    assertEquals(\"/\", \"/.\".toPath(normalize = false).toString())\n    assertEquals(\"/\", \"/..\".toPath(normalize = true).toString())\n    assertEquals(\"/\", \"/..\".toPath(normalize = false).toString())\n    assertEquals(\"/\", \"/../..\".toPath(normalize = true).toString())\n    assertEquals(\"/\", \"/../..\".toPath(normalize = false).toString())\n\n    assertEquals(\"/a/b\", \"/a/./b\".toPath(normalize = true).toString())\n    assertEquals(\"/a/b\", \"/a/./b\".toPath(normalize = false).toString())\n    assertEquals(\"/a/.../b\", \"/a/..././b\".toPath(normalize = true).toString())\n    assertEquals(\"/a/.../b\", \"/a/..././b\".toPath(normalize = false).toString())\n    assertEquals(\"/\", \"/a/..\".toPath(normalize = true).toString())\n    assertEquals(\"/a/..\", \"/a/..\".toPath(normalize = false).toString())\n    assertEquals(\"/b\", \"/../a/../b\".toPath(normalize = true).toString())\n    assertEquals(\"/a/../b\", \"/../a/../b\".toPath(normalize = false).toString())\n  }\n\n  @Test fun normalizeRelative() {\n    assertEquals(\".\", \".\".toPath(normalize = true).toString())\n    assertEquals(\".\", \".\".toPath(normalize = false).toString())\n    assertEquals(\"..\", \"..\".toPath(normalize = true).toString())\n    assertEquals(\"..\", \"..\".toPath(normalize = false).toString())\n    assertEquals(\"../..\", \"../..\".toPath(normalize = true).toString())\n    assertEquals(\"../..\", \"../..\".toPath(normalize = false).toString())\n\n    assertEquals(\"a/b\", \"a/./b\".toPath(normalize = true).toString())\n    assertEquals(\"a/b\", \"a/./b\".toPath(normalize = false).toString())\n    assertEquals(\"a/.../b\", \"a/..././b\".toPath(normalize = true).toString())\n    assertEquals(\"a/.../b\", \"a/..././b\".toPath(normalize = false).toString())\n    assertEquals(\".\", \"a/..\".toPath(normalize = true).toString())\n    assertEquals(\"a/..\", \"a/..\".toPath(normalize = false).toString())\n    assertEquals(\"../b\", \"../a/../b\".toPath(normalize = true).toString())\n    assertEquals(\"../a/../b\", \"../a/../b\".toPath(normalize = false).toString())\n  }\n\n  @Test fun normalized() {\n    val normalizedRoot = \"/\".toPath()\n    assertEquals(normalizedRoot, \"/a/..\".toPath(normalize = true))\n    assertEquals(normalizedRoot, \"/a/..\".toPath(normalize = false).normalized())\n    assertEquals(normalizedRoot, \"/a/..\".toPath(normalize = true).normalized())\n\n    val normalizedRelative = \"../b\".toPath()\n    assertEquals(normalizedRelative, \"../a/../b\".toPath(normalize = true))\n    assertEquals(normalizedRelative, \"../a/../b\".toPath(normalize = false).normalized())\n    assertEquals(normalizedRelative, \"../a/../b\".toPath(normalize = true).normalized())\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/TypedOptionsTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport okio.ByteString.Companion.encodeUtf8\n\nclass TypedOptionsTest {\n  @Test\n  fun happyPath() {\n    val colors = listOf(\"Red\", \"Green\", \"Blue\")\n    val colorOptions = TypedOptions.of(colors) { it.lowercase().encodeUtf8() }\n    val buffer = Buffer().writeUtf8(\"bluegreenyellow\")\n    assertEquals(\"Blue\", buffer.select(colorOptions))\n    assertEquals(\"greenyellow\", buffer.snapshot().utf8())\n    assertEquals(\"Green\", buffer.select(colorOptions))\n    assertEquals(\"yellow\", buffer.snapshot().utf8())\n    assertEquals(null, buffer.select(colorOptions))\n    assertEquals(\"yellow\", buffer.snapshot().utf8())\n  }\n\n  @Test\n  fun typedOptionsConstructor() {\n    val colors = listOf(\"Red\", \"Green\", \"Blue\")\n    val colorOptions = TypedOptions(\n      colors,\n      Options.of(\"red\".encodeUtf8(), \"green\".encodeUtf8(), \"blue\".encodeUtf8()),\n    )\n    val buffer = Buffer().writeUtf8(\"bluegreenyellow\")\n    assertEquals(\"Blue\", buffer.select(colorOptions))\n    assertEquals(\"greenyellow\", buffer.snapshot().utf8())\n    assertEquals(\"Green\", buffer.select(colorOptions))\n    assertEquals(\"yellow\", buffer.snapshot().utf8())\n    assertEquals(null, buffer.select(colorOptions))\n    assertEquals(\"yellow\", buffer.snapshot().utf8())\n  }\n\n  @Test\n  fun typedOptionsConstructorEnforcesSizeMatch() {\n    val colors = listOf(\"Red\", \"Green\", \"Blue\")\n    assertFailsWith<IllegalArgumentException> {\n      TypedOptions(\n        colors,\n        Options.of(\"red\".encodeUtf8(), \"green\".encodeUtf8()),\n      )\n    }\n  }\n\n  @Test\n  fun listFunctionsWork() {\n    val colors = listOf(\"Red\", \"Green\", \"Blue\")\n    val colorOptions = TypedOptions.of(colors) { it.lowercase().encodeUtf8() }\n    assertEquals(3, colorOptions.size)\n    assertEquals(\"Red\", colorOptions[0])\n    assertEquals(\"Green\", colorOptions[1])\n    assertEquals(\"Blue\", colorOptions[2])\n    assertFailsWith<IndexOutOfBoundsException> {\n      colorOptions[3]\n    }\n  }\n\n  /**\n   * Confirm we can mutate the collection used to create our [TypedOptions] without corrupting its\n   * behavior.\n   */\n  @Test\n  fun safeToMutateSourceCollectionAfterConstruction() {\n    val colors = mutableListOf(\"Red\", \"Green\")\n    val colorOptions = TypedOptions.of(colors) { it.lowercase().encodeUtf8() }\n    colors[0] = \"Black\"\n\n    val buffer = Buffer().writeUtf8(\"red\")\n    assertEquals(\"Red\", buffer.select(colorOptions))\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/UnsafeCursorTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\nclass UnsafeCursorTest {\n  @Test fun acquireForRead() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"xo\".repeat(5000))\n\n    val cursor = buffer.readAndWriteUnsafe()\n    try {\n      val copy = Buffer()\n      while (cursor.next() != -1) {\n        copy.write(cursor.data!!, cursor.start, cursor.end - cursor.start)\n      }\n    } finally {\n      cursor.close()\n    }\n\n    assertEquals(\"xo\".repeat(5000), buffer.readUtf8())\n  }\n\n  @Test fun acquireForWrite() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"xo\".repeat(5000))\n\n    val cursor = buffer.readAndWriteUnsafe()\n    try {\n      while (cursor.next() != -1) {\n        cursor.data!!.fill('z'.code.toByte(), cursor.start, cursor.end)\n      }\n    } finally {\n      cursor.close()\n    }\n\n    assertEquals(\"zz\".repeat(5000), buffer.readUtf8())\n  }\n\n  @Test fun expand() {\n    val buffer = Buffer()\n\n    val cursor = buffer.readAndWriteUnsafe()\n    try {\n      cursor.expandBuffer(100)\n      cursor.data!!.fill('z'.code.toByte(), cursor.start, cursor.start + 100)\n      cursor.resizeBuffer(100L)\n    } finally {\n      cursor.close()\n    }\n\n    val expected = \"z\".repeat(100)\n    val actual = buffer.readUtf8()\n    println(actual)\n    println(expected)\n    assertEquals(expected, actual)\n  }\n\n  @Test fun resizeBuffer() {\n    val buffer = Buffer()\n\n    val cursor = buffer.readAndWriteUnsafe()\n    try {\n      cursor.resizeBuffer(100L)\n      cursor.data!!.fill('z'.code.toByte(), cursor.start, cursor.end)\n    } finally {\n      cursor.close()\n    }\n\n    assertEquals(\"z\".repeat(100), buffer.readUtf8())\n  }\n\n  @Test fun testUnsafeCursorIsClosable() {\n    assertTrue(Closeable::class.isInstance(Buffer.UnsafeCursor()))\n  }\n}\n"
  },
  {
    "path": "okio/src/commonTest/kotlin/okio/Utf8KotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport okio.ByteString.Companion.decodeHex\nimport okio.internal.commonAsUtf8ToByteArray\n\nclass Utf8KotlinTest {\n  @Test fun oneByteCharacters() {\n    assertEncoded(\"00\", 0x00) // Smallest 1-byte character.\n    assertEncoded(\"20\", ' '.code)\n    assertEncoded(\"7e\", '~'.code)\n    assertEncoded(\"7f\", 0x7f) // Largest 1-byte character.\n  }\n\n  @Test fun twoByteCharacters() {\n    assertEncoded(\"c280\", 0x0080) // Smallest 2-byte character.\n    assertEncoded(\"c3bf\", 0x00ff)\n    assertEncoded(\"c480\", 0x0100)\n    assertEncoded(\"dfbf\", 0x07ff) // Largest 2-byte character.\n  }\n\n  @Test fun threeByteCharacters() {\n    assertEncoded(\"e0a080\", 0x0800) // Smallest 3-byte character.\n    assertEncoded(\"e0bfbf\", 0x0fff)\n    assertEncoded(\"e18080\", 0x1000)\n    assertEncoded(\"e1bfbf\", 0x1fff)\n    assertEncoded(\"ed8080\", 0xd000)\n    assertEncoded(\"ed9fbf\", 0xd7ff) // Largest character lower than the min surrogate.\n    assertEncoded(\"ee8080\", 0xe000) // Smallest character greater than the max surrogate.\n    assertEncoded(\"eebfbf\", 0xefff)\n    assertEncoded(\"ef8080\", 0xf000)\n    assertEncoded(\"efbfbf\", 0xffff) // Largest 3-byte character.\n  }\n\n  @Test fun fourByteCharacters() {\n    assertEncoded(\"f0908080\", 0x010000) // Smallest surrogate pair.\n    assertEncoded(\"f48fbfbf\", 0x10ffff) // Largest code point expressible by UTF-16.\n  }\n\n  @Test fun unknownBytes() {\n    assertCodePointDecoded(\"f8\", REPLACEMENT_CODE_POINT) // Too large\n    assertCodePointDecoded(\"f0f8\", REPLACEMENT_CODE_POINT, REPLACEMENT_CODE_POINT)\n    assertCodePointDecoded(\"ff\", REPLACEMENT_CODE_POINT) // Largest\n    assertCodePointDecoded(\"f0ff\", REPLACEMENT_CODE_POINT, REPLACEMENT_CODE_POINT)\n\n    // Lone continuation\n    assertCodePointDecoded(\"80\", REPLACEMENT_CODE_POINT) // Smallest\n    assertCodePointDecoded(\"bf\", REPLACEMENT_CODE_POINT) // Largest\n  }\n\n  @Test fun overlongSequences() {\n    // Overlong representation of the NUL character\n    assertCodePointDecoded(\"c080\", REPLACEMENT_CODE_POINT)\n    assertCodePointDecoded(\"e08080\", REPLACEMENT_CODE_POINT)\n    assertCodePointDecoded(\"f0808080\", REPLACEMENT_CODE_POINT)\n\n    // Maximum overlong sequences\n    assertCodePointDecoded(\"c1bf\", REPLACEMENT_CODE_POINT)\n    assertCodePointDecoded(\"e09fbf\", REPLACEMENT_CODE_POINT)\n    assertCodePointDecoded(\"f08fbfbf\", REPLACEMENT_CODE_POINT)\n  }\n\n  @Test fun danglingHighSurrogate() {\n    assertStringEncoded(\"3f\", \"\\ud800\") // \"?\"\n    assertCodePointDecoded(\"eda080\", REPLACEMENT_CODE_POINT)\n  }\n\n  @Test fun lowSurrogateWithoutHighSurrogate() {\n    assertStringEncoded(\"3f\", \"\\udc00\") // \"?\"\n    assertCodePointDecoded(\"edb080\", REPLACEMENT_CODE_POINT)\n  }\n\n  @Test fun highSurrogateFollowedByNonSurrogate() {\n    assertStringEncoded(\"3fee8080\", \"\\ud800\\ue000\") // \"?\\ue000\": Following character is too high.\n    assertCodePointDecoded(\"f090ee8080\", REPLACEMENT_CODE_POINT, '\\ue000'.code)\n\n    assertStringEncoded(\"3f61\", \"\\ud800\\u0061\") // \"?a\": Following character is too low.\n    assertCodePointDecoded(\"f09061\", REPLACEMENT_CODE_POINT, 'a'.code)\n  }\n\n  @Test fun doubleLowSurrogate() {\n    assertStringEncoded(\"3f3f\", \"\\udc00\\udc00\") // \"??\"\n    assertCodePointDecoded(\"edb080edb080\", REPLACEMENT_CODE_POINT, REPLACEMENT_CODE_POINT)\n  }\n\n  @Test fun doubleHighSurrogate() {\n    assertStringEncoded(\"3f3f\", \"\\ud800\\ud800\") // \"??\"\n    assertCodePointDecoded(\"eda080eda080\", REPLACEMENT_CODE_POINT, REPLACEMENT_CODE_POINT)\n  }\n\n  @Test fun lowSurrogateHighSurrogate() {\n    assertStringEncoded(\"3f3f\", \"\\udc00\\ud800\") // \"??\"\n    assertCodePointDecoded(\"edb080eda080\", REPLACEMENT_CODE_POINT, REPLACEMENT_CODE_POINT)\n  }\n\n  @Test fun writeSurrogateCodePoint() {\n    assertStringEncoded(\"ed9fbf\", \"\\ud7ff\") // Below lowest surrogate is okay.\n    assertCodePointDecoded(\"ed9fbf\", '\\ud7ff'.code)\n\n    assertStringEncoded(\"3f\", \"\\ud800\") // Lowest surrogate gets '?'.\n    assertCodePointDecoded(\"eda080\", REPLACEMENT_CODE_POINT)\n\n    assertStringEncoded(\"3f\", \"\\udfff\") // Highest surrogate gets '?'.\n    assertCodePointDecoded(\"edbfbf\", REPLACEMENT_CODE_POINT)\n\n    assertStringEncoded(\"ee8080\", \"\\ue000\") // Above highest surrogate is okay.\n    assertCodePointDecoded(\"ee8080\", '\\ue000'.code)\n  }\n\n  @Test fun size() {\n    assertEquals(0, \"\".utf8Size())\n    assertEquals(3, \"abc\".utf8Size())\n    assertEquals(16, \"təˈranəˌsôr\".utf8Size())\n  }\n\n  @Test fun sizeWithBounds() {\n    assertEquals(0, \"\".utf8Size(0, 0))\n    assertEquals(0, \"abc\".utf8Size(0, 0))\n    assertEquals(1, \"abc\".utf8Size(1, 2))\n    assertEquals(2, \"abc\".utf8Size(0, 2))\n    assertEquals(3, \"abc\".utf8Size(0, 3))\n    assertEquals(16, \"təˈranəˌsôr\".utf8Size(0, 11))\n    assertEquals(5, \"təˈranəˌsôr\".utf8Size(3, 7))\n  }\n\n  @Test fun sizeBoundsCheck() {\n    assertFailsWith<IllegalArgumentException> {\n      \"abc\".utf8Size(-1, 2)\n    }\n\n    assertFailsWith<IllegalArgumentException> {\n      \"abc\".utf8Size(2, 1)\n    }\n\n    assertFailsWith<IllegalArgumentException> {\n      \"abc\".utf8Size(1, 4)\n    }\n  }\n\n  private fun assertEncoded(hex: String, vararg codePoints: Int) {\n    assertCodePointDecoded(hex, *codePoints)\n  }\n\n  private fun assertCodePointDecoded(hex: String, vararg codePoints: Int) {\n    val bytes = hex.decodeHex().toByteArray()\n    var i = 0\n    bytes.processUtf8CodePoints(0, bytes.size) { codePoint ->\n      if (i < codePoints.size) assertEquals(codePoints[i], codePoint, \"index=$i\")\n      i++\n    }\n    assertEquals(i, codePoints.size) // Checked them all\n  }\n\n  private fun assertStringEncoded(hex: String, string: String) {\n    val expectedUtf8 = hex.decodeHex()\n\n    // Confirm our expectations are consistent with the platform.\n    val platformUtf8 = ByteString.of(*string.asUtf8ToByteArray())\n    assertEquals(expectedUtf8, platformUtf8)\n\n    // Confirm our implementations matches those expectations.\n    val actualUtf8 = ByteString.of(*string.commonAsUtf8ToByteArray())\n    assertEquals(expectedUtf8, actualUtf8)\n\n    // TODO Confirm we are consistent when writing one code point at a time.\n\n    // Confirm we are consistent when measuring lengths.\n    assertEquals(expectedUtf8.size.toLong(), string.utf8Size())\n    assertEquals(expectedUtf8.size.toLong(), string.utf8Size(0, string.length))\n  }\n}\n"
  },
  {
    "path": "okio/src/hashFunctions/kotlin/okio/internal/HashFunction.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage okio.internal\n\n/** A cryptographic hash function. */\ninternal interface HashFunction {\n  fun update(\n    input: ByteArray,\n    offset: Int = 0,\n    byteCount: Int = input.size,\n  )\n\n  fun digest(): ByteArray\n}\n"
  },
  {
    "path": "okio/src/hashFunctions/kotlin/okio/internal/Hmac.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.ByteString\nimport okio.xor\n\ninternal class Hmac private constructor(\n  private val hashFunction: HashFunction,\n  private val outerKey: ByteArray,\n) : HashFunction {\n  override fun update(input: ByteArray, offset: Int, byteCount: Int) {\n    hashFunction.update(input, offset, byteCount)\n  }\n\n  override fun digest(): ByteArray {\n    val digest = hashFunction.digest()\n\n    hashFunction.update(outerKey)\n    hashFunction.update(digest)\n\n    return hashFunction.digest()\n  }\n\n  companion object {\n    private const val IPAD: Byte = 54\n    private const val OPAD: Byte = 92\n\n    fun sha1(key: ByteString) =\n      create(key, hashFunction = Sha1(), blockLength = 64)\n\n    fun sha256(key: ByteString) =\n      create(key, hashFunction = Sha256(), blockLength = 64)\n\n    fun sha512(key: ByteString) =\n      create(key, hashFunction = Sha512(), blockLength = 128)\n\n    private fun create(\n      key: ByteString,\n      hashFunction: HashFunction,\n      blockLength: Int,\n    ): Hmac {\n      val keySize = key.size\n      val paddedKey = when {\n        keySize == 0 -> throw IllegalArgumentException(\"Empty key\")\n        keySize == blockLength -> key.data\n        keySize < blockLength -> key.data.copyOf(blockLength)\n        else -> hashFunction.apply { update(key.data) }.digest().copyOf(blockLength)\n      }\n\n      val innerKey = ByteArray(blockLength) { paddedKey[it] xor IPAD }\n      val outerKey = ByteArray(blockLength) { paddedKey[it] xor OPAD }\n\n      hashFunction.update(innerKey)\n\n      return Hmac(\n        hashFunction,\n        outerKey,\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/hashFunctions/kotlin/okio/internal/Md5.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.leftRotate\n\ninternal class Md5 : HashFunction {\n  private var messageLength = 0L\n  private val unprocessed = ByteArray(64)\n  private var unprocessedLimit = 0\n  private val words = IntArray(16)\n\n  private var h0: Int = 1732584193\n  private var h1: Int = -271733879\n  private var h2: Int = -1732584194\n  private var h3: Int = 271733878\n\n  override fun update(\n    input: ByteArray,\n    offset: Int,\n    byteCount: Int,\n  ) {\n    messageLength += byteCount\n    var pos = offset\n    val limit = pos + byteCount\n    val unprocessed = this.unprocessed\n    val unprocessedLimit = this.unprocessedLimit\n\n    if (unprocessedLimit > 0) {\n      if (unprocessedLimit + byteCount < 64) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, unprocessedLimit, pos, limit)\n        this.unprocessedLimit = unprocessedLimit + byteCount\n        return\n      }\n\n      // Process a chunk combining leftover bytes and the input.\n      val consumeByteCount = 64 - unprocessedLimit\n      input.copyInto(unprocessed, unprocessedLimit, pos, pos + consumeByteCount)\n      processChunk(unprocessed, 0)\n      this.unprocessedLimit = 0\n      pos += consumeByteCount\n    }\n\n    while (pos < limit) {\n      val nextPos = pos + 64\n\n      if (nextPos > limit) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, 0, pos, limit)\n        this.unprocessedLimit = limit - pos\n        return\n      }\n\n      // Process a chunk.\n      processChunk(input, pos)\n      pos = nextPos\n    }\n  }\n\n  private fun processChunk(input: ByteArray, pos: Int) {\n    val words = this.words\n\n    var pos = pos\n    for (w in 0 until 16) {\n      words[w] = ((input[pos++].toInt() and 0xff)) or\n        ((input[pos++].toInt() and 0xff) shl 8) or\n        ((input[pos++].toInt() and 0xff) shl 16) or\n        ((input[pos++].toInt() and 0xff) shl 24)\n    }\n\n    hash(words)\n  }\n\n  private fun hash(words: IntArray) {\n    val localK = k\n    val localS = s\n\n    var a = h0\n    var b = h1\n    var c = h2\n    var d = h3\n\n    for (i in 0 until 16) {\n      val g = i\n      val f = ((b and c) or (b.inv() and d)) + a + localK[i] + words[g]\n      a = d\n      d = c\n      c = b\n      b += f leftRotate localS[i]\n    }\n\n    for (i in 16 until 32) {\n      val g = ((5 * i) + 1) % 16\n      val f = ((d and b) or (d.inv() and c)) + a + localK[i] + words[g]\n      a = d\n      d = c\n      c = b\n      b += f leftRotate localS[i]\n    }\n\n    for (i in 32 until 48) {\n      val g = ((3 * i) + 5) % 16\n      val f = (b xor c xor d) + a + localK[i] + words[g]\n      a = d\n      d = c\n      c = b\n      b += f leftRotate localS[i]\n    }\n\n    for (i in 48 until 64) {\n      val g = (7 * i) % 16\n      val f = (c xor (b or d.inv())) + a + localK[i] + words[g]\n      a = d\n      d = c\n      c = b\n      b += f leftRotate localS[i]\n    }\n\n    h0 += a\n    h1 += b\n    h2 += c\n    h3 += d\n  }\n\n  /* ktlint-disable */\n  override fun digest(): ByteArray {\n    val messageLengthBits = messageLength * 8\n\n    unprocessed[unprocessedLimit++] = 0x80.toByte()\n    if (unprocessedLimit > 56) {\n      unprocessed.fill(0, unprocessedLimit, 64)\n      processChunk(unprocessed, 0)\n      unprocessed.fill(0, 0, unprocessedLimit)\n    } else {\n      unprocessed.fill(0, unprocessedLimit, 56)\n    }\n    unprocessed[56] = (messageLengthBits        ).toByte()\n    unprocessed[57] = (messageLengthBits ushr  8).toByte()\n    unprocessed[58] = (messageLengthBits ushr 16).toByte()\n    unprocessed[59] = (messageLengthBits ushr 24).toByte()\n    unprocessed[60] = (messageLengthBits ushr 32).toByte()\n    unprocessed[61] = (messageLengthBits ushr 40).toByte()\n    unprocessed[62] = (messageLengthBits ushr 48).toByte()\n    unprocessed[63] = (messageLengthBits ushr 56).toByte()\n    processChunk(unprocessed, 0)\n\n    val a = h0\n    val b = h1\n    val c = h2\n    val d = h3\n\n    return byteArrayOf(\n      (a       ).toByte(),\n      (a shr  8).toByte(),\n      (a shr 16).toByte(),\n      (a shr 24).toByte(),\n      (b       ).toByte(),\n      (b shr  8).toByte(),\n      (b shr 16).toByte(),\n      (b shr 24).toByte(),\n      (c       ).toByte(),\n      (c shr  8).toByte(),\n      (c shr 16).toByte(),\n      (c shr 24).toByte(),\n      (d       ).toByte(),\n      (d shr  8).toByte(),\n      (d shr 16).toByte(),\n      (d shr 24).toByte()\n    )\n  }\n  /* ktlint-enable */\n\n  companion object {\n    private val s = intArrayOf(\n      7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9,\n      14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15,\n      21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,\n    )\n\n    private val k = intArrayOf(\n      -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341,\n      -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290,\n      1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335,\n      -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784,\n      1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353,\n      -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835,\n      530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571,\n      -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649,\n      -145523070, -1120210379, 718787259, -343485551,\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/hashFunctions/kotlin/okio/internal/Sha1.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.leftRotate\n\ninternal class Sha1 : HashFunction {\n  private var messageLength = 0L\n  private val unprocessed = ByteArray(64)\n  private var unprocessedLimit = 0\n  private val words = IntArray(80)\n\n  private var h0 = 1732584193\n  private var h1 = -271733879\n  private var h2 = -1732584194\n  private var h3 = 271733878\n  private var h4 = -1009589776\n\n  override fun update(\n    input: ByteArray,\n    offset: Int,\n    byteCount: Int,\n  ) {\n    messageLength += byteCount\n    var pos = offset\n    val limit = pos + byteCount\n    val unprocessed = this.unprocessed\n    val unprocessedLimit = this.unprocessedLimit\n\n    if (unprocessedLimit > 0) {\n      if (unprocessedLimit + byteCount < 64) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, unprocessedLimit, pos, limit)\n        this.unprocessedLimit = unprocessedLimit + byteCount\n        return\n      }\n\n      // Process a chunk combining leftover bytes and the input.\n      val consumeByteCount = 64 - unprocessedLimit\n      input.copyInto(unprocessed, unprocessedLimit, pos, pos + consumeByteCount)\n      processChunk(unprocessed, 0)\n      this.unprocessedLimit = 0\n      pos += consumeByteCount\n    }\n\n    while (pos < limit) {\n      val nextPos = pos + 64\n\n      if (nextPos > limit) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, 0, pos, limit)\n        this.unprocessedLimit = limit - pos\n        return\n      }\n\n      // Process a chunk.\n      processChunk(input, pos)\n      pos = nextPos\n    }\n  }\n\n  private fun processChunk(input: ByteArray, pos: Int) {\n    val words = this.words\n\n    var pos = pos\n    for (w in 0 until 16) {\n      words[w] =\n        ((input[pos++].toInt() and 0xff) shl 24) or\n        ((input[pos++].toInt() and 0xff) shl 16) or\n        ((input[pos++].toInt() and 0xff) shl 8) or\n        ((input[pos++].toInt() and 0xff))\n    }\n\n    for (w in 16 until 80) {\n      words[w] = (words[w - 3] xor words[w - 8] xor words[w - 14] xor words[w - 16]) leftRotate 1\n    }\n\n    var a = h0\n    var b = h1\n    var c = h2\n    var d = h3\n    var e = h4\n\n    for (i in 0 until 80) {\n      val a2 = when {\n        i < 20 -> {\n          val f = d xor (b and (c xor d))\n          val k = 1518500249\n          (a leftRotate 5) + f + e + k + words[i]\n        }\n        i < 40 -> {\n          val f = b xor c xor d\n          val k = 1859775393\n          (a leftRotate 5) + f + e + k + words[i]\n        }\n        i < 60 -> {\n          val f = (b and c) or (b and d) or (c and d)\n          val k = -1894007588\n          (a leftRotate 5) + f + e + k + words[i]\n        }\n        else -> {\n          val f = b xor c xor d\n          val k = -899497514\n          (a leftRotate 5) + f + e + k + words[i]\n        }\n      }\n\n      e = d\n      d = c\n      c = b leftRotate 30\n      b = a\n      a = a2\n    }\n\n    h0 += a\n    h1 += b\n    h2 += c\n    h3 += d\n    h4 += e\n  }\n\n  /* ktlint-disable */\n  override fun digest(): ByteArray {\n    val unprocessed = this.unprocessed\n    var unprocessedLimit = this.unprocessedLimit\n    val messageLengthBits = messageLength * 8\n\n    unprocessed[unprocessedLimit++] = 0x80.toByte()\n    if (unprocessedLimit > 56) {\n      unprocessed.fill(0, unprocessedLimit, 64)\n      processChunk(unprocessed, 0)\n      unprocessed.fill(0, 0, unprocessedLimit)\n    } else {\n      unprocessed.fill(0, unprocessedLimit, 56)\n    }\n    unprocessed[56] = (messageLengthBits ushr 56).toByte()\n    unprocessed[57] = (messageLengthBits ushr 48).toByte()\n    unprocessed[58] = (messageLengthBits ushr 40).toByte()\n    unprocessed[59] = (messageLengthBits ushr 32).toByte()\n    unprocessed[60] = (messageLengthBits ushr 24).toByte()\n    unprocessed[61] = (messageLengthBits ushr 16).toByte()\n    unprocessed[62] = (messageLengthBits ushr  8).toByte()\n    unprocessed[63] = (messageLengthBits        ).toByte()\n    processChunk(unprocessed, 0)\n\n    val a = h0\n    val b = h1\n    val c = h2\n    val d = h3\n    val e = h4\n\n    reset()\n\n    return byteArrayOf(\n      (a shr 24).toByte(),\n      (a shr 16).toByte(),\n      (a shr  8).toByte(),\n      (a       ).toByte(),\n      (b shr 24).toByte(),\n      (b shr 16).toByte(),\n      (b shr  8).toByte(),\n      (b       ).toByte(),\n      (c shr 24).toByte(),\n      (c shr 16).toByte(),\n      (c shr  8).toByte(),\n      (c       ).toByte(),\n      (d shr 24).toByte(),\n      (d shr 16).toByte(),\n      (d shr  8).toByte(),\n      (d       ).toByte(),\n      (e shr 24).toByte(),\n      (e shr 16).toByte(),\n      (e shr  8).toByte(),\n      (e       ).toByte()\n    )\n  }\n  /* ktlint-enable */\n\n  private fun reset() {\n    messageLength = 0L\n    unprocessed.fill(0)\n    unprocessedLimit = 0\n    words.fill(0)\n\n    h0 = 1732584193\n    h1 = -271733879\n    h2 = -1732584194\n    h3 = 271733878\n    h4 = -1009589776\n  }\n}\n"
  },
  {
    "path": "okio/src/hashFunctions/kotlin/okio/internal/Sha256.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.and\n\ninternal class Sha256 : HashFunction {\n  private var messageLength = 0L\n  private val unprocessed = ByteArray(64)\n  private var unprocessedLimit = 0\n  private val words = IntArray(64)\n\n  private var h0 = 1779033703\n  private var h1 = -1150833019\n  private var h2 = 1013904242\n  private var h3 = -1521486534\n  private var h4 = 1359893119\n  private var h5 = -1694144372\n  private var h6 = 528734635\n  private var h7 = 1541459225\n\n  override fun update(\n    input: ByteArray,\n    offset: Int,\n    byteCount: Int,\n  ) {\n    messageLength += byteCount\n    var pos = offset\n    val limit = pos + byteCount\n    val unprocessed = this.unprocessed\n    val unprocessedLimit = this.unprocessedLimit\n\n    if (unprocessedLimit > 0) {\n      if (unprocessedLimit + byteCount < 64) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, unprocessedLimit, pos, limit)\n        this.unprocessedLimit = unprocessedLimit + byteCount\n        return\n      }\n\n      // Process a chunk combining leftover bytes and the input.\n      val consumeByteCount = 64 - unprocessedLimit\n      input.copyInto(unprocessed, unprocessedLimit, pos, pos + consumeByteCount)\n      processChunk(unprocessed, 0)\n      this.unprocessedLimit = 0\n      pos += consumeByteCount\n    }\n\n    while (pos < limit) {\n      val nextPos = pos + 64\n\n      if (nextPos > limit) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, 0, pos, limit)\n        this.unprocessedLimit = limit - pos\n        return\n      }\n\n      // Process a chunk.\n      processChunk(input, pos)\n      pos = nextPos\n    }\n  }\n\n  private fun processChunk(input: ByteArray, pos: Int) {\n    val words = this.words\n\n    var pos = pos\n    for (w in 0 until 16) {\n      words[w] = ((input[pos++] and 0xff) shl 24) or\n        ((input[pos++] and 0xff) shl 16) or\n        ((input[pos++] and 0xff) shl 8) or\n        ((input[pos++] and 0xff))\n    }\n\n    for (w in 16 until 64) {\n      val w15 = words[w - 15]\n      val s0 = ((w15 ushr 7) or (w15 shl 25)) xor ((w15 ushr 18) or (w15 shl 14)) xor (w15 ushr 3)\n      val w2 = words[w - 2]\n      val s1 = ((w2 ushr 17) or (w2 shl 15)) xor ((w2 ushr 19) or (w2 shl 13)) xor (w2 ushr 10)\n      val w16 = words[w - 16]\n      val w7 = words[w - 7]\n      words[w] = w16 + s0 + w7 + s1\n    }\n\n    hash(words)\n  }\n\n  private fun hash(\n    words: IntArray,\n  ) {\n    val localK = k\n    var a = h0\n    var b = h1\n    var c = h2\n    var d = h3\n    var e = h4\n    var f = h5\n    var g = h6\n    var h = h7\n\n    for (i in 0 until 64) {\n      val s0 = ((a ushr 2) or (a shl 30)) xor\n        ((a ushr 13) or (a shl 19)) xor\n        ((a ushr 22) or (a shl 10))\n      val s1 = ((e ushr 6) or (e shl 26)) xor\n        ((e ushr 11) or (e shl 21)) xor\n        ((e ushr 25) or (e shl 7))\n\n      val ch = (e and f) xor\n        (e.inv() and g)\n      val maj = (a and b) xor\n        (a and c) xor\n        (b and c)\n\n      val t1 = h + s1 + ch + localK[i] + words[i]\n      val t2 = s0 + maj\n\n      h = g\n      g = f\n      f = e\n      e = d + t1\n      d = c\n      c = b\n      b = a\n      a = t1 + t2\n    }\n\n    h0 += a\n    h1 += b\n    h2 += c\n    h3 += d\n    h4 += e\n    h5 += f\n    h6 += g\n    h7 += h\n  }\n\n  /* ktlint-disable */\n  override fun digest(): ByteArray {\n    val unprocessed = this.unprocessed\n    var unprocessedLimit = this.unprocessedLimit\n    val messageLengthBits = messageLength * 8\n\n    unprocessed[unprocessedLimit++] = 0x80.toByte()\n    if (unprocessedLimit > 56) {\n      unprocessed.fill(0, unprocessedLimit, 64)\n      processChunk(unprocessed, 0)\n      unprocessed.fill(0, 0, unprocessedLimit)\n    } else {\n      unprocessed.fill(0, unprocessedLimit, 56)\n    }\n    unprocessed[56] = (messageLengthBits ushr 56).toByte()\n    unprocessed[57] = (messageLengthBits ushr 48).toByte()\n    unprocessed[58] = (messageLengthBits ushr 40).toByte()\n    unprocessed[59] = (messageLengthBits ushr 32).toByte()\n    unprocessed[60] = (messageLengthBits ushr 24).toByte()\n    unprocessed[61] = (messageLengthBits ushr 16).toByte()\n    unprocessed[62] = (messageLengthBits ushr  8).toByte()\n    unprocessed[63] = (messageLengthBits        ).toByte()\n    processChunk(unprocessed, 0)\n\n    val a = h0\n    val b = h1\n    val c = h2\n    val d = h3\n    val e = h4\n    val f = h5\n    val g = h6\n    val h = h7\n\n    reset()\n\n    return byteArrayOf(\n      (a shr 24).toByte(),\n      (a shr 16).toByte(),\n      (a shr  8).toByte(),\n      (a       ).toByte(),\n      (b shr 24).toByte(),\n      (b shr 16).toByte(),\n      (b shr  8).toByte(),\n      (b       ).toByte(),\n      (c shr 24).toByte(),\n      (c shr 16).toByte(),\n      (c shr  8).toByte(),\n      (c       ).toByte(),\n      (d shr 24).toByte(),\n      (d shr 16).toByte(),\n      (d shr  8).toByte(),\n      (d       ).toByte(),\n      (e shr 24).toByte(),\n      (e shr 16).toByte(),\n      (e shr  8).toByte(),\n      (e       ).toByte(),\n      (f shr 24).toByte(),\n      (f shr 16).toByte(),\n      (f shr  8).toByte(),\n      (f       ).toByte(),\n      (g shr 24).toByte(),\n      (g shr 16).toByte(),\n      (g shr  8).toByte(),\n      (g       ).toByte(),\n      (h shr 24).toByte(),\n      (h shr 16).toByte(),\n      (h shr  8).toByte(),\n      (h       ).toByte()\n    )\n  }\n  /* ktlint-enable */\n\n  private fun reset() {\n    messageLength = 0L\n    unprocessed.fill(0)\n    unprocessedLimit = 0\n    words.fill(0)\n\n    h0 = 1779033703\n    h1 = -1150833019\n    h2 = 1013904242\n    h3 = -1521486534\n    h4 = 1359893119\n    h5 = -1694144372\n    h6 = 528734635\n    h7 = 1541459225\n  }\n\n  companion object {\n    private val k = intArrayOf(\n      1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548,\n      -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090,\n      -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122,\n      1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405,\n      -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700,\n      1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525,\n      -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877,\n      958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844,\n      -1933114872, -1866530822, -1538233109, -1090935817, -965641998,\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/hashFunctions/kotlin/okio/internal/Sha512.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.rightRotate\n\ninternal class Sha512 : HashFunction {\n  private var messageLength = 0L\n  private val unprocessed = ByteArray(128)\n  private var unprocessedLimit = 0\n  private val words = LongArray(80)\n\n  private var h0 = 7640891576956012808L\n  private var h1 = -4942790177534073029L\n  private var h2 = 4354685564936845355L\n  private var h3 = -6534734903238641935L\n  private var h4 = 5840696475078001361L\n  private var h5 = -7276294671716946913L\n  private var h6 = 2270897969802886507L\n  private var h7 = 6620516959819538809L\n\n  override fun update(\n    input: ByteArray,\n    offset: Int,\n    byteCount: Int,\n  ) {\n    messageLength += byteCount\n    var pos = offset\n    val limit = pos + byteCount\n    val unprocessed = this.unprocessed\n    val unprocessedLimit = this.unprocessedLimit\n\n    if (unprocessedLimit > 0) {\n      if (unprocessedLimit + byteCount < 128) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, unprocessedLimit, pos, limit)\n        this.unprocessedLimit = unprocessedLimit + byteCount\n        return\n      }\n\n      // Process a chunk combining leftover bytes and the input.\n      val consumeByteCount = 128 - unprocessedLimit\n      input.copyInto(unprocessed, unprocessedLimit, pos, pos + consumeByteCount)\n      processChunk(unprocessed, 0)\n      this.unprocessedLimit = 0\n      pos += consumeByteCount\n    }\n\n    while (pos < limit) {\n      val nextPos = pos + 128\n\n      if (nextPos > limit) {\n        // Not enough bytes for a chunk.\n        input.copyInto(unprocessed, 0, pos, limit)\n        this.unprocessedLimit = limit - pos\n        return\n      }\n\n      // Process a chunk.\n      processChunk(input, pos)\n      pos = nextPos\n    }\n  }\n\n  private fun processChunk(input: ByteArray, pos: Int) {\n    val words = this.words\n\n    var pos = pos\n    for (w in 0 until 16) {\n      words[w] = ((input[pos++].toLong() and 0xff) shl 56) or\n        ((input[pos++].toLong() and 0xff) shl 48) or\n        ((input[pos++].toLong() and 0xff) shl 40) or\n        ((input[pos++].toLong() and 0xff) shl 32) or\n        ((input[pos++].toLong() and 0xff) shl 24) or\n        ((input[pos++].toLong() and 0xff) shl 16) or\n        ((input[pos++].toLong() and 0xff) shl 8) or\n        ((input[pos++].toLong() and 0xff))\n    }\n\n    for (i in 16 until 80) {\n      val w15 = words[i - 15]\n      val s0 = (w15 rightRotate 1) xor (w15 rightRotate 8) xor (w15 ushr 7)\n      val w2 = words[i - 2]\n      val s1 = (w2 rightRotate 19) xor (w2 rightRotate 61) xor (w2 ushr 6)\n      val w16 = words[i - 16]\n      val w7 = words[i - 7]\n      words[i] = w16 + s0 + w7 + s1\n    }\n\n    hash(words)\n  }\n\n  private fun hash(words: LongArray) {\n    val localK = k\n    var a = h0\n    var b = h1\n    var c = h2\n    var d = h3\n    var e = h4\n    var f = h5\n    var g = h6\n    var h = h7\n\n    for (i in 0 until 80) {\n      val s0 = (a rightRotate 28) xor (a rightRotate 34) xor (a rightRotate 39)\n      val s1 = (e rightRotate 14) xor (e rightRotate 18) xor (e rightRotate 41)\n\n      val ch = (e and f) xor (e.inv() and g)\n      val maj = (a and b) xor (a and c) xor (b and c)\n\n      val t1 = h + s1 + ch + localK[i] + words[i]\n      val t2 = s0 + maj\n\n      h = g\n      g = f\n      f = e\n      e = d + t1\n      d = c\n      c = b\n      b = a\n      a = t1 + t2\n    }\n\n    h0 += a\n    h1 += b\n    h2 += c\n    h3 += d\n    h4 += e\n    h5 += f\n    h6 += g\n    h7 += h\n  }\n\n  /* ktlint-disable */\n  override fun digest(): ByteArray {\n    val unprocessed = this.unprocessed\n    var unprocessedLimit = this.unprocessedLimit\n    val messageLengthBits = messageLength * 8\n\n    unprocessed[unprocessedLimit++] = 0x80.toByte()\n    if (unprocessedLimit > 112) {\n      unprocessed.fill(0, unprocessedLimit, 128)\n      processChunk(unprocessed, 0)\n      unprocessed.fill(0, 0, unprocessedLimit)\n    } else {\n      unprocessed.fill(0, unprocessedLimit, 120)\n    }\n    unprocessed[120] = (messageLengthBits ushr 56).toByte()\n    unprocessed[121] = (messageLengthBits ushr 48).toByte()\n    unprocessed[122] = (messageLengthBits ushr 40).toByte()\n    unprocessed[123] = (messageLengthBits ushr 32).toByte()\n    unprocessed[124] = (messageLengthBits ushr 24).toByte()\n    unprocessed[125] = (messageLengthBits ushr 16).toByte()\n    unprocessed[126] = (messageLengthBits ushr  8).toByte()\n    unprocessed[127] = (messageLengthBits        ).toByte()\n    processChunk(unprocessed, 0)\n\n    val a = h0\n    val b = h1\n    val c = h2\n    val d = h3\n    val e = h4\n    val f = h5\n    val g = h6\n    val h = h7\n\n    reset()\n\n    return byteArrayOf(\n      (a shr 56).toByte(),\n      (a shr 48).toByte(),\n      (a shr 40).toByte(),\n      (a shr 32).toByte(),\n      (a shr 24).toByte(),\n      (a shr 16).toByte(),\n      (a shr  8).toByte(),\n      (a       ).toByte(),\n      (b shr 56).toByte(),\n      (b shr 48).toByte(),\n      (b shr 40).toByte(),\n      (b shr 32).toByte(),\n      (b shr 24).toByte(),\n      (b shr 16).toByte(),\n      (b shr  8).toByte(),\n      (b       ).toByte(),\n      (c shr 56).toByte(),\n      (c shr 48).toByte(),\n      (c shr 40).toByte(),\n      (c shr 32).toByte(),\n      (c shr 24).toByte(),\n      (c shr 16).toByte(),\n      (c shr  8).toByte(),\n      (c       ).toByte(),\n      (d shr 56).toByte(),\n      (d shr 48).toByte(),\n      (d shr 40).toByte(),\n      (d shr 32).toByte(),\n      (d shr 24).toByte(),\n      (d shr 16).toByte(),\n      (d shr  8).toByte(),\n      (d       ).toByte(),\n      (e shr 56).toByte(),\n      (e shr 48).toByte(),\n      (e shr 40).toByte(),\n      (e shr 32).toByte(),\n      (e shr 24).toByte(),\n      (e shr 16).toByte(),\n      (e shr  8).toByte(),\n      (e       ).toByte(),\n      (f shr 56).toByte(),\n      (f shr 48).toByte(),\n      (f shr 40).toByte(),\n      (f shr 32).toByte(),\n      (f shr 24).toByte(),\n      (f shr 16).toByte(),\n      (f shr  8).toByte(),\n      (f       ).toByte(),\n      (g shr 56).toByte(),\n      (g shr 48).toByte(),\n      (g shr 40).toByte(),\n      (g shr 32).toByte(),\n      (g shr 24).toByte(),\n      (g shr 16).toByte(),\n      (g shr  8).toByte(),\n      (g       ).toByte(),\n      (h shr 56).toByte(),\n      (h shr 48).toByte(),\n      (h shr 40).toByte(),\n      (h shr 32).toByte(),\n      (h shr 24).toByte(),\n      (h shr 16).toByte(),\n      (h shr  8).toByte(),\n      (h       ).toByte()\n    )\n  }\n  /* ktlint-enable */\n\n  private fun reset() {\n    messageLength = 0L\n    unprocessed.fill(0)\n    unprocessedLimit = 0\n    words.fill(0)\n\n    h0 = 7640891576956012808L\n    h1 = -4942790177534073029L\n    h2 = 4354685564936845355L\n    h3 = -6534734903238641935L\n    h4 = 5840696475078001361L\n    h5 = -7276294671716946913L\n    h6 = 2270897969802886507L\n    h7 = 6620516959819538809L\n  }\n\n  companion object {\n    private val k = longArrayOf(\n      4794697086780616226L, 8158064640168781261L, -5349999486874862801L, -1606136188198331460L,\n      4131703408338449720L, 6480981068601479193L, -7908458776815382629L, -6116909921290321640L,\n      -2880145864133508542L, 1334009975649890238L, 2608012711638119052L, 6128411473006802146L,\n      8268148722764581231L, -9160688886553864527L, -7215885187991268811L, -4495734319001033068L,\n      -1973867731355612462L, -1171420211273849373L, 1135362057144423861L, 2597628984639134821L,\n      3308224258029322869L, 5365058923640841347L, 6679025012923562964L, 8573033837759648693L,\n      -7476448914759557205L, -6327057829258317296L, -5763719355590565569L, -4658551843659510044L,\n      -4116276920077217854L, -3051310485924567259L, 489312712824947311L, 1452737877330783856L,\n      2861767655752347644L, 3322285676063803686L, 5560940570517711597L, 5996557281743188959L,\n      7280758554555802590L, 8532644243296465576L, -9096487096722542874L, -7894198246740708037L,\n      -6719396339535248540L, -6333637450476146687L, -4446306890439682159L, -4076793802049405392L,\n      -3345356375505022440L, -2983346525034927856L, -860691631967231958L, 1182934255886127544L,\n      1847814050463011016L, 2177327727835720531L, 2830643537854262169L, 3796741975233480872L,\n      4115178125766777443L, 5681478168544905931L, 6601373596472566643L, 7507060721942968483L,\n      8399075790359081724L, 8693463985226723168L, -8878714635349349518L, -8302665154208450068L,\n      -8016688836872298968L, -6606660893046293015L, -4685533653050689259L, -4147400797238176981L,\n      -3880063495543823972L, -3348786107499101689L, -1523767162380948706L, -757361751448694408L,\n      500013540394364858L, 748580250866718886L, 1242879168328830382L, 1977374033974150939L,\n      2944078676154940804L, 3659926193048069267L, 4368137639120453308L, 4836135668995329356L,\n      5532061633213252278L, 6448918945643986474L, 6902733635092675308L, 7801388544844847127L,\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/jsMain/kotlin/okio/FileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.contracts.InvocationKind\nimport kotlin.contracts.contract\nimport okio.Path.Companion.toPath\nimport okio.internal.commonCopy\nimport okio.internal.commonCreateDirectories\nimport okio.internal.commonDeleteRecursively\nimport okio.internal.commonExists\nimport okio.internal.commonListRecursively\nimport okio.internal.commonMetadata\n\nactual abstract class FileSystem : Closeable {\n  actual abstract fun canonicalize(path: Path): Path\n\n  actual fun metadata(path: Path): FileMetadata = commonMetadata(path)\n\n  actual abstract fun metadataOrNull(path: Path): FileMetadata?\n\n  actual fun exists(path: Path): Boolean = commonExists(path)\n\n  actual abstract fun list(dir: Path): List<Path>\n\n  actual abstract fun listOrNull(dir: Path): List<Path>?\n\n  actual open fun listRecursively(dir: Path, followSymlinks: Boolean): Sequence<Path> =\n    commonListRecursively(dir, followSymlinks)\n\n  actual abstract fun openReadOnly(file: Path): FileHandle\n\n  actual abstract fun openReadWrite(\n    file: Path,\n    mustCreate: Boolean,\n    mustExist: Boolean,\n  ): FileHandle\n\n  actual abstract fun source(file: Path): Source\n\n  actual inline fun <T> read(file: Path, readerAction: BufferedSource.() -> T): T {\n    contract {\n      callsInPlace(readerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return source(file).buffer().use {\n      it.readerAction()\n    }\n  }\n\n  actual abstract fun sink(file: Path, mustCreate: Boolean): Sink\n\n  actual inline fun <T> write(\n    file: Path,\n    mustCreate: Boolean,\n    writerAction: BufferedSink.() -> T,\n  ): T {\n    contract {\n      callsInPlace(writerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return sink(file, mustCreate).buffer().use {\n      it.writerAction()\n    }\n  }\n\n  actual abstract fun appendingSink(file: Path, mustExist: Boolean): Sink\n\n  actual abstract fun createDirectory(dir: Path, mustCreate: Boolean)\n\n  actual fun createDirectories(dir: Path, mustCreate: Boolean): Unit =\n    commonCreateDirectories(dir, mustCreate)\n\n  actual abstract fun atomicMove(source: Path, target: Path)\n\n  actual open fun copy(source: Path, target: Path): Unit = commonCopy(source, target)\n\n  actual abstract fun delete(path: Path, mustExist: Boolean)\n\n  actual open fun deleteRecursively(fileOrDirectory: Path, mustExist: Boolean): Unit =\n    commonDeleteRecursively(fileOrDirectory, mustExist)\n\n  actual abstract fun createSymlink(source: Path, target: Path)\n\n  actual override fun close() {\n  }\n\n  actual companion object {\n    actual val SYSTEM_TEMPORARY_DIRECTORY: Path = tmpdir.toPath()\n  }\n}\n"
  },
  {
    "path": "okio/src/jsMain/kotlin/okio/JsPlatform.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\n/*\n * This file exposes Node.js `os` and `path` APIs to Kotlin/JS, using reasonable default behaviors\n * if those symbols aren't available.\n *\n * This was originally implemented using a Kotlin/JS [JsModule], but that broke browser builds\n * because modules weren't available to browsers.\n *\n * https://nodejs.org/api/os.html\n * https://github.com/browserify/path-browserify/blob/master/index.js\n * https://github.com/CoderPuppy/os-browserify/blob/master/browser.js\n */\n\ninternal actual val PLATFORM_DIRECTORY_SEPARATOR: String\n  get() = (path?.sep) as? String ?: \"/\"\n\nprivate val os: dynamic\n  get() {\n    return try {\n      js(\"require('os')\")\n    } catch (t: Throwable) {\n      null\n    }\n  }\n\nprivate val path: dynamic\n  get() {\n    return try {\n      js(\"require('path')\")\n    } catch (t: Throwable) {\n      null\n    }\n  }\n\ninternal val tmpdir: String\n  get() = os?.tmpdir() as? String ?: \"/tmp\"\n"
  },
  {
    "path": "okio/src/jsMain/kotlin/okio/internal/ByteStringJs.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.ByteString\n\nprivate val charToNibble = js(\n  \"\"\"\n    {\n      0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9,\n      a: 10, b: 11, c: 12, d: 13, e: 14, f: 15,\n      A: 10, B: 11, C: 12, D: 13, E: 14, F: 15\n    }\n    \"\"\",\n)\n\n/**\n * Here we implement a custom hex decoder because the vanilla Kotlin one is too slow. The Kotlin\n * transpiles to reasonable-looking but very inefficient JavaScript!\n *\n * This does a plain JavaScript implementation of hex decoding, and it's dramatically faster. In\n * one measurement hex decoding went from 25% of CPU samples to 0% of them.\n */\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal actual inline fun String.commonDecodeHex(): ByteString {\n  require(length % 2 == 0) { \"Unexpected hex string: $this\" }\n\n  val string = this\n  val charToNibble = charToNibble\n  val result = ByteArray(string.length / 2)\n  var invalidDigitIndex = -1\n\n  js(\n    \"\"\"\n      var stringIndex = 0;\n      var byteIndex = 0;\n      while (stringIndex < string.length) {\n        var charA = string[stringIndex++];\n        var nibbleA = charToNibble[charA];\n\n        var charB = string[stringIndex++];\n        var nibbleB = charToNibble[charB];\n\n        if (nibbleA == null || nibbleB == null) {\n          invalidDigitIndex = stringIndex;\n          break;\n        }\n\n        result[byteIndex++] = (nibbleA << 4) | nibbleB;\n      }\n      \"\"\",\n  )\n\n  require(invalidDigitIndex == -1) {\n    \"Unexpected hex digit: ${string[invalidDigitIndex]}\"\n  }\n\n  return ByteString(result)\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/-DeprecatedOkio.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport java.io.File\nimport java.io.InputStream\nimport java.io.OutputStream\nimport java.net.Socket\nimport java.nio.file.OpenOption\nimport java.nio.file.Path as NioPath\n\n@Deprecated(message = \"changed in Okio 2.x\")\nobject `-DeprecatedOkio` {\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"file.appendingSink()\",\n      imports = [\"okio.appendingSink\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun appendingSink(file: File) = file.appendingSink()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"sink.buffer()\",\n      imports = [\"okio.buffer\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun buffer(sink: Sink) = sink.buffer()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"source.buffer()\",\n      imports = [\"okio.buffer\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun buffer(source: Source) = source.buffer()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"file.sink()\",\n      imports = [\"okio.sink\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun sink(file: File) = file.sink()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"outputStream.sink()\",\n      imports = [\"okio.sink\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun sink(outputStream: OutputStream) = outputStream.sink()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"path.sink(*options)\",\n      imports = [\"okio.sink\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun sink(path: NioPath, vararg options: OpenOption) = path.sink(*options)\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"socket.sink()\",\n      imports = [\"okio.sink\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun sink(socket: Socket) = socket.sink()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"file.source()\",\n      imports = [\"okio.source\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun source(file: File) = file.source()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"inputStream.source()\",\n      imports = [\"okio.source\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun source(inputStream: InputStream) = inputStream.source()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"path.source(*options)\",\n      imports = [\"okio.source\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun source(path: NioPath, vararg options: OpenOption) = path.source(*options)\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"socket.source()\",\n      imports = [\"okio.source\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun source(socket: Socket) = socket.source()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"blackholeSink()\",\n      imports = [\"okio.blackholeSink\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun blackhole() = blackholeSink()\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/-DeprecatedUtf8.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\n@Deprecated(message = \"changed in Okio 2.x\")\nobject `-DeprecatedUtf8` {\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"string.utf8Size()\",\n      imports = [\"okio.utf8Size\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun size(string: String) = string.utf8Size()\n\n  @Deprecated(\n    message = \"moved to extension function\",\n    replaceWith = ReplaceWith(\n      expression = \"string.utf8Size(beginIndex, endIndex)\",\n      imports = [\"okio.utf8Size\"],\n    ),\n    level = DeprecationLevel.ERROR,\n  )\n  fun size(string: String, beginIndex: Int, endIndex: Int) = string.utf8Size(beginIndex, endIndex)\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/-JvmPlatform.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport java.util.concurrent.locks.ReentrantLock\nimport kotlin.concurrent.withLock as jvmWithLock\nimport kotlin.contracts.InvocationKind\nimport kotlin.contracts.contract\n\ninternal actual fun ByteArray.toUtf8String(): String = String(this, Charsets.UTF_8)\n\ninternal actual fun String.asUtf8ToByteArray(): ByteArray = toByteArray(Charsets.UTF_8)\n\n// TODO remove if https://youtrack.jetbrains.com/issue/KT-20641 provides a better solution\nactual typealias ArrayIndexOutOfBoundsException = java.lang.ArrayIndexOutOfBoundsException\n\nactual typealias Lock = ReentrantLock\n\ninternal actual fun newLock(): Lock = ReentrantLock()\n\nactual inline fun <T> Lock.withLock(action: () -> T): T {\n  contract {\n    callsInPlace(action, InvocationKind.EXACTLY_ONCE)\n  }\n\n  return jvmWithLock(action)\n}\n\nactual typealias IOException = java.io.IOException\n\nactual typealias ProtocolException = java.net.ProtocolException\n\nactual typealias EOFException = java.io.EOFException\n\nactual typealias FileNotFoundException = java.io.FileNotFoundException\n\nactual typealias Closeable = java.io.Closeable\n\nactual typealias Deflater = java.util.zip.Deflater\n\nactual typealias Inflater = java.util.zip.Inflater\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/AsyncTimeout.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.InterruptedIOException\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.locks.Condition\nimport java.util.concurrent.locks.ReentrantLock\nimport kotlin.concurrent.withLock\nimport okio.AsyncTimeout.Companion.IDLE_TIMEOUT_NANOS\nimport okio.AsyncTimeout.Companion.condition\nimport okio.AsyncTimeout.Companion.idleSentinel\nimport okio.AsyncTimeout.Companion.queue\n\n/**\n * This timeout uses a background thread to take action exactly when the timeout occurs. Use this to\n * implement timeouts where they aren't supported natively, such as to sockets that are blocked on\n * writing.\n *\n * Subclasses should override [timedOut] to take action when a timeout occurs. This method will be\n * invoked by the shared watchdog thread so it should not do any long-running operations. Otherwise,\n * we risk starving other timeouts from being triggered.\n *\n * Use [sink] and [source] to apply this timeout to a stream. The returned value will apply the\n * timeout to each operation on the wrapped stream.\n *\n * Callers should call [enter] before doing work that is subject to timeouts, and [exit] afterward.\n * The return value of [exit] indicates whether a timeout was triggered. Note that the call to\n * [timedOut] is asynchronous, and may be called after [exit].\n */\nopen class AsyncTimeout : Timeout() {\n  private var state = STATE_IDLE\n\n  /** Index in [queue], or -1 if this isn't currently in the heap. */\n  @JvmField internal var index: Int = -1\n\n  /** If scheduled, this is the time that the watchdog should time this out.  */\n  internal var timeoutAt: Long = 0L\n    private set\n\n  fun enter() {\n    val timeoutNanos = timeoutNanos()\n    val hasDeadline = hasDeadline()\n    if (timeoutNanos == 0L && !hasDeadline) {\n      return // No timeout and no deadline? Don't bother with the queue.\n    }\n\n    lock.withLock {\n      check(state == STATE_IDLE) { \"Unbalanced enter/exit\" }\n      state = STATE_IN_QUEUE\n      insertIntoQueue(this)\n    }\n  }\n\n  /** Returns true if the timeout occurred.  */\n  fun exit(): Boolean {\n    lock.withLock {\n      val oldState = this.state\n      state = STATE_IDLE\n\n      if (oldState == STATE_IN_QUEUE) {\n        queue.remove(this)\n        return false\n      } else {\n        return oldState == STATE_TIMED_OUT\n      }\n    }\n  }\n\n  override fun cancel() {\n    super.cancel()\n\n    lock.withLock {\n      if (state == STATE_IN_QUEUE) {\n        queue.remove(this)\n        state = STATE_CANCELED\n      }\n    }\n  }\n\n  /**\n   * Returns the amount of time left until the time out. This will be negative if the timeout has\n   * elapsed and the timeout should occur immediately.\n   */\n  internal fun remainingNanos(now: Long) = timeoutAt - now\n\n  /**\n   * Sets the timeoutAt value as a sum of [now] and the time to wait for this timeout.\n   */\n  internal fun setTimeoutAt(now: Long = System.nanoTime()) {\n    val timeoutNanos = timeoutNanos()\n    val hasDeadline = hasDeadline()\n    if (timeoutNanos() != 0L && hasDeadline()) {\n      // Compute the earliest event; either timeout or deadline. Because nanoTime can wrap\n      // around, minOf() is undefined for absolute values, but meaningful for relative ones.\n      timeoutAt = now + minOf(timeoutNanos, deadlineNanoTime() - now)\n    } else if (timeoutNanos != 0L) {\n      timeoutAt = now + timeoutNanos\n    } else if (hasDeadline) {\n      timeoutAt = deadlineNanoTime()\n    } else {\n      throw AssertionError()\n    }\n  }\n\n  /**\n   * Invoked by the watchdog thread when the time between calls to [enter] and [exit] has exceeded\n   * the timeout.\n   */\n  protected open fun timedOut() {}\n\n  /**\n   * Returns a new sink that delegates to [sink], using this to implement timeouts. This works\n   * best if [timedOut] is overridden to interrupt [sink]'s current operation.\n   */\n  fun sink(sink: Sink): Sink {\n    return object : Sink {\n      override fun write(source: Buffer, byteCount: Long) {\n        checkOffsetAndCount(source.size, 0, byteCount)\n\n        var remaining = byteCount\n        while (remaining > 0L) {\n          // Count how many bytes to write. This loop guarantees we split on a segment boundary.\n          var toWrite = 0L\n          var s = source.head!!\n          while (toWrite < TIMEOUT_WRITE_SIZE) {\n            val segmentSize = s.limit - s.pos\n            toWrite += segmentSize.toLong()\n            if (toWrite >= remaining) {\n              toWrite = remaining\n              break\n            }\n            s = s.next!!\n          }\n\n          // Emit one write. Only this section is subject to the timeout.\n          withTimeout { sink.write(source, toWrite) }\n          remaining -= toWrite\n        }\n      }\n\n      override fun flush() {\n        withTimeout { sink.flush() }\n      }\n\n      override fun close() {\n        withTimeout { sink.close() }\n      }\n\n      override fun timeout() = this@AsyncTimeout\n\n      override fun toString() = \"AsyncTimeout.sink($sink)\"\n    }\n  }\n\n  /**\n   * Returns a new source that delegates to [source], using this to implement timeouts. This works\n   * best if [timedOut] is overridden to interrupt [source]'s current operation.\n   */\n  fun source(source: Source): Source {\n    return object : Source {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        return withTimeout { source.read(sink, byteCount) }\n      }\n\n      override fun close() {\n        withTimeout { source.close() }\n      }\n\n      override fun timeout() = this@AsyncTimeout\n\n      override fun toString() = \"AsyncTimeout.source($source)\"\n    }\n  }\n\n  /**\n   * Surrounds [block] with calls to [enter] and [exit], throwing an exception from\n   * [newTimeoutException] if a timeout occurred.\n   */\n  inline fun <T> withTimeout(block: () -> T): T {\n    var throwOnTimeout = false\n    enter()\n    try {\n      val result = block()\n      throwOnTimeout = true\n      return result\n    } catch (e: IOException) {\n      throw if (!exit()) e else `access$newTimeoutException`(e)\n    } finally {\n      val timedOut = exit()\n      if (timedOut && throwOnTimeout) throw `access$newTimeoutException`(null)\n    }\n  }\n\n  @PublishedApi // Binary compatible trampoline function\n  internal fun `access$newTimeoutException`(cause: IOException?) = newTimeoutException(cause)\n\n  /**\n   * Returns an [IOException] to represent a timeout. By default this method returns\n   * [InterruptedIOException]. If [cause] is non-null it is set as the cause of the\n   * returned exception.\n   */\n  protected open fun newTimeoutException(cause: IOException?): IOException {\n    val e = InterruptedIOException(\"timeout\")\n    if (cause != null) {\n      e.initCause(cause)\n    }\n    return e\n  }\n\n  private class Watchdog : Thread(\"Okio Watchdog\") {\n    init {\n      isDaemon = true\n    }\n\n    override fun run() {\n      while (true) {\n        try {\n          var timedOut: AsyncTimeout?\n          lock.withLock {\n            timedOut = awaitTimeout()\n\n            // The queue is completely empty. Let this thread exit and let another watchdog thread\n            // get created on the next call to scheduleTimeout().\n            if (timedOut === idleSentinel) {\n              idleSentinel = null\n              return\n            }\n          }\n\n          // Close the timed out node, if one was found.\n          timedOut?.timedOut()\n        } catch (_: InterruptedException) {\n        }\n      }\n    }\n  }\n\n  private companion object {\n    /**\n     * The watchdog thread processes this queue containing pending timeouts. It synchronizes on\n     * [condition] to guard accesses to the queue.\n     *\n     * The queue's first element is the next node to time out, which is null if the queue is empty.\n     *\n     * The [idleSentinel] is null until the watchdog thread is started and also after being\n     * idle for [AsyncTimeout.IDLE_TIMEOUT_MILLIS].\n     */\n    val queue = PriorityQueue()\n    var idleSentinel: AsyncTimeout? = null\n    val lock: ReentrantLock = ReentrantLock()\n    val condition: Condition = lock.newCondition()\n\n    /**\n     * Don't write more than 64 KiB of data at a time, give or take a segment. Otherwise, slow\n     * connections may suffer timeouts even when they're making (slow) progress. Without this,\n     * writing a single 1 MiB buffer may never succeed on a sufficiently slow connection.\n     */\n    private const val TIMEOUT_WRITE_SIZE = 64 * 1024\n\n    /** Duration for the watchdog thread to be idle before it shuts itself down.  */\n    private val IDLE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60)\n    private val IDLE_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(IDLE_TIMEOUT_MILLIS)\n\n    /*\n     *                                       .-------------.\n     *                                       |             |\n     *            .------------ exit() ------|  CANCELED   |\n     *            |                          |             |\n     *            |                          '-------------'\n     *            |                                 ^\n     *            |                                 |  cancel()\n     *            v                                 |\n     *     .-------------.                   .-------------.\n     *     |             |---- enter() ----->|             |\n     *     |    IDLE     |                   |  IN QUEUE   |\n     *     |             |<---- exit() ------|             |\n     *     '-------------'                   '-------------'\n     *            ^                                 |\n     *            |                                 |  time out\n     *            |                                 v\n     *            |                          .-------------.\n     *            |                          |             |\n     *            '------------ exit() ------|  TIMED OUT  |\n     *                                       |             |\n     *                                       '-------------'\n     *\n     * Notes:\n     *  * enter() crashes if called from a state other than IDLE.\n     *  * If there's no timeout (ie. wait forever), then enter() is a no-op. There's no state to\n     *    track entered but not in the queue.\n     *  * exit() is a no-op from IDLE. This is probably too lenient, but it made it simpler for\n     *    early implementations to support cases where enter() as a no-op.\n     *  * cancel() is a no-op from every state but IN QUEUE.\n     */\n\n    private const val STATE_IDLE = 0\n    private const val STATE_IN_QUEUE = 1\n    private const val STATE_TIMED_OUT = 2\n    private const val STATE_CANCELED = 3\n\n    private fun insertIntoQueue(node: AsyncTimeout) {\n      // Start the watchdog thread and create the sentinel node when the first timeout is scheduled.\n      if (idleSentinel == null) {\n        idleSentinel = AsyncTimeout()\n        Watchdog().start()\n      }\n      node.setTimeoutAt()\n      // Insert the node into the queue.\n      queue.add(node)\n      if (node.index == 1) {\n        // Wake up the watchdog when inserting at the front.\n        condition.signal()\n      }\n    }\n\n    /**\n     * Removes and returns the next node to timeout, waiting for it to time out if necessary.\n     *\n     * This returns [idleSentinel] if the queue was empty when starting, and it continues to be\n     * empty after waiting [IDLE_TIMEOUT_NANOS].\n     *\n     * This returns null if a new node was inserted while waiting.\n     */\n    @Throws(InterruptedException::class)\n    fun awaitTimeout(): AsyncTimeout? {\n      // Get the next eligible node.\n      val node = queue.first()\n\n      // The queue is empty. Wait until either something is enqueued or the idle timeout elapses.\n      if (node == null) {\n        val startNanos = System.nanoTime()\n        condition.await(IDLE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)\n        return if (queue.first() == null && System.nanoTime() - startNanos >= IDLE_TIMEOUT_NANOS) {\n          idleSentinel // The idle timeout elapsed.\n        } else {\n          null // The situation has changed.\n        }\n      }\n\n      val waitNanos = node.remainingNanos(System.nanoTime())\n\n      // The first node in the queue hasn't timed out yet. Await that.\n      if (waitNanos > 0) {\n        condition.await(waitNanos, TimeUnit.NANOSECONDS)\n        return null\n      }\n\n      // The first node in the queue has timed out. Remove it.\n      queue.remove(node)\n      node.state = STATE_TIMED_OUT\n      return node\n    }\n  }\n}\n\n/**\n * A min-heap binary heap, stored in an array.\n *\n * Nodes are [AsyncTimeout] instances directly. To support fast random removals, each [AsyncTimeout]\n * knows its index in the heap.\n *\n * The first node is at array index 1.\n *\n * https://en.wikipedia.org/wiki/Binary_heap\n */\ninternal class PriorityQueue {\n  @JvmField\n  internal var size = 0\n\n  @JvmField\n  internal var array = arrayOfNulls<AsyncTimeout?>(8)\n\n  fun first(): AsyncTimeout? = array[1]\n\n  fun add(node: AsyncTimeout) {\n    val newSize = size + 1\n    size = newSize\n    if (newSize == array.size) {\n      val doubledArray = arrayOfNulls<AsyncTimeout?>(newSize * 2)\n      array.copyInto(doubledArray)\n      array = doubledArray\n    }\n\n    heapifyUp(newSize, node)\n  }\n\n  fun remove(node: AsyncTimeout) {\n    require(node.index != -1)\n    val oldSize = size\n\n    // Take the heap's last node to fill this node's position.\n    val removedIndex = node.index\n    val last = array[oldSize]!!\n    node.index = -1\n    array[oldSize] = null\n    size = oldSize - 1\n\n    if (node === last) return // The last node is the removed node.\n\n    val nodeCompareToLast = node.compareTo(last)\n    when {\n      // The last node fits in the vacated spot.\n      nodeCompareToLast == 0 -> {\n        array[removedIndex] = last\n        last.index = removedIndex\n      }\n\n      // The last node might be too large for the vacated spot.\n      nodeCompareToLast < 0 -> heapifyDown(removedIndex, last)\n\n      // The last node might be too small for the vacated spot.\n      else -> heapifyUp(removedIndex, last)\n    }\n  }\n\n  /**\n   * Put [node] in the right position in the heap by moving it up the heap.\n   *\n   * When this is done it'll put something in [vacantIndex], and [node] somewhere in the heap.\n   *\n   * @param vacantIndex an index in [array] that is vacant.\n   */\n  private fun heapifyUp(\n    vacantIndex: Int,\n    node: AsyncTimeout,\n  ) {\n    var vacantIndex = vacantIndex\n    while (true) {\n      val parentIndex = vacantIndex shr 1\n      if (parentIndex == 0) break // No parent.\n\n      val parentNode = array[parentIndex]!!\n      if (parentNode <= node) break // No need to swap with the parent.\n\n      // Put our parent in the vacant index, and its index is the new vacant index.\n      parentNode.index = vacantIndex\n      array[vacantIndex] = parentNode\n      vacantIndex = parentIndex\n    }\n\n    array[vacantIndex] = node\n    node.index = vacantIndex\n  }\n\n  /**\n   * Put [node] in the right position in the heap by moving it down the heap.\n   *\n   * When this is done it'll put something in [vacantIndex], and [node] somewhere in the heap.\n   *\n   * @param vacantIndex an index in [array] that is vacant.\n   */\n  private fun heapifyDown(\n    vacantIndex: Int,\n    node: AsyncTimeout,\n  ) {\n    var vacantIndex = vacantIndex\n    while (true) {\n      val leftIndex = vacantIndex shl 1\n      val rightIndex = leftIndex + 1\n\n      val smallestChild = when {\n        rightIndex <= size -> {\n          val leftNode = array[leftIndex]!!\n          val rightNode = array[rightIndex]!!\n          when {\n            leftNode < rightNode -> leftNode\n            else -> rightNode\n          }\n        }\n        leftIndex <= size -> {\n          array[leftIndex]!! // Left node.\n        }\n        else -> break // No children.\n      }\n\n      if (node <= smallestChild) break // No need to swap with the children.\n\n      // Put our smallest child in the vacant index, and its index is the new vacant index.\n      val newVacantIndex = smallestChild.index\n      smallestChild.index = vacantIndex\n      array[vacantIndex] = smallestChild\n      vacantIndex = newVacantIndex\n    }\n\n    array[vacantIndex] = node\n    node.index = vacantIndex\n  }\n\n  /**\n   * Compares timeouts by their [AsyncTimeout.timeoutAt] values, in ascending order.\n   */\n  @Suppress(\"NOTHING_TO_INLINE\")\n  private inline operator fun AsyncTimeout.compareTo(other: AsyncTimeout): Int {\n    val a = timeoutAt\n    val b = other.timeoutAt\n    return 0L.compareTo(b - a)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/Buffer.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.Closeable\nimport java.io.EOFException\nimport java.io.IOException\nimport java.io.InputStream\nimport java.io.OutputStream\nimport java.nio.ByteBuffer\nimport java.nio.channels.ByteChannel\nimport java.nio.charset.Charset\nimport java.security.InvalidKeyException\nimport java.security.MessageDigest\nimport javax.crypto.Mac\nimport javax.crypto.spec.SecretKeySpec\nimport okio.internal.commonClear\nimport okio.internal.commonClose\nimport okio.internal.commonCompleteSegmentByteCount\nimport okio.internal.commonCopy\nimport okio.internal.commonCopyTo\nimport okio.internal.commonEquals\nimport okio.internal.commonExpandBuffer\nimport okio.internal.commonGet\nimport okio.internal.commonHashCode\nimport okio.internal.commonIndexOf\nimport okio.internal.commonIndexOfElement\nimport okio.internal.commonNext\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonRead\nimport okio.internal.commonReadAll\nimport okio.internal.commonReadAndWriteUnsafe\nimport okio.internal.commonReadByte\nimport okio.internal.commonReadByteArray\nimport okio.internal.commonReadByteString\nimport okio.internal.commonReadDecimalLong\nimport okio.internal.commonReadFully\nimport okio.internal.commonReadHexadecimalUnsignedLong\nimport okio.internal.commonReadInt\nimport okio.internal.commonReadLong\nimport okio.internal.commonReadShort\nimport okio.internal.commonReadUnsafe\nimport okio.internal.commonReadUtf8CodePoint\nimport okio.internal.commonReadUtf8Line\nimport okio.internal.commonReadUtf8LineStrict\nimport okio.internal.commonResizeBuffer\nimport okio.internal.commonSeek\nimport okio.internal.commonSelect\nimport okio.internal.commonSkip\nimport okio.internal.commonSnapshot\nimport okio.internal.commonWritableSegment\nimport okio.internal.commonWrite\nimport okio.internal.commonWriteAll\nimport okio.internal.commonWriteByte\nimport okio.internal.commonWriteDecimalLong\nimport okio.internal.commonWriteHexadecimalUnsignedLong\nimport okio.internal.commonWriteInt\nimport okio.internal.commonWriteLong\nimport okio.internal.commonWriteShort\nimport okio.internal.commonWriteUtf8\nimport okio.internal.commonWriteUtf8CodePoint\n\nactual class Buffer : BufferedSource, BufferedSink, Cloneable, ByteChannel {\n  @JvmField internal actual var head: Segment? = null\n\n  @get:JvmName(\"size\")\n  actual var size: Long = 0L\n    internal set\n\n  override fun buffer() = this\n\n  actual override val buffer get() = this\n\n  override fun outputStream(): OutputStream {\n    return object : OutputStream() {\n      override fun write(b: Int) {\n        writeByte(b)\n      }\n\n      override fun write(data: ByteArray, offset: Int, byteCount: Int) {\n        this@Buffer.write(data, offset, byteCount)\n      }\n\n      override fun flush() {}\n\n      override fun close() {}\n\n      override fun toString(): String = \"${this@Buffer}.outputStream()\"\n    }\n  }\n\n  actual override fun emitCompleteSegments() = this // Nowhere to emit to!\n\n  actual override fun emit() = this // Nowhere to emit to!\n\n  actual override fun exhausted() = size == 0L\n\n  @Throws(EOFException::class)\n  actual override fun require(byteCount: Long) {\n    if (size < byteCount) throw EOFException()\n  }\n\n  actual override fun request(byteCount: Long) = size >= byteCount\n\n  actual override fun peek(): BufferedSource {\n    return PeekSource(this).buffer()\n  }\n\n  override fun inputStream(): InputStream {\n    return object : InputStream() {\n      override fun read(): Int {\n        return if (size > 0L) {\n          readByte() and 0xff\n        } else {\n          -1\n        }\n      }\n\n      override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int {\n        return this@Buffer.read(sink, offset, byteCount)\n      }\n\n      override fun available() = minOf(size, Integer.MAX_VALUE).toInt()\n\n      override fun close() {}\n\n      override fun toString() = \"${this@Buffer}.inputStream()\"\n    }\n  }\n\n  /** Copy `byteCount` bytes from this, starting at `offset`, to `out`. */\n  @Throws(IOException::class)\n  @JvmOverloads\n  fun copyTo(\n    out: OutputStream,\n    offset: Long = 0L,\n    byteCount: Long = size - offset,\n  ): Buffer {\n    var offset = offset\n    var byteCount = byteCount\n    checkOffsetAndCount(size, offset, byteCount)\n    if (byteCount == 0L) return this\n\n    // Skip segments that we aren't copying from.\n    var s = head\n    while (offset >= s!!.limit - s.pos) {\n      offset -= (s.limit - s.pos).toLong()\n      s = s.next\n    }\n\n    // Copy from one segment at a time.\n    while (byteCount > 0L) {\n      val pos = (s!!.pos + offset).toInt()\n      val toCopy = minOf(s.limit - pos, byteCount).toInt()\n      out.write(s.data, pos, toCopy)\n      byteCount -= toCopy.toLong()\n      offset = 0L\n      s = s.next\n    }\n\n    return this\n  }\n\n  actual fun copyTo(\n    out: Buffer,\n    offset: Long,\n    byteCount: Long,\n  ): Buffer = commonCopyTo(out, offset, byteCount)\n\n  actual fun copyTo(\n    out: Buffer,\n    offset: Long,\n  ): Buffer = copyTo(out, offset, size - offset)\n\n  /** Write `byteCount` bytes from this to `out`. */\n  @Throws(IOException::class)\n  @JvmOverloads\n  fun writeTo(out: OutputStream, byteCount: Long = size): Buffer {\n    var byteCount = byteCount\n    checkOffsetAndCount(size, 0, byteCount)\n\n    var s = head\n    while (byteCount > 0L) {\n      val toCopy = minOf(byteCount, s!!.limit - s.pos).toInt()\n      out.write(s.data, s.pos, toCopy)\n\n      s.pos += toCopy\n      size -= toCopy.toLong()\n      byteCount -= toCopy.toLong()\n\n      if (s.pos == s.limit) {\n        val toRecycle = s\n        s = toRecycle.pop()\n        head = s\n        SegmentPool.recycle(toRecycle)\n      }\n    }\n\n    return this\n  }\n\n  /** Read and exhaust bytes from `input` into this. */\n  @Throws(IOException::class)\n  fun readFrom(input: InputStream): Buffer {\n    readFrom(input, Long.MAX_VALUE, true)\n    return this\n  }\n\n  /** Read `byteCount` bytes from `input` into this. */\n  @Throws(IOException::class)\n  fun readFrom(input: InputStream, byteCount: Long): Buffer {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    readFrom(input, byteCount, false)\n    return this\n  }\n\n  @Throws(IOException::class)\n  private fun readFrom(input: InputStream, byteCount: Long, forever: Boolean) {\n    var byteCount = byteCount\n    while (byteCount > 0L || forever) {\n      val tail = writableSegment(1)\n      val maxToCopy = minOf(byteCount, Segment.SIZE - tail.limit).toInt()\n      val bytesRead = input.read(tail.data, tail.limit, maxToCopy)\n      if (bytesRead == -1) {\n        if (tail.pos == tail.limit) {\n          // We allocated a tail segment, but didn't end up needing it. Recycle!\n          head = tail.pop()\n          SegmentPool.recycle(tail)\n        }\n        if (forever) return\n        throw EOFException()\n      }\n      tail.limit += bytesRead\n      size += bytesRead.toLong()\n      byteCount -= bytesRead.toLong()\n    }\n  }\n\n  actual fun completeSegmentByteCount(): Long = commonCompleteSegmentByteCount()\n\n  @Throws(EOFException::class)\n  actual override fun readByte(): Byte = commonReadByte()\n\n  @JvmName(\"getByte\")\n  actual operator fun get(pos: Long): Byte = commonGet(pos)\n\n  @Throws(EOFException::class)\n  actual override fun readShort(): Short = commonReadShort()\n\n  @Throws(EOFException::class)\n  actual override fun readInt(): Int = commonReadInt()\n\n  @Throws(EOFException::class)\n  actual override fun readLong(): Long = commonReadLong()\n\n  @Throws(EOFException::class)\n  actual override fun readShortLe() = readShort().reverseBytes()\n\n  @Throws(EOFException::class)\n  actual override fun readIntLe() = readInt().reverseBytes()\n\n  @Throws(EOFException::class)\n  actual override fun readLongLe() = readLong().reverseBytes()\n\n  @Throws(EOFException::class)\n  actual override fun readDecimalLong(): Long = commonReadDecimalLong()\n\n  @Throws(EOFException::class)\n  actual override fun readHexadecimalUnsignedLong(): Long = commonReadHexadecimalUnsignedLong()\n\n  actual override fun readByteString(): ByteString = commonReadByteString()\n\n  @Throws(EOFException::class)\n  actual override fun readByteString(byteCount: Long) = commonReadByteString(byteCount)\n\n  actual override fun select(options: Options): Int = commonSelect(options)\n\n  actual override fun <T : Any> select(options: TypedOptions<T>): T? = commonSelect(options)\n\n  @Throws(EOFException::class)\n  actual override fun readFully(sink: Buffer, byteCount: Long): Unit = commonReadFully(sink, byteCount)\n\n  @Throws(IOException::class)\n  actual override fun readAll(sink: Sink): Long = commonReadAll(sink)\n\n  actual override fun readUtf8() = readString(size, Charsets.UTF_8)\n\n  @Throws(EOFException::class)\n  actual override fun readUtf8(byteCount: Long) = readString(byteCount, Charsets.UTF_8)\n\n  override fun readString(charset: Charset) = readString(size, charset)\n\n  @Throws(EOFException::class)\n  override fun readString(byteCount: Long, charset: Charset): String {\n    require(byteCount >= 0 && byteCount <= Integer.MAX_VALUE) { \"byteCount: $byteCount\" }\n    if (size < byteCount) throw EOFException()\n    if (byteCount == 0L) return \"\"\n\n    val s = head!!\n    if (s.pos + byteCount > s.limit) {\n      // If the string spans multiple segments, delegate to readBytes().\n      return String(readByteArray(byteCount), charset)\n    }\n\n    val result = String(s.data, s.pos, byteCount.toInt(), charset)\n    s.pos += byteCount.toInt()\n    size -= byteCount\n\n    if (s.pos == s.limit) {\n      head = s.pop()\n      SegmentPool.recycle(s)\n    }\n\n    return result\n  }\n\n  @Throws(EOFException::class)\n  actual override fun readUtf8Line(): String? = commonReadUtf8Line()\n\n  @Throws(EOFException::class)\n  actual override fun readUtf8LineStrict() = readUtf8LineStrict(Long.MAX_VALUE)\n\n  @Throws(EOFException::class)\n  actual override fun readUtf8LineStrict(limit: Long): String = commonReadUtf8LineStrict(limit)\n\n  @Throws(EOFException::class)\n  actual override fun readUtf8CodePoint(): Int = commonReadUtf8CodePoint()\n\n  actual override fun readByteArray() = commonReadByteArray()\n\n  @Throws(EOFException::class)\n  actual override fun readByteArray(byteCount: Long): ByteArray = commonReadByteArray(byteCount)\n\n  actual override fun read(sink: ByteArray) = commonRead(sink)\n\n  @Throws(EOFException::class)\n  actual override fun readFully(sink: ByteArray) = commonReadFully(sink)\n\n  actual override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int =\n    commonRead(sink, offset, byteCount)\n\n  @Throws(IOException::class)\n  override fun read(sink: ByteBuffer): Int {\n    val s = head ?: return -1\n\n    val toCopy = minOf(sink.remaining(), s.limit - s.pos)\n    sink.put(s.data, s.pos, toCopy)\n\n    s.pos += toCopy\n    size -= toCopy.toLong()\n\n    if (s.pos == s.limit) {\n      head = s.pop()\n      SegmentPool.recycle(s)\n    }\n\n    return toCopy\n  }\n\n  actual fun clear() = commonClear()\n\n  @Throws(EOFException::class)\n  actual override fun skip(byteCount: Long) = commonSkip(byteCount)\n\n  actual override fun write(byteString: ByteString): Buffer = commonWrite(byteString)\n\n  actual override fun write(byteString: ByteString, offset: Int, byteCount: Int) =\n    commonWrite(byteString, offset, byteCount)\n\n  actual override fun writeUtf8(string: String): Buffer = writeUtf8(string, 0, string.length)\n\n  actual override fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): Buffer =\n    commonWriteUtf8(string, beginIndex, endIndex)\n\n  actual override fun writeUtf8CodePoint(codePoint: Int): Buffer =\n    commonWriteUtf8CodePoint(codePoint)\n\n  override fun writeString(string: String, charset: Charset) = writeString(\n    string,\n    0,\n    string.length,\n    charset,\n  )\n\n  override fun writeString(\n    string: String,\n    beginIndex: Int,\n    endIndex: Int,\n    charset: Charset,\n  ): Buffer {\n    require(beginIndex >= 0) { \"beginIndex < 0: $beginIndex\" }\n    require(endIndex >= beginIndex) { \"endIndex < beginIndex: $endIndex < $beginIndex\" }\n    require(endIndex <= string.length) { \"endIndex > string.length: $endIndex > ${string.length}\" }\n    if (charset == Charsets.UTF_8) return writeUtf8(string, beginIndex, endIndex)\n    val data = string.substring(beginIndex, endIndex).toByteArray(charset)\n    return write(data, 0, data.size)\n  }\n\n  actual override fun write(source: ByteArray): Buffer = commonWrite(source)\n\n  actual override fun write(\n    source: ByteArray,\n    offset: Int,\n    byteCount: Int,\n  ): Buffer = commonWrite(source, offset, byteCount)\n\n  @Throws(IOException::class)\n  override fun write(source: ByteBuffer): Int {\n    val byteCount = source.remaining()\n    var remaining = byteCount\n    while (remaining > 0) {\n      val tail = writableSegment(1)\n\n      val toCopy = minOf(remaining, Segment.SIZE - tail.limit)\n      source.get(tail.data, tail.limit, toCopy)\n\n      remaining -= toCopy\n      tail.limit += toCopy\n    }\n\n    size += byteCount.toLong()\n    return byteCount\n  }\n\n  @Throws(IOException::class)\n  actual override fun writeAll(source: Source): Long = commonWriteAll(source)\n\n  @Throws(IOException::class)\n  actual override fun write(source: Source, byteCount: Long): Buffer =\n    commonWrite(source, byteCount)\n\n  actual override fun writeByte(b: Int): Buffer = commonWriteByte(b)\n\n  actual override fun writeShort(s: Int): Buffer = commonWriteShort(s)\n\n  actual override fun writeShortLe(s: Int) = writeShort(s.toShort().reverseBytes().toInt())\n\n  actual override fun writeInt(i: Int): Buffer = commonWriteInt(i)\n\n  actual override fun writeIntLe(i: Int) = writeInt(i.reverseBytes())\n\n  actual override fun writeLong(v: Long): Buffer = commonWriteLong(v)\n\n  actual override fun writeLongLe(v: Long) = writeLong(v.reverseBytes())\n\n  actual override fun writeDecimalLong(v: Long): Buffer = commonWriteDecimalLong(v)\n\n  actual override fun writeHexadecimalUnsignedLong(v: Long): Buffer =\n    commonWriteHexadecimalUnsignedLong(v)\n\n  internal actual fun writableSegment(minimumCapacity: Int): Segment =\n    commonWritableSegment(minimumCapacity)\n\n  actual override fun write(source: Buffer, byteCount: Long): Unit = commonWrite(source, byteCount)\n\n  actual override fun read(sink: Buffer, byteCount: Long): Long = commonRead(sink, byteCount)\n\n  actual override fun indexOf(b: Byte) = indexOf(b, 0, Long.MAX_VALUE)\n\n  /**\n   * Returns the index of `b` in this at or beyond `fromIndex`, or -1 if this buffer does not\n   * contain `b` in that range.\n   */\n  actual override fun indexOf(b: Byte, fromIndex: Long) = indexOf(b, fromIndex, Long.MAX_VALUE)\n\n  actual override fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(b, fromIndex = fromIndex, toIndex = toIndex)\n\n  @Throws(IOException::class)\n  actual override fun indexOf(bytes: ByteString): Long = indexOf(bytes, 0)\n\n  @Throws(IOException::class)\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long): Long =\n    indexOf(bytes, fromIndex, Long.MAX_VALUE)\n\n  @Throws(IOException::class)\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(bytes, fromIndex = fromIndex, toIndex = toIndex)\n\n  actual override fun indexOfElement(targetBytes: ByteString) = indexOfElement(targetBytes, 0L)\n\n  actual override fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long =\n    commonIndexOfElement(targetBytes, fromIndex)\n\n  actual override fun rangeEquals(offset: Long, bytes: ByteString) =\n    rangeEquals(offset, bytes, 0, bytes.size)\n\n  actual override fun rangeEquals(\n    offset: Long,\n    bytes: ByteString,\n    bytesOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, bytes, bytesOffset, byteCount)\n\n  actual override fun flush() {}\n\n  override fun isOpen() = true\n\n  actual override fun close() {}\n\n  actual override fun timeout() = Timeout.NONE\n\n  /**\n   * Returns the 128-bit MD5 hash of this buffer.\n   *\n   * MD5 has been vulnerable to collisions since 2004. It should not be used in new code.\n   */\n  actual fun md5() = digest(\"MD5\")\n\n  /**\n   * Returns the 160-bit SHA-1 hash of this buffer.\n   *\n   * SHA-1 has been vulnerable to collisions since 2017. It should not be used in new code.\n   */\n  actual fun sha1() = digest(\"SHA-1\")\n\n  /** Returns the 256-bit SHA-256 hash of this buffer. */\n  actual fun sha256() = digest(\"SHA-256\")\n\n  /** Returns the 512-bit SHA-512 hash of this buffer. */\n  actual fun sha512() = digest(\"SHA-512\")\n\n  private fun digest(algorithm: String): ByteString {\n    val messageDigest = MessageDigest.getInstance(algorithm)\n    head?.let { head ->\n      messageDigest.update(head.data, head.pos, head.limit - head.pos)\n      var s = head.next!!\n      while (s !== head) {\n        messageDigest.update(s.data, s.pos, s.limit - s.pos)\n        s = s.next!!\n      }\n    }\n    return ByteString(messageDigest.digest())\n  }\n\n  /** Returns the 160-bit SHA-1 HMAC of this buffer. */\n  actual fun hmacSha1(key: ByteString) = hmac(\"HmacSHA1\", key)\n\n  /** Returns the 256-bit SHA-256 HMAC of this buffer. */\n  actual fun hmacSha256(key: ByteString) = hmac(\"HmacSHA256\", key)\n\n  /** Returns the 512-bit SHA-512 HMAC of this buffer. */\n  actual fun hmacSha512(key: ByteString) = hmac(\"HmacSHA512\", key)\n\n  private fun hmac(algorithm: String, key: ByteString): ByteString {\n    try {\n      val mac = Mac.getInstance(algorithm)\n      mac.init(SecretKeySpec(key.internalArray(), algorithm))\n      head?.let { head ->\n        mac.update(head.data, head.pos, head.limit - head.pos)\n        var s = head.next!!\n        while (s !== head) {\n          mac.update(s.data, s.pos, s.limit - s.pos)\n          s = s.next!!\n        }\n      }\n      return ByteString(mac.doFinal())\n    } catch (e: InvalidKeyException) {\n      throw IllegalArgumentException(e)\n    }\n  }\n\n  override fun equals(other: Any?): Boolean = commonEquals(other)\n\n  override fun hashCode(): Int = commonHashCode()\n\n  /**\n   * Returns a human-readable string that describes the contents of this buffer. Typically this\n   * is a string like `[text=Hello]` or `[hex=0000ffff]`.\n   */\n  override fun toString() = snapshot().toString()\n\n  actual fun copy(): Buffer = commonCopy()\n\n  /**\n   * Returns a deep copy of this buffer. This is the same as [copy] but allows [Buffer] to implement\n   * the [Cloneable] interface on the JVM.\n   */\n  public override fun clone(): Buffer = copy()\n\n  actual fun snapshot(): ByteString = commonSnapshot()\n\n  actual fun snapshot(byteCount: Int): ByteString = commonSnapshot(byteCount)\n\n  @JvmOverloads\n  actual fun readUnsafe(unsafeCursor: UnsafeCursor): UnsafeCursor = commonReadUnsafe(unsafeCursor)\n\n  @JvmOverloads\n  actual fun readAndWriteUnsafe(unsafeCursor: UnsafeCursor): UnsafeCursor =\n    commonReadAndWriteUnsafe(unsafeCursor)\n\n  @JvmName(\"-deprecated_getByte\")\n  @Deprecated(\n    message = \"moved to operator function\",\n    replaceWith = ReplaceWith(expression = \"this[index]\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun getByte(index: Long) = this[index]\n\n  @JvmName(\"-deprecated_size\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"size\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun size() = size\n\n  actual class UnsafeCursor : Closeable {\n    @JvmField actual var buffer: Buffer? = null\n\n    @JvmField actual var readWrite: Boolean = false\n\n    internal actual var segment: Segment? = null\n\n    @JvmField actual var offset = -1L\n\n    @JvmField actual var data: ByteArray? = null\n\n    @JvmField actual var start = -1\n\n    @JvmField actual var end = -1\n\n    actual fun next(): Int = commonNext()\n\n    actual fun seek(offset: Long): Int = commonSeek(offset)\n\n    actual fun resizeBuffer(newSize: Long): Long = commonResizeBuffer(newSize)\n\n    actual fun expandBuffer(minByteCount: Int): Long = commonExpandBuffer(minByteCount)\n\n    actual override fun close() {\n      commonClose()\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/BufferedSink.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.OutputStream\nimport java.nio.channels.WritableByteChannel\nimport java.nio.charset.Charset\n\nactual sealed interface BufferedSink : Sink, WritableByteChannel {\n  /** Returns this sink's internal buffer. */\n  @Deprecated(\n    message = \"moved to val: use getBuffer() instead\",\n    replaceWith = ReplaceWith(expression = \"buffer\"),\n    level = DeprecationLevel.WARNING,\n  )\n  fun buffer(): Buffer\n\n  actual val buffer: Buffer\n\n  @Throws(IOException::class)\n  actual fun write(byteString: ByteString): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun write(byteString: ByteString, offset: Int, byteCount: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun write(source: ByteArray): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun write(source: ByteArray, offset: Int, byteCount: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeAll(source: Source): Long\n\n  @Throws(IOException::class)\n  actual fun write(source: Source, byteCount: Long): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeUtf8(string: String): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeUtf8CodePoint(codePoint: Int): BufferedSink\n\n  @Throws(IOException::class)\n  fun writeString(string: String, charset: Charset): BufferedSink\n\n  @Throws(IOException::class)\n  fun writeString(string: String, beginIndex: Int, endIndex: Int, charset: Charset): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeByte(b: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeShort(s: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeShortLe(s: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeInt(i: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeIntLe(i: Int): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeLong(v: Long): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeLongLe(v: Long): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeDecimalLong(v: Long): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun writeHexadecimalUnsignedLong(v: Long): BufferedSink\n\n  @Throws(IOException::class)\n  actual override fun flush()\n\n  @Throws(IOException::class)\n  actual fun emit(): BufferedSink\n\n  @Throws(IOException::class)\n  actual fun emitCompleteSegments(): BufferedSink\n\n  /** Returns an output stream that writes to this sink. */\n  fun outputStream(): OutputStream\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/BufferedSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.InputStream\nimport java.nio.channels.ReadableByteChannel\nimport java.nio.charset.Charset\n\nactual sealed interface BufferedSource : Source, ReadableByteChannel {\n  /** Returns this source's internal buffer. */\n  @Deprecated(\n    message = \"moved to val: use getBuffer() instead\",\n    replaceWith = ReplaceWith(expression = \"buffer\"),\n    level = DeprecationLevel.WARNING,\n  )\n  fun buffer(): Buffer\n\n  actual val buffer: Buffer\n\n  @Throws(IOException::class)\n  actual fun exhausted(): Boolean\n\n  @Throws(IOException::class)\n  actual fun require(byteCount: Long)\n\n  @Throws(IOException::class)\n  actual fun request(byteCount: Long): Boolean\n\n  @Throws(IOException::class)\n  actual fun readByte(): Byte\n\n  @Throws(IOException::class)\n  actual fun readShort(): Short\n\n  @Throws(IOException::class)\n  actual fun readShortLe(): Short\n\n  @Throws(IOException::class)\n  actual fun readInt(): Int\n\n  @Throws(IOException::class)\n  actual fun readIntLe(): Int\n\n  @Throws(IOException::class)\n  actual fun readLong(): Long\n\n  @Throws(IOException::class)\n  actual fun readLongLe(): Long\n\n  @Throws(IOException::class)\n  actual fun readDecimalLong(): Long\n\n  @Throws(IOException::class)\n  actual fun readHexadecimalUnsignedLong(): Long\n\n  @Throws(IOException::class)\n  actual fun skip(byteCount: Long)\n\n  @Throws(IOException::class)\n  actual fun readByteString(): ByteString\n\n  @Throws(IOException::class)\n  actual fun readByteString(byteCount: Long): ByteString\n\n  @Throws(IOException::class)\n  actual fun select(options: Options): Int\n\n  @Throws(IOException::class)\n  actual fun <T : Any> select(options: TypedOptions<T>): T?\n\n  @Throws(IOException::class)\n  actual fun readByteArray(): ByteArray\n\n  @Throws(IOException::class)\n  actual fun readByteArray(byteCount: Long): ByteArray\n\n  @Throws(IOException::class)\n  actual fun read(sink: ByteArray): Int\n\n  @Throws(IOException::class)\n  actual fun readFully(sink: ByteArray)\n\n  @Throws(IOException::class)\n  actual fun read(sink: ByteArray, offset: Int, byteCount: Int): Int\n\n  @Throws(IOException::class)\n  actual fun readFully(sink: Buffer, byteCount: Long)\n\n  @Throws(IOException::class)\n  actual fun readAll(sink: Sink): Long\n\n  @Throws(IOException::class)\n  actual fun readUtf8(): String\n\n  @Throws(IOException::class)\n  actual fun readUtf8(byteCount: Long): String\n\n  @Throws(IOException::class)\n  actual fun readUtf8Line(): String?\n\n  @Throws(IOException::class)\n  actual fun readUtf8LineStrict(): String\n\n  @Throws(IOException::class)\n  actual fun readUtf8LineStrict(limit: Long): String\n\n  @Throws(IOException::class)\n  actual fun readUtf8CodePoint(): Int\n\n  /** Removes all bytes from this, decodes them as `charset`, and returns the string. */\n  @Throws(IOException::class)\n  fun readString(charset: Charset): String\n\n  /**\n   * Removes `byteCount` bytes from this, decodes them as `charset`, and returns the\n   * string.\n   */\n  @Throws(IOException::class)\n  fun readString(byteCount: Long, charset: Charset): String\n\n  @Throws(IOException::class)\n  actual fun indexOf(b: Byte): Long\n\n  @Throws(IOException::class)\n  actual fun indexOf(b: Byte, fromIndex: Long): Long\n\n  @Throws(IOException::class)\n  actual fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long\n\n  @Throws(IOException::class)\n  actual fun indexOf(bytes: ByteString): Long\n\n  @Throws(IOException::class)\n  actual fun indexOf(bytes: ByteString, fromIndex: Long): Long\n\n  @Throws(IOException::class)\n  actual fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long\n\n  @Throws(IOException::class)\n  actual fun indexOfElement(targetBytes: ByteString): Long\n\n  @Throws(IOException::class)\n  actual fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long\n\n  @Throws(IOException::class)\n  actual fun rangeEquals(offset: Long, bytes: ByteString): Boolean\n\n  @Throws(IOException::class)\n  actual fun rangeEquals(offset: Long, bytes: ByteString, bytesOffset: Int, byteCount: Int): Boolean\n\n  actual fun peek(): BufferedSource\n\n  /** Returns an input stream that reads from this source. */\n  fun inputStream(): InputStream\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/ByteString.kt",
    "content": "/*\n * Copyright 2014 Square Inc.\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 */\npackage okio\n\nimport java.io.EOFException\nimport java.io.IOException\nimport java.io.InputStream\nimport java.io.ObjectInputStream\nimport java.io.ObjectOutputStream\nimport java.io.OutputStream\nimport java.io.Serializable\nimport java.nio.ByteBuffer\nimport java.nio.charset.Charset\nimport java.security.InvalidKeyException\nimport java.security.MessageDigest\nimport javax.crypto.Mac\nimport javax.crypto.spec.SecretKeySpec\nimport okio.internal.commonBase64\nimport okio.internal.commonBase64Url\nimport okio.internal.commonCompareTo\nimport okio.internal.commonCopyInto\nimport okio.internal.commonDecodeBase64\nimport okio.internal.commonDecodeHex\nimport okio.internal.commonEncodeUtf8\nimport okio.internal.commonEndsWith\nimport okio.internal.commonEquals\nimport okio.internal.commonGetByte\nimport okio.internal.commonGetSize\nimport okio.internal.commonHashCode\nimport okio.internal.commonHex\nimport okio.internal.commonIndexOf\nimport okio.internal.commonInternalArray\nimport okio.internal.commonLastIndexOf\nimport okio.internal.commonOf\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonStartsWith\nimport okio.internal.commonSubstring\nimport okio.internal.commonToAsciiLowercase\nimport okio.internal.commonToAsciiUppercase\nimport okio.internal.commonToByteArray\nimport okio.internal.commonToByteString\nimport okio.internal.commonToString\nimport okio.internal.commonUtf8\nimport okio.internal.commonWrite\n\nactual open class ByteString\ninternal actual constructor(\n  internal actual val data: ByteArray,\n) : Serializable, Comparable<ByteString> {\n  @Transient internal actual var hashCode: Int = 0 // Lazily computed; 0 if unknown.\n  @Transient internal actual var utf8: String? = null // Lazily computed.\n\n  actual open fun utf8(): String = commonUtf8()\n\n  /** Constructs a new `String` by decoding the bytes using `charset`.  */\n  open fun string(charset: Charset) = String(data, charset)\n\n  actual open fun base64() = commonBase64()\n\n  actual fun md5() = digest(\"MD5\")\n\n  actual fun sha1() = digest(\"SHA-1\")\n\n  actual fun sha256() = digest(\"SHA-256\")\n\n  actual fun sha512() = digest(\"SHA-512\")\n\n  internal open fun digest(algorithm: String): ByteString {\n    val digestBytes = MessageDigest.getInstance(algorithm).run {\n      update(data, 0, size)\n      digest()\n    }\n    return ByteString(digestBytes)\n  }\n\n  /** Returns the 160-bit SHA-1 HMAC of this byte string.  */\n  actual open fun hmacSha1(key: ByteString) = hmac(\"HmacSHA1\", key)\n\n  /** Returns the 256-bit SHA-256 HMAC of this byte string.  */\n  actual open fun hmacSha256(key: ByteString) = hmac(\"HmacSHA256\", key)\n\n  /** Returns the 512-bit SHA-512 HMAC of this byte string.  */\n  actual open fun hmacSha512(key: ByteString) = hmac(\"HmacSHA512\", key)\n\n  internal open fun hmac(algorithm: String, key: ByteString): ByteString {\n    try {\n      val mac = Mac.getInstance(algorithm)\n      mac.init(SecretKeySpec(key.toByteArray(), algorithm))\n      return ByteString(mac.doFinal(data))\n    } catch (e: InvalidKeyException) {\n      throw IllegalArgumentException(e)\n    }\n  }\n\n  actual open fun base64Url() = commonBase64Url()\n\n  actual open fun hex(): String = commonHex()\n\n  actual open fun toAsciiLowercase(): ByteString = commonToAsciiLowercase()\n\n  actual open fun toAsciiUppercase(): ByteString = commonToAsciiUppercase()\n\n  @JvmOverloads\n  actual open fun substring(beginIndex: Int, endIndex: Int): ByteString =\n    commonSubstring(beginIndex, endIndex)\n\n  internal actual open fun internalGet(pos: Int) = commonGetByte(pos)\n\n  @JvmName(\"getByte\")\n  actual operator fun get(index: Int): Byte = internalGet(index)\n\n  actual val size\n    @JvmName(\"size\")\n    get() = getSize()\n\n  internal actual open fun getSize() = commonGetSize()\n\n  actual open fun toByteArray() = commonToByteArray()\n\n  internal actual open fun internalArray() = commonInternalArray()\n\n  /** Returns a `ByteBuffer` view of the bytes in this `ByteString`. */\n  open fun asByteBuffer(): ByteBuffer = ByteBuffer.wrap(data).asReadOnlyBuffer()\n\n  /** Writes the contents of this byte string to `out`.  */\n  @Throws(IOException::class)\n  open fun write(out: OutputStream) {\n    out.write(data)\n  }\n\n  internal actual open fun write(buffer: Buffer, offset: Int, byteCount: Int) =\n    commonWrite(buffer, offset, byteCount)\n\n  actual open fun rangeEquals(\n    offset: Int,\n    other: ByteString,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  actual open fun rangeEquals(\n    offset: Int,\n    other: ByteArray,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  actual open fun copyInto(\n    offset: Int,\n    target: ByteArray,\n    targetOffset: Int,\n    byteCount: Int,\n  ) = commonCopyInto(offset, target, targetOffset, byteCount)\n\n  actual fun startsWith(prefix: ByteString) = commonStartsWith(prefix)\n\n  actual fun startsWith(prefix: ByteArray) = commonStartsWith(prefix)\n\n  actual fun endsWith(suffix: ByteString) = commonEndsWith(suffix)\n\n  actual fun endsWith(suffix: ByteArray) = commonEndsWith(suffix)\n\n  @JvmOverloads\n  actual fun indexOf(other: ByteString, fromIndex: Int) = indexOf(other.internalArray(), fromIndex)\n\n  @JvmOverloads\n  actual open fun indexOf(other: ByteArray, fromIndex: Int) = commonIndexOf(other, fromIndex)\n\n  @JvmOverloads\n  actual fun lastIndexOf(other: ByteString, fromIndex: Int) = commonLastIndexOf(other, fromIndex)\n\n  @JvmOverloads\n  actual open fun lastIndexOf(other: ByteArray, fromIndex: Int) = commonLastIndexOf(other, fromIndex)\n\n  actual override fun equals(other: Any?) = commonEquals(other)\n\n  actual override fun hashCode() = commonHashCode()\n\n  actual override fun compareTo(other: ByteString) = commonCompareTo(other)\n\n  actual override fun toString() = commonToString()\n\n  @Throws(IOException::class)\n  private fun readObject(`in`: ObjectInputStream) {\n    val dataLength = `in`.readInt()\n    val byteString = `in`.readByteString(dataLength)\n    val field = ByteString::class.java.getDeclaredField(\"data\")\n    field.isAccessible = true\n    field.set(this, byteString.data)\n  }\n\n  @Throws(IOException::class)\n  private fun writeObject(out: ObjectOutputStream) {\n    out.writeInt(data.size)\n    out.write(data)\n  }\n\n  @JvmName(\"-deprecated_getByte\")\n  @Deprecated(\n    message = \"moved to operator function\",\n    replaceWith = ReplaceWith(expression = \"this[index]\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun getByte(index: Int) = this[index]\n\n  @JvmName(\"-deprecated_size\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"size\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun size() = size\n\n  actual companion object {\n    private const val serialVersionUID = 1L\n\n    @JvmField\n    actual val EMPTY: ByteString = ByteString(byteArrayOf())\n\n    @JvmStatic\n    actual fun of(vararg data: Byte) = commonOf(data)\n\n    @JvmStatic\n    @JvmName(\"of\")\n    actual fun ByteArray.toByteString(offset: Int, byteCount: Int): ByteString =\n      commonToByteString(offset, byteCount)\n\n    /** Returns a [ByteString] containing a copy of this [ByteBuffer]. */\n    @JvmStatic\n    @JvmName(\"of\")\n    fun ByteBuffer.toByteString(): ByteString {\n      val copy = ByteArray(remaining())\n      get(copy)\n      return ByteString(copy)\n    }\n\n    @JvmStatic\n    actual fun String.encodeUtf8(): ByteString = commonEncodeUtf8()\n\n    /** Returns a new [ByteString] containing the `charset`-encoded bytes of this [String].  */\n    @JvmStatic\n    @JvmName(\"encodeString\")\n    fun String.encode(charset: Charset = Charsets.UTF_8) = ByteString(toByteArray(charset))\n\n    @JvmStatic\n    actual fun String.decodeBase64() = commonDecodeBase64()\n\n    @JvmStatic\n    actual fun String.decodeHex() = commonDecodeHex()\n\n    /**\n     * Reads `count` bytes from this [InputStream] and returns the result.\n     *\n     * @throws java.io.EOFException if `in` has fewer than `count` bytes to read.\n     */\n    @Throws(IOException::class)\n    @JvmStatic\n    @JvmName(\"read\")\n    fun InputStream.readByteString(byteCount: Int): ByteString {\n      require(byteCount >= 0) { \"byteCount < 0: $byteCount\" }\n\n      val result = ByteArray(byteCount)\n      var offset = 0\n      var read: Int\n      while (offset < byteCount) {\n        read = read(result, offset, byteCount - offset)\n        if (read == -1) throw EOFException()\n        offset += read\n      }\n      return ByteString(result)\n    }\n\n    @JvmName(\"-deprecated_decodeBase64\")\n    @Deprecated(\n      message = \"moved to extension function\",\n      replaceWith = ReplaceWith(\n        expression = \"string.decodeBase64()\",\n        imports = [\"okio.ByteString.Companion.decodeBase64\"],\n      ),\n      level = DeprecationLevel.ERROR,\n    )\n    fun decodeBase64(string: String) = string.decodeBase64()\n\n    @JvmName(\"-deprecated_decodeHex\")\n    @Deprecated(\n      message = \"moved to extension function\",\n      replaceWith = ReplaceWith(\n        expression = \"string.decodeHex()\",\n        imports = [\"okio.ByteString.Companion.decodeHex\"],\n      ),\n      level = DeprecationLevel.ERROR,\n    )\n    fun decodeHex(string: String) = string.decodeHex()\n\n    @JvmName(\"-deprecated_encodeString\")\n    @Deprecated(\n      message = \"moved to extension function\",\n      replaceWith = ReplaceWith(\n        expression = \"string.encode(charset)\",\n        imports = [\"okio.ByteString.Companion.encode\"],\n      ),\n      level = DeprecationLevel.ERROR,\n    )\n    fun encodeString(string: String, charset: Charset) = string.encode(charset)\n\n    @JvmName(\"-deprecated_encodeUtf8\")\n    @Deprecated(\n      message = \"moved to extension function\",\n      replaceWith = ReplaceWith(\n        expression = \"string.encodeUtf8()\",\n        imports = [\"okio.ByteString.Companion.encodeUtf8\"],\n      ),\n      level = DeprecationLevel.ERROR,\n    )\n    fun encodeUtf8(string: String) = string.encodeUtf8()\n\n    @JvmName(\"-deprecated_of\")\n    @Deprecated(\n      message = \"moved to extension function\",\n      replaceWith = ReplaceWith(\n        expression = \"buffer.toByteString()\",\n        imports = [\"okio.ByteString.Companion.toByteString\"],\n      ),\n      level = DeprecationLevel.ERROR,\n    )\n    fun of(buffer: ByteBuffer) = buffer.toByteString()\n\n    @JvmName(\"-deprecated_of\")\n    @Deprecated(\n      message = \"moved to extension function\",\n      replaceWith = ReplaceWith(\n        expression = \"array.toByteString(offset, byteCount)\",\n        imports = [\"okio.ByteString.Companion.toByteString\"],\n      ),\n      level = DeprecationLevel.ERROR,\n    )\n    fun of(array: ByteArray, offset: Int, byteCount: Int) = array.toByteString(offset, byteCount)\n\n    @JvmName(\"-deprecated_read\")\n    @Deprecated(\n      message = \"moved to extension function\",\n      replaceWith = ReplaceWith(\n        expression = \"inputstream.readByteString(byteCount)\",\n        imports = [\"okio.ByteString.Companion.readByteString\"],\n      ),\n      level = DeprecationLevel.ERROR,\n    )\n    fun read(inputstream: InputStream, byteCount: Int) = inputstream.readByteString(byteCount)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/CipherSink.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage okio\n\nimport java.io.IOException\nimport javax.crypto.Cipher\n\nclass CipherSink(\n  private val sink: BufferedSink,\n  val cipher: Cipher,\n) : Sink {\n  private val blockSize = cipher.blockSize\n  private var closed = false\n\n  init {\n    // Require block cipher\n    require(blockSize > 0) { \"Block cipher required $cipher\" }\n  }\n\n  @Throws(IOException::class)\n  override fun write(source: Buffer, byteCount: Long) {\n    checkOffsetAndCount(source.size, 0, byteCount)\n    check(!closed) { \"closed\" }\n\n    var remaining = byteCount\n    while (remaining > 0) {\n      val size = update(source, remaining)\n      remaining -= size\n    }\n  }\n\n  private fun update(source: Buffer, remaining: Long): Int {\n    val head = source.head!!\n    var size = minOf(remaining, head.limit - head.pos).toInt()\n    val buffer = sink.buffer\n\n    // Shorten input until output is guaranteed to fit within a segment\n    var outputSize = cipher.getOutputSize(size)\n    while (outputSize > Segment.SIZE) {\n      if (size <= blockSize) {\n        // Bug: For AES-GCM on Android `update` method never outputs any data\n        // As a consequence, `getOutputSize` just keeps increasing indefinitely after each update\n        // When that happens, the fallback is to perform the update operation without using a pre-allocated segment\n        sink.write(cipher.update(source.readByteArray(remaining)))\n        return remaining.toInt()\n      }\n      size -= blockSize\n      outputSize = cipher.getOutputSize(size)\n    }\n    val s = buffer.writableSegment(outputSize)\n\n    val ciphered = cipher.update(head.data, head.pos, size, s.data, s.limit)\n\n    s.limit += ciphered\n    buffer.size += ciphered\n\n    // We allocated a tail segment, but didn't end up needing it. Recycle!\n    if (s.pos == s.limit) {\n      buffer.head = s.pop()\n      SegmentPool.recycle(s)\n    }\n\n    sink.emitCompleteSegments()\n\n    // Mark those bytes as read.\n    source.size -= size\n    head.pos += size\n    if (head.pos == head.limit) {\n      source.head = head.pop()\n      SegmentPool.recycle(head)\n    }\n\n    return size\n  }\n\n  override fun flush() = sink.flush()\n\n  override fun timeout() = sink.timeout()\n\n  @Throws(IOException::class)\n  override fun close() {\n    if (closed) return\n    closed = true\n\n    var thrown = doFinal()\n\n    try {\n      sink.close()\n    } catch (e: Throwable) {\n      if (thrown == null) thrown = e\n    }\n\n    if (thrown != null) throw thrown\n  }\n\n  private fun doFinal(): Throwable? {\n    val outputSize = cipher.getOutputSize(0)\n    if (outputSize == 0) return null\n\n    if (outputSize > Segment.SIZE) {\n      // Bug: For AES-GCM on Android `update` method never outputs any data\n      // As a consequence, `doFinal` returns the fully encrypted data, which may be arbitrarily large\n      // When that happens, the fallback is to perform the `doFinal` operation without using a pre-allocated segment\n      try {\n        sink.write(cipher.doFinal())\n      } catch (t: Throwable) {\n        return t\n      }\n      return null\n    }\n\n    var thrown: Throwable? = null\n    val buffer = sink.buffer\n\n    // For block cipher, output size cannot exceed block size in doFinal\n    val s = buffer.writableSegment(outputSize)\n\n    try {\n      val ciphered = cipher.doFinal(s.data, s.limit)\n\n      s.limit += ciphered\n      buffer.size += ciphered\n    } catch (e: Throwable) {\n      thrown = e\n    }\n\n    if (s.pos == s.limit) {\n      buffer.head = s.pop()\n      SegmentPool.recycle(s)\n    }\n\n    return thrown\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/CipherSource.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage okio\n\nimport java.io.IOException\nimport javax.crypto.Cipher\n\nclass CipherSource(\n  private val source: BufferedSource,\n  val cipher: Cipher,\n) : Source {\n  private val blockSize = cipher.blockSize\n  private val buffer = Buffer()\n  private var final = false\n  private var closed = false\n\n  init {\n    // Require block cipher\n    require(blockSize > 0) { \"Block cipher required $cipher\" }\n  }\n\n  @Throws(IOException::class)\n  override fun read(sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    check(!closed) { \"closed\" }\n    if (byteCount == 0L) return 0L\n\n    refill()\n\n    return buffer.read(sink, byteCount)\n  }\n\n  private fun refill() {\n    while (buffer.size == 0L && !final) {\n      if (source.exhausted()) {\n        final = true\n        doFinal()\n        break\n      } else {\n        update()\n      }\n    }\n  }\n\n  private fun update() {\n    val head = source.buffer.head!!\n    var size = head.limit - head.pos\n\n    // Shorten input until output is guaranteed to fit within a segment\n    var outputSize = cipher.getOutputSize(size)\n    while (outputSize > Segment.SIZE) {\n      if (size <= blockSize) {\n        // Bug: For AES-GCM on Android `update` method never outputs any data\n        // As a consequence, `getOutputSize` just keeps increasing indefinitely after each update\n        // When that happens, the fallback is to break the streaming implementation and just cipher the rest of the data all at once\n        final = true\n        buffer.write(cipher.doFinal(source.readByteArray()))\n        return\n      }\n      size -= blockSize\n      outputSize = cipher.getOutputSize(size)\n    }\n    val s = buffer.writableSegment(outputSize)\n\n    val ciphered =\n      cipher.update(head.data, head.pos, size, s.data, s.pos)\n\n    source.skip(size.toLong())\n\n    s.limit += ciphered\n    buffer.size += ciphered\n\n    // We allocated a tail segment, but didn't end up needing it. Recycle!\n    if (s.pos == s.limit) {\n      buffer.head = s.pop()\n      SegmentPool.recycle(s)\n    }\n  }\n\n  private fun doFinal() {\n    val outputSize = cipher.getOutputSize(0)\n    if (outputSize == 0) return\n\n    // For block cipher, output size cannot exceed block size in doFinal.\n    val s = buffer.writableSegment(outputSize)\n\n    val ciphered = cipher.doFinal(s.data, s.pos)\n\n    s.limit += ciphered\n    buffer.size += ciphered\n\n    // We allocated a tail segment, but didn't end up needing it. Recycle!\n    if (s.pos == s.limit) {\n      buffer.head = s.pop()\n      SegmentPool.recycle(s)\n    }\n  }\n\n  override fun timeout() = source.timeout()\n\n  @Throws(IOException::class)\n  override fun close() {\n    closed = true\n    source.close()\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/DeflaterSink.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\n@file:Suppress(\"NOTHING_TO_INLINE\") // Aliases to public API.\n\npackage okio\n\nimport java.util.zip.Deflater\nimport okio.internal.EMPTY_BYTE_ARRAY\n\nactual class DeflaterSink internal actual constructor(\n  private val sink: BufferedSink,\n  private val deflater: Deflater,\n) : Sink {\n  actual constructor(sink: Sink, deflater: Deflater) : this(sink.buffer(), deflater)\n\n  private var closed = false\n\n  @Throws(IOException::class)\n  actual override fun write(source: Buffer, byteCount: Long) {\n    checkOffsetAndCount(source.size, 0, byteCount)\n\n    var remaining = byteCount\n    while (remaining > 0) {\n      // Share bytes from the head segment of 'source' with the deflater.\n      val head = source.head!!\n      val toDeflate = minOf(remaining, head.limit - head.pos).toInt()\n      deflater.setInput(head.data, head.pos, toDeflate)\n\n      // Deflate those bytes into sink.\n      deflate(false)\n\n      // Mark those bytes as read.\n      source.size -= toDeflate\n      head.pos += toDeflate\n      if (head.pos == head.limit) {\n        source.head = head.pop()\n        SegmentPool.recycle(head)\n      }\n\n      remaining -= toDeflate\n    }\n\n    // Deflater still holds a reference to the most recent segment's byte array. That can cause\n    // problems in JNI, so clear it now. https://github.com/square/okio/issues/1608\n    deflater.setInput(EMPTY_BYTE_ARRAY, 0, 0)\n  }\n\n  private fun deflate(syncFlush: Boolean) {\n    val buffer = sink.buffer\n    while (true) {\n      val s = buffer.writableSegment(1)\n\n      // The 4-parameter overload of deflate() doesn't exist in the RI until\n      // Java 1.7, and is public (although with @hide) on Android since 2.3.\n      // The @hide tag means that this code won't compile against the Android\n      // 2.3 SDK, but it will run fine there.\n      val deflated = try {\n        if (syncFlush) {\n          deflater.deflate(s.data, s.limit, Segment.SIZE - s.limit, Deflater.SYNC_FLUSH)\n        } else {\n          deflater.deflate(s.data, s.limit, Segment.SIZE - s.limit)\n        }\n      } catch (ise: IllegalStateException) {\n        // Java 25+ documented behavior.\n        throw IOException(\"Deflater already closed\", ise)\n      } catch (npe: NullPointerException) {\n        // Java 24 and earlier undocumented behavior.\n        throw IOException(\"Deflater already closed\", npe)\n      }\n\n      if (deflated > 0) {\n        s.limit += deflated\n        buffer.size += deflated\n        sink.emitCompleteSegments()\n      } else if (deflater.needsInput()) {\n        if (s.pos == s.limit) {\n          // We allocated a tail segment, but didn't end up needing it. Recycle!\n          buffer.head = s.pop()\n          SegmentPool.recycle(s)\n        }\n        return\n      }\n    }\n  }\n\n  @Throws(IOException::class)\n  actual override fun flush() {\n    deflate(true)\n    sink.flush()\n  }\n\n  internal actual fun finishDeflate() {\n    deflater.finish()\n    deflate(false)\n  }\n\n  @Throws(IOException::class)\n  actual override fun close() {\n    if (closed) return\n\n    // Emit deflated data to the underlying sink. If this fails, we still need\n    // to close the deflater and the sink; otherwise we risk leaking resources.\n    var thrown: Throwable? = null\n    try {\n      finishDeflate()\n    } catch (e: Throwable) {\n      thrown = e\n    }\n\n    try {\n      deflater.end()\n    } catch (e: Throwable) {\n      if (thrown == null) thrown = e\n    }\n\n    try {\n      sink.close()\n    } catch (e: Throwable) {\n      if (thrown == null) thrown = e\n    }\n\n    closed = true\n\n    if (thrown != null) throw thrown\n  }\n\n  actual override fun timeout(): Timeout = sink.timeout()\n\n  override fun toString() = \"DeflaterSink($sink)\"\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/DeprecatedUpgrade.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n@file:JvmName(\"-DeprecatedUpgrade\")\n\npackage okio\n\nval Okio = `-DeprecatedOkio`\nval Utf8 = `-DeprecatedUtf8`\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/FileSystem.System.kt",
    "content": "@file:JvmName(\"SystemFileSystem\")\n\npackage okio\n\n/*\n * JVM and native platforms do offer a [SYSTEM] [FileSystem], however we cannot refine an 'expect' companion object.\n * Therefore an extension property is provided, which on respective platforms (here JVM) will be shadowed by the\n * original implementation.\n */\n@Suppress(\"EXTENSION_SHADOWED_BY_MEMBER\")\nactual inline val FileSystem.Companion.SYSTEM: FileSystem\n  @JvmSynthetic\n  get() = SYSTEM\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/FileSystem.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport java.nio.file.FileSystem as JavaNioFileSystem\nimport kotlin.contracts.InvocationKind\nimport kotlin.contracts.contract\nimport okio.Path.Companion.toPath\nimport okio.internal.ResourceFileSystem\nimport okio.internal.commonCopy\nimport okio.internal.commonCreateDirectories\nimport okio.internal.commonDeleteRecursively\nimport okio.internal.commonExists\nimport okio.internal.commonListRecursively\nimport okio.internal.commonMetadata\n\nactual abstract class FileSystem : Closeable {\n  @Throws(IOException::class)\n  actual abstract fun canonicalize(path: Path): Path\n\n  @Throws(IOException::class)\n  actual fun metadata(path: Path): FileMetadata = commonMetadata(path)\n\n  @Throws(IOException::class)\n  actual abstract fun metadataOrNull(path: Path): FileMetadata?\n\n  @Throws(IOException::class)\n  actual fun exists(path: Path): Boolean = commonExists(path)\n\n  @Throws(IOException::class)\n  actual abstract fun list(dir: Path): List<Path>\n\n  actual abstract fun listOrNull(dir: Path): List<Path>?\n\n  actual open fun listRecursively(dir: Path, followSymlinks: Boolean): Sequence<Path> =\n    commonListRecursively(dir, followSymlinks)\n\n  fun listRecursively(dir: Path): Sequence<Path> = listRecursively(dir, followSymlinks = false)\n\n  @Throws(IOException::class)\n  actual abstract fun openReadOnly(file: Path): FileHandle\n\n  @Throws(IOException::class)\n  actual abstract fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle\n\n  @Throws(IOException::class)\n  fun openReadWrite(file: Path): FileHandle =\n    openReadWrite(file, mustCreate = false, mustExist = false)\n\n  @Throws(IOException::class)\n  actual abstract fun source(file: Path): Source\n\n  @Throws(IOException::class)\n  @JvmName(\"-read\")\n  actual inline fun <T> read(file: Path, readerAction: BufferedSource.() -> T): T {\n    contract {\n      callsInPlace(readerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return source(file).buffer().use {\n      it.readerAction()\n    }\n  }\n\n  @Throws(IOException::class)\n  actual abstract fun sink(file: Path, mustCreate: Boolean): Sink\n\n  @Throws(IOException::class)\n  fun sink(file: Path): Sink = sink(file, mustCreate = false)\n\n  @Throws(IOException::class)\n  @JvmName(\"-write\")\n  actual inline fun <T> write(\n    file: Path,\n    mustCreate: Boolean,\n    writerAction: BufferedSink.() -> T,\n  ): T {\n    contract {\n      callsInPlace(writerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return sink(file, mustCreate = mustCreate).buffer().use {\n      it.writerAction()\n    }\n  }\n\n  @Throws(IOException::class)\n  actual abstract fun appendingSink(file: Path, mustExist: Boolean): Sink\n\n  @Throws(IOException::class)\n  fun appendingSink(file: Path): Sink = appendingSink(file, mustExist = false)\n\n  @Throws(IOException::class)\n  actual abstract fun createDirectory(dir: Path, mustCreate: Boolean)\n\n  @Throws(IOException::class)\n  fun createDirectory(dir: Path) = createDirectory(dir, mustCreate = false)\n\n  @Throws(IOException::class)\n  actual fun createDirectories(dir: Path, mustCreate: Boolean): Unit =\n    commonCreateDirectories(dir, mustCreate)\n\n  @Throws(IOException::class)\n  fun createDirectories(dir: Path): Unit = createDirectories(dir, mustCreate = false)\n\n  @Throws(IOException::class)\n  actual abstract fun atomicMove(source: Path, target: Path)\n\n  @Throws(IOException::class)\n  actual open fun copy(source: Path, target: Path): Unit = commonCopy(source, target)\n\n  @Throws(IOException::class)\n  actual abstract fun delete(path: Path, mustExist: Boolean)\n\n  @Throws(IOException::class)\n  fun delete(path: Path) = delete(path, mustExist = false)\n\n  @Throws(IOException::class)\n  actual open fun deleteRecursively(fileOrDirectory: Path, mustExist: Boolean): Unit =\n    commonDeleteRecursively(fileOrDirectory, mustExist)\n\n  @Throws(IOException::class)\n  fun deleteRecursively(fileOrDirectory: Path): Unit =\n    deleteRecursively(fileOrDirectory, mustExist = false)\n\n  @Throws(IOException::class)\n  actual abstract fun createSymlink(source: Path, target: Path)\n\n  @Throws(IOException::class)\n  actual override fun close() {\n  }\n\n  actual companion object {\n    /**\n     * The current process's host file system. Use this instance directly, or dependency inject a\n     * [FileSystem] to make code testable.\n     */\n    @JvmField\n    val SYSTEM: FileSystem = run {\n      try {\n        Class.forName(\"java.nio.file.Files\")\n        return@run NioSystemFileSystem()\n      } catch (e: ClassNotFoundException) {\n        return@run JvmSystemFileSystem()\n      }\n    }\n\n    @JvmField\n    actual val SYSTEM_TEMPORARY_DIRECTORY: Path = System.getProperty(\"java.io.tmpdir\").toPath()\n\n    /**\n     * A read-only file system holding the classpath resources of the current process. If a resource\n     * is available with [ClassLoader.getResource], it is also available via this file system.\n     *\n     * In applications that compose multiple class loaders, this holds only the resources of\n     * whichever class loader includes Okio classes. Use [ClassLoader.asResourceFileSystem] for the\n     * resources of a specific class loader.\n     *\n     * This file system does not need to be closed. Calling its close function does nothing.\n     */\n    @JvmField\n    val RESOURCES: FileSystem = ResourceFileSystem(\n      classLoader = ResourceFileSystem::class.java.classLoader,\n      indexEagerly = false,\n    )\n\n    /**\n     * Closing the returned file system will close the underlying [java.nio.file.FileSystem].\n     *\n     * Note that the [default file system][java.nio.file.FileSystems.getDefault] is not closeable\n     * and calling its close function will throw an [UnsupportedOperationException].\n     */\n    @JvmName(\"get\")\n    @JvmStatic\n    fun JavaNioFileSystem.asOkioFileSystem(): FileSystem = NioFileSystemWrappingFileSystem(this)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/ForwardingSink.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\n\n/** A [Sink] which forwards calls to another. Useful for subclassing. */\nabstract class ForwardingSink(\n  /** [Sink] to which this instance is delegating. */\n  @get:JvmName(\"delegate\")\n  val delegate: Sink,\n) : Sink {\n  // TODO 'Sink by delegate' once https://youtrack.jetbrains.com/issue/KT-23935 is fixed.\n\n  @Throws(IOException::class)\n  override fun write(source: Buffer, byteCount: Long) = delegate.write(source, byteCount)\n\n  @Throws(IOException::class)\n  override fun flush() = delegate.flush()\n\n  override fun timeout() = delegate.timeout()\n\n  @Throws(IOException::class)\n  override fun close() = delegate.close()\n\n  override fun toString() = \"${javaClass.simpleName}($delegate)\"\n\n  @JvmName(\"-deprecated_delegate\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"delegate\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun delegate() = delegate\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/ForwardingSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\n\nactual abstract class ForwardingSource actual constructor(\n  @get:JvmName(\"delegate\")\n  actual val delegate: Source,\n) : Source {\n  // TODO 'Source by delegate' once https://youtrack.jetbrains.com/issue/KT-23935 is fixed.\n\n  @Throws(IOException::class)\n  actual override fun read(sink: Buffer, byteCount: Long): Long = delegate.read(sink, byteCount)\n\n  actual override fun timeout() = delegate.timeout()\n\n  @Throws(IOException::class)\n  actual override fun close() = delegate.close()\n\n  actual override fun toString() = \"${javaClass.simpleName}($delegate)\"\n\n  @JvmName(\"-deprecated_delegate\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"delegate\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun delegate() = delegate\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/ForwardingTimeout.kt",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.locks.Condition\n\n/** A [Timeout] which forwards calls to another. Useful for subclassing.  */\nopen class ForwardingTimeout(\n  @get:JvmName(\"delegate\")\n  @set:JvmSynthetic // So .java callers get the setter that returns this.\n  var delegate: Timeout,\n) : Timeout() {\n\n  // For backwards compatibility with Okio 1.x, this exists so it can return `ForwardingTimeout`.\n  fun setDelegate(delegate: Timeout): ForwardingTimeout {\n    this.delegate = delegate\n    return this\n  }\n\n  override fun timeout(timeout: Long, unit: TimeUnit) = delegate.timeout(timeout, unit)\n\n  override fun timeoutNanos() = delegate.timeoutNanos()\n\n  override fun hasDeadline() = delegate.hasDeadline()\n\n  override fun deadlineNanoTime() = delegate.deadlineNanoTime()\n\n  override fun deadlineNanoTime(deadlineNanoTime: Long) = delegate.deadlineNanoTime(\n    deadlineNanoTime,\n  )\n\n  override fun clearTimeout() = delegate.clearTimeout()\n\n  override fun clearDeadline() = delegate.clearDeadline()\n\n  @Throws(IOException::class)\n  override fun throwIfReached() = delegate.throwIfReached()\n\n  override fun cancel() = delegate.cancel()\n\n  override fun awaitSignal(condition: Condition) = delegate.awaitSignal(condition)\n\n  override fun waitUntilNotified(monitor: Any) = delegate.waitUntilNotified(monitor)\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/HashingSink.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.security.InvalidKeyException\nimport java.security.MessageDigest\nimport javax.crypto.Mac\nimport javax.crypto.spec.SecretKeySpec\n\n/**\n * A sink that computes a hash of the full stream of bytes it has accepted. To use, create an\n * instance with your preferred hash algorithm. Write all of the data to the sink and then call\n * [hash] to compute the final hash value.\n *\n * In this example we use `HashingSink` with a [BufferedSink] to make writing to the\n * sink easier.\n *\n * ```java\n * HashingSink hashingSink = HashingSink.sha256(s);\n * BufferedSink bufferedSink = Okio.buffer(hashingSink);\n *\n * ... // Write to bufferedSink and either flush or close it.\n *\n * ByteString hash = hashingSink.hash();\n * ```\n */\nactual class HashingSink : ForwardingSink, Sink { // Need to explicitly declare sink pending fix for https://youtrack.jetbrains.com/issue/KT-20641\n  private val messageDigest: MessageDigest?\n  private val mac: Mac?\n\n  internal constructor(sink: Sink, digest: MessageDigest) : super(sink) {\n    this.messageDigest = digest\n    this.mac = null\n  }\n\n  internal constructor(sink: Sink, algorithm: String) : this(sink, MessageDigest.getInstance(algorithm))\n\n  internal constructor(sink: Sink, mac: Mac) : super(sink) {\n    this.mac = mac\n    this.messageDigest = null\n  }\n\n  internal constructor(sink: Sink, key: ByteString, algorithm: String) : this(\n    sink,\n    try {\n      Mac.getInstance(algorithm).apply {\n        init(SecretKeySpec(key.toByteArray(), algorithm))\n      }\n    } catch (e: InvalidKeyException) {\n      throw IllegalArgumentException(e)\n    },\n  )\n\n  @Throws(IOException::class)\n  actual override fun write(source: Buffer, byteCount: Long) {\n    checkOffsetAndCount(source.size, 0, byteCount)\n\n    // Hash byteCount bytes from the prefix of source.\n    var hashedCount = 0L\n    var s = source.head!!\n    while (hashedCount < byteCount) {\n      val toHash = minOf(byteCount - hashedCount, s.limit - s.pos).toInt()\n      if (messageDigest != null) {\n        messageDigest.update(s.data, s.pos, toHash)\n      } else {\n        mac!!.update(s.data, s.pos, toHash)\n      }\n      hashedCount += toHash\n      s = s.next!!\n    }\n\n    // Write those bytes to the sink.\n    super.write(source, byteCount)\n  }\n\n  /**\n   * Returns the hash of the bytes accepted thus far and resets the internal state of this sink.\n   *\n   * **Warning:** This method is not idempotent. Each time this method is called its\n   * internal state is cleared. This starts a new hash with zero bytes accepted.\n   */\n  @get:JvmName(\"hash\")\n  actual val hash: ByteString\n    get() {\n      val result = if (messageDigest != null) messageDigest.digest() else mac!!.doFinal()\n      return ByteString(result)\n    }\n\n  @JvmName(\"-deprecated_hash\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"hash\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun hash() = hash\n\n  actual companion object {\n    /**\n     * Returns a sink that uses the obsolete MD5 hash algorithm to produce 128-bit hashes.\n     *\n     * MD5 has been vulnerable to collisions since 2004. It should not be used in new code.\n     */\n    @JvmStatic\n    actual fun md5(sink: Sink) = HashingSink(sink, \"MD5\")\n\n    /**\n     * Returns a sink that uses the obsolete SHA-1 hash algorithm to produce 160-bit hashes.\n     *\n     * SHA-1 has been vulnerable to collisions since 2017. It should not be used in new code.\n     */\n    @JvmStatic\n    actual fun sha1(sink: Sink) = HashingSink(sink, \"SHA-1\")\n\n    /** Returns a sink that uses the SHA-256 hash algorithm to produce 256-bit hashes. */\n    @JvmStatic\n    actual fun sha256(sink: Sink) = HashingSink(sink, \"SHA-256\")\n\n    /** Returns a sink that uses the SHA-512 hash algorithm to produce 512-bit hashes. */\n    @JvmStatic\n    actual fun sha512(sink: Sink) = HashingSink(sink, \"SHA-512\")\n\n    /** Returns a sink that uses the obsolete SHA-1 HMAC algorithm to produce 160-bit hashes. */\n    @JvmStatic\n    actual fun hmacSha1(sink: Sink, key: ByteString) = HashingSink(sink, key, \"HmacSHA1\")\n\n    /** Returns a sink that uses the SHA-256 HMAC algorithm to produce 256-bit hashes. */\n    @JvmStatic\n    actual fun hmacSha256(sink: Sink, key: ByteString) = HashingSink(sink, key, \"HmacSHA256\")\n\n    /** Returns a sink that uses the SHA-512 HMAC algorithm to produce 512-bit hashes. */\n    @JvmStatic\n    actual fun hmacSha512(sink: Sink, key: ByteString) = HashingSink(sink, key, \"HmacSHA512\")\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/HashingSource.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.security.InvalidKeyException\nimport java.security.MessageDigest\nimport javax.crypto.Mac\nimport javax.crypto.spec.SecretKeySpec\n\n/**\n * A source that computes a hash of the full stream of bytes it has supplied. To use, create an\n * instance with your preferred hash algorithm. Exhaust the source by reading all of its bytes and\n * then call [hash] to compute the final hash value.\n *\n *\n * In this example we use `HashingSource` with a [BufferedSource] to make reading\n * from the source easier.\n *\n * ```java\n * HashingSource hashingSource = HashingSource.sha256(rawSource);\n * BufferedSource bufferedSource = Okio.buffer(hashingSource);\n *\n * ... // Read all of bufferedSource.\n *\n * ByteString hash = hashingSource.hash();\n * ```\n */\nactual class HashingSource : ForwardingSource, Source { // Need to explicitly declare source pending fix for https://youtrack.jetbrains.com/issue/KT-20641\n  private val messageDigest: MessageDigest?\n  private val mac: Mac?\n\n  internal constructor(source: Source, digest: MessageDigest) : super(source) {\n    this.messageDigest = digest\n    this.mac = null\n  }\n\n  internal constructor(source: Source, algorithm: String) : this(source, MessageDigest.getInstance(algorithm))\n\n  internal constructor(source: Source, mac: Mac) : super(source) {\n    this.mac = mac\n    this.messageDigest = null\n  }\n\n  internal constructor(source: Source, key: ByteString, algorithm: String) : this(\n    source,\n    try {\n      Mac.getInstance(algorithm).apply {\n        init(SecretKeySpec(key.toByteArray(), algorithm))\n      }\n    } catch (e: InvalidKeyException) {\n      throw IllegalArgumentException(e)\n    },\n  )\n\n  @Throws(IOException::class)\n  actual override fun read(sink: Buffer, byteCount: Long): Long {\n    val result = super.read(sink, byteCount)\n\n    if (result != -1L) {\n      var start = sink.size - result\n\n      // Find the first segment that has new bytes.\n      var offset = sink.size\n      var s = sink.head!!\n      while (offset > start) {\n        s = s.prev!!\n        offset -= (s.limit - s.pos).toLong()\n      }\n\n      // Hash that segment and all the rest until the end.\n      while (offset < sink.size) {\n        val pos = (s.pos + start - offset).toInt()\n        if (messageDigest != null) {\n          messageDigest.update(s.data, pos, s.limit - pos)\n        } else {\n          mac!!.update(s.data, pos, s.limit - pos)\n        }\n        offset += s.limit - s.pos\n        start = offset\n        s = s.next!!\n      }\n    }\n\n    return result\n  }\n\n  /**\n   * Returns the hash of the bytes supplied thus far and resets the internal state of this source.\n   *\n   * **Warning:** This method is not idempotent. Each time this method is called its\n   * internal state is cleared. This starts a new hash with zero bytes supplied.\n   */\n  @get:JvmName(\"hash\")\n  actual val hash: ByteString\n    get() {\n      val result = if (messageDigest != null) messageDigest.digest() else mac!!.doFinal()\n      return ByteString(result)\n    }\n\n  @JvmName(\"-deprecated_hash\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"hash\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun hash() = hash\n\n  actual companion object {\n    /**\n     * Returns a source that uses the obsolete MD5 hash algorithm to produce 128-bit hashes.\n     *\n     * MD5 has been vulnerable to collisions since 2004. It should not be used in new code.\n     */\n    @JvmStatic\n    actual fun md5(source: Source) = HashingSource(source, \"MD5\")\n\n    /**\n     * Returns a source that uses the obsolete SHA-1 hash algorithm to produce 160-bit hashes.\n     *\n     * SHA-1 has been vulnerable to collisions since 2017. It should not be used in new code.\n     */\n    @JvmStatic\n    actual fun sha1(source: Source) = HashingSource(source, \"SHA-1\")\n\n    /** Returns a source that uses the SHA-256 hash algorithm to produce 256-bit hashes. */\n    @JvmStatic\n    actual fun sha256(source: Source) = HashingSource(source, \"SHA-256\")\n\n    /** Returns a source that uses the SHA-512 hash algorithm to produce 512-bit hashes. */\n    @JvmStatic\n    actual fun sha512(source: Source) = HashingSource(source, \"SHA-512\")\n\n    /** Returns a source that uses the obsolete SHA-1 HMAC algorithm to produce 160-bit hashes. */\n    @JvmStatic\n    actual fun hmacSha1(source: Source, key: ByteString) = HashingSource(source, key, \"HmacSHA1\")\n\n    /** Returns a source that uses the SHA-256 HMAC algorithm to produce 256-bit hashes. */\n    @JvmStatic\n    actual fun hmacSha256(source: Source, key: ByteString) = HashingSource(source, key, \"HmacSHA256\")\n\n    /** Returns a source that uses the SHA-512 HMAC algorithm to produce 512-bit hashes. */\n    @JvmStatic\n    actual fun hmacSha512(source: Source, key: ByteString) = HashingSource(source, key, \"HmacSHA512\")\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/InflaterSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\n\n@file:Suppress(\"NOTHING_TO_INLINE\") // Aliases to public API.\n\npackage okio\n\nimport java.io.IOException\nimport java.util.zip.DataFormatException\nimport java.util.zip.Inflater\n\nactual class InflaterSource internal actual constructor(\n  private val source: BufferedSource,\n  private val inflater: Inflater,\n) : Source {\n\n  /**\n   * When we call Inflater.setInput(), the inflater keeps our byte array until it needs input again.\n   * This tracks how many bytes the inflater is currently holding on to.\n   */\n  private var bufferBytesHeldByInflater = 0\n  private var closed = false\n\n  actual constructor(source: Source, inflater: Inflater) : this(source.buffer(), inflater)\n\n  @Throws(IOException::class)\n  actual override fun read(sink: Buffer, byteCount: Long): Long {\n    while (true) {\n      val bytesInflated = readOrInflate(sink, byteCount)\n      if (bytesInflated > 0) return bytesInflated\n      if (inflater.finished() || inflater.needsDictionary()) return -1L\n      if (source.exhausted()) throw EOFException(\"source exhausted prematurely\")\n    }\n  }\n\n  /**\n   * Consume deflated bytes from the underlying source, and write any inflated bytes to [sink].\n   * Returns the number of inflated bytes written to [sink]. This may return 0L, though it will\n   * always consume 1 or more bytes from the underlying source if it is not exhausted.\n   *\n   * Use this instead of [read] when it is useful to consume the deflated stream even when doing so\n   * doesn't yield inflated bytes.\n   */\n  @Throws(IOException::class)\n  fun readOrInflate(sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    check(!closed) { \"closed\" }\n    if (byteCount == 0L) return 0L\n\n    try {\n      // Prepare the destination that we'll write into.\n      val tail = sink.writableSegment(1)\n      val toRead = minOf(byteCount, Segment.SIZE - tail.limit).toInt()\n\n      // Prepare the source that we'll read from.\n      refill()\n\n      // Decompress the inflater's compressed data into the sink.\n      val bytesInflated = inflater.inflate(tail.data, tail.limit, toRead)\n\n      // Release consumed bytes from the source.\n      releaseBytesAfterInflate()\n\n      // Track produced bytes in the destination.\n      if (bytesInflated > 0) {\n        tail.limit += bytesInflated\n        sink.size += bytesInflated\n        return bytesInflated.toLong()\n      }\n\n      // We allocated a tail segment, but didn't end up needing it. Recycle!\n      if (tail.pos == tail.limit) {\n        sink.head = tail.pop()\n        SegmentPool.recycle(tail)\n      }\n\n      return 0L\n    } catch (e: DataFormatException) {\n      throw IOException(e)\n    }\n  }\n\n  /**\n   * Refills the inflater with compressed data if it needs input. (And only if it needs input).\n   * Returns true if the inflater required input but the source was exhausted.\n   */\n  @Throws(IOException::class)\n  fun refill(): Boolean {\n    if (!inflater.needsInput()) return false\n\n    // If there are no further bytes in the source, we cannot refill.\n    if (source.exhausted()) return true\n\n    // Assign buffer bytes to the inflater.\n    val head = source.buffer.head!!\n    bufferBytesHeldByInflater = head.limit - head.pos\n    inflater.setInput(head.data, head.pos, bufferBytesHeldByInflater)\n    return false\n  }\n\n  /** When the inflater has processed compressed data, remove it from the buffer.  */\n  private fun releaseBytesAfterInflate() {\n    if (bufferBytesHeldByInflater == 0) return\n    val toRelease = bufferBytesHeldByInflater - inflater.remaining\n    bufferBytesHeldByInflater -= toRelease\n    source.skip(toRelease.toLong())\n  }\n\n  actual override fun timeout(): Timeout = source.timeout()\n\n  @Throws(IOException::class)\n  actual override fun close() {\n    if (closed) return\n    inflater.end()\n    closed = true\n    source.close()\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/JvmFileHandle.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport java.io.RandomAccessFile\n\ninternal class JvmFileHandle(\n  readWrite: Boolean,\n  private val randomAccessFile: RandomAccessFile,\n) : FileHandle(readWrite) {\n\n  @Synchronized\n  override fun protectedResize(size: Long) {\n    val currentSize = size()\n    val delta = size - currentSize\n    if (delta > 0) {\n      protectedWrite(currentSize, ByteArray(delta.toInt()), 0, delta.toInt())\n    } else {\n      randomAccessFile.setLength(size)\n    }\n  }\n\n  @Synchronized\n  override fun protectedSize(): Long {\n    return randomAccessFile.length()\n  }\n\n  @Synchronized\n  override fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    randomAccessFile.seek(fileOffset)\n    var bytesRead = 0\n    while (bytesRead < byteCount) {\n      val readResult = randomAccessFile.read(array, arrayOffset, byteCount - bytesRead)\n      if (readResult == -1) {\n        if (bytesRead == 0) return -1\n        break\n      }\n      bytesRead += readResult\n    }\n    return bytesRead\n  }\n\n  @Synchronized\n  override fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    randomAccessFile.seek(fileOffset)\n    randomAccessFile.write(array, arrayOffset, byteCount)\n  }\n\n  @Synchronized\n  override fun protectedFlush() {\n    randomAccessFile.fd.sync()\n  }\n\n  @Synchronized\n  override fun protectedClose() {\n    randomAccessFile.close()\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/JvmOkio.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\n\n/** Essential APIs for working with Okio. */\n@file:JvmMultifileClass\n@file:JvmName(\"Okio\")\n\npackage okio\n\nimport java.io.File\nimport java.io.FileNotFoundException\nimport java.io.FileOutputStream\nimport java.io.IOException\nimport java.io.InputStream\nimport java.io.OutputStream\nimport java.net.Socket\nimport java.nio.file.Files\nimport java.nio.file.OpenOption\nimport java.nio.file.Path as NioPath\nimport java.security.MessageDigest\nimport javax.crypto.Cipher\nimport javax.crypto.Mac\nimport okio.internal.DefaultSocket\nimport okio.internal.PipeSocket\nimport okio.internal.ResourceFileSystem\nimport okio.internal.SocketAsyncTimeout\nimport okio.internal.isAndroidGetsocknameError\n\n/** Returns a sink that writes to `out`. */\nfun OutputStream.sink(): Sink = OutputStreamSink(this, Timeout())\n\nprivate class OutputStreamSink(\n  private val out: OutputStream,\n  private val timeout: Timeout,\n) : Sink {\n\n  override fun write(source: Buffer, byteCount: Long) {\n    checkOffsetAndCount(source.size, 0, byteCount)\n    var remaining = byteCount\n    while (remaining > 0) {\n      timeout.throwIfReached()\n      val head = source.head!!\n      val toCopy = minOf(remaining, head.limit - head.pos).toInt()\n      out.write(head.data, head.pos, toCopy)\n\n      head.pos += toCopy\n      remaining -= toCopy\n      source.size -= toCopy\n\n      if (head.pos == head.limit) {\n        source.head = head.pop()\n        SegmentPool.recycle(head)\n      }\n    }\n  }\n\n  override fun flush() = out.flush()\n\n  override fun close() = out.close()\n\n  override fun timeout() = timeout\n\n  override fun toString() = \"sink($out)\"\n}\n\n/** Returns a source that reads from `in`. */\nfun InputStream.source(): Source = InputStreamSource(this, Timeout())\n\nprivate open class InputStreamSource(\n  private val input: InputStream,\n  private val timeout: Timeout,\n) : Source {\n\n  override fun read(sink: Buffer, byteCount: Long): Long {\n    if (byteCount == 0L) return 0L\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    try {\n      timeout.throwIfReached()\n      val tail = sink.writableSegment(1)\n      val maxToCopy = minOf(byteCount, Segment.SIZE - tail.limit).toInt()\n      val bytesRead = input.read(tail.data, tail.limit, maxToCopy)\n      if (bytesRead == -1) {\n        if (tail.pos == tail.limit) {\n          // We allocated a tail segment, but didn't end up needing it. Recycle!\n          sink.head = tail.pop()\n          SegmentPool.recycle(tail)\n        }\n        return -1\n      }\n      tail.limit += bytesRead\n      sink.size += bytesRead\n      return bytesRead.toLong()\n    } catch (e: AssertionError) {\n      if (e.isAndroidGetsocknameError) throw IOException(e)\n      throw e\n    }\n  }\n\n  override fun close() = input.close()\n\n  override fun timeout() = timeout\n\n  override fun toString() = \"source($input)\"\n}\n\n/**\n * Returns a sink that writes to `socket`. Prefer this over [sink]\n * because this method honors timeouts. When the socket\n * write times out, the socket is asynchronously closed by a watchdog thread.\n */\n@Throws(IOException::class)\nfun Socket.sink(): Sink {\n  val timeout = SocketAsyncTimeout(this)\n  val sink = OutputStreamSink(getOutputStream(), timeout)\n  return timeout.sink(sink)\n}\n\n/**\n * Returns a source that reads from `socket`. Prefer this over [source]\n * because this method honors timeouts. When the socket\n * read times out, the socket is asynchronously closed by a watchdog thread.\n */\n@Throws(IOException::class)\nfun Socket.source(): Source {\n  val timeout = SocketAsyncTimeout(this)\n  val source = InputStreamSource(getInputStream(), timeout)\n  return timeout.source(source)\n}\n\n@JvmName(\"socket\")\nfun Socket.asOkioSocket(): okio.Socket = DefaultSocket(this)\n\n/**\n * Returns an array of two symmetric sockets, _A_ (element 0) and _B_ (element 1) that are mutually\n * connected:\n *\n *  * Pipe AB connects _A_’s sink to _B_’s source.\n *  * Pipe BA connects _B_’s sink to _A_’s source.\n *\n * Each pipe uses a buffer to decouple source and sink. This buffer has a user-specified maximum\n * size. When a socket writer outruns its corresponding reader, the buffer fills up and eventually\n * writes to the sink will block until the reader has caught up. Symmetrically, if a reader outruns\n * its writer, reads block until there is data to be read.\n *\n * There is a buffer for Pipe AB and another for Pipe BA. The maximum amount of memory that could be\n * held by the two sockets together is `maxBufferSize * 2`.\n *\n * Limit the amount of time spent waiting for the other party by configuring [timeouts][Timeout] on\n * the source and the sink.\n *\n * When the sink is closed, source reads will continue to complete normally until the buffer is\n * exhausted. At that point reads will return -1, indicating the end of the stream. But if the\n * source is closed first, writes to the sink will immediately fail with an [IOException].\n *\n * Canceling either socket immediately fails all reads and writes on both sockets.\n */\nfun inMemorySocketPair(maxBufferSize: Long): Array<okio.Socket> {\n  val ab = Pipe(maxBufferSize)\n  val ba = Pipe(maxBufferSize)\n  return arrayOf(PipeSocket(ab, ba), PipeSocket(ba, ab))\n}\n\n/** Returns a sink that writes to `file`. */\n@JvmOverloads\n@Throws(FileNotFoundException::class)\nfun File.sink(append: Boolean = false): Sink = FileOutputStream(this, append).sink()\n\n/** Returns a sink that writes to `file`. */\n@Throws(FileNotFoundException::class)\nfun File.appendingSink(): Sink = FileOutputStream(this, true).sink()\n\n/** Returns a source that reads from `file`. */\n@Throws(FileNotFoundException::class)\nfun File.source(): Source = InputStreamSource(inputStream(), Timeout.NONE)\n\n/** Returns a sink that writes to `path`. */\n@Throws(IOException::class)\nfun NioPath.sink(vararg options: OpenOption): Sink =\n  Files.newOutputStream(this, *options).sink()\n\n/** Returns a source that reads from `path`. */\n@Throws(IOException::class)\nfun NioPath.source(vararg options: OpenOption): Source =\n  Files.newInputStream(this, *options).source()\n\n/**\n * Returns a sink that uses [cipher] to encrypt or decrypt [this].\n *\n * @throws IllegalArgumentException if [cipher] isn't a block cipher.\n */\nfun Sink.cipherSink(cipher: Cipher): CipherSink = CipherSink(this.buffer(), cipher)\n\n/**\n * Returns a source that uses [cipher] to encrypt or decrypt [this].\n *\n * @throws IllegalArgumentException if [cipher] isn't a block cipher.\n */\nfun Source.cipherSource(cipher: Cipher): CipherSource = CipherSource(this.buffer(), cipher)\n\n/**\n * Returns a sink that uses [mac] to hash [this].\n */\nfun Sink.hashingSink(mac: Mac): HashingSink = HashingSink(this, mac)\n\n/**\n * Returns a source that uses [mac] to hash [this].\n */\nfun Source.hashingSource(mac: Mac): HashingSource = HashingSource(this, mac)\n\n/**\n * Returns a sink that uses [digest] to hash [this].\n */\nfun Sink.hashingSink(digest: MessageDigest): HashingSink = HashingSink(this, digest)\n\n/**\n * Returns a source that uses [digest] to hash [this].\n */\nfun Source.hashingSource(digest: MessageDigest): HashingSource = HashingSource(this, digest)\n\nfun ClassLoader.asResourceFileSystem(): FileSystem = ResourceFileSystem(this, indexEagerly = true)\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/JvmSystemFileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport java.io.InterruptedIOException\nimport java.io.RandomAccessFile\nimport okio.Path.Companion.toOkioPath\n\n/**\n * A file system that adapts `java.io`.\n *\n * This base class is used on Android API levels 15 (our minimum supported API) through 26\n * (the first release that includes java.nio.file).\n */\ninternal open class JvmSystemFileSystem : FileSystem() {\n  override fun canonicalize(path: Path): Path {\n    val canonicalFile = path.toFile().canonicalFile\n    if (!canonicalFile.exists()) throw FileNotFoundException(\"no such file\")\n    return canonicalFile.toOkioPath()\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    val file = path.toFile()\n    val isRegularFile = file.isFile\n    val isDirectory = file.isDirectory\n    val lastModifiedAtMillis = file.lastModified()\n    val size = file.length()\n\n    if (!isRegularFile &&\n      !isDirectory &&\n      lastModifiedAtMillis == 0L &&\n      size == 0L &&\n      !file.exists()\n    ) {\n      return null\n    }\n\n    return FileMetadata(\n      isRegularFile = isRegularFile,\n      isDirectory = isDirectory,\n      symlinkTarget = null,\n      size = size,\n      createdAtMillis = null,\n      lastModifiedAtMillis = lastModifiedAtMillis,\n      lastAccessedAtMillis = null,\n    )\n  }\n\n  override fun list(dir: Path): List<Path> = list(dir, throwOnFailure = true)!!\n\n  override fun listOrNull(dir: Path): List<Path>? = list(dir, throwOnFailure = false)\n\n  private fun list(dir: Path, throwOnFailure: Boolean): List<Path>? {\n    val file = dir.toFile()\n    val entries = file.list()\n    if (entries == null) {\n      if (throwOnFailure) {\n        if (!file.exists()) throw FileNotFoundException(\"no such file: $dir\")\n        throw IOException(\"failed to list $dir\")\n      } else {\n        return null\n      }\n    }\n    val result = entries.mapTo(mutableListOf()) { dir / it }\n    result.sort()\n    return result\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    return JvmFileHandle(readWrite = false, randomAccessFile = RandomAccessFile(file.toFile(), \"r\"))\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    require(!mustCreate || !mustExist) {\n      \"Cannot require mustCreate and mustExist at the same time.\"\n    }\n    if (mustCreate) file.requireCreate()\n    if (mustExist) file.requireExist()\n    return JvmFileHandle(readWrite = true, randomAccessFile = RandomAccessFile(file.toFile(), \"rw\"))\n  }\n\n  override fun source(file: Path): Source {\n    return file.toFile().source()\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    if (mustCreate) file.requireCreate()\n    return file.toFile().sink()\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    if (mustExist) file.requireExist()\n    return file.toFile().sink(append = true)\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    if (!dir.toFile().mkdir()) {\n      val alreadyExist = metadataOrNull(dir)?.isDirectory == true\n      if (alreadyExist) {\n        if (mustCreate) {\n          throw IOException(\"$dir already exists.\")\n        } else {\n          return\n        }\n      }\n      throw IOException(\"failed to create directory: $dir\")\n    }\n  }\n\n  override fun atomicMove(source: Path, target: Path) {\n    // Note that on Windows, this will fail if [target] already exists.\n    val renamed = source.toFile().renameTo(target.toFile())\n    if (!renamed) throw IOException(\"failed to move $source to $target\")\n  }\n\n  override fun delete(path: Path, mustExist: Boolean) {\n    if (Thread.interrupted()) {\n      // If the current thread has been interrupted.\n      throw InterruptedIOException(\"interrupted\")\n    }\n    val file = path.toFile()\n    val deleted = file.delete()\n    if (!deleted) {\n      if (file.exists()) throw IOException(\"failed to delete $path\")\n      if (mustExist) throw FileNotFoundException(\"no such file: $path\")\n    }\n  }\n\n  override fun createSymlink(source: Path, target: Path) {\n    throw IOException(\"unsupported\")\n  }\n\n  override fun toString() = \"JvmSystemFileSystem\"\n\n  // We have to implement existence verification non-atomically on the JVM because there's no API\n  // to do so.\n  private fun Path.requireExist() {\n    if (!exists(this)) throw IOException(\"$this doesn't exist.\")\n  }\n\n  private fun Path.requireCreate() {\n    if (exists(this)) throw IOException(\"$this already exists.\")\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/NioFileSystemFileHandle.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport java.nio.ByteBuffer\nimport java.nio.channels.FileChannel\n\ninternal class NioFileSystemFileHandle(\n  readWrite: Boolean,\n  private val fileChannel: FileChannel,\n) : FileHandle(readWrite) {\n\n  @Synchronized\n  override fun protectedResize(size: Long) {\n    val currentSize = size()\n    val delta = size - currentSize\n    if (delta > 0) {\n      protectedWrite(currentSize, ByteArray(delta.toInt()), 0, delta.toInt())\n    } else {\n      fileChannel.truncate(size)\n    }\n  }\n\n  @Synchronized\n  override fun protectedSize(): Long {\n    return fileChannel.size()\n  }\n\n  @Synchronized\n  override fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    fileChannel.position(fileOffset)\n    val byteBuffer = ByteBuffer.wrap(array, arrayOffset, byteCount)\n    var bytesRead = 0\n    while (bytesRead < byteCount) {\n      val readResult = fileChannel.read(byteBuffer)\n      if (readResult == -1) {\n        if (bytesRead == 0) return -1\n        break\n      }\n      bytesRead += readResult\n    }\n    return bytesRead\n  }\n\n  @Synchronized\n  override fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    fileChannel.position(fileOffset)\n    val byteBuffer = ByteBuffer.wrap(array, arrayOffset, byteCount)\n    fileChannel.write(byteBuffer)\n  }\n\n  @Synchronized\n  override fun protectedFlush() {\n    fileChannel.force(true)\n  }\n\n  @Synchronized\n  override fun protectedClose() {\n    fileChannel.close()\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/NioFileSystemWrappingFileSystem.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport java.io.InterruptedIOException\nimport java.nio.channels.FileChannel\nimport java.nio.file.FileSystem as NioFileSystem\nimport java.nio.file.NoSuchFileException\nimport java.nio.file.Path as NioPath\nimport java.nio.file.StandardCopyOption\nimport java.nio.file.StandardOpenOption\nimport kotlin.io.path.createDirectory\nimport kotlin.io.path.createSymbolicLinkPointingTo\nimport kotlin.io.path.deleteExisting\nimport kotlin.io.path.exists\nimport kotlin.io.path.inputStream\nimport kotlin.io.path.listDirectoryEntries\nimport kotlin.io.path.moveTo\nimport kotlin.io.path.outputStream\nimport okio.Path.Companion.toOkioPath\n\n/**\n * A file system that wraps a `java.nio.file.FileSystem` and executes all operations in the context of the wrapped file\n * system.\n */\ninternal class NioFileSystemWrappingFileSystem(private val nioFileSystem: NioFileSystem) : NioSystemFileSystem() {\n  /**\n   * On a [java.nio.file.FileSystem], paths are stateful and hold a reference to the file system they got provided from.\n   * Using [getPath][NioFileSystem.getPath], we ask [nioFileSystem] to wrap the [Path]'s value in order to set itself as\n   * its provider which is needed for operations on the nio file system to work properly.\n   */\n  private fun Path.resolve(): NioPath {\n    return nioFileSystem.getPath(toString())\n  }\n\n  override fun canonicalize(path: Path): Path {\n    try {\n      return path.resolve().toRealPath().toOkioPath()\n    } catch (e: NoSuchFileException) {\n      throw FileNotFoundException(\"no such file: $path\")\n    }\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    return metadataOrNull(path.resolve())\n  }\n\n  override fun list(dir: Path): List<Path> = list(dir, throwOnFailure = true)!!\n\n  override fun listOrNull(dir: Path): List<Path>? = list(dir, throwOnFailure = false)\n\n  private fun list(dir: Path, throwOnFailure: Boolean): List<Path>? {\n    val nioDir = dir.resolve()\n    val entries = try {\n      nioDir.listDirectoryEntries()\n    } catch (e: Exception) {\n      if (throwOnFailure) {\n        if (!nioDir.exists()) throw FileNotFoundException(\"no such file: $dir\")\n        throw IOException(\"failed to list $dir\")\n      } else {\n        return null\n      }\n    }\n    val result = entries.mapTo(mutableListOf()) { entry -> entry.toOkioPath() }\n    result.sort()\n    return result\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    val channel = try {\n      FileChannel.open(file.resolve(), StandardOpenOption.READ)\n    } catch (e: NoSuchFileException) {\n      throw FileNotFoundException(\"no such file: $file\")\n    }\n    return NioFileSystemFileHandle(readWrite = false, fileChannel = channel)\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    require(!mustCreate || !mustExist) { \"Cannot require mustCreate and mustExist at the same time.\" }\n    val openOptions = buildList {\n      add(StandardOpenOption.READ)\n      add(StandardOpenOption.WRITE)\n      if (mustCreate) {\n        add(StandardOpenOption.CREATE_NEW)\n      } else if (!mustExist) {\n        add(StandardOpenOption.CREATE)\n      }\n    }\n\n    val channel = try {\n      FileChannel.open(file.resolve(), *openOptions.toTypedArray())\n    } catch (e: NoSuchFileException) {\n      throw FileNotFoundException(\"no such file: $file\")\n    }\n    return NioFileSystemFileHandle(readWrite = true, fileChannel = channel)\n  }\n\n  override fun source(file: Path): Source {\n    try {\n      return file.resolve().inputStream().source()\n    } catch (e: NoSuchFileException) {\n      throw FileNotFoundException(\"no such file: $file\")\n    }\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    val openOptions = buildList {\n      if (mustCreate) add(StandardOpenOption.CREATE_NEW)\n    }\n    try {\n      return file.resolve()\n        .outputStream(*openOptions.toTypedArray())\n        .sink()\n    } catch (e: NoSuchFileException) {\n      throw FileNotFoundException(\"no such file: $file\")\n    }\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    val openOptions = buildList {\n      add(StandardOpenOption.APPEND)\n      if (!mustExist) add(StandardOpenOption.CREATE)\n    }\n    return file.resolve()\n      .outputStream(*openOptions.toTypedArray())\n      .sink()\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    val alreadyExist = metadataOrNull(dir)?.isDirectory == true\n    if (alreadyExist && mustCreate) {\n      throw IOException(\"$dir already exists.\")\n    }\n\n    try {\n      dir.resolve().createDirectory()\n    } catch (e: IOException) {\n      if (alreadyExist) return\n      throw IOException(\"failed to create directory: $dir\", e)\n    }\n  }\n\n  // Note that `java.nio.file.FileSystem` allows atomic moves of a file even if the target is an existing directory.\n  override fun atomicMove(source: Path, target: Path) {\n    try {\n      source.resolve().moveTo(\n        target.resolve(),\n        StandardCopyOption.ATOMIC_MOVE,\n        StandardCopyOption.REPLACE_EXISTING,\n      )\n    } catch (e: NoSuchFileException) {\n      throw FileNotFoundException(e.message)\n    } catch (e: UnsupportedOperationException) {\n      throw IOException(\"atomic move not supported\")\n    }\n  }\n\n  override fun delete(path: Path, mustExist: Boolean) {\n    if (Thread.interrupted()) {\n      // If the current thread has been interrupted.\n      throw InterruptedIOException(\"interrupted\")\n    }\n    val nioPath = path.resolve()\n    try {\n      nioPath.deleteExisting()\n    } catch (e: NoSuchFileException) {\n      if (mustExist) throw FileNotFoundException(\"no such file: $path\")\n    } catch (e: IOException) {\n      if (nioPath.exists()) throw IOException(\"failed to delete $path\")\n    }\n  }\n\n  override fun createSymlink(source: Path, target: Path) {\n    source.resolve().createSymbolicLinkPointingTo(target.resolve())\n  }\n\n  override fun close() {\n    nioFileSystem.close()\n  }\n\n  override fun toString() = nioFileSystem::class.simpleName!!\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/NioSystemFileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport java.nio.file.FileSystemException\nimport java.nio.file.Files\nimport java.nio.file.LinkOption\nimport java.nio.file.NoSuchFileException\nimport java.nio.file.Path as NioPath\nimport java.nio.file.StandardCopyOption.ATOMIC_MOVE\nimport java.nio.file.StandardCopyOption.REPLACE_EXISTING\nimport java.nio.file.attribute.BasicFileAttributes\nimport java.nio.file.attribute.FileTime\nimport okio.Path.Companion.toOkioPath\n\n/**\n * Extends [JvmSystemFileSystem] for platforms that support `java.nio.file` first introduced in\n * Java 7 and Android 8.0 (API level 26).\n */\ninternal open class NioSystemFileSystem : JvmSystemFileSystem() {\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    return metadataOrNull(path.toNioPath())\n  }\n\n  protected fun metadataOrNull(nioPath: NioPath): FileMetadata? {\n    val attributes = try {\n      Files.readAttributes(\n        nioPath,\n        BasicFileAttributes::class.java,\n        LinkOption.NOFOLLOW_LINKS,\n      )\n    } catch (_: NoSuchFileException) {\n      return null\n    } catch (_: FileSystemException) {\n      return null\n    }\n\n    val symlinkTarget: NioPath? = if (attributes.isSymbolicLink) {\n      Files.readSymbolicLink(nioPath)\n    } else {\n      null\n    }\n\n    return FileMetadata(\n      isRegularFile = attributes.isRegularFile,\n      isDirectory = attributes.isDirectory,\n      symlinkTarget = symlinkTarget?.toOkioPath(),\n      size = attributes.size(),\n      createdAtMillis = attributes.creationTime()?.zeroToNull(),\n      lastModifiedAtMillis = attributes.lastModifiedTime()?.zeroToNull(),\n      lastAccessedAtMillis = attributes.lastAccessTime()?.zeroToNull(),\n    )\n  }\n\n  /**\n   * Returns this time as an epoch millis. If this is 0L this returns null, because epoch time 0L is\n   * a special value that indicates the requested time was not available.\n   */\n  private fun FileTime.zeroToNull(): Long? {\n    return toMillis().takeIf { it != 0L }\n  }\n\n  override fun atomicMove(source: Path, target: Path) {\n    try {\n      Files.move(source.toNioPath(), target.toNioPath(), ATOMIC_MOVE, REPLACE_EXISTING)\n    } catch (e: NoSuchFileException) {\n      throw FileNotFoundException(e.message)\n    } catch (e: UnsupportedOperationException) {\n      throw IOException(\"atomic move not supported\")\n    }\n  }\n\n  override fun createSymlink(source: Path, target: Path) {\n    Files.createSymbolicLink(source.toNioPath(), target.toNioPath())\n  }\n\n  override fun toString() = \"NioSystemFileSystem\"\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/Path.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport java.io.File\nimport java.nio.file.Path as NioPath\nimport java.nio.file.Paths\nimport okio.internal.commonCompareTo\nimport okio.internal.commonEquals\nimport okio.internal.commonHashCode\nimport okio.internal.commonIsAbsolute\nimport okio.internal.commonIsRelative\nimport okio.internal.commonIsRoot\nimport okio.internal.commonName\nimport okio.internal.commonNameBytes\nimport okio.internal.commonNormalized\nimport okio.internal.commonParent\nimport okio.internal.commonRelativeTo\nimport okio.internal.commonResolve\nimport okio.internal.commonRoot\nimport okio.internal.commonSegments\nimport okio.internal.commonSegmentsBytes\nimport okio.internal.commonToPath\nimport okio.internal.commonToString\nimport okio.internal.commonVolumeLetter\n\nactual class Path internal actual constructor(\n  internal actual val bytes: ByteString,\n) : Comparable<Path> {\n  actual val root: Path?\n    get() = commonRoot()\n\n  actual val segments: List<String>\n    get() = commonSegments()\n\n  actual val segmentsBytes: List<ByteString>\n    get() = commonSegmentsBytes()\n\n  actual val isAbsolute: Boolean\n    get() = commonIsAbsolute()\n\n  actual val isRelative: Boolean\n    get() = commonIsRelative()\n\n  @get:JvmName(\"volumeLetter\")\n  actual val volumeLetter: Char?\n    get() = commonVolumeLetter()\n\n  @get:JvmName(\"nameBytes\")\n  actual val nameBytes: ByteString\n    get() = commonNameBytes()\n\n  @get:JvmName(\"name\")\n  actual val name: String\n    get() = commonName()\n\n  @get:JvmName(\"parent\")\n  actual val parent: Path?\n    get() = commonParent()\n\n  actual val isRoot: Boolean\n    get() = commonIsRoot()\n\n  @JvmName(\"resolve\")\n  actual operator fun div(child: String): Path = commonResolve(child, normalize = false)\n\n  @JvmName(\"resolve\")\n  actual operator fun div(child: ByteString): Path = commonResolve(child, normalize = false)\n\n  @JvmName(\"resolve\")\n  actual operator fun div(child: Path): Path = commonResolve(child, normalize = false)\n\n  actual fun resolve(child: String, normalize: Boolean): Path =\n    commonResolve(child, normalize = normalize)\n\n  actual fun resolve(child: ByteString, normalize: Boolean): Path =\n    commonResolve(child, normalize = normalize)\n\n  actual fun resolve(child: Path, normalize: Boolean): Path =\n    commonResolve(child = child, normalize = normalize)\n\n  actual fun relativeTo(other: Path): Path = commonRelativeTo(other)\n\n  actual fun normalized(): Path = commonNormalized()\n\n  fun toFile(): File = File(toString())\n\n  // Can only be invoked on platforms that have java.nio.file.\n  fun toNioPath(): NioPath = Paths.get(toString())\n\n  actual override fun compareTo(other: Path): Int = commonCompareTo(other)\n\n  actual override fun equals(other: Any?): Boolean = commonEquals(other)\n\n  actual override fun hashCode() = commonHashCode()\n\n  actual override fun toString() = commonToString()\n\n  actual companion object {\n    @JvmField\n    actual val DIRECTORY_SEPARATOR: String = File.separator\n\n    @JvmName(\"get\")\n    @JvmStatic\n    @JvmOverloads\n    actual fun String.toPath(normalize: Boolean): Path = commonToPath(normalize)\n\n    @JvmName(\"get\")\n    @JvmStatic\n    @JvmOverloads\n    fun File.toOkioPath(normalize: Boolean = false): Path = toString().toPath(normalize)\n\n    @JvmName(\"get\")\n    @JvmStatic\n    @JvmOverloads\n    fun NioPath.toOkioPath(normalize: Boolean = false): Path = toString().toPath(normalize)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/Pipe.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport java.util.concurrent.locks.Condition\nimport java.util.concurrent.locks.ReentrantLock\nimport kotlin.concurrent.withLock\n\n/**\n * A source and a sink that are attached. The sink's output is the source's input. Typically each\n * is accessed by its own thread: a producer thread writes data to the sink and a consumer thread\n * reads data from the source.\n *\n * This class uses a buffer to decouple source and sink. This buffer has a user-specified maximum\n * size. When a producer thread outruns its consumer the buffer fills up and eventually writes to\n * the sink will block until the consumer has caught up. Symmetrically, if a consumer outruns its\n * producer reads block until there is data to be read. Limits on the amount of time spent waiting\n * for the other party can be configured with [timeouts][Timeout] on the source and the\n * sink.\n *\n * When the sink is closed, source reads will continue to complete normally until the buffer has\n * been exhausted. At that point reads will return -1, indicating the end of the stream. But if the\n * source is closed first, writes to the sink will immediately fail with an [IOException].\n *\n * A pipe may be canceled to immediately fail writes to the sink and reads from the source.\n */\nclass Pipe(internal val maxBufferSize: Long) {\n  internal val buffer = Buffer()\n  internal var canceled = false\n  internal var sinkClosed = false\n  internal var sourceClosed = false\n  internal var foldedSink: Sink? = null\n\n  val lock: ReentrantLock = ReentrantLock()\n  val condition: Condition = lock.newCondition()\n\n  init {\n    require(maxBufferSize >= 1L) { \"maxBufferSize < 1: $maxBufferSize\" }\n  }\n\n  @get:JvmName(\"sink\")\n  val sink = object : Sink {\n    private val timeout = Timeout()\n\n    override fun write(source: Buffer, byteCount: Long) {\n      var byteCount = byteCount\n      var delegate: Sink? = null\n      lock.withLock {\n        check(!sinkClosed) { \"closed\" }\n        if (canceled) throw IOException(\"canceled\")\n\n        while (byteCount > 0) {\n          foldedSink?.let {\n            delegate = it\n            return@withLock\n          }\n\n          if (sourceClosed) throw IOException(\"source is closed\")\n\n          val bufferSpaceAvailable = maxBufferSize - buffer.size\n          if (bufferSpaceAvailable == 0L) {\n            timeout.awaitSignal(condition) // Wait until the source drains the buffer.\n            if (canceled) throw IOException(\"canceled\")\n            continue\n          }\n\n          val bytesToWrite = minOf(bufferSpaceAvailable, byteCount)\n          buffer.write(source, bytesToWrite)\n          byteCount -= bytesToWrite\n          condition.signalAll() // Notify the source that it can resume reading.\n        }\n      }\n\n      delegate?.forward { write(source, byteCount) }\n    }\n\n    override fun flush() {\n      var delegate: Sink? = null\n      lock.withLock {\n        check(!sinkClosed) { \"closed\" }\n        if (canceled) throw IOException(\"canceled\")\n\n        foldedSink?.let {\n          delegate = it\n          return@withLock\n        }\n\n        if (sourceClosed && buffer.size > 0L) {\n          throw IOException(\"source is closed\")\n        }\n      }\n\n      delegate?.forward { flush() }\n    }\n\n    override fun close() {\n      var delegate: Sink? = null\n      lock.withLock {\n        if (sinkClosed) return\n\n        foldedSink?.let {\n          delegate = it\n          return@withLock\n        }\n\n        if (sourceClosed && buffer.size > 0L) throw IOException(\"source is closed\")\n        sinkClosed = true\n        condition.signalAll() // Notify the source that no more bytes are coming.\n      }\n\n      delegate?.forward { close() }\n    }\n\n    override fun timeout(): Timeout = timeout\n  }\n\n  @get:JvmName(\"source\")\n  val source = object : Source {\n    private val timeout = Timeout()\n\n    override fun read(sink: Buffer, byteCount: Long): Long {\n      lock.withLock {\n        check(!sourceClosed) { \"closed\" }\n        if (canceled) throw IOException(\"canceled\")\n\n        while (buffer.size == 0L) {\n          if (sinkClosed) return -1L\n          timeout.awaitSignal(condition) // Wait until the sink fills the buffer.\n          if (canceled) throw IOException(\"canceled\")\n        }\n\n        val result = buffer.read(sink, byteCount)\n        condition.signalAll() // Notify the sink that it can resume writing.\n        return result\n      }\n    }\n\n    override fun close() {\n      lock.withLock {\n        sourceClosed = true\n        condition.signalAll() // Notify the sink that no more bytes are desired.\n      }\n    }\n\n    override fun timeout(): Timeout = timeout\n  }\n\n  /**\n   * Writes any buffered contents of this pipe to `sink`, then replace this pipe's source with\n   * `sink`. This pipe's source is closed and attempts to read it will throw an\n   * [IllegalStateException].\n   *\n   * This method must not be called while concurrently accessing this pipe's source. It is safe,\n   * however, to call this while concurrently writing this pipe's sink.\n   */\n  @Throws(IOException::class)\n  fun fold(sink: Sink) {\n    while (true) {\n      // Either the buffer is empty and we can swap and return. Or the buffer is non-empty and we\n      // must copy it to sink without holding any locks, then try it all again.\n      var closed = false\n      var done = false\n      lateinit var sinkBuffer: Buffer\n      lock.withLock {\n        check(foldedSink == null) { \"sink already folded\" }\n\n        if (canceled) {\n          foldedSink = sink\n          throw IOException(\"canceled\")\n        }\n\n        closed = sinkClosed\n        if (buffer.exhausted()) {\n          sourceClosed = true\n          foldedSink = sink\n          done = true\n          return@withLock\n        }\n\n        sinkBuffer = Buffer()\n        sinkBuffer.write(buffer, buffer.size)\n        condition.signalAll() // Notify the sink that it can resume writing.\n      }\n\n      if (done) {\n        if (closed) {\n          sink.close()\n        }\n        return\n      }\n\n      var success = false\n      try {\n        sink.write(sinkBuffer, sinkBuffer.size)\n        sink.flush()\n        success = true\n      } finally {\n        if (!success) {\n          lock.withLock {\n            sourceClosed = true\n            condition.signalAll() // Notify the sink that it can resume writing.\n          }\n        }\n      }\n    }\n  }\n\n  private inline fun Sink.forward(block: Sink.() -> Unit) {\n    this.timeout().intersectWith(this@Pipe.sink.timeout()) { this.block() }\n  }\n\n  @JvmName(\"-deprecated_sink\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"sink\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun sink() = sink\n\n  @JvmName(\"-deprecated_source\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"source\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun source() = source\n\n  /**\n   * Fail any in-flight and future operations. After canceling:\n   *\n   *  * Any attempt to write or flush [sink] will fail immediately with an [IOException].\n   *  * Any attempt to read [source] will fail immediately with an [IOException].\n   *  * Any attempt to [fold] will fail immediately with an [IOException].\n   *\n   * Closing the source and the sink will complete normally even after a pipe has been canceled. If\n   * this sink has been folded, closing it will close the folded sink. This operation may block.\n   *\n   * This operation may be called by any thread at any time. It is safe to call concurrently while\n   * operating on the source or the sink.\n   */\n  fun cancel() {\n    lock.withLock {\n      canceled = true\n      buffer.clear()\n      condition.signalAll() // Notify the source and sink that they're canceled.\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/RealBufferedSink.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.OutputStream\nimport java.nio.ByteBuffer\nimport java.nio.charset.Charset\nimport okio.internal.commonClose\nimport okio.internal.commonEmit\nimport okio.internal.commonEmitCompleteSegments\nimport okio.internal.commonFlush\nimport okio.internal.commonTimeout\nimport okio.internal.commonToString\nimport okio.internal.commonWrite\nimport okio.internal.commonWriteAll\nimport okio.internal.commonWriteByte\nimport okio.internal.commonWriteDecimalLong\nimport okio.internal.commonWriteHexadecimalUnsignedLong\nimport okio.internal.commonWriteInt\nimport okio.internal.commonWriteIntLe\nimport okio.internal.commonWriteLong\nimport okio.internal.commonWriteLongLe\nimport okio.internal.commonWriteShort\nimport okio.internal.commonWriteShortLe\nimport okio.internal.commonWriteUtf8\nimport okio.internal.commonWriteUtf8CodePoint\n\ninternal actual class RealBufferedSink actual constructor(\n  @JvmField actual val sink: Sink,\n) : BufferedSink {\n  @JvmField val bufferField = Buffer()\n\n  @JvmField actual var closed: Boolean = false\n\n  @Suppress(\"OVERRIDE_BY_INLINE\") // Prevent internal code from calling the getter.\n  actual override val buffer: Buffer\n    inline get() = bufferField\n\n  override fun buffer() = bufferField\n\n  actual override fun write(source: Buffer, byteCount: Long) = commonWrite(source, byteCount)\n  actual override fun write(byteString: ByteString) = commonWrite(byteString)\n  actual override fun write(byteString: ByteString, offset: Int, byteCount: Int) =\n    commonWrite(byteString, offset, byteCount)\n  actual override fun writeUtf8(string: String) = commonWriteUtf8(string)\n  actual override fun writeUtf8(string: String, beginIndex: Int, endIndex: Int) =\n    commonWriteUtf8(string, beginIndex, endIndex)\n\n  actual override fun writeUtf8CodePoint(codePoint: Int) = commonWriteUtf8CodePoint(codePoint)\n\n  override fun writeString(string: String, charset: Charset): BufferedSink {\n    check(!closed) { \"closed\" }\n    buffer.writeString(string, charset)\n    return emitCompleteSegments()\n  }\n\n  override fun writeString(\n    string: String,\n    beginIndex: Int,\n    endIndex: Int,\n    charset: Charset,\n  ): BufferedSink {\n    check(!closed) { \"closed\" }\n    buffer.writeString(string, beginIndex, endIndex, charset)\n    return emitCompleteSegments()\n  }\n\n  actual override fun write(source: ByteArray) = commonWrite(source)\n  actual override fun write(source: ByteArray, offset: Int, byteCount: Int) =\n    commonWrite(source, offset, byteCount)\n\n  override fun write(source: ByteBuffer): Int {\n    check(!closed) { \"closed\" }\n    val result = buffer.write(source)\n    emitCompleteSegments()\n    return result\n  }\n\n  actual override fun writeAll(source: Source) = commonWriteAll(source)\n  actual override fun write(source: Source, byteCount: Long): BufferedSink = commonWrite(source, byteCount)\n  actual override fun writeByte(b: Int) = commonWriteByte(b)\n  actual override fun writeShort(s: Int) = commonWriteShort(s)\n  actual override fun writeShortLe(s: Int) = commonWriteShortLe(s)\n  actual override fun writeInt(i: Int) = commonWriteInt(i)\n  actual override fun writeIntLe(i: Int) = commonWriteIntLe(i)\n  actual override fun writeLong(v: Long) = commonWriteLong(v)\n  actual override fun writeLongLe(v: Long) = commonWriteLongLe(v)\n  actual override fun writeDecimalLong(v: Long) = commonWriteDecimalLong(v)\n  actual override fun writeHexadecimalUnsignedLong(v: Long) = commonWriteHexadecimalUnsignedLong(v)\n  actual override fun emitCompleteSegments() = commonEmitCompleteSegments()\n  actual override fun emit() = commonEmit()\n\n  override fun outputStream(): OutputStream {\n    return object : OutputStream() {\n      override fun write(b: Int) {\n        if (closed) throw IOException(\"closed\")\n        buffer.writeByte(b.toByte().toInt())\n        emitCompleteSegments()\n      }\n\n      override fun write(data: ByteArray, offset: Int, byteCount: Int) {\n        if (closed) throw IOException(\"closed\")\n        buffer.write(data, offset, byteCount)\n        emitCompleteSegments()\n      }\n\n      override fun flush() {\n        // For backwards compatibility, a flush() on a closed stream is a no-op.\n        if (!closed) {\n          this@RealBufferedSink.flush()\n        }\n      }\n\n      override fun close() = this@RealBufferedSink.close()\n\n      override fun toString() = \"${this@RealBufferedSink}.outputStream()\"\n    }\n  }\n\n  actual override fun flush() = commonFlush()\n\n  override fun isOpen() = !closed\n\n  actual override fun close() = commonClose()\n  actual override fun timeout() = commonTimeout()\n  override fun toString() = commonToString()\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/RealBufferedSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.InputStream\nimport java.io.OutputStream\nimport java.nio.ByteBuffer\nimport java.nio.charset.Charset\nimport okio.internal.commonClose\nimport okio.internal.commonExhausted\nimport okio.internal.commonIndexOf\nimport okio.internal.commonIndexOfElement\nimport okio.internal.commonPeek\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonRead\nimport okio.internal.commonReadAll\nimport okio.internal.commonReadByte\nimport okio.internal.commonReadByteArray\nimport okio.internal.commonReadByteString\nimport okio.internal.commonReadDecimalLong\nimport okio.internal.commonReadFully\nimport okio.internal.commonReadHexadecimalUnsignedLong\nimport okio.internal.commonReadInt\nimport okio.internal.commonReadIntLe\nimport okio.internal.commonReadLong\nimport okio.internal.commonReadLongLe\nimport okio.internal.commonReadShort\nimport okio.internal.commonReadShortLe\nimport okio.internal.commonReadUtf8\nimport okio.internal.commonReadUtf8CodePoint\nimport okio.internal.commonReadUtf8Line\nimport okio.internal.commonReadUtf8LineStrict\nimport okio.internal.commonRequest\nimport okio.internal.commonRequire\nimport okio.internal.commonSelect\nimport okio.internal.commonSkip\nimport okio.internal.commonTimeout\nimport okio.internal.commonToString\n\ninternal actual class RealBufferedSource actual constructor(\n  @JvmField actual val source: Source,\n) : BufferedSource {\n  @JvmField val bufferField = Buffer()\n\n  @JvmField actual var closed: Boolean = false\n\n  @Suppress(\"OVERRIDE_BY_INLINE\") // Prevent internal code from calling the getter.\n  actual override val buffer: Buffer\n    inline get() = bufferField\n\n  override fun buffer() = bufferField\n\n  actual override fun read(sink: Buffer, byteCount: Long): Long = commonRead(sink, byteCount)\n  actual override fun exhausted(): Boolean = commonExhausted()\n  actual override fun require(byteCount: Long): Unit = commonRequire(byteCount)\n  actual override fun request(byteCount: Long): Boolean = commonRequest(byteCount)\n  actual override fun readByte(): Byte = commonReadByte()\n  actual override fun readByteString(): ByteString = commonReadByteString()\n  actual override fun readByteString(byteCount: Long): ByteString = commonReadByteString(byteCount)\n  actual override fun select(options: Options): Int = commonSelect(options)\n  actual override fun <T : Any> select(options: TypedOptions<T>): T? = commonSelect(options)\n  actual override fun readByteArray(): ByteArray = commonReadByteArray()\n  actual override fun readByteArray(byteCount: Long): ByteArray = commonReadByteArray(byteCount)\n  actual override fun read(sink: ByteArray): Int = read(sink, 0, sink.size)\n  actual override fun readFully(sink: ByteArray): Unit = commonReadFully(sink)\n  actual override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int =\n    commonRead(sink, offset, byteCount)\n\n  override fun read(sink: ByteBuffer): Int {\n    if (buffer.size == 0L) {\n      val read = source.read(buffer, Segment.SIZE.toLong())\n      if (read == -1L) return -1\n    }\n\n    return buffer.read(sink)\n  }\n\n  actual override fun readFully(sink: Buffer, byteCount: Long): Unit =\n    commonReadFully(sink, byteCount)\n  actual override fun readAll(sink: Sink): Long = commonReadAll(sink)\n  actual override fun readUtf8(): String = commonReadUtf8()\n  actual override fun readUtf8(byteCount: Long): String = commonReadUtf8(byteCount)\n\n  override fun readString(charset: Charset): String {\n    buffer.writeAll(source)\n    return buffer.readString(charset)\n  }\n\n  override fun readString(byteCount: Long, charset: Charset): String {\n    require(byteCount)\n    return buffer.readString(byteCount, charset)\n  }\n\n  actual override fun readUtf8Line(): String? = commonReadUtf8Line()\n  actual override fun readUtf8LineStrict() = readUtf8LineStrict(Long.MAX_VALUE)\n  actual override fun readUtf8LineStrict(limit: Long): String = commonReadUtf8LineStrict(limit)\n  actual override fun readUtf8CodePoint(): Int = commonReadUtf8CodePoint()\n  actual override fun readShort(): Short = commonReadShort()\n  actual override fun readShortLe(): Short = commonReadShortLe()\n  actual override fun readInt(): Int = commonReadInt()\n  actual override fun readIntLe(): Int = commonReadIntLe()\n  actual override fun readLong(): Long = commonReadLong()\n  actual override fun readLongLe(): Long = commonReadLongLe()\n  actual override fun readDecimalLong(): Long = commonReadDecimalLong()\n  actual override fun readHexadecimalUnsignedLong(): Long = commonReadHexadecimalUnsignedLong()\n  actual override fun skip(byteCount: Long): Unit = commonSkip(byteCount)\n  actual override fun indexOf(b: Byte): Long = indexOf(b, 0L, Long.MAX_VALUE)\n  actual override fun indexOf(b: Byte, fromIndex: Long): Long =\n    indexOf(b, fromIndex, Long.MAX_VALUE)\n  actual override fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(b, fromIndex = fromIndex, toIndex = toIndex)\n\n  actual override fun indexOf(bytes: ByteString): Long = indexOf(bytes, 0L)\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long): Long =\n    indexOf(bytes, fromIndex, Long.MAX_VALUE)\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(bytes, fromIndex = fromIndex, toIndex = toIndex)\n  actual override fun indexOfElement(targetBytes: ByteString): Long =\n    indexOfElement(targetBytes, 0L)\n  actual override fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long =\n    commonIndexOfElement(targetBytes, fromIndex)\n\n  actual override fun rangeEquals(offset: Long, bytes: ByteString) = rangeEquals(\n    offset,\n    bytes,\n    0,\n    bytes.size,\n  )\n\n  actual override fun rangeEquals(\n    offset: Long,\n    bytes: ByteString,\n    bytesOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, bytes, bytesOffset, byteCount)\n\n  actual override fun peek(): BufferedSource = commonPeek()\n\n  override fun inputStream(): InputStream {\n    return object : InputStream() {\n      override fun read(): Int {\n        if (closed) throw IOException(\"closed\")\n        if (buffer.size == 0L) {\n          val count = source.read(buffer, Segment.SIZE.toLong())\n          if (count == -1L) return -1\n        }\n        return buffer.readByte() and 0xff\n      }\n\n      override fun read(data: ByteArray, offset: Int, byteCount: Int): Int {\n        if (closed) throw IOException(\"closed\")\n        checkOffsetAndCount(data.size.toLong(), offset.toLong(), byteCount.toLong())\n\n        if (buffer.size == 0L) {\n          val count = source.read(buffer, Segment.SIZE.toLong())\n          if (count == -1L) return -1\n        }\n\n        return buffer.read(data, offset, byteCount)\n      }\n\n      override fun available(): Int {\n        if (closed) throw IOException(\"closed\")\n        return minOf(buffer.size, Integer.MAX_VALUE).toInt()\n      }\n\n      override fun close() = this@RealBufferedSource.close()\n\n      override fun toString() = \"${this@RealBufferedSource}.inputStream()\"\n\n      override fun transferTo(out: OutputStream): Long {\n        if (closed) throw IOException(\"closed\")\n        var count = 0L\n        while (true) {\n          if (buffer.size == 0L) {\n            val read = source.read(buffer, Segment.SIZE.toLong())\n            if (read == -1L) break\n          }\n          count += buffer.size\n          buffer.writeTo(out)\n        }\n        return count\n      }\n    }\n  }\n\n  override fun isOpen() = !closed\n\n  actual override fun close(): Unit = commonClose()\n  actual override fun timeout(): Timeout = commonTimeout()\n  override fun toString(): String = commonToString()\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/SegmentPool.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.util.concurrent.atomic.AtomicReference\nimport okio.SegmentPool.LOCK\nimport okio.SegmentPool.recycle\nimport okio.SegmentPool.take\n\n/**\n * This class pools segments in a lock-free singly-linked stack. Though this code is lock-free it\n * does use a sentinel [LOCK] value to defend against races. Conflicted operations are not retried,\n * so there is no chance of blocking despite the term \"lock\".\n *\n * On [take], a caller swaps the stack's next pointer with the [LOCK] sentinel. If the stack was\n * not already locked, the caller replaces the head node with its successor.\n *\n * On [recycle], a caller swaps the stack's next pointer with the [LOCK] sentinel. If the stack was\n * not already locked, the caller replaces the head node with a new node whose successor is the\n * replaced head.\n *\n * On conflict, operations succeed, but segments are not pushed into the stack. For example, a\n * [take] that loses a race allocates a new segment regardless of the pool size. A [recycle] call\n * that loses a race will not increase the size of the pool. Under significant contention, this pool\n * will have fewer hits and the VM will do more GC and zero filling of arrays.\n *\n * This tracks the number of bytes in each linked list in its [Segment.limit] property. Each element\n * has a limit that's one segment size greater than its successor element. The maximum size of the\n * pool is a product of [MAX_SIZE] and [HASH_BUCKET_COUNT].\n */\ninternal actual object SegmentPool {\n  /** The maximum number of bytes to pool per hash bucket. */\n  // TODO: Is 64 KiB a good maximum size? Do we ever have that many idle segments?\n  actual val MAX_SIZE = 64 * 1024 // 64 KiB.\n\n  /** A sentinel segment to indicate that the linked list is currently being modified. */\n  private val LOCK = Segment(ByteArray(0), pos = 0, limit = 0, shared = false, owner = false)\n\n  /**\n   * The number of hash buckets. This number needs to balance keeping the pool small and contention\n   * low. We use the number of processors rounded up to the nearest power of two. For example a\n   * machine with 6 cores will have 8 hash buckets.\n   */\n  private val HASH_BUCKET_COUNT =\n    Integer.highestOneBit(Runtime.getRuntime().availableProcessors() * 2 - 1)\n\n  /**\n   * Hash buckets each contain a singly-linked list of segments. The index/key is a hash function of\n   * thread ID because it may reduce contention or increase locality.\n   *\n   * We don't use [ThreadLocal] because we don't know how many threads the host process has and we\n   * don't want to leak memory for the duration of a thread's life.\n   */\n  private val hashBuckets: Array<AtomicReference<Segment?>> = Array(HASH_BUCKET_COUNT) {\n    AtomicReference<Segment?>() // null value implies an empty bucket\n  }\n\n  actual val byteCount: Int\n    get() {\n      val first = firstRef().get() ?: return 0\n      return first.limit\n    }\n\n  @JvmStatic\n  actual fun take(): Segment {\n    val firstRef = firstRef()\n\n    val first = firstRef.getAndSet(LOCK)\n    when {\n      first === LOCK -> {\n        // We didn't acquire the lock. Don't take a pooled segment.\n        return Segment()\n      }\n      first == null -> {\n        // We acquired the lock but the pool was empty. Unlock and return a new segment.\n        firstRef.set(null)\n        return Segment()\n      }\n      else -> {\n        // We acquired the lock and the pool was not empty. Pop the first element and return it.\n        firstRef.set(first.next)\n        first.next = null\n        first.limit = 0\n        return first\n      }\n    }\n  }\n\n  @JvmStatic\n  actual fun recycle(segment: Segment) {\n    require(segment.next == null && segment.prev == null)\n    if (segment.shared) return // This segment cannot be recycled.\n\n    val firstRef = firstRef()\n\n    val first = firstRef.getAndSet(LOCK)\n    if (first === LOCK) return // A take() or recycle() is currently in progress.\n    val firstLimit = first?.limit ?: 0\n    if (firstLimit >= MAX_SIZE) {\n      firstRef.set(first) // Pool is full.\n      return\n    }\n\n    segment.next = first\n    segment.pos = 0\n    segment.limit = firstLimit + Segment.SIZE\n\n    firstRef.set(segment)\n  }\n\n  private fun firstRef(): AtomicReference<Segment?> {\n    // Get a value in [0..HASH_BUCKET_COUNT) based on the current thread.\n    val hashBucket = (Thread.currentThread().id and (HASH_BUCKET_COUNT - 1L)).toInt()\n    return hashBuckets[hashBucket]\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/SegmentedByteString.kt",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.OutputStream\nimport java.nio.ByteBuffer\nimport java.nio.charset.Charset\nimport java.security.InvalidKeyException\nimport java.security.MessageDigest\nimport javax.crypto.Mac\nimport javax.crypto.spec.SecretKeySpec\nimport okio.internal.commonCopyInto\nimport okio.internal.commonEquals\nimport okio.internal.commonGetSize\nimport okio.internal.commonHashCode\nimport okio.internal.commonInternalGet\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonSubstring\nimport okio.internal.commonToByteArray\nimport okio.internal.commonWrite\nimport okio.internal.forEachSegment\n\ninternal actual class SegmentedByteString internal actual constructor(\n  @Transient internal actual val segments: Array<ByteArray>,\n  @Transient internal actual val directory: IntArray,\n) : ByteString(EMPTY.data) {\n\n  override fun string(charset: Charset) = toByteString().string(charset)\n\n  override fun base64() = toByteString().base64()\n\n  override fun hex() = toByteString().hex()\n\n  override fun toAsciiLowercase() = toByteString().toAsciiLowercase()\n\n  override fun toAsciiUppercase() = toByteString().toAsciiUppercase()\n\n  override fun digest(algorithm: String): ByteString {\n    val digestBytes = MessageDigest.getInstance(algorithm).run {\n      forEachSegment { data, offset, byteCount ->\n        update(data, offset, byteCount)\n      }\n      digest()\n    }\n    return ByteString(digestBytes)\n  }\n\n  override fun hmac(algorithm: String, key: ByteString): ByteString {\n    try {\n      val mac = Mac.getInstance(algorithm)\n      mac.init(SecretKeySpec(key.toByteArray(), algorithm))\n      forEachSegment { data, offset, byteCount ->\n        mac.update(data, offset, byteCount)\n      }\n      return ByteString(mac.doFinal())\n    } catch (e: InvalidKeyException) {\n      throw IllegalArgumentException(e)\n    }\n  }\n\n  override fun base64Url() = toByteString().base64Url()\n\n  override fun substring(beginIndex: Int, endIndex: Int): ByteString =\n    commonSubstring(beginIndex, endIndex)\n\n  override fun internalGet(pos: Int): Byte = commonInternalGet(pos)\n\n  override fun getSize() = commonGetSize()\n\n  override fun toByteArray(): ByteArray = commonToByteArray()\n\n  override fun asByteBuffer(): ByteBuffer = ByteBuffer.wrap(toByteArray()).asReadOnlyBuffer()\n\n  @Throws(IOException::class)\n  override fun write(out: OutputStream) {\n    forEachSegment { data, offset, byteCount ->\n      out.write(data, offset, byteCount)\n    }\n  }\n\n  override fun write(buffer: Buffer, offset: Int, byteCount: Int): Unit =\n    commonWrite(buffer, offset, byteCount)\n\n  override fun rangeEquals(\n    offset: Int,\n    other: ByteString,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  override fun rangeEquals(\n    offset: Int,\n    other: ByteArray,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  override fun copyInto(\n    offset: Int,\n    target: ByteArray,\n    targetOffset: Int,\n    byteCount: Int,\n  ) = commonCopyInto(offset, target, targetOffset, byteCount)\n\n  override fun indexOf(other: ByteArray, fromIndex: Int) = toByteString().indexOf(other, fromIndex)\n\n  override fun lastIndexOf(other: ByteArray, fromIndex: Int) = toByteString().lastIndexOf(\n    other,\n    fromIndex,\n  )\n\n  /** Returns a copy as a non-segmented byte string.  */\n  private fun toByteString() = ByteString(toByteArray())\n\n  override fun internalArray() = toByteArray()\n\n  override fun equals(other: Any?): Boolean = commonEquals(other)\n\n  override fun hashCode(): Int = commonHashCode()\n\n  override fun toString() = toByteString().toString()\n\n  @Suppress(\"unused\", \"PLATFORM_CLASS_MAPPED_TO_KOTLIN\") // For Java Serialization.\n  private fun writeReplace(): Object = toByteString() as Object\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/Sink.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.Closeable\nimport java.io.Flushable\nimport java.io.IOException\n\nactual interface Sink : Closeable, Flushable {\n  @Throws(IOException::class)\n  actual fun write(source: Buffer, byteCount: Long)\n\n  @Throws(IOException::class)\n  actual override fun flush()\n\n  actual fun timeout(): Timeout\n\n  @Throws(IOException::class)\n  actual override fun close()\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/Throttler.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.InterruptedIOException\nimport java.util.concurrent.locks.Condition\nimport java.util.concurrent.locks.ReentrantLock\nimport kotlin.concurrent.withLock\n\n/**\n * Enables limiting of Source and Sink throughput. Attach to this throttler via [source] and [sink]\n * and set the desired throughput via [bytesPerSecond]. Multiple Sources and Sinks can be\n * attached to a single Throttler and they will be throttled as a group, where their combined\n * throughput will not exceed the desired throughput. The same Source or Sink can be attached to\n * multiple Throttlers and its throughput will not exceed the desired throughput of any of the\n * Throttlers.\n *\n * This class has these tuning parameters:\n *\n *  * `bytesPerSecond`: Maximum sustained throughput. Use 0 for no limit.\n *  * `waitByteCount`: When the requested byte count is greater than this many bytes and isn't\n *    immediately available, only wait until we can allocate at least this many bytes. Use this to\n *    set the ideal byte count during sustained throughput.\n *  * `maxByteCount`: Maximum number of bytes to allocate on any call. This is also the number of\n *    bytes that will be returned before any waiting.\n */\nclass Throttler internal constructor(\n  /**\n   * The nanoTime that we've consumed all bytes through. This is never greater than the current\n   * nanoTime plus nanosForMaxByteCount.\n   */\n  private var allocatedUntil: Long,\n) {\n  private var bytesPerSecond: Long = 0L\n  private var waitByteCount: Long = 8 * 1024 // 8 KiB.\n  private var maxByteCount: Long = 256 * 1024 // 256 KiB.\n\n  val lock: ReentrantLock = ReentrantLock()\n  val condition: Condition = lock.newCondition()\n\n  constructor() : this(allocatedUntil = System.nanoTime())\n\n  /** Sets the rate at which bytes will be allocated. Use 0 for no limit. */\n  @JvmOverloads\n  fun bytesPerSecond(\n    bytesPerSecond: Long,\n    waitByteCount: Long = this.waitByteCount,\n    maxByteCount: Long = this.maxByteCount,\n  ) {\n    lock.withLock {\n      require(bytesPerSecond >= 0)\n      require(waitByteCount > 0)\n      require(maxByteCount >= waitByteCount)\n\n      this.bytesPerSecond = bytesPerSecond\n      this.waitByteCount = waitByteCount\n      this.maxByteCount = maxByteCount\n      condition.signalAll()\n    }\n  }\n\n  /**\n   * Take up to `byteCount` bytes, waiting if necessary. Returns the number of bytes that were\n   * taken.\n   */\n  internal fun take(byteCount: Long): Long {\n    require(byteCount > 0)\n\n    lock.withLock {\n      while (true) {\n        val now = System.nanoTime()\n        val byteCountOrWaitNanos = byteCountOrWaitNanos(now, byteCount)\n        if (byteCountOrWaitNanos >= 0) return byteCountOrWaitNanos\n        condition.awaitNanos(-byteCountOrWaitNanos)\n      }\n    }\n  }\n\n  /**\n   * Returns the byte count to take immediately or -1 times the number of nanos to wait until the\n   * next attempt. If the returned value is negative it should be interpreted as a duration in\n   * nanos; if it is positive it should be interpreted as a byte count.\n   */\n  internal fun byteCountOrWaitNanos(now: Long, byteCount: Long): Long {\n    if (bytesPerSecond == 0L) return byteCount // No limits.\n\n    val idleInNanos = maxOf(allocatedUntil - now, 0L)\n    val immediateBytes = maxByteCount - idleInNanos.nanosToBytes()\n\n    // Fulfill the entire request without waiting.\n    if (immediateBytes >= byteCount) {\n      allocatedUntil = now + idleInNanos + byteCount.bytesToNanos()\n      return byteCount\n    }\n\n    // Fulfill a big-enough block without waiting.\n    if (immediateBytes >= waitByteCount) {\n      allocatedUntil = now + maxByteCount.bytesToNanos()\n      return immediateBytes\n    }\n\n    // Looks like we'll need to wait until we can take the minimum required bytes.\n    val minByteCount = minOf(waitByteCount, byteCount)\n    val minWaitNanos = idleInNanos + (minByteCount - maxByteCount).bytesToNanos()\n\n    // But if the wait duration truncates to zero nanos after division, don't wait.\n    if (minWaitNanos == 0L) {\n      allocatedUntil = now + maxByteCount.bytesToNanos()\n      return minByteCount\n    }\n\n    return -minWaitNanos\n  }\n\n  private fun Long.nanosToBytes() = this * bytesPerSecond / 1_000_000_000L\n\n  private fun Long.bytesToNanos() = this * 1_000_000_000L / bytesPerSecond\n\n  /** Create a Source which honors this Throttler.  */\n  fun source(source: Source): Source {\n    return object : ForwardingSource(source) {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        try {\n          val toRead = take(byteCount)\n          return super.read(sink, toRead)\n        } catch (e: InterruptedException) {\n          Thread.currentThread().interrupt()\n          throw InterruptedIOException(\"interrupted\")\n        }\n      }\n    }\n  }\n\n  /** Create a Sink which honors this Throttler.  */\n  fun sink(sink: Sink): Sink {\n    return object : ForwardingSink(sink) {\n      @Throws(IOException::class)\n      override fun write(source: Buffer, byteCount: Long) {\n        try {\n          var remaining = byteCount\n          while (remaining > 0L) {\n            val toWrite = take(remaining)\n            super.write(source, toWrite)\n            remaining -= toWrite\n          }\n        } catch (e: InterruptedException) {\n          Thread.currentThread().interrupt()\n          throw InterruptedIOException(\"interrupted\")\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/Timeout.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.InterruptedIOException\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.locks.Condition\nimport kotlin.concurrent.Volatile\nimport kotlin.time.Duration\nimport kotlin.time.DurationUnit\nimport kotlin.time.toTimeUnit\n\nactual open class Timeout {\n  /**\n   * True if `deadlineNanoTime` is defined. There is no equivalent to null or 0 for\n   * [System.nanoTime].\n   */\n  private var hasDeadline = false\n  private var deadlineNanoTime = 0L\n  private var timeoutNanos = 0L\n\n  /**\n   * A sentinel that is updated to a new object on each call to [cancel]. Sample this property\n   * before and after an operation to test if the timeout was canceled during the operation.\n   */\n  @Volatile private var cancelMark: Any? = null\n\n  /**\n   * Wait at most `timeout` time before aborting an operation. Using a per-operation timeout means\n   * that as long as forward progress is being made, no sequence of operations will fail.\n   *\n   * If `timeout == 0`, operations will run indefinitely. (Operating system timeouts may still\n   * apply.)\n   */\n  open fun timeout(timeout: Long, unit: TimeUnit): Timeout {\n    require(timeout >= 0) { \"timeout < 0: $timeout\" }\n    timeoutNanos = unit.toNanos(timeout)\n    return this\n  }\n\n  /** Returns the timeout in nanoseconds, or `0` for no timeout. */\n  open fun timeoutNanos(): Long = timeoutNanos\n\n  /** Returns true if a deadline is enabled. */\n  open fun hasDeadline(): Boolean = hasDeadline\n\n  /**\n   * Returns the [nano time][System.nanoTime] when the deadline will be reached.\n   *\n   * @throws IllegalStateException if no deadline is set.\n   */\n  open fun deadlineNanoTime(): Long {\n    check(hasDeadline) { \"No deadline\" }\n    return deadlineNanoTime\n  }\n\n  /**\n   * Sets the [nano time][System.nanoTime] when the deadline will be reached. All operations must\n   * complete before this time. Use a deadline to set a maximum bound on the time spent on a\n   * sequence of operations.\n   */\n  open fun deadlineNanoTime(deadlineNanoTime: Long): Timeout {\n    this.hasDeadline = true\n    this.deadlineNanoTime = deadlineNanoTime\n    return this\n  }\n\n  /** Set a deadline of now plus `duration` time.  */\n  fun deadline(duration: Long, unit: TimeUnit): Timeout {\n    require(duration > 0) { \"duration <= 0: $duration\" }\n    return deadlineNanoTime(System.nanoTime() + unit.toNanos(duration))\n  }\n\n  /** Clears the timeout. Operating system timeouts may still apply. */\n  open fun clearTimeout(): Timeout {\n    timeoutNanos = 0\n    return this\n  }\n\n  /** Clears the deadline. */\n  open fun clearDeadline(): Timeout {\n    hasDeadline = false\n    return this\n  }\n\n  /**\n   * Throws an [InterruptedIOException] if the deadline has been reached or if the current thread\n   * has been interrupted. This method doesn't detect timeouts; that should be implemented to\n   * asynchronously abort an in-progress operation.\n   */\n  @Throws(IOException::class)\n  open fun throwIfReached() {\n    if (Thread.currentThread().isInterrupted) {\n      // If the current thread has been interrupted.\n      throw InterruptedIOException(\"interrupted\")\n    }\n\n    if (hasDeadline && deadlineNanoTime - System.nanoTime() <= 0) {\n      throw InterruptedIOException(\"deadline reached\")\n    }\n  }\n\n  /**\n   * Prevent all current applications of this timeout from firing. Use this when a time-limited\n   * operation should no longer be time-limited because the nature of the operation has changed.\n   *\n   * This function does not mutate the [deadlineNanoTime] or [timeoutNanos] properties of this\n   * timeout. It only applies to active operations that are limited by this timeout, and applies by\n   * allowing those operations to run indefinitely.\n   *\n   * Subclasses that override this method must call `super.cancel()`.\n   */\n  open fun cancel() {\n    cancelMark = Any()\n  }\n\n  /**\n   * Waits on `monitor` until it is signaled. Throws [InterruptedIOException] if either the thread\n   * is interrupted or if this timeout elapses before `monitor` is signaled.\n   * The caller must hold the lock that monitor is bound to.\n   *\n   * Here's a sample class that uses `awaitSignal()` to await a specific state. Note that the\n   * call is made within a loop to avoid unnecessary waiting and to mitigate spurious notifications.\n   *\n   * ```java\n   * class Dice {\n   *   Random random = new Random();\n   *   int latestTotal;\n   *\n   *   ReentrantLock lock = new ReentrantLock();\n   *   Condition condition = lock.newCondition();\n   *\n   *   public void roll() {\n   *     lock.withLock {\n   *       latestTotal = 2 + random.nextInt(6) + random.nextInt(6);\n   *       System.out.println(\"Rolled \" + latestTotal);\n   *       condition.signalAll();\n   *     }\n   *   }\n   *\n   *   public void rollAtFixedRate(int period, TimeUnit timeUnit) {\n   *     Executors.newScheduledThreadPool(0).scheduleAtFixedRate(new Runnable() {\n   *       public void run() {\n   *         roll();\n   *       }\n   *     }, 0, period, timeUnit);\n   *   }\n   *\n   *   public void awaitTotal(Timeout timeout, int total)\n   *       throws InterruptedIOException {\n   *     lock.withLock {\n   *       while (latestTotal != total) {\n   *         timeout.awaitSignal(this);\n   *       }\n   *     }\n   *   }\n   * }\n   * ```\n   */\n  @Throws(InterruptedIOException::class)\n  open fun awaitSignal(condition: Condition) {\n    try {\n      val hasDeadline = hasDeadline()\n      val timeoutNanos = timeoutNanos()\n\n      if (!hasDeadline && timeoutNanos == 0L) {\n        condition.await() // There is no timeout: wait forever.\n        return\n      }\n\n      // Compute how long we'll wait.\n      val waitNanos = if (hasDeadline && timeoutNanos != 0L) {\n        val deadlineNanos = deadlineNanoTime() - System.nanoTime()\n        minOf(timeoutNanos, deadlineNanos)\n      } else if (hasDeadline) {\n        deadlineNanoTime() - System.nanoTime()\n      } else {\n        timeoutNanos\n      }\n\n      if (waitNanos <= 0) throw InterruptedIOException(\"timeout\")\n\n      val cancelMarkBefore = cancelMark\n\n      // Attempt to wait that long. This will return early if the monitor is notified.\n      val nanosRemaining = condition.awaitNanos(waitNanos)\n\n      // If there's time remaining, we probably got the call we were waiting for.\n      if (nanosRemaining > 0) return\n\n      // Return without throwing if this timeout was canceled while we were waiting. Note that this\n      // return is a 'spurious wakeup' because Condition.signal() was not called.\n      if (cancelMark !== cancelMarkBefore) return\n\n      throw InterruptedIOException(\"timeout\")\n    } catch (e: InterruptedException) {\n      Thread.currentThread().interrupt() // Retain interrupted status.\n      throw InterruptedIOException(\"interrupted\")\n    }\n  }\n\n  /**\n   * Waits on `monitor` until it is notified. Throws [InterruptedIOException] if either the thread\n   * is interrupted or if this timeout elapses before `monitor` is notified. The caller must be\n   * synchronized on `monitor`.\n   *\n   * Here's a sample class that uses `waitUntilNotified()` to await a specific state. Note that the\n   * call is made within a loop to avoid unnecessary waiting and to mitigate spurious notifications.\n   *\n   * ```java\n   * class Dice {\n   *   Random random = new Random();\n   *   int latestTotal;\n   *\n   *   public synchronized void roll() {\n   *     latestTotal = 2 + random.nextInt(6) + random.nextInt(6);\n   *     System.out.println(\"Rolled \" + latestTotal);\n   *     notifyAll();\n   *   }\n   *\n   *   public void rollAtFixedRate(int period, TimeUnit timeUnit) {\n   *     Executors.newScheduledThreadPool(0).scheduleAtFixedRate(new Runnable() {\n   *       public void run() {\n   *         roll();\n   *       }\n   *     }, 0, period, timeUnit);\n   *   }\n   *\n   *   public synchronized void awaitTotal(Timeout timeout, int total)\n   *       throws InterruptedIOException {\n   *     while (latestTotal != total) {\n   *       timeout.waitUntilNotified(this);\n   *     }\n   *   }\n   * }\n   * ```\n   */\n  @Throws(InterruptedIOException::class)\n  open fun waitUntilNotified(monitor: Any) {\n    try {\n      val hasDeadline = hasDeadline()\n      val timeoutNanos = timeoutNanos()\n\n      if (!hasDeadline && timeoutNanos == 0L) {\n        (monitor as Object).wait() // There is no timeout: wait forever.\n        return\n      }\n\n      // Compute how long we'll wait.\n      val start = System.nanoTime()\n      val waitNanos = if (hasDeadline && timeoutNanos != 0L) {\n        val deadlineNanos = deadlineNanoTime() - start\n        minOf(timeoutNanos, deadlineNanos)\n      } else if (hasDeadline) {\n        deadlineNanoTime() - start\n      } else {\n        timeoutNanos\n      }\n\n      if (waitNanos <= 0) throw InterruptedIOException(\"timeout\")\n\n      val cancelMarkBefore = cancelMark\n\n      // Attempt to wait that long. This will return early if the monitor is notified.\n      val waitMillis = waitNanos / 1000000L\n      (monitor as Object).wait(waitMillis, (waitNanos - waitMillis * 1000000L).toInt())\n      val elapsedNanos = System.nanoTime() - start\n\n      // If there's time remaining, we probably got the call we were waiting for.\n      if (elapsedNanos < waitNanos) return\n\n      // Return without throwing if this timeout was canceled while we were waiting. Note that this\n      // return is a 'spurious wakeup' because Object.notify() was not called.\n      if (cancelMark !== cancelMarkBefore) return\n\n      throw InterruptedIOException(\"timeout\")\n    } catch (e: InterruptedException) {\n      Thread.currentThread().interrupt() // Retain interrupted status.\n      throw InterruptedIOException(\"interrupted\")\n    }\n  }\n\n  /**\n   * Applies the minimum intersection between this timeout and `other`, run `block`, then finally\n   * rollback this timeout's values.\n   */\n  inline fun <T> intersectWith(other: Timeout, block: () -> T): T {\n    val originalTimeout = this.timeoutNanos()\n    this.timeout(minTimeout(other.timeoutNanos(), this.timeoutNanos()), TimeUnit.NANOSECONDS)\n\n    if (this.hasDeadline()) {\n      val originalDeadline = this.deadlineNanoTime()\n      if (other.hasDeadline()) {\n        this.deadlineNanoTime(Math.min(this.deadlineNanoTime(), other.deadlineNanoTime()))\n      }\n      try {\n        return block()\n      } finally {\n        this.timeout(originalTimeout, TimeUnit.NANOSECONDS)\n        if (other.hasDeadline()) {\n          this.deadlineNanoTime(originalDeadline)\n        }\n      }\n    } else {\n      if (other.hasDeadline()) {\n        this.deadlineNanoTime(other.deadlineNanoTime())\n      }\n      try {\n        return block()\n      } finally {\n        this.timeout(originalTimeout, TimeUnit.NANOSECONDS)\n        if (other.hasDeadline()) {\n          this.clearDeadline()\n        }\n      }\n    }\n  }\n\n  actual companion object {\n    @JvmField actual val NONE: Timeout = object : Timeout() {\n      override fun timeout(timeout: Long, unit: TimeUnit): Timeout = this\n\n      override fun deadlineNanoTime(deadlineNanoTime: Long): Timeout = this\n\n      override fun throwIfReached() {}\n    }\n\n    fun Timeout.timeout(timeout: Long, unit: DurationUnit): Timeout {\n      return timeout(timeout, unit.toTimeUnit())\n    }\n\n    fun Timeout.timeout(duration: Duration): Timeout {\n      return timeout(duration.inWholeNanoseconds, TimeUnit.NANOSECONDS)\n    }\n\n    fun minTimeout(aNanos: Long, bNanos: Long) = when {\n      aNanos == 0L -> bNanos\n      bNanos == 0L -> aNanos\n      aNanos < bNanos -> aNanos\n      else -> bNanos\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/internal/-Atomic.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.internal\n\nimport java.util.concurrent.atomic.AtomicInteger\n\n/**\n * Returns the new value of the bit field if a change was made, or 0 if no change was made.\n */\ninternal fun AtomicInteger.setBitsOrZero(bits: Int): Int {\n  while (true) {\n    val current = get()\n    if (current and bits != 0) return 0 // At least one bit is already set.\n    val updated = current or bits\n    if (compareAndSet(current, updated)) return updated\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/internal/-JavaIo.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.internal\n\nimport java.io.IOException\nimport java.net.Socket as JavaNetSocket\nimport java.net.SocketTimeoutException\nimport java.util.logging.Level\nimport java.util.logging.Logger\nimport okio.AsyncTimeout\n\nprivate val logger = Logger.getLogger(\"okio.Okio\")\n\ninternal class SocketAsyncTimeout(private val socket: JavaNetSocket) : AsyncTimeout() {\n  override fun newTimeoutException(cause: IOException?): IOException {\n    val ioe = SocketTimeoutException(\"timeout\")\n    if (cause != null) {\n      ioe.initCause(cause)\n    }\n    return ioe\n  }\n\n  override fun timedOut() {\n    try {\n      socket.close()\n    } catch (e: Exception) {\n      logger.log(Level.WARNING, \"Failed to close timed out socket $socket\", e)\n    } catch (e: AssertionError) {\n      if (e.isAndroidGetsocknameError) {\n        // Catch this exception due to a Firmware issue up to android 4.2.2\n        // https://code.google.com/p/android/issues/detail?id=54072\n        logger.log(Level.WARNING, \"Failed to close timed out socket $socket\", e)\n      } else {\n        throw e\n      }\n    }\n  }\n}\n\n/**\n * Returns true if this error is due to a firmware bug fixed after Android 4.2.2.\n * https://code.google.com/p/android/issues/detail?id=54072\n */\ninternal val AssertionError.isAndroidGetsocknameError: Boolean get() {\n  return cause != null && message?.contains(\"getsockname failed\") ?: false\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/internal/-ZlibJvm.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.internal\n\nimport java.util.Calendar\nimport java.util.GregorianCalendar\n\ninternal actual val DEFAULT_COMPRESSION = java.util.zip.Deflater.DEFAULT_COMPRESSION\n\ninternal actual typealias CRC32 = java.util.zip.CRC32\n\ninternal actual fun datePartsToEpochMillis(\n  year: Int,\n  month: Int,\n  day: Int,\n  hour: Int,\n  minute: Int,\n  second: Int,\n): Long {\n  val calendar = GregorianCalendar()\n  calendar.set(Calendar.MILLISECOND, 0)\n  calendar.set(year, month - 1, day, hour, minute, second)\n  return calendar.time.time\n}\n\ninternal val EMPTY_BYTE_ARRAY = byteArrayOf()\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/internal/DefaultSocket.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.internal\n\nimport java.io.IOException\nimport java.net.Socket as JavaNetSocket\nimport java.util.concurrent.atomic.AtomicInteger\nimport okio.Buffer\nimport okio.Segment\nimport okio.SegmentPool\nimport okio.Sink\nimport okio.Socket\nimport okio.Source\nimport okio.checkOffsetAndCount\nimport okio.minOf\n\n/**\n * Implement Okio's [okio.Socket] interface on a any `java.net.Socket`, which may itself be a secure\n * socket or other subclass.\n *\n * Note this behaves differently from [java.net.Socket.source()] and [java.net.Socket.sink()]\n * because those return streams that close the entire socket when they are closed, whereas this\n * class only closes the input or output respectively.\n */\ninternal class DefaultSocket(val socket: JavaNetSocket) : Socket {\n  private var closeBits = AtomicInteger()\n\n  override val source: Source = SocketSource()\n  override val sink: Sink = SocketSink()\n\n  override fun cancel() {\n    socket.close()\n  }\n\n  override fun toString() = socket.toString()\n\n  inner class SocketSink : Sink {\n    private val outputStream = socket.outputStream\n    private val timeout = SocketAsyncTimeout(socket)\n\n    override fun write(source: Buffer, byteCount: Long) {\n      checkOffsetAndCount(source.size, 0, byteCount)\n      var remaining = byteCount\n      while (remaining > 0L) {\n        timeout.throwIfReached()\n        val head = source.head!!\n        val toCopy = minOf(remaining, head.limit - head.pos).toInt()\n        timeout.withTimeout {\n          outputStream.write(head.data, head.pos, toCopy)\n        }\n\n        head.pos += toCopy\n        remaining -= toCopy\n        source.size -= toCopy\n\n        if (head.pos == head.limit) {\n          source.head = head.pop()\n          SegmentPool.recycle(head)\n        }\n      }\n    }\n\n    override fun flush() {\n      timeout.withTimeout {\n        outputStream.flush()\n      }\n    }\n\n    override fun close() {\n      timeout.withTimeout {\n        when (closeBits.setBitsOrZero(SINK_CLOSED_BIT)) {\n          // If setBitOrZero() returns 0, this sink is already closed.\n          0 -> return\n\n          // Release the socket if both streams are closed.\n          ALL_CLOSED_BITS -> socket.close()\n\n          // Close this stream only.\n          else -> {\n            if (socket.isClosed || socket.isOutputShutdown) return // Nothing to do.\n            outputStream.flush()\n            try {\n              socket.shutdownOutput()\n            } catch (_: UnsupportedOperationException) {\n              // Android API 21's SSLSocket doesn't implement this! So close the whole socket.\n              // https://github.com/square/okhttp/issues/9123\n              outputStream.close()\n            }\n          }\n        }\n      }\n    }\n\n    override fun timeout() = timeout\n\n    override fun toString() = \"sink($socket)\"\n  }\n\n  inner class SocketSource : Source {\n    private val inputStream = socket.inputStream\n    private val timeout = SocketAsyncTimeout(socket)\n\n    override fun read(sink: Buffer, byteCount: Long): Long {\n      if (byteCount == 0L) return 0L\n      require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n      timeout.throwIfReached()\n      val tail = sink.writableSegment(1)\n      val maxToCopy = minOf(byteCount, Segment.Companion.SIZE - tail.limit).toInt()\n      val bytesRead = try {\n        timeout.withTimeout {\n          inputStream.read(tail.data, tail.limit, maxToCopy)\n        }\n      } catch (e: AssertionError) {\n        if (e.isAndroidGetsocknameError) throw IOException(e)\n        throw e\n      }\n      if (bytesRead == -1) {\n        if (tail.pos == tail.limit) {\n          // We allocated a tail segment, but didn't end up needing it. Recycle!\n          sink.head = tail.pop()\n          SegmentPool.recycle(tail)\n        }\n        return -1\n      }\n      tail.limit += bytesRead\n      sink.size += bytesRead\n      return bytesRead.toLong()\n    }\n\n    override fun close() {\n      timeout.withTimeout {\n        when (closeBits.setBitsOrZero(SOURCE_CLOSED_BIT)) {\n          // If setBitOrZero() returns 0, this source is already closed.\n          0 -> return\n\n          // Release the socket if both streams are closed.\n          ALL_CLOSED_BITS -> socket.close()\n\n          // Close this stream only.\n          else -> {\n            if (socket.isClosed || socket.isInputShutdown) return // Nothing to do.\n            try {\n              socket.shutdownInput()\n            } catch (_: UnsupportedOperationException) {\n              // Android API 21's SSLSocket doesn't implement this! So close the whole socket.\n              // https://github.com/square/okhttp/issues/9123\n              inputStream.close()\n            }\n          }\n        }\n      }\n    }\n\n    override fun timeout() = timeout\n\n    override fun toString() = \"source($socket)\"\n  }\n}\n\nprivate const val SINK_CLOSED_BIT = 1\nprivate const val SOURCE_CLOSED_BIT = 2\nprivate const val ALL_CLOSED_BITS = SINK_CLOSED_BIT or SOURCE_CLOSED_BIT\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/internal/PipeSocket.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.Pipe\nimport okio.Sink\nimport okio.Socket\nimport okio.Source\n\ninternal class PipeSocket(val sinkPipe: Pipe, val sourcePipe: Pipe) : Socket {\n  override val source: Source\n    get() = sourcePipe.source\n\n  override val sink: Sink\n    get() = sinkPipe.sink\n\n  override fun cancel() {\n    sourcePipe.cancel()\n    sinkPipe.cancel()\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmMain/kotlin/okio/internal/ResourceFileSystem.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio.internal\n\nimport java.io.File\nimport java.io.IOException\nimport java.net.JarURLConnection\nimport java.net.URI\nimport java.net.URL\nimport okio.FileHandle\nimport okio.FileMetadata\nimport okio.FileNotFoundException\nimport okio.FileSystem\nimport okio.Path\nimport okio.Path.Companion.toOkioPath\nimport okio.Path.Companion.toPath\nimport okio.Sink\nimport okio.Source\nimport okio.source\n\n/**\n * A file system exposing Java classpath resources. It is equivalent to the files returned by\n * [ClassLoader.getResource] but supports extra features like [metadataOrNull] and [list].\n *\n * If `.jar` files overlap, this returns an arbitrary element. For overlapping directories it unions\n * their contents.\n *\n * ResourceFileSystem excludes `.class` files.\n *\n * This file system is read-only.\n */\ninternal class ResourceFileSystem internal constructor(\n  private val classLoader: ClassLoader,\n  indexEagerly: Boolean,\n  private val systemFileSystem: FileSystem = SYSTEM,\n) : FileSystem() {\n  private val roots: List<Pair<FileSystem, Path>> by lazy { classLoader.toClasspathRoots() }\n\n  init {\n    if (indexEagerly) {\n      roots.size\n    }\n  }\n\n  override fun canonicalize(path: Path): Path {\n    // TODO(jwilson): throw FileNotFoundException if the canonical file doesn't exist.\n    return canonicalizeInternal(path)\n  }\n\n  /** Don't throw [FileNotFoundException] if the path doesn't identify a file. */\n  private fun canonicalizeInternal(path: Path): Path {\n    return ROOT.resolve(path, normalize = true)\n  }\n\n  override fun list(dir: Path): List<Path> {\n    val relativePath = dir.toRelativePath()\n    val result = mutableSetOf<Path>()\n    var foundAny = false\n    for ((fileSystem, base) in roots) {\n      try {\n        result += fileSystem.list(base / relativePath)\n          .filter { keepPath(it) }\n          .map { it.removeBase(base) }\n        foundAny = true\n      } catch (_: IOException) {\n      }\n    }\n    if (!foundAny) throw FileNotFoundException(\"file not found: $dir\")\n    return result.toList()\n  }\n\n  override fun listOrNull(dir: Path): List<Path>? {\n    val relativePath = dir.toRelativePath()\n    val result = mutableSetOf<Path>()\n    var foundAny = false\n    for ((fileSystem, base) in roots) {\n      val baseResult = fileSystem.listOrNull(base / relativePath)\n        ?.filter { keepPath(it) }\n        ?.map { it.removeBase(base) }\n      if (baseResult != null) {\n        result += baseResult\n        foundAny = true\n      }\n    }\n    return if (foundAny) result.toList() else null\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    if (!keepPath(file)) throw FileNotFoundException(\"file not found: $file\")\n    val relativePath = file.toRelativePath()\n    for ((fileSystem, base) in roots) {\n      try {\n        return fileSystem.openReadOnly(base / relativePath)\n      } catch (_: FileNotFoundException) {\n      }\n    }\n    throw FileNotFoundException(\"file not found: $file\")\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    throw IOException(\"resources are not writable\")\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    if (!keepPath(path)) return null\n    val relativePath = path.toRelativePath()\n    for ((fileSystem, base) in roots) {\n      return fileSystem.metadataOrNull(base / relativePath) ?: continue\n    }\n    return null\n  }\n\n  override fun source(file: Path): Source {\n    if (!keepPath(file)) throw FileNotFoundException(\"file not found: $file\")\n    // Make sure we have a path that doesn't start with '/'.\n    val relativePath = ROOT.resolve(file).relativeTo(ROOT)\n    val resource = classLoader.getResource(relativePath.toString()) ?: throw FileNotFoundException(\"file not found: $file\")\n    val urlConnection = resource.openConnection()\n    if (urlConnection is JarURLConnection) {\n      urlConnection.useCaches = false\n    }\n    return urlConnection.getInputStream().source()\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    throw IOException(\"$this is read-only\")\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    throw IOException(\"$this is read-only\")\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean): Unit =\n    throw IOException(\"$this is read-only\")\n\n  override fun atomicMove(source: Path, target: Path): Unit =\n    throw IOException(\"$this is read-only\")\n\n  override fun delete(path: Path, mustExist: Boolean): Unit =\n    throw IOException(\"$this is read-only\")\n\n  override fun createSymlink(source: Path, target: Path): Unit =\n    throw IOException(\"$this is read-only\")\n\n  private fun Path.toRelativePath(): String {\n    val canonicalThis = canonicalizeInternal(this)\n    return canonicalThis.relativeTo(ROOT).toString()\n  }\n\n  /**\n   * Returns a search path of classpath roots. Each element contains a file system to use, and\n   * the base directory of that file system to search from.\n   */\n  private fun ClassLoader.toClasspathRoots(): List<Pair<FileSystem, Path>> {\n    // We'd like to build this upon an API like ClassLoader.getURLs() but unfortunately that\n    // API exists only on URLClassLoader (and that isn't the default class loader implementation).\n    //\n    // The closest we have is `ClassLoader.getResources(\"\")`. It returns all classpath roots that\n    // are directories but none that are .jar files. To mitigate that we also search for all\n    // `META-INF/MANIFEST.MF` files, hastily assuming that every .jar file will have such an\n    // entry.\n    //\n    // Classpath entries that aren't directories and don't have a META-INF/MANIFEST.MF file will\n    // not be visible in this file system.\n    return getResources(\"\").toList().mapNotNull { it.toFileRoot() } +\n      getResources(\"META-INF/MANIFEST.MF\").toList().mapNotNull { it.toJarRoot() }\n  }\n\n  private fun URL.toFileRoot(): Pair<FileSystem, Path>? {\n    if (protocol != \"file\") return null // Ignore unexpected URLs.\n    return systemFileSystem to File(toURI()).toOkioPath()\n  }\n\n  private fun URL.toJarRoot(): Pair<FileSystem, Path>? {\n    val urlString = toString()\n    if (!urlString.startsWith(\"jar:file:\")) return null // Ignore unexpected URLs.\n\n    // Given a URL like `jar:file:/tmp/foo.jar!/META-INF/MANIFEST.MF`, get the path to the archive\n    // file, like `/tmp/foo.jar`.\n    val suffixStart = urlString.lastIndexOf(\"!\")\n    if (suffixStart == -1) return null\n    val path = File(URI.create(urlString.substring(\"jar:\".length, suffixStart))).toOkioPath()\n    val zip = openZip(\n      zipPath = path,\n      fileSystem = systemFileSystem,\n      predicate = { entry -> keepPath(entry.canonicalPath) },\n    )\n    return zip to ROOT\n  }\n\n  private companion object {\n    val ROOT = \"/\".toPath()\n\n    fun Path.removeBase(base: Path): Path {\n      val prefix = base.toString()\n      return ROOT / (toString().removePrefix(prefix).replace('\\\\', '/'))\n    }\n\n    private fun keepPath(path: Path) = !path.name.endsWith(\".class\", ignoreCase = true)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/AsyncSocket.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio\n\nimport java.util.concurrent.CompletableFuture\nimport java.util.concurrent.LinkedBlockingDeque\nimport kotlin.concurrent.thread\n\n/**\n * Queues reads and writes onto a background thread. This prevents potential deadlock if such\n * operations were done on the caller's thread.\n */\nclass AsyncSocket(\n  socket: Socket,\n) : Closeable {\n  private val sink = socket.sink.buffer()\n  private val source = socket.source.buffer()\n  private val tasks = LinkedBlockingDeque<Task>()\n  private val taskThread = thread(name = \"AsyncSocket($socket)\") {\n    while (true) {\n      val task = tasks.take()\n      when (task) {\n        is Task.Read -> {\n          task.future.complete(source.readUtf8LineStrict())\n        }\n        is Task.Write -> {\n          sink.writeUtf8(\"${task.string}\\n\")\n          sink.flush()\n        }\n        Task.CloseSource -> {\n          source.close()\n        }\n        Task.CloseSink -> {\n          sink.close()\n        }\n        Task.Close -> {\n          source.close()\n          sink.close()\n          break\n        }\n      }\n    }\n  }\n\n  fun read(): String {\n    val future = CompletableFuture<String>()\n    tasks += Task.Read(future)\n    return future.get()\n  }\n\n  fun write(string: String) {\n    tasks += Task.Write(string)\n  }\n\n  fun closeSource() {\n    tasks += Task.CloseSource\n  }\n\n  fun closeSink() {\n    tasks += Task.CloseSink\n  }\n\n  override fun close() {\n    tasks += Task.Close\n    taskThread.join()\n  }\n\n  private sealed interface Task {\n    data class Write(val string: String) : Task\n    data class Read(val future: CompletableFuture<String>) : Task\n    data object CloseSink : Task\n    data object CloseSource : Task\n    data object Close : Task\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/AsyncTimeoutTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.InterruptedIOException\nimport java.util.Random\nimport java.util.concurrent.LinkedBlockingDeque\nimport java.util.concurrent.TimeUnit\nimport okio.ByteString.Companion.of\nimport okio.TestUtil.bufferWithRandomSegmentLayout\nimport org.junit.Assert\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Before\nimport org.junit.Ignore\nimport org.junit.Test\n\n/**\n * This test uses four timeouts of varying durations: 250ms, 500ms, 750ms and\n * 1000ms, named 'a', 'b', 'c' and 'd'.\n */\nclass AsyncTimeoutTest {\n  private val timedOut = LinkedBlockingDeque<AsyncTimeout>()\n  private val a = RecordingAsyncTimeout()\n  private val b = RecordingAsyncTimeout()\n  private val c = RecordingAsyncTimeout()\n  private val d = RecordingAsyncTimeout()\n\n  @Before\n  fun setUp() {\n    a.timeout(250, TimeUnit.MILLISECONDS)\n    b.timeout(500, TimeUnit.MILLISECONDS)\n    c.timeout(750, TimeUnit.MILLISECONDS)\n    d.timeout(1000, TimeUnit.MILLISECONDS)\n  }\n\n  @Test\n  fun zeroTimeoutIsNoTimeout() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(0, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    Thread.sleep(250)\n    assertFalse(timeout.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun singleInstanceTimedOut() {\n    a.enter()\n    Thread.sleep(500)\n    assertTrue(a.exit())\n    assertTimedOut(a)\n  }\n\n  @Test\n  fun singleInstanceNotTimedOut() {\n    b.enter()\n    Thread.sleep(250)\n    b.exit()\n    assertFalse(b.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun instancesAddedAtEnd() {\n    a.enter()\n    b.enter()\n    c.enter()\n    d.enter()\n    Thread.sleep(1250)\n    assertTrue(a.exit())\n    assertTrue(b.exit())\n    assertTrue(c.exit())\n    assertTrue(d.exit())\n    assertTimedOut(a, b, c, d)\n  }\n\n  @Test\n  fun instancesAddedAtFront() {\n    d.enter()\n    c.enter()\n    b.enter()\n    a.enter()\n    Thread.sleep(1250)\n    assertTrue(d.exit())\n    assertTrue(c.exit())\n    assertTrue(b.exit())\n    assertTrue(a.exit())\n    assertTimedOut(a, b, c, d)\n  }\n\n  @Test\n  fun instancesRemovedAtFront() {\n    a.enter()\n    b.enter()\n    c.enter()\n    d.enter()\n    assertFalse(a.exit())\n    assertFalse(b.exit())\n    assertFalse(c.exit())\n    assertFalse(d.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun instancesRemovedAtEnd() {\n    a.enter()\n    b.enter()\n    c.enter()\n    d.enter()\n    assertFalse(d.exit())\n    assertFalse(c.exit())\n    assertFalse(b.exit())\n    assertFalse(a.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun doubleEnter() {\n    a.enter()\n    try {\n      a.enter()\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun reEnter() {\n    a.timeout(10, TimeUnit.SECONDS)\n    a.enter()\n    assertFalse(a.exit())\n    a.enter()\n    assertFalse(a.exit())\n  }\n\n  @Test\n  fun reEnterAfterTimeout() {\n    a.timeout(1, TimeUnit.MILLISECONDS)\n    a.enter()\n    Assert.assertSame(a, timedOut.take())\n    assertTrue(a.exit())\n    a.enter()\n    assertFalse(a.exit())\n  }\n\n  @Test\n  fun deadlineOnly() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.deadline(250, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    Thread.sleep(500)\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun deadlineBeforeTimeout() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.deadline(250, TimeUnit.MILLISECONDS)\n    timeout.timeout(750, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    Thread.sleep(500)\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun deadlineAfterTimeout() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.deadline(750, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    Thread.sleep(500)\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun deadlineStartsBeforeEnter() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.deadline(500, TimeUnit.MILLISECONDS)\n    Thread.sleep(500)\n    timeout.enter()\n    Thread.sleep(250)\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun deadlineInThePast() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.deadlineNanoTime(System.nanoTime() - 1)\n    timeout.enter()\n    Thread.sleep(250)\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun wrappedSinkTimesOut() {\n    val sink: Sink = object : ForwardingSink(Buffer()) {\n      override fun write(source: Buffer, byteCount: Long) {\n        Thread.sleep(500)\n      }\n    }\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSink = timeout.sink(sink)\n    val data = Buffer().writeUtf8(\"a\")\n    try {\n      timeoutSink.write(data, 1)\n      fail()\n    } catch (expected: InterruptedIOException) {\n    }\n  }\n\n  @Test\n  fun wrappedSinkFlushTimesOut() {\n    val sink: Sink = object : ForwardingSink(Buffer()) {\n      override fun flush() {\n        Thread.sleep(500)\n      }\n    }\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSink = timeout.sink(sink)\n    try {\n      timeoutSink.flush()\n      fail()\n    } catch (expected: InterruptedIOException) {\n    }\n  }\n\n  @Test\n  fun wrappedSinkCloseTimesOut() {\n    val sink: Sink = object : ForwardingSink(Buffer()) {\n      override fun close() {\n        Thread.sleep(500)\n      }\n    }\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSink = timeout.sink(sink)\n    try {\n      timeoutSink.close()\n      fail()\n    } catch (expected: InterruptedIOException) {\n    }\n  }\n\n  @Test\n  fun wrappedSourceTimesOut() {\n    val source: Source = object : ForwardingSource(Buffer()) {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        Thread.sleep(500)\n        return -1\n      }\n    }\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSource = timeout.source(source)\n    try {\n      timeoutSource.read(Buffer(), 0)\n      fail()\n    } catch (expected: InterruptedIOException) {\n    }\n  }\n\n  @Test\n  fun wrappedSourceCloseTimesOut() {\n    val source: Source = object : ForwardingSource(Buffer()) {\n      override fun close() {\n        Thread.sleep(500)\n      }\n    }\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSource = timeout.source(source)\n    try {\n      timeoutSource.close()\n      fail()\n    } catch (expected: InterruptedIOException) {\n    }\n  }\n\n  @Test\n  fun wrappedThrowsWithTimeout() {\n    val sink: Sink = object : ForwardingSink(Buffer()) {\n      override fun write(source: Buffer, byteCount: Long) {\n        Thread.sleep(500)\n        throw IOException(\"exception and timeout\")\n      }\n    }\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSink = timeout.sink(sink)\n    val data = Buffer().writeUtf8(\"a\")\n    try {\n      timeoutSink.write(data, 1)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n      assertEquals(\"exception and timeout\", expected.cause!!.message)\n    }\n  }\n\n  @Test\n  fun wrappedThrowsWithoutTimeout() {\n    val sink: Sink = object : ForwardingSink(Buffer()) {\n      override fun write(source: Buffer, byteCount: Long) {\n        throw IOException(\"no timeout occurred\")\n      }\n    }\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSink = timeout.sink(sink)\n    val data = Buffer().writeUtf8(\"a\")\n    try {\n      timeoutSink.write(data, 1)\n      fail()\n    } catch (expected: IOException) {\n      assertEquals(\"no timeout occurred\", expected.message)\n    }\n  }\n\n  /**\n   * We had a bug where writing a very large buffer would fail with an\n   * unexpected timeout because although the sink was making steady forward\n   * progress, doing it all as a single write caused a timeout.\n   */\n  @Ignore(\"Flaky\")\n  @Test\n  fun sinkSplitsLargeWrites() {\n    val data = ByteArray(512 * 1024)\n    val dice = Random(0)\n    dice.nextBytes(data)\n    val source = bufferWithRandomSegmentLayout(dice, data)\n    val target = Buffer()\n    val sink: Sink = object : ForwardingSink(Buffer()) {\n      override fun write(source: Buffer, byteCount: Long) {\n        Thread.sleep(byteCount / 500) // ~500 KiB/s.\n        target.write(source, byteCount)\n      }\n    }\n\n    // Timeout after 250 ms of inactivity.\n    val timeout = AsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    val timeoutSink = timeout.sink(sink)\n\n    // Transmit 500 KiB of data, which should take ~1 second. But expect no timeout!\n    timeoutSink.write(source, source.size)\n\n    // The data should all have arrived.\n    assertEquals(of(*data), target.readByteString())\n  }\n\n  @Test\n  fun enterCancelSleepExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    timeout.cancel()\n    Thread.sleep(500)\n\n    // Call didn't time out because the timeout was canceled.\n    assertFalse(timeout.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun enterCancelCancelSleepExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    timeout.cancel()\n    timeout.cancel()\n    Thread.sleep(500)\n\n    // Call didn't time out because the timeout was canceled.\n    assertFalse(timeout.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun enterSleepCancelExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    Thread.sleep(500)\n    timeout.cancel()\n\n    // Call timed out because the cancel was too late.\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun enterSleepCancelCancelExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    Thread.sleep(500)\n    timeout.cancel()\n    timeout.cancel()\n\n    // Call timed out because both cancels were too late.\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun enterCancelSleepCancelExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.enter()\n    timeout.cancel()\n    Thread.sleep(500)\n    timeout.cancel()\n\n    // Call didn't time out because the timeout was canceled.\n    assertFalse(timeout.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun cancelEnterSleepExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.cancel()\n    timeout.enter()\n    Thread.sleep(500)\n\n    // Call timed out because the cancel was too early.\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  @Test\n  fun cancelEnterCancelSleepExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n    timeout.cancel()\n    timeout.enter()\n    timeout.cancel()\n    Thread.sleep(500)\n\n    // Call didn't time out because the timeout was canceled.\n    assertFalse(timeout.exit())\n    assertTimedOut()\n  }\n\n  @Test\n  fun enterCancelSleepExitEnterSleepExit() {\n    val timeout = RecordingAsyncTimeout()\n    timeout.timeout(250, TimeUnit.MILLISECONDS)\n\n    // First call doesn't time out because we cancel it.\n    timeout.enter()\n    timeout.cancel()\n    Thread.sleep(500)\n    assertFalse(timeout.exit())\n    assertTimedOut()\n\n    // Second call does time out because it isn't canceled a second time.\n    timeout.enter()\n    Thread.sleep(500)\n    assertTrue(timeout.exit())\n    assertTimedOut(timeout)\n  }\n\n  /** Asserts which timeouts fired, and in which order.  */\n  private fun assertTimedOut(vararg expected: Timeout) {\n    assertEquals(expected.toList(), timedOut.toList())\n    timedOut.clear()\n  }\n\n  internal inner class RecordingAsyncTimeout : AsyncTimeout() {\n    override fun timedOut() {\n      timedOut.add(this)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/AwaitSignalTest.kt",
    "content": "/*\n * Copyright (C) 2023 Block Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport app.cash.burst.InterceptTest\nimport java.io.InterruptedIOException\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.locks.Condition\nimport java.util.concurrent.locks.ReentrantLock\nimport kotlin.time.Duration.Companion.milliseconds\nimport okio.TestUtil.assumeNotWindows\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Test\n\n@Burst\nclass AwaitSignalTest(\n  factory: TimeoutFactory,\n) {\n  private val timeout = factory.newTimeout()\n\n  @InterceptTest\n  private val executorService = TestExecutor(0)\n\n  val lock: ReentrantLock = ReentrantLock()\n  val condition: Condition = lock.newCondition()\n\n  @Test\n  fun signaled() = lock.withLock {\n    timeout.timeout(5000, TimeUnit.MILLISECONDS)\n    val start = now()\n    executorService.schedule(1000.milliseconds) {\n      lock.withLock { condition.signal() }\n    }\n    timeout.awaitSignal(condition)\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  fun timeout() = lock.withLock {\n    assumeNotWindows()\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.awaitSignal(condition)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  fun deadline() = lock.withLock {\n    assumeNotWindows()\n    timeout.deadline(1000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.awaitSignal(condition)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  fun deadlineBeforeTimeout() = lock.withLock {\n    assumeNotWindows()\n    timeout.timeout(5000, TimeUnit.MILLISECONDS)\n    timeout.deadline(1000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.awaitSignal(condition)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  fun timeoutBeforeDeadline() = lock.withLock {\n    assumeNotWindows()\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.deadline(5000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.awaitSignal(condition)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  fun deadlineAlreadyReached() = lock.withLock {\n    assumeNotWindows()\n    timeout.deadlineNanoTime(System.nanoTime())\n    val start = now()\n    try {\n      timeout.awaitSignal(condition)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(0.0, start)\n  }\n\n  @Test\n  fun threadInterrupted() = lock.withLock {\n    assumeNotWindows()\n    val start = now()\n    Thread.currentThread().interrupt()\n    try {\n      timeout.awaitSignal(condition)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"interrupted\", expected.message)\n      assertTrue(Thread.interrupted())\n    }\n    assertElapsed(0.0, start)\n  }\n\n  @Test\n  fun threadInterruptedOnThrowIfReached() = lock.withLock {\n    assumeNotWindows()\n    Thread.currentThread().interrupt()\n    try {\n      timeout.throwIfReached()\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"interrupted\", expected.message)\n      assertTrue(Thread.interrupted())\n    }\n  }\n\n  @Test\n  fun cancelBeforeWaitDoesNothing() = lock.withLock {\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.cancel()\n    val start = now()\n    try {\n      timeout.awaitSignal(condition)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  fun canceledTimeoutDoesNotThrowWhenNotNotifiedOnTime() = lock.withLock {\n    assumeNotWindows()\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.cancelLater(500)\n\n    val start = now()\n    timeout.awaitSignal(condition) // Returns early but doesn't throw.\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun multipleCancelsAreIdempotent() = lock.withLock {\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.cancelLater(250)\n    timeout.cancelLater(500)\n    timeout.cancelLater(750)\n\n    val start = now()\n    timeout.awaitSignal(condition) // Returns early but doesn't throw.\n    assertElapsed(1000.0, start)\n  }\n\n  /** Returns the nanotime in milliseconds as a double for measuring timeouts.  */\n  private fun now(): Double {\n    return System.nanoTime() / 1000000.0\n  }\n\n  /**\n   * Fails the test unless the time from start until now is duration, accepting differences in\n   * -50..+450 milliseconds.\n   */\n  private fun assertElapsed(duration: Double, start: Double) {\n    assertEquals(duration, now() - start - 200.0, 250.0)\n  }\n\n  private fun Timeout.cancelLater(delay: Long) {\n    executorService.schedule(delay.milliseconds) {\n      cancel()\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferCursorKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNotSame\nimport kotlin.test.assertSame\nimport kotlin.test.assertTrue\nimport okio.Buffer.UnsafeCursor\nimport okio.TestUtil.deepCopy\nimport org.junit.Assume.assumeTrue\nimport org.junit.Test\n\n@Burst\nclass BufferCursorKotlinTest(\n  private val bufferFactory: BufferFactory,\n) {\n  @Test fun acquireReadOnlyDoesNotCopySharedDataArray() {\n    val buffer = deepCopy(bufferFactory.newBuffer())\n    assumeTrue(buffer.size > 0L)\n\n    val shared = buffer.clone()\n    assertTrue(buffer.head!!.shared)\n\n    buffer.readUnsafe().use { cursor ->\n      cursor.seek(0)\n      assertSame(cursor.data, shared.head!!.data)\n    }\n  }\n\n  @Test fun acquireReadWriteDoesNotCopyUnsharedDataArray() {\n    val buffer = deepCopy(bufferFactory.newBuffer())\n    assumeTrue(buffer.size > 0L)\n    assertFalse(buffer.head!!.shared)\n\n    val originalData = buffer.head!!.data\n\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(0)\n      assertSame(cursor.data, originalData)\n    }\n  }\n\n  @Test fun acquireReadWriteCopiesSharedDataArray() {\n    val buffer = deepCopy(bufferFactory.newBuffer())\n    assumeTrue(buffer.size > 0L)\n\n    val shared = buffer.clone()\n    assertTrue(buffer.head!!.shared)\n\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(0)\n      assertNotSame(cursor.data, shared.head!!.data)\n    }\n  }\n\n  @Test fun writeSharedSegments() {\n    val buffer = bufferFactory.newBuffer()\n\n    // Make a deep copy. This buffer's segments are not shared.\n    val deepCopy = deepCopy(buffer)\n    assertTrue(deepCopy.head == null || !deepCopy.head!!.shared)\n\n    // Make a shallow copy. Both buffers' segments are shared as a side effect.\n    val shallowCopy = buffer.clone()\n    assertTrue(shallowCopy.head == null || shallowCopy.head!!.shared)\n    assertTrue(buffer.head == null || buffer.head!!.shared)\n\n    val expected = Buffer()\n    expected.writeUtf8(\"x\".repeat(buffer.size.toInt()))\n\n    buffer.readAndWriteUnsafe().use { cursor ->\n      while (cursor.next() != -1) {\n        cursor.data!!.fill('x'.code.toByte(), cursor.start, cursor.end)\n      }\n    }\n\n    // The buffer was fully changed.\n    assertEquals(expected, buffer)\n\n    // The buffer we're shared with is unchanged.\n    assertEquals(deepCopy, shallowCopy)\n  }\n\n  /** As an optimization it's okay to use the same cursor on multiple buffers.  */\n  @Test fun cursorReuse() {\n    val cursor = UnsafeCursor()\n\n    val buffer1 = bufferFactory.newBuffer()\n    buffer1.readUnsafe(cursor)\n    assertSame(buffer1, cursor.buffer)\n    assertFalse(cursor.readWrite)\n    cursor.close()\n    assertSame(null, cursor.buffer)\n\n    val buffer2 = bufferFactory.newBuffer()\n    buffer2.readAndWriteUnsafe(cursor)\n    assertSame(buffer2, cursor.buffer)\n    assertTrue(cursor.readWrite)\n    cursor.close()\n    assertSame(null, cursor.buffer)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferCursorTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport java.util.Arrays\nimport okio.ByteString.Companion.of\nimport okio.TestUtil.SEGMENT_SIZE\nimport okio.TestUtil.deepCopy\nimport org.junit.Assert\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertNotEquals\nimport org.junit.Assert.assertNotNull\nimport org.junit.Assert.assertNull\nimport org.junit.Assert.fail\nimport org.junit.Assume.assumeTrue\nimport org.junit.Test\n\n@Burst\nclass BufferCursorTest(\n  private var bufferFactory: BufferFactory,\n) {\n\n  @Test\n  fun apiExample() {\n    val buffer = Buffer()\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.resizeBuffer(1000000)\n      do {\n        Arrays.fill(cursor.data, cursor.start, cursor.end, 'x'.code.toByte())\n      } while (cursor.next() != -1)\n      cursor.seek(3)\n      cursor.data!![cursor.start] = 'o'.code.toByte()\n      cursor.seek(1)\n      cursor.data!![cursor.start] = 'o'.code.toByte()\n      cursor.resizeBuffer(4)\n    }\n    assertEquals(Buffer().writeUtf8(\"xoxo\"), buffer)\n  }\n\n  @Test\n  fun accessSegmentBySegment() {\n    val buffer = bufferFactory.newBuffer()\n    buffer.readUnsafe().use { cursor ->\n      val actual = Buffer()\n      while (cursor.next().toLong() != -1L) {\n        actual.write(cursor.data!!, cursor.start, cursor.end - cursor.start)\n      }\n      assertEquals(buffer, actual)\n    }\n  }\n\n  @Test\n  fun seekToNegativeOneSeeksBeforeFirstSegment() {\n    val buffer = bufferFactory.newBuffer()\n    buffer.readUnsafe().use { cursor ->\n      cursor.seek(-1L)\n      assertEquals(-1, cursor.offset)\n      assertNull(cursor.data)\n      assertEquals(-1, cursor.start.toLong())\n      assertEquals(-1, cursor.end.toLong())\n      cursor.next()\n      assertEquals(0, cursor.offset)\n    }\n  }\n\n  @Test\n  fun accessByteByByte() {\n    val buffer = bufferFactory.newBuffer()\n    buffer.readUnsafe().use { cursor ->\n      val actual = ByteArray(buffer.size.toInt())\n      for (i in 0 until buffer.size) {\n        cursor.seek(i)\n        actual[i.toInt()] = cursor.data!![cursor.start]\n      }\n      assertEquals(of(*actual), buffer.snapshot())\n    }\n  }\n\n  @Test\n  fun accessByteByByteReverse() {\n    val buffer = bufferFactory.newBuffer()\n    buffer.readUnsafe().use { cursor ->\n      val actual = ByteArray(buffer.size.toInt())\n      for (i in (buffer.size - 1).toInt() downTo 0) {\n        cursor.seek(i.toLong())\n        actual[i] = cursor.data!![cursor.start]\n      }\n      assertEquals(of(*actual), buffer.snapshot())\n    }\n  }\n\n  @Test\n  fun accessByteByByteAlwaysResettingToZero() {\n    val buffer = bufferFactory.newBuffer()\n    buffer.readUnsafe().use { cursor ->\n      val actual = ByteArray(buffer.size.toInt())\n      for (i in 0 until buffer.size) {\n        cursor.seek(i)\n        actual[i.toInt()] = cursor.data!![cursor.start]\n        cursor.seek(0L)\n      }\n      assertEquals(of(*actual), buffer.snapshot())\n    }\n  }\n\n  @Test\n  fun segmentBySegmentNavigation() {\n    val buffer = bufferFactory.newBuffer()\n    val cursor = buffer.readUnsafe()\n    assertEquals(-1, cursor.offset)\n    try {\n      var lastOffset = cursor.offset\n      while (cursor.next().toLong() != -1L) {\n        Assert.assertTrue(cursor.offset > lastOffset)\n        lastOffset = cursor.offset\n      }\n      assertEquals(buffer.size, cursor.offset)\n      assertNull(cursor.data)\n      assertEquals(-1, cursor.start.toLong())\n      assertEquals(-1, cursor.end.toLong())\n    } finally {\n      cursor.close()\n    }\n  }\n\n  @Test\n  fun seekWithinSegment() {\n    assumeTrue(bufferFactory === BufferFactory.SmallSegmentedBuffer)\n    val buffer = bufferFactory.newBuffer()\n    assertEquals(\"abcdefghijkl\", buffer.clone().readUtf8())\n    buffer.readUnsafe().use { cursor ->\n      assertEquals(2, cursor.seek(5).toLong()) // 2 for 2 bytes left in the segment: \"fg\".\n      assertEquals(5, cursor.offset)\n      assertEquals(2, (cursor.end - cursor.start).toLong())\n      assertEquals('d'.code.toLong(), Char(cursor.data!![cursor.start - 2].toUShort()).code.toLong()) // Out of bounds!\n      assertEquals('e'.code.toLong(), Char(cursor.data!![cursor.start - 1].toUShort()).code.toLong()) // Out of bounds!\n      assertEquals('f'.code.toLong(), Char(cursor.data!![cursor.start].toUShort()).code.toLong())\n      assertEquals('g'.code.toLong(), Char(cursor.data!![cursor.start + 1].toUShort()).code.toLong())\n    }\n  }\n\n  @Test\n  fun acquireAndRelease() {\n    val buffer = bufferFactory.newBuffer()\n    val cursor = Buffer.UnsafeCursor()\n\n    // Nothing initialized before acquire.\n    assertEquals(-1, cursor.offset)\n    assertNull(cursor.data)\n    assertEquals(-1, cursor.start.toLong())\n    assertEquals(-1, cursor.end.toLong())\n    buffer.readUnsafe(cursor)\n    cursor.close()\n\n    // Nothing initialized after close.\n    assertEquals(-1, cursor.offset)\n    assertNull(cursor.data)\n    assertEquals(-1, cursor.start.toLong())\n    assertEquals(-1, cursor.end.toLong())\n  }\n\n  @Test\n  fun doubleAcquire() {\n    val buffer = bufferFactory.newBuffer()\n    try {\n      buffer.readUnsafe().use { cursor ->\n        buffer.readUnsafe(cursor)\n        fail()\n      }\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun releaseWithoutAcquire() {\n    val cursor = Buffer.UnsafeCursor()\n    try {\n      cursor.close()\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun releaseAfterRelease() {\n    val buffer = bufferFactory.newBuffer()\n    val cursor = buffer.readUnsafe()\n    cursor.close()\n    try {\n      cursor.close()\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun enlarge() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    val expected = deepCopy(buffer)\n    expected.writeUtf8(\"abc\")\n    buffer.readAndWriteUnsafe().use { cursor ->\n      assertEquals(originalSize, cursor.resizeBuffer(originalSize + 3))\n      cursor.seek(originalSize)\n      cursor.data!![cursor.start] = 'a'.code.toByte()\n      cursor.seek(originalSize + 1)\n      cursor.data!![cursor.start] = 'b'.code.toByte()\n      cursor.seek(originalSize + 2)\n      cursor.data!![cursor.start] = 'c'.code.toByte()\n    }\n    assertEquals(expected, buffer)\n  }\n\n  @Test\n  fun enlargeByManySegments() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    val expected = deepCopy(buffer)\n    expected.writeUtf8(\"x\".repeat(1000000))\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.resizeBuffer(originalSize + 1000000)\n      cursor.seek(originalSize)\n      do {\n        Arrays.fill(cursor.data, cursor.start, cursor.end, 'x'.code.toByte())\n      } while (cursor.next() != -1)\n    }\n    assertEquals(expected, buffer)\n  }\n\n  @Test\n  fun resizeNotAcquired() {\n    val cursor = Buffer.UnsafeCursor()\n    try {\n      cursor.resizeBuffer(10)\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun expandNotAcquired() {\n    val cursor = Buffer.UnsafeCursor()\n    try {\n      cursor.expandBuffer(10)\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun resizeAcquiredReadOnly() {\n    val buffer = bufferFactory.newBuffer()\n    try {\n      buffer.readUnsafe().use { cursor ->\n        cursor.resizeBuffer(10)\n        fail()\n      }\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun expandAcquiredReadOnly() {\n    val buffer = bufferFactory.newBuffer()\n    try {\n      buffer.readUnsafe().use { cursor ->\n        cursor.expandBuffer(10)\n        fail()\n      }\n    } catch (expected: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun shrink() {\n    val buffer = bufferFactory.newBuffer()\n    assumeTrue(buffer.size > 3)\n    val originalSize = buffer.size\n    val expected = Buffer()\n    deepCopy(buffer).copyTo(expected, 0, originalSize - 3)\n    buffer.readAndWriteUnsafe().use { cursor ->\n      assertEquals(originalSize, cursor.resizeBuffer(originalSize - 3))\n    }\n    assertEquals(expected, buffer)\n  }\n\n  @Test\n  fun shrinkByManySegments() {\n    val buffer = bufferFactory.newBuffer()\n    assumeTrue(buffer.size <= 1000000)\n    val originalSize = buffer.size\n    val toShrink = Buffer()\n    toShrink.writeUtf8(\"x\".repeat(1000000))\n    deepCopy(buffer).copyTo(toShrink, 0, originalSize)\n    val cursor = Buffer.UnsafeCursor()\n    toShrink.readAndWriteUnsafe(cursor)\n    try {\n      cursor.resizeBuffer(originalSize)\n    } finally {\n      cursor.close()\n    }\n    val expected = Buffer()\n    expected.writeUtf8(\"x\".repeat(originalSize.toInt()))\n    assertEquals(expected, toShrink)\n  }\n\n  @Test\n  fun shrinkAdjustOffset() {\n    val buffer = bufferFactory.newBuffer()\n    assumeTrue(buffer.size > 4)\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(buffer.size - 1)\n      cursor.resizeBuffer(3)\n      assertEquals(3, cursor.offset)\n      assertNull(cursor.data)\n      assertEquals(-1, cursor.start.toLong())\n      assertEquals(-1, cursor.end.toLong())\n    }\n  }\n\n  @Test\n  fun resizeToSameSizeSeeksToEnd() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(buffer.size / 2)\n      assertEquals(originalSize, buffer.size)\n      cursor.resizeBuffer(originalSize)\n      assertEquals(originalSize, buffer.size)\n      assertEquals(originalSize, cursor.offset)\n      assertNull(cursor.data)\n      assertEquals(-1, cursor.start.toLong())\n      assertEquals(-1, cursor.end.toLong())\n    }\n  }\n\n  @Test\n  fun resizeEnlargeMovesCursorToOldSize() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    val expected = deepCopy(buffer)\n    expected.writeUtf8(\"a\")\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(buffer.size / 2)\n      assertEquals(originalSize, buffer.size)\n      cursor.resizeBuffer(originalSize + 1)\n      assertEquals(originalSize, cursor.offset)\n      assertNotNull(cursor.data)\n      assertNotEquals(-1, cursor.start.toLong())\n      assertEquals((cursor.start + 1).toLong(), cursor.end.toLong())\n      cursor.data!![cursor.start] = 'a'.code.toByte()\n    }\n    assertEquals(expected, buffer)\n  }\n\n  @Test\n  fun resizeShrinkMovesCursorToEnd() {\n    val buffer = bufferFactory.newBuffer()\n    assumeTrue(buffer.size > 0)\n    val originalSize = buffer.size\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(buffer.size / 2)\n      assertEquals(originalSize, buffer.size)\n      cursor.resizeBuffer(originalSize - 1)\n      assertEquals(originalSize - 1, cursor.offset)\n      assertNull(cursor.data)\n      assertEquals(-1, cursor.start.toLong())\n      assertEquals(-1, cursor.end.toLong())\n    }\n  }\n\n  @Test\n  fun expand() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    val expected = deepCopy(buffer)\n    expected.writeUtf8(\"abcde\")\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.expandBuffer(5)\n      for (i in 0..4) {\n        cursor.data!![cursor.start + i] = ('a'.code + i).toByte()\n      }\n      cursor.resizeBuffer(originalSize + 5)\n    }\n    assertEquals(expected, buffer)\n  }\n\n  @Test\n  fun expandSameSegment() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    assumeTrue(originalSize > 0)\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(originalSize - 1)\n      val originalEnd = cursor.end\n      assumeTrue(originalEnd < SEGMENT_SIZE)\n      val addedByteCount = cursor.expandBuffer(1)\n      assertEquals((SEGMENT_SIZE - originalEnd).toLong(), addedByteCount)\n      assertEquals(originalSize + addedByteCount, buffer.size)\n      assertEquals(originalSize, cursor.offset)\n      assertEquals(originalEnd.toLong(), cursor.start.toLong())\n      assertEquals(SEGMENT_SIZE.toLong(), cursor.end.toLong())\n    }\n  }\n\n  @Test\n  fun expandNewSegment() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    buffer.readAndWriteUnsafe().use { cursor ->\n      val addedByteCount = cursor.expandBuffer(SEGMENT_SIZE)\n      assertEquals(SEGMENT_SIZE.toLong(), addedByteCount)\n      assertEquals(originalSize, cursor.offset)\n      assertEquals(0, cursor.start.toLong())\n      assertEquals(SEGMENT_SIZE.toLong(), cursor.end.toLong())\n    }\n  }\n\n  @Test\n  fun expandMovesOffsetToOldSize() {\n    val buffer = bufferFactory.newBuffer()\n    val originalSize = buffer.size\n    buffer.readAndWriteUnsafe().use { cursor ->\n      cursor.seek(buffer.size / 2)\n      assertEquals(originalSize, buffer.size)\n      val addedByteCount = cursor.expandBuffer(5)\n      assertEquals(originalSize + addedByteCount, buffer.size)\n      assertEquals(originalSize, cursor.offset)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferFactory.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nimport java.util.Random\nimport okio.TestUtil.bufferWithRandomSegmentLayout\nimport okio.TestUtil.bufferWithSegments\n\nenum class BufferFactory {\n  Empty {\n    override fun newBuffer(): Buffer {\n      return Buffer()\n    }\n  },\n\n  SmallBuffer {\n    override fun newBuffer(): Buffer {\n      return Buffer().writeUtf8(\"abcde\")\n    }\n  },\n\n  SmallSegmentedBuffer {\n    @Throws(Exception::class)\n    override fun newBuffer(): Buffer {\n      return bufferWithSegments(\"abc\", \"defg\", \"hijkl\")\n    }\n  },\n\n  LargeBuffer {\n    @Throws(Exception::class)\n    override fun newBuffer(): Buffer {\n      val dice = Random(0)\n      val largeByteArray = ByteArray(512 * 1024)\n      dice.nextBytes(largeByteArray)\n\n      return Buffer().write(largeByteArray)\n    }\n  },\n\n  LargeBufferWithRandomLayout {\n    @Throws(Exception::class)\n    override fun newBuffer(): Buffer {\n      val dice = Random(0)\n      val largeByteArray = ByteArray(512 * 1024)\n      dice.nextBytes(largeByteArray)\n\n      return bufferWithRandomSegmentLayout(dice, largeByteArray)\n    }\n  },\n  ;\n\n  @Throws(Exception::class)\n  abstract fun newBuffer(): Buffer\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport kotlin.test.assertFailsWith\nimport org.junit.Test\n\nclass BufferKotlinTest {\n  @Test fun get() {\n    val actual = Buffer().writeUtf8(\"abc\")\n    assertThat(actual[0]).isEqualTo('a'.code.toByte())\n    assertThat(actual[1]).isEqualTo('b'.code.toByte())\n    assertThat(actual[2]).isEqualTo('c'.code.toByte())\n    assertFailsWith<IndexOutOfBoundsException> {\n      actual[-1]\n    }\n    assertFailsWith<IndexOutOfBoundsException> {\n      actual[3]\n    }\n  }\n\n  @Test fun copyToOutputStream() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n\n    val target = Buffer()\n    source.copyTo(target.outputStream())\n    assertThat(target.readUtf8()).isEqualTo(\"party\")\n    assertThat(source.readUtf8()).isEqualTo(\"party\")\n  }\n\n  @Test fun copyToOutputStreamWithOffset() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n\n    val target = Buffer()\n    source.copyTo(target.outputStream(), offset = 2)\n    assertThat(target.readUtf8()).isEqualTo(\"rty\")\n    assertThat(source.readUtf8()).isEqualTo(\"party\")\n  }\n\n  @Test fun copyToOutputStreamWithByteCount() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n\n    val target = Buffer()\n    source.copyTo(target.outputStream(), byteCount = 3)\n    assertThat(target.readUtf8()).isEqualTo(\"par\")\n    assertThat(source.readUtf8()).isEqualTo(\"party\")\n  }\n\n  @Test fun copyToOutputStreamWithOffsetAndByteCount() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n\n    val target = Buffer()\n    source.copyTo(target.outputStream(), offset = 1, byteCount = 3)\n    assertThat(target.readUtf8()).isEqualTo(\"art\")\n    assertThat(source.readUtf8()).isEqualTo(\"party\")\n  }\n\n  @Test fun writeToOutputStream() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n\n    val target = Buffer()\n    source.writeTo(target.outputStream())\n    assertThat(target.readUtf8()).isEqualTo(\"party\")\n    assertThat(source.readUtf8()).isEqualTo(\"\")\n  }\n\n  @Test fun writeToOutputStreamWithByteCount() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n\n    val target = Buffer()\n    source.writeTo(target.outputStream(), byteCount = 3)\n    assertThat(target.readUtf8()).isEqualTo(\"par\")\n    assertThat(source.readUtf8()).isEqualTo(\"ty\")\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.ByteArrayInputStream\nimport java.io.ByteArrayOutputStream\nimport java.io.EOFException\nimport java.io.InputStream\nimport java.util.Arrays\nimport java.util.Random\nimport kotlin.text.Charsets.UTF_8\nimport okio.ByteString.Companion.decodeHex\nimport okio.TestUtil.SEGMENT_POOL_MAX_SIZE\nimport okio.TestUtil.SEGMENT_SIZE\nimport okio.TestUtil.bufferWithRandomSegmentLayout\nimport okio.TestUtil.segmentPoolByteCount\nimport okio.TestUtil.segmentSizes\nimport org.junit.Assert\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.Test\n\n/**\n * Tests solely for the behavior of Buffer's implementation. For generic BufferedSink or\n * BufferedSource behavior use BufferedSinkTest or BufferedSourceTest, respectively.\n */\nclass BufferTest {\n  @Test\n  fun readAndWriteUtf8() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"ab\")\n    assertEquals(2, buffer.size)\n    buffer.writeUtf8(\"cdef\")\n    assertEquals(6, buffer.size)\n    assertEquals(\"abcd\", buffer.readUtf8(4))\n    assertEquals(2, buffer.size)\n    assertEquals(\"ef\", buffer.readUtf8(2))\n    assertEquals(0, buffer.size)\n    try {\n      buffer.readUtf8(1)\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  /** Buffer's toString is the same as ByteString's.  */\n  @Test\n  fun bufferToString() {\n    assertEquals(\"[size=0]\", Buffer().toString())\n    assertEquals(\n      \"[text=a\\\\r\\\\nb\\\\nc\\\\rd\\\\\\\\e]\",\n      Buffer().writeUtf8(\"a\\r\\nb\\nc\\rd\\\\e\").toString(),\n    )\n    assertEquals(\n      \"[text=Tyrannosaur]\",\n      Buffer().writeUtf8(\"Tyrannosaur\").toString(),\n    )\n    assertEquals(\n      \"[text=təˈranəˌsôr]\",\n      Buffer()\n        .write(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex())\n        .toString(),\n    )\n    assertEquals(\n      \"[hex=0000000000000000000000000000000000000000000000000000000000000000000000000000\" +\n        \"0000000000000000000000000000000000000000000000000000]\",\n      Buffer().write(ByteArray(64)).toString(),\n    )\n  }\n\n  @Test\n  fun multipleSegmentBuffers() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"a\".repeat(1000))\n    buffer.writeUtf8(\"b\".repeat(2500))\n    buffer.writeUtf8(\"c\".repeat(5000))\n    buffer.writeUtf8(\"d\".repeat(10000))\n    buffer.writeUtf8(\"e\".repeat(25000))\n    buffer.writeUtf8(\"f\".repeat(50000))\n    assertEquals(\"a\".repeat(999), buffer.readUtf8(999)) // a...a\n    assertEquals(\"a\" + \"b\".repeat(2500) + \"c\", buffer.readUtf8(2502)) // ab...bc\n    assertEquals(\"c\".repeat(4998), buffer.readUtf8(4998)) // c...c\n    assertEquals(\"c\" + \"d\".repeat(10000) + \"e\", buffer.readUtf8(10002)) // cd...de\n    assertEquals(\"e\".repeat(24998), buffer.readUtf8(24998)) // e...e\n    assertEquals(\"e\" + \"f\".repeat(50000), buffer.readUtf8(50001)) // ef...f\n    assertEquals(0, buffer.size)\n  }\n\n  @Test\n  fun fillAndDrainPool() {\n    val buffer = Buffer()\n\n    // Take 2 * MAX_SIZE segments. This will drain the pool, even if other tests filled it.\n    buffer.write(ByteArray(SEGMENT_POOL_MAX_SIZE))\n    buffer.write(ByteArray(SEGMENT_POOL_MAX_SIZE))\n    assertEquals(0, segmentPoolByteCount().toLong())\n\n    // Recycle MAX_SIZE segments. They're all in the pool.\n    buffer.skip(SEGMENT_POOL_MAX_SIZE.toLong())\n    assertEquals(SEGMENT_POOL_MAX_SIZE.toLong(), segmentPoolByteCount().toLong())\n\n    // Recycle MAX_SIZE more segments. The pool is full so they get garbage collected.\n    buffer.skip(SEGMENT_POOL_MAX_SIZE.toLong())\n    assertEquals(SEGMENT_POOL_MAX_SIZE.toLong(), segmentPoolByteCount().toLong())\n\n    // Take MAX_SIZE segments to drain the pool.\n    buffer.write(ByteArray(SEGMENT_POOL_MAX_SIZE))\n    assertEquals(0, segmentPoolByteCount().toLong())\n\n    // Take MAX_SIZE more segments. The pool is drained so these will need to be allocated.\n    buffer.write(ByteArray(SEGMENT_POOL_MAX_SIZE))\n    assertEquals(0, segmentPoolByteCount().toLong())\n  }\n\n  @Test\n  fun moveBytesBetweenBuffersShareSegment() {\n    val size: Int = SEGMENT_SIZE / 2 - 1\n    val segmentSizes = moveBytesBetweenBuffers(\"a\".repeat(size), \"b\".repeat(size))\n    assertEquals(Arrays.asList(size * 2), segmentSizes)\n  }\n\n  @Test\n  fun moveBytesBetweenBuffersReassignSegment() {\n    val size: Int = SEGMENT_SIZE / 2 + 1\n    val segmentSizes = moveBytesBetweenBuffers(\"a\".repeat(size), \"b\".repeat(size))\n    assertEquals(Arrays.asList(size, size), segmentSizes)\n  }\n\n  @Test\n  fun moveBytesBetweenBuffersMultipleSegments() {\n    val size: Int = 3 * SEGMENT_SIZE + 1\n    val segmentSizes = moveBytesBetweenBuffers(\"a\".repeat(size), \"b\".repeat(size))\n    assertEquals(\n      listOf(\n        SEGMENT_SIZE,\n        SEGMENT_SIZE,\n        SEGMENT_SIZE,\n        1,\n        SEGMENT_SIZE,\n        SEGMENT_SIZE,\n        SEGMENT_SIZE,\n        1,\n      ),\n      segmentSizes,\n    )\n  }\n\n  private fun moveBytesBetweenBuffers(vararg contents: String): List<Int> {\n    val expected = StringBuilder()\n    val buffer = Buffer()\n    for (s in contents) {\n      val source = Buffer()\n      source.writeUtf8(s)\n      buffer.writeAll(source)\n      expected.append(s)\n    }\n    val segmentSizes = segmentSizes(buffer)\n    assertEquals(expected.toString(), buffer.readUtf8(expected.length.toLong()))\n    return segmentSizes\n  }\n\n  /** The big part of source's first segment is being moved.  */\n  @Test\n  fun writeSplitSourceBufferLeft() {\n    val writeSize: Int = SEGMENT_SIZE / 2 + 1\n    val sink = Buffer()\n    sink.writeUtf8(\"b\".repeat(SEGMENT_SIZE - 10))\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    sink.write(source, writeSize.toLong())\n    assertEquals(Arrays.asList<Int>(SEGMENT_SIZE - 10, writeSize), segmentSizes(sink))\n    assertEquals(Arrays.asList<Int>(SEGMENT_SIZE - writeSize, SEGMENT_SIZE), segmentSizes(source))\n  }\n\n  /** The big part of source's first segment is staying put.  */\n  @Test\n  fun writeSplitSourceBufferRight() {\n    val writeSize: Int = SEGMENT_SIZE / 2 - 1\n    val sink = Buffer()\n    sink.writeUtf8(\"b\".repeat(SEGMENT_SIZE - 10))\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    sink.write(source, writeSize.toLong())\n    assertEquals(Arrays.asList<Int>(SEGMENT_SIZE - 10, writeSize), segmentSizes(sink))\n    assertEquals(Arrays.asList<Int>(SEGMENT_SIZE - writeSize, SEGMENT_SIZE), segmentSizes(source))\n  }\n\n  @Test\n  fun writePrefixDoesntSplit() {\n    val sink = Buffer()\n    sink.writeUtf8(\"b\".repeat(10))\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    sink.write(source, 20)\n    assertEquals(mutableListOf(30), segmentSizes(sink))\n    assertEquals(Arrays.asList<Int>(SEGMENT_SIZE - 20, SEGMENT_SIZE), segmentSizes(source))\n    assertEquals(30, sink.size)\n    assertEquals((SEGMENT_SIZE * 2 - 20).toLong(), source.size)\n  }\n\n  @Test\n  fun writePrefixDoesntSplitButRequiresCompact() {\n    val sink = Buffer()\n    sink.writeUtf8(\"b\".repeat(SEGMENT_SIZE - 10)) // limit = size - 10\n    sink.readUtf8((SEGMENT_SIZE - 20).toLong()) // pos = size = 20\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    sink.write(source, 20)\n    assertEquals(mutableListOf(30), segmentSizes(sink))\n    assertEquals(Arrays.asList<Int>(SEGMENT_SIZE - 20, SEGMENT_SIZE), segmentSizes(source))\n    assertEquals(30, sink.size)\n    assertEquals((SEGMENT_SIZE * 2 - 20).toLong(), source.size)\n  }\n\n  @Test\n  fun copyToSpanningSegments() {\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    source.writeUtf8(\"b\".repeat(SEGMENT_SIZE * 2))\n    val out = ByteArrayOutputStream()\n    source.copyTo(out, 10, (SEGMENT_SIZE * 3).toLong())\n    assertEquals(\n      \"a\".repeat(SEGMENT_SIZE * 2 - 10) + \"b\".repeat(SEGMENT_SIZE + 10),\n      out.toString(),\n    )\n    assertEquals(\n      \"a\".repeat(SEGMENT_SIZE * 2) + \"b\".repeat(SEGMENT_SIZE * 2),\n      source.readUtf8((SEGMENT_SIZE * 4).toLong()),\n    )\n  }\n\n  @Test\n  fun copyToStream() {\n    val buffer = Buffer().writeUtf8(\"hello, world!\")\n    val out = ByteArrayOutputStream()\n    buffer.copyTo(out)\n    val outString = out.toByteArray().toString(UTF_8)\n    assertEquals(\"hello, world!\", outString)\n    assertEquals(\"hello, world!\", buffer.readUtf8())\n  }\n\n  @Test\n  fun writeToSpanningSegments() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    buffer.writeUtf8(\"b\".repeat(SEGMENT_SIZE * 2))\n    val out = ByteArrayOutputStream()\n    buffer.skip(10)\n    buffer.writeTo(out, (SEGMENT_SIZE * 3).toLong())\n    assertEquals(\n      \"a\".repeat(SEGMENT_SIZE * 2 - 10) + \"b\".repeat(SEGMENT_SIZE + 10),\n      out.toString(),\n    )\n    assertEquals(\"b\".repeat(SEGMENT_SIZE - 10), buffer.readUtf8(buffer.size))\n  }\n\n  @Test\n  fun writeToStream() {\n    val buffer = Buffer().writeUtf8(\"hello, world!\")\n    val out = ByteArrayOutputStream()\n    buffer.writeTo(out)\n    val outString = out.toByteArray().toString(UTF_8)\n    assertEquals(\"hello, world!\", outString)\n    assertEquals(0, buffer.size)\n  }\n\n  @Test\n  fun readFromStream() {\n    val `in`: InputStream = ByteArrayInputStream(\"hello, world!\".toByteArray(UTF_8))\n    val buffer = Buffer()\n    buffer.readFrom(`in`)\n    val out = buffer.readUtf8()\n    assertEquals(\"hello, world!\", out)\n  }\n\n  @Test\n  fun readFromSpanningSegments() {\n    val `in`: InputStream = ByteArrayInputStream(\"hello, world!\".toByteArray(UTF_8))\n    val buffer = Buffer().writeUtf8(\"a\".repeat(SEGMENT_SIZE - 10))\n    buffer.readFrom(`in`)\n    val out = buffer.readUtf8()\n    assertEquals(\"a\".repeat(SEGMENT_SIZE - 10) + \"hello, world!\", out)\n  }\n\n  @Test\n  fun readFromStreamWithCount() {\n    val `in`: InputStream = ByteArrayInputStream(\"hello, world!\".toByteArray(UTF_8))\n    val buffer = Buffer()\n    buffer.readFrom(`in`, 10)\n    val out = buffer.readUtf8()\n    assertEquals(\"hello, wor\", out)\n  }\n\n  @Test\n  fun readFromDoesNotLeaveEmptyTailSegment() {\n    val buffer = Buffer()\n    buffer.readFrom(ByteArrayInputStream(ByteArray(SEGMENT_SIZE)))\n    assertNoEmptySegments(buffer)\n  }\n\n  @Test\n  fun moveAllRequestedBytesWithRead() {\n    val sink = Buffer()\n    sink.writeUtf8(\"a\".repeat(10))\n    val source = Buffer()\n    source.writeUtf8(\"b\".repeat(15))\n    assertEquals(10, source.read(sink, 10))\n    assertEquals(20, sink.size)\n    assertEquals(5, source.size)\n    assertEquals(\"a\".repeat(10) + \"b\".repeat(10), sink.readUtf8(20))\n  }\n\n  @Test\n  fun moveFewerThanRequestedBytesWithRead() {\n    val sink = Buffer()\n    sink.writeUtf8(\"a\".repeat(10))\n    val source = Buffer()\n    source.writeUtf8(\"b\".repeat(20))\n    assertEquals(20, source.read(sink, 25))\n    assertEquals(30, sink.size)\n    assertEquals(0, source.size)\n    assertEquals(\"a\".repeat(10) + \"b\".repeat(20), sink.readUtf8(30))\n  }\n\n  @Test\n  fun indexOfWithOffset() {\n    val buffer = Buffer()\n    val halfSegment: Int = SEGMENT_SIZE / 2\n    buffer.writeUtf8(\"a\".repeat(halfSegment))\n    buffer.writeUtf8(\"b\".repeat(halfSegment))\n    buffer.writeUtf8(\"c\".repeat(halfSegment))\n    buffer.writeUtf8(\"d\".repeat(halfSegment))\n    assertEquals(0, buffer.indexOf('a'.code.toByte(), 0))\n    assertEquals((halfSegment - 1).toLong(), buffer.indexOf('a'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals(halfSegment.toLong(), buffer.indexOf('b'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals((halfSegment * 2).toLong(), buffer.indexOf('c'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment - 1).toLong()))\n    assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 2).toLong()))\n    assertEquals((halfSegment * 3).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 3).toLong()))\n    assertEquals((halfSegment * 4 - 1).toLong(), buffer.indexOf('d'.code.toByte(), (halfSegment * 4 - 1).toLong()))\n  }\n\n  @Test\n  fun byteAt() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"a\")\n    buffer.writeUtf8(\"b\".repeat(SEGMENT_SIZE))\n    buffer.writeUtf8(\"c\")\n    assertEquals('a'.code.toLong(), buffer[0].toLong())\n    assertEquals('a'.code.toLong(), buffer[0].toLong()) // getByte doesn't mutate!\n    assertEquals('c'.code.toLong(), buffer[buffer.size - 1].toLong())\n    assertEquals('b'.code.toLong(), buffer[buffer.size - 2].toLong())\n    assertEquals('b'.code.toLong(), buffer[buffer.size - 3].toLong())\n  }\n\n  @Test\n  fun getByteOfEmptyBuffer() {\n    val buffer = Buffer()\n    try {\n      buffer[0]\n      fail()\n    } catch (expected: IndexOutOfBoundsException) {\n    }\n  }\n\n  @Test\n  fun writePrefixToEmptyBuffer() {\n    val sink = Buffer()\n    val source = Buffer()\n    source.writeUtf8(\"abcd\")\n    sink.write(source, 2)\n    assertEquals(\"ab\", sink.readUtf8(2))\n  }\n\n  @Test\n  fun cloneDoesNotObserveWritesToOriginal() {\n    val original = Buffer()\n    val clone = original.clone()\n    original.writeUtf8(\"abc\")\n    assertEquals(0, clone.size)\n  }\n\n  @Test\n  fun cloneDoesNotObserveReadsFromOriginal() {\n    val original = Buffer()\n    original.writeUtf8(\"abc\")\n    val clone = original.clone()\n    assertEquals(\"abc\", original.readUtf8(3))\n    assertEquals(3, clone.size)\n    assertEquals(\"ab\", clone.readUtf8(2))\n  }\n\n  @Test\n  fun originalDoesNotObserveWritesToClone() {\n    val original = Buffer()\n    val clone = original.clone()\n    clone.writeUtf8(\"abc\")\n    assertEquals(0, original.size)\n  }\n\n  @Test\n  fun originalDoesNotObserveReadsFromClone() {\n    val original = Buffer()\n    original.writeUtf8(\"abc\")\n    val clone = original.clone()\n    assertEquals(\"abc\", clone.readUtf8(3))\n    assertEquals(3, original.size)\n    assertEquals(\"ab\", original.readUtf8(2))\n  }\n\n  @Test\n  fun cloneMultipleSegments() {\n    val original = Buffer()\n    original.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 3))\n    val clone = original.clone()\n    original.writeUtf8(\"b\".repeat(SEGMENT_SIZE * 3))\n    clone.writeUtf8(\"c\".repeat(SEGMENT_SIZE * 3))\n    assertEquals(\n      \"a\".repeat(SEGMENT_SIZE * 3) + \"b\".repeat(SEGMENT_SIZE * 3),\n      original.readUtf8((SEGMENT_SIZE * 6).toLong()),\n    )\n    assertEquals(\n      \"a\".repeat(SEGMENT_SIZE * 3) + \"c\".repeat(SEGMENT_SIZE * 3),\n      clone.readUtf8((SEGMENT_SIZE * 6).toLong()),\n    )\n  }\n\n  @Test\n  fun equalsAndHashCodeEmpty() {\n    val a = Buffer()\n    val b = Buffer()\n    assertEquals(a, b)\n    assertEquals(a.hashCode().toLong(), b.hashCode().toLong())\n  }\n\n  @Test\n  fun equalsAndHashCode() {\n    val a = Buffer().writeUtf8(\"dog\")\n    val b = Buffer().writeUtf8(\"hotdog\")\n    Assert.assertNotEquals(a, b)\n    Assert.assertNotEquals(a.hashCode().toLong(), b.hashCode().toLong())\n    b.readUtf8(3) // Leaves b containing 'dog'.\n    assertEquals(a, b)\n    assertEquals(a.hashCode().toLong(), b.hashCode().toLong())\n  }\n\n  @Test\n  fun equalsAndHashCodeSpanningSegments() {\n    val data = ByteArray(1024 * 1024)\n    val dice = Random(0)\n    dice.nextBytes(data)\n    val a = bufferWithRandomSegmentLayout(dice, data)\n    val b = bufferWithRandomSegmentLayout(dice, data)\n    assertEquals(a, b)\n    assertEquals(a.hashCode().toLong(), b.hashCode().toLong())\n    data[data.size / 2]++ // Change a single byte.\n    val c = bufferWithRandomSegmentLayout(dice, data)\n    Assert.assertNotEquals(a, c)\n    Assert.assertNotEquals(a.hashCode().toLong(), c.hashCode().toLong())\n  }\n\n  @Test\n  fun bufferInputStreamByteByByte() {\n    val source = Buffer()\n    source.writeUtf8(\"abc\")\n    val `in` = source.inputStream()\n    assertEquals(3, `in`.available().toLong())\n    assertEquals('a'.code.toLong(), `in`.read().toLong())\n    assertEquals('b'.code.toLong(), `in`.read().toLong())\n    assertEquals('c'.code.toLong(), `in`.read().toLong())\n    assertEquals(-1, `in`.read().toLong())\n    assertEquals(0, `in`.available().toLong())\n  }\n\n  @Test\n  fun bufferInputStreamBulkReads() {\n    val source = Buffer()\n    source.writeUtf8(\"abc\")\n    val byteArray = ByteArray(4)\n    byteArray.fill(-5)\n    val `in` = source.inputStream()\n    assertEquals(3, `in`.read(byteArray).toLong())\n    assertEquals(\"[97, 98, 99, -5]\", Arrays.toString(byteArray))\n    byteArray.fill(-7)\n    assertEquals(-1, `in`.read(byteArray).toLong())\n    assertEquals(\"[-7, -7, -7, -7]\", Arrays.toString(byteArray))\n  }\n\n  /**\n   * When writing data that's already buffered, there's no reason to page the\n   * data by segment.\n   */\n  @Test\n  fun readAllWritesAllSegmentsAtOnce() {\n    val write1 = Buffer().writeUtf8(\n      \"\" +\n        \"a\".repeat(SEGMENT_SIZE) +\n        \"b\".repeat(SEGMENT_SIZE) +\n        \"c\".repeat(SEGMENT_SIZE),\n    )\n    val source = Buffer().writeUtf8(\n      \"\" +\n        \"a\".repeat(SEGMENT_SIZE) +\n        \"b\".repeat(SEGMENT_SIZE) +\n        \"c\".repeat(SEGMENT_SIZE),\n    )\n    val mockSink = MockSink()\n    assertEquals((SEGMENT_SIZE * 3).toLong(), source.readAll(mockSink))\n    assertEquals(0, source.size)\n    mockSink.assertLog(\"write(\" + write1 + \", \" + write1.size + \")\")\n  }\n\n  @Test\n  fun writeAllMultipleSegments() {\n    val source = Buffer().writeUtf8(\"a\".repeat(SEGMENT_SIZE * 3))\n    val sink = Buffer()\n    assertEquals((SEGMENT_SIZE * 3).toLong(), sink.writeAll(source))\n    assertEquals(0, source.size)\n    assertEquals(\"a\".repeat(SEGMENT_SIZE * 3), sink.readUtf8())\n  }\n\n  @Test\n  fun copyTo() {\n    val source = Buffer()\n    source.writeUtf8(\"party\")\n    val target = Buffer()\n    source.copyTo(target, 1, 3)\n    assertEquals(\"art\", target.readUtf8())\n    assertEquals(\"party\", source.readUtf8())\n  }\n\n  @Test\n  fun copyToOnSegmentBoundary() {\n    val `as` = \"a\".repeat(SEGMENT_SIZE)\n    val bs = \"b\".repeat(SEGMENT_SIZE)\n    val cs = \"c\".repeat(SEGMENT_SIZE)\n    val ds = \"d\".repeat(SEGMENT_SIZE)\n    val source = Buffer()\n    source.writeUtf8(`as`)\n    source.writeUtf8(bs)\n    source.writeUtf8(cs)\n    val target = Buffer()\n    target.writeUtf8(ds)\n    source.copyTo(target, `as`.length.toLong(), (bs.length + cs.length).toLong())\n    assertEquals(ds + bs + cs, target.readUtf8())\n  }\n\n  @Test\n  fun copyToOffSegmentBoundary() {\n    val `as` = \"a\".repeat(SEGMENT_SIZE - 1)\n    val bs = \"b\".repeat(SEGMENT_SIZE + 2)\n    val cs = \"c\".repeat(SEGMENT_SIZE - 4)\n    val ds = \"d\".repeat(SEGMENT_SIZE + 8)\n    val source = Buffer()\n    source.writeUtf8(`as`)\n    source.writeUtf8(bs)\n    source.writeUtf8(cs)\n    val target = Buffer()\n    target.writeUtf8(ds)\n    source.copyTo(target, `as`.length.toLong(), (bs.length + cs.length).toLong())\n    assertEquals(ds + bs + cs, target.readUtf8())\n  }\n\n  @Test\n  fun copyToSourceAndTargetCanBeTheSame() {\n    val `as` = \"a\".repeat(SEGMENT_SIZE)\n    val bs = \"b\".repeat(SEGMENT_SIZE)\n    val source = Buffer()\n    source.writeUtf8(`as`)\n    source.writeUtf8(bs)\n    source.copyTo(source, 0, source.size)\n    assertEquals(`as` + bs + `as` + bs, source.readUtf8())\n  }\n\n  @Test\n  fun copyToEmptySource() {\n    val source = Buffer()\n    val target = Buffer().writeUtf8(\"aaa\")\n    source.copyTo(target, 0L, 0L)\n    assertEquals(\"\", source.readUtf8())\n    assertEquals(\"aaa\", target.readUtf8())\n  }\n\n  @Test\n  fun copyToEmptyTarget() {\n    val source = Buffer().writeUtf8(\"aaa\")\n    val target = Buffer()\n    source.copyTo(target, 0L, 3L)\n    assertEquals(\"aaa\", source.readUtf8())\n    assertEquals(\"aaa\", target.readUtf8())\n  }\n\n  @Test\n  fun snapshotReportsAccurateSize() {\n    val buf = Buffer().write(byteArrayOf(0, 1, 2, 3))\n    assertEquals(1, buf.snapshot(1).size.toLong())\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferedSinkJavaTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport okio.TestUtil.SEGMENT_SIZE\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.Test\n\n/**\n * Tests solely for the behavior of RealBufferedSink's implementation. For generic\n * BufferedSink behavior use BufferedSinkTest.\n */\nclass BufferedSinkJavaTest {\n  @Test\n  fun inputStreamCloses() {\n    val sink = (Buffer() as Sink).buffer()\n    val out = sink.outputStream()\n    out.close()\n    try {\n      sink.writeUtf8(\"Hi!\")\n      fail()\n    } catch (e: IllegalStateException) {\n      assertEquals(\"closed\", e.message)\n    }\n  }\n\n  @Test\n  fun bufferedSinkEmitsTailWhenItIsComplete() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 1))\n    assertEquals(0, sink.size)\n    bufferedSink.writeByte(0)\n    assertEquals(SEGMENT_SIZE.toLong(), sink.size)\n    assertEquals(0, bufferedSink.buffer.size)\n  }\n\n  @Test\n  fun bufferedSinkEmitMultipleSegments() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 4 - 1))\n    assertEquals((SEGMENT_SIZE * 3).toLong(), sink.size)\n    assertEquals((SEGMENT_SIZE - 1).toLong(), bufferedSink.buffer.size)\n  }\n\n  @Test\n  fun bufferedSinkFlush() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeByte('a'.code)\n    assertEquals(0, sink.size)\n    bufferedSink.flush()\n    assertEquals(0, bufferedSink.buffer.size)\n    assertEquals(1, sink.size)\n  }\n\n  @Test\n  fun bytesEmittedToSinkWithFlush() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"abc\")\n    bufferedSink.flush()\n    assertEquals(3, sink.size)\n  }\n\n  @Test\n  fun bytesNotEmittedToSinkWithoutFlush() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"abc\")\n    assertEquals(0, sink.size)\n  }\n\n  @Test\n  fun bytesEmittedToSinkWithEmit() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"abc\")\n    bufferedSink.emit()\n    assertEquals(3, sink.size)\n  }\n\n  @Test\n  fun completeSegmentsEmitted() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 3))\n    assertEquals((SEGMENT_SIZE * 3).toLong(), sink.size)\n  }\n\n  @Test\n  fun incompleteSegmentsNotEmitted() {\n    val sink = Buffer()\n    val bufferedSink = (sink as Sink).buffer()\n    bufferedSink.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 3 - 1))\n    assertEquals((SEGMENT_SIZE * 2).toLong(), sink.size)\n  }\n\n  @Test\n  fun closeWithExceptionWhenWriting() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(0, IOException())\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    try {\n      bufferedSink.close()\n      fail()\n    } catch (expected: IOException) {\n    }\n    mockSink.assertLog(\"write([text=a], 1)\", \"close()\")\n  }\n\n  @Test\n  fun closeWithExceptionWhenClosing() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(1, IOException())\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    try {\n      bufferedSink.close()\n      fail()\n    } catch (expected: IOException) {\n    }\n    mockSink.assertLog(\"write([text=a], 1)\", \"close()\")\n  }\n\n  @Test\n  fun closeWithExceptionWhenWritingAndClosing() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(0, IOException(\"first\"))\n    mockSink.scheduleThrow(1, IOException(\"second\"))\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    try {\n      bufferedSink.close()\n      fail()\n    } catch (expected: IOException) {\n      assertEquals(\"first\", expected.message)\n    }\n    mockSink.assertLog(\"write([text=a], 1)\", \"close()\")\n  }\n\n  @Test\n  fun operationsAfterClose() {\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.writeByte('a'.code)\n    bufferedSink.close()\n\n    // Test a sample set of methods.\n    try {\n      bufferedSink.writeByte('a'.code)\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n    try {\n      bufferedSink.write(ByteArray(10))\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n    try {\n      bufferedSink.emitCompleteSegments()\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n    try {\n      bufferedSink.emit()\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n    try {\n      bufferedSink.flush()\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n\n    // Test a sample set of methods on the OutputStream.\n    val os = bufferedSink.outputStream()\n    try {\n      os.write('a'.code)\n      fail()\n    } catch (expected: IOException) {\n    }\n    try {\n      os.write(ByteArray(10))\n      fail()\n    } catch (expected: IOException) {\n    }\n\n    // Permitted\n    os.flush()\n  }\n\n  @Test\n  fun writeAll() {\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n    bufferedSink.buffer.writeUtf8(\"abc\")\n    assertEquals(3, bufferedSink.writeAll(Buffer().writeUtf8(\"def\")))\n    assertEquals(6, bufferedSink.buffer.size)\n    assertEquals(\"abcdef\", bufferedSink.buffer.readUtf8(6))\n    mockSink.assertLog() // No writes.\n  }\n\n  @Test\n  fun writeAllExhausted() {\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n    assertEquals(0, bufferedSink.writeAll(Buffer()))\n    assertEquals(0, bufferedSink.buffer.size)\n    mockSink.assertLog() // No writes.\n  }\n\n  @Test\n  fun writeAllWritesOneSegmentAtATime() {\n    val write1 = Buffer().writeUtf8(\"a\".repeat(SEGMENT_SIZE))\n    val write2 = Buffer().writeUtf8(\"b\".repeat(SEGMENT_SIZE))\n    val write3 = Buffer().writeUtf8(\"c\".repeat(SEGMENT_SIZE))\n    val source = Buffer().writeUtf8(\n      \"\" +\n        \"a\".repeat(SEGMENT_SIZE) +\n        \"b\".repeat(SEGMENT_SIZE) +\n        \"c\".repeat(SEGMENT_SIZE),\n    )\n    val mockSink = MockSink()\n    val bufferedSink = mockSink.buffer()\n    assertEquals((SEGMENT_SIZE * 3).toLong(), bufferedSink.writeAll(source))\n    mockSink.assertLog(\n      \"write(\" + write1 + \", \" + write1.size + \")\",\n      \"write(\" + write2 + \", \" + write2.size + \")\",\n      \"write(\" + write3 + \", \" + write3.size + \")\",\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferedSinkTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport java.io.EOFException\nimport java.math.BigInteger\nimport java.nio.ByteBuffer\nimport java.nio.charset.Charset\nimport kotlin.text.Charsets.UTF_8\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.TestUtil.SEGMENT_SIZE\nimport okio.TestUtil.segmentSizes\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.Test\n\n@Burst\nclass BufferedSinkTest(\n  factory: Factory,\n) {\n  enum class Factory {\n    NewBuffer {\n      override fun create(data: Buffer) = data\n    },\n    SinkBuffer {\n      override fun create(data: Buffer) = (data as Sink).buffer()\n    },\n    ;\n\n    abstract fun create(data: Buffer): BufferedSink\n  }\n\n  private val data: Buffer = Buffer()\n  private val sink: BufferedSink = factory.create(data)\n\n  @Test\n  fun writeNothing() {\n    sink.writeUtf8(\"\")\n    sink.flush()\n    assertEquals(0, data.size)\n  }\n\n  @Test\n  fun writeBytes() {\n    sink.writeByte(0xab)\n    sink.writeByte(0xcd)\n    sink.flush()\n    assertEquals(\"[hex=abcd]\", data.toString())\n  }\n\n  @Test\n  fun writeLastByteInSegment() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 1))\n    sink.writeByte(0x20)\n    sink.writeByte(0x21)\n    sink.flush()\n    assertEquals(listOf(SEGMENT_SIZE, 1), segmentSizes(data))\n    assertEquals(\"a\".repeat(SEGMENT_SIZE - 1), data.readUtf8((SEGMENT_SIZE - 1).toLong()))\n    assertEquals(\"[text= !]\", data.toString())\n  }\n\n  @Test\n  fun writeShort() {\n    sink.writeShort(0xabcd)\n    sink.writeShort(0x4321)\n    sink.flush()\n    assertEquals(\"[hex=abcd4321]\", data.toString())\n  }\n\n  @Test\n  fun writeShortLe() {\n    sink.writeShortLe(0xcdab)\n    sink.writeShortLe(0x2143)\n    sink.flush()\n    assertEquals(\"[hex=abcd4321]\", data.toString())\n  }\n\n  @Test\n  fun writeInt() {\n    sink.writeInt(-0x543210ff)\n    sink.writeInt(-0x789abcdf)\n    sink.flush()\n    assertEquals(\"[hex=abcdef0187654321]\", data.toString())\n  }\n\n  @Test\n  fun writeLastIntegerInSegment() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 4))\n    sink.writeInt(-0x543210ff)\n    sink.writeInt(-0x789abcdf)\n    sink.flush()\n    assertEquals(listOf(SEGMENT_SIZE, 4), segmentSizes(data))\n    assertEquals(\"a\".repeat(SEGMENT_SIZE - 4), data.readUtf8((SEGMENT_SIZE - 4).toLong()))\n    assertEquals(\"[hex=abcdef0187654321]\", data.toString())\n  }\n\n  @Test\n  fun writeIntegerDoesNotQuiteFitInSegment() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 3))\n    sink.writeInt(-0x543210ff)\n    sink.writeInt(-0x789abcdf)\n    sink.flush()\n    assertEquals(listOf(SEGMENT_SIZE - 3, 8), segmentSizes(data))\n    assertEquals(\"a\".repeat(SEGMENT_SIZE - 3), data.readUtf8((SEGMENT_SIZE - 3).toLong()))\n    assertEquals(\"[hex=abcdef0187654321]\", data.toString())\n  }\n\n  @Test\n  fun writeIntLe() {\n    sink.writeIntLe(-0x543210ff)\n    sink.writeIntLe(-0x789abcdf)\n    sink.flush()\n    assertEquals(\"[hex=01efcdab21436587]\", data.toString())\n  }\n\n  @Test\n  fun writeLong() {\n    sink.writeLong(-0x543210fe789abcdfL)\n    sink.writeLong(-0x350145414f4ea400L)\n    sink.flush()\n    assertEquals(\"[hex=abcdef0187654321cafebabeb0b15c00]\", data.toString())\n  }\n\n  @Test\n  fun writeLongLe() {\n    sink.writeLongLe(-0x543210fe789abcdfL)\n    sink.writeLongLe(-0x350145414f4ea400L)\n    sink.flush()\n    assertEquals(\"[hex=2143658701efcdab005cb1b0bebafeca]\", data.toString())\n  }\n\n  @Test\n  fun writeByteString() {\n    sink.write(\"təˈranəˌsôr\".encodeUtf8())\n    sink.flush()\n    assertEquals(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex(), data.readByteString())\n  }\n\n  @Test\n  fun writeByteStringOffset() {\n    sink.write(\"təˈranəˌsôr\".encodeUtf8(), 5, 5)\n    sink.flush()\n    assertEquals(\"72616ec999\".decodeHex(), data.readByteString())\n  }\n\n  @Test\n  fun writeSegmentedByteString() {\n    sink.write(Buffer().write(\"təˈranəˌsôr\".encodeUtf8()).snapshot())\n    sink.flush()\n    assertEquals(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex(), data.readByteString())\n  }\n\n  @Test\n  fun writeSegmentedByteStringOffset() {\n    sink.write(Buffer().write(\"təˈranəˌsôr\".encodeUtf8()).snapshot(), 5, 5)\n    sink.flush()\n    assertEquals(\"72616ec999\".decodeHex(), data.readByteString())\n  }\n\n  @Test\n  fun writeStringUtf8() {\n    sink.writeUtf8(\"təˈranəˌsôr\")\n    sink.flush()\n    assertEquals(\"74c999cb8872616ec999cb8c73c3b472\".decodeHex(), data.readByteString())\n  }\n\n  @Test\n  fun writeSubstringUtf8() {\n    sink.writeUtf8(\"təˈranəˌsôr\", 3, 7)\n    sink.flush()\n    assertEquals(\"72616ec999\".decodeHex(), data.readByteString())\n  }\n\n  @Test\n  fun writeStringWithCharset() {\n    sink.writeString(\"təˈranəˌsôr\", Charset.forName(\"utf-32be\"))\n    sink.flush()\n    assertEquals(\n      (\n        \"0000007400000259000002c800000072000000610000006e00000259\" +\n          \"000002cc00000073000000f400000072\"\n        ).decodeHex(),\n      data.readByteString(),\n    )\n  }\n\n  @Test\n  fun writeSubstringWithCharset() {\n    sink.writeString(\"təˈranəˌsôr\", 3, 7, Charset.forName(\"utf-32be\"))\n    sink.flush()\n    assertEquals(\"00000072000000610000006e00000259\".decodeHex(), data.readByteString())\n  }\n\n  @Test\n  fun writeUtf8SubstringWithCharset() {\n    sink.writeString(\"təˈranəˌsôr\", 3, 7, Charset.forName(\"utf-8\"))\n    sink.flush()\n    assertEquals(\"ranə\".encodeUtf8(), data.readByteString())\n  }\n\n  @Test\n  fun writeAll() {\n    val source = Buffer().writeUtf8(\"abcdef\")\n    assertEquals(6, sink.writeAll(source))\n    assertEquals(0, source.size)\n    sink.flush()\n    assertEquals(\"abcdef\", data.readUtf8())\n  }\n\n  @Test\n  fun writeSource() {\n    val source = Buffer().writeUtf8(\"abcdef\")\n\n    // Force resolution of the Source method overload.\n    sink.write((source as Source), 4)\n    sink.flush()\n    assertEquals(\"abcd\", data.readUtf8())\n    assertEquals(\"ef\", source.readUtf8())\n  }\n\n  @Test\n  fun writeSourceReadsFully() {\n    val source: Source = object : ForwardingSource(Buffer()) {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        sink.writeUtf8(\"abcd\")\n        return 4\n      }\n    }\n    sink.write(source, 8)\n    sink.flush()\n    assertEquals(\"abcdabcd\", data.readUtf8())\n  }\n\n  @Test\n  fun writeSourcePropagatesEof() {\n    val source: Source = Buffer().writeUtf8(\"abcd\")\n    try {\n      sink.write(source, 8)\n      fail()\n    } catch (expected: EOFException) {\n    }\n\n    // Ensure that whatever was available was correctly written.\n    sink.flush()\n    assertEquals(\"abcd\", data.readUtf8())\n  }\n\n  @Test\n  fun writeSourceWithZeroIsNoOp() {\n    // This test ensures that a zero byte count never calls through to read the source. It may be\n    // tied to something like a socket which will potentially block trying to read a segment when\n    // ultimately we don't want any data.\n    val source: Source = object : ForwardingSource(Buffer()) {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        throw AssertionError()\n      }\n    }\n    sink.write(source, 0)\n    assertEquals(0, data.size)\n  }\n\n  @Test\n  fun writeAllExhausted() {\n    val source = Buffer()\n    assertEquals(0, sink.writeAll(source))\n    assertEquals(0, source.size)\n  }\n\n  @Test\n  fun closeEmitsBufferedBytes() {\n    sink.writeByte('a'.code)\n    sink.close()\n    assertEquals('a'.code.toLong(), data.readByte().toLong())\n  }\n\n  @Test\n  fun outputStream() {\n    val out = sink.outputStream()\n    out.write('a'.code)\n    out.write(\"b\".repeat(9998).toByteArray(UTF_8))\n    out.write('c'.code)\n    out.flush()\n    assertEquals(\"a\" + \"b\".repeat(9998) + \"c\", data.readUtf8())\n  }\n\n  @Test\n  fun outputStreamBounds() {\n    val out = sink.outputStream()\n    try {\n      out.write(ByteArray(100), 50, 51)\n      fail()\n    } catch (expected: ArrayIndexOutOfBoundsException) {\n    }\n  }\n\n  @Test\n  fun longDecimalString() {\n    assertLongDecimalString(0)\n    assertLongDecimalString(Long.MIN_VALUE)\n    assertLongDecimalString(Long.MAX_VALUE)\n    for (i in 1..19) {\n      val value = BigInteger.valueOf(10L).pow(i).toLong()\n      assertLongDecimalString(value - 1)\n      assertLongDecimalString(value)\n    }\n  }\n\n  private fun assertLongDecimalString(value: Long) {\n    sink.writeDecimalLong(value).writeUtf8(\"zzz\").flush()\n    val expected = java.lang.Long.toString(value) + \"zzz\"\n    val actual = data.readUtf8()\n    assertEquals(\"$value expected $expected but was $actual\", actual, expected)\n  }\n\n  @Test\n  fun longHexString() {\n    assertLongHexString(0)\n    assertLongHexString(Long.MIN_VALUE)\n    assertLongHexString(Long.MAX_VALUE)\n    for (i in 0..62) {\n      assertLongHexString((1L shl i) - 1)\n      assertLongHexString(1L shl i)\n    }\n  }\n\n  @Test\n  fun writeNioBuffer() {\n    val expected = \"abcdefg\"\n    val nioByteBuffer = ByteBuffer.allocate(1024)\n    nioByteBuffer.put(\"abcdefg\".toByteArray(UTF_8))\n    (nioByteBuffer as java.nio.Buffer).flip() // Cast necessary for Java 8.\n    val byteCount = sink.write(nioByteBuffer)\n    assertEquals(expected.length.toLong(), byteCount.toLong())\n    assertEquals(expected.length.toLong(), nioByteBuffer.position().toLong())\n    assertEquals(expected.length.toLong(), nioByteBuffer.limit().toLong())\n    sink.flush()\n    assertEquals(expected, data.readUtf8())\n  }\n\n  @Test\n  fun writeLargeNioBufferWritesAllData() {\n    val expected = \"a\".repeat(SEGMENT_SIZE * 3)\n    val nioByteBuffer = ByteBuffer.allocate(SEGMENT_SIZE * 4)\n    nioByteBuffer.put(\"a\".repeat(SEGMENT_SIZE * 3).toByteArray(UTF_8))\n    (nioByteBuffer as java.nio.Buffer).flip() // Cast necessary for Java 8.\n    val byteCount = sink.write(nioByteBuffer)\n    assertEquals(expected.length.toLong(), byteCount.toLong())\n    assertEquals(expected.length.toLong(), nioByteBuffer.position().toLong())\n    assertEquals(expected.length.toLong(), nioByteBuffer.limit().toLong())\n    sink.flush()\n    assertEquals(expected, data.readUtf8())\n  }\n\n  private fun assertLongHexString(value: Long) {\n    sink.writeHexadecimalUnsignedLong(value).writeUtf8(\"zzz\").flush()\n    val expected = String.format(\"%x\", value) + \"zzz\"\n    val actual = data.readUtf8()\n    assertEquals(\"$value expected $expected but was $actual\", actual, expected)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferedSourceJavaTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.EOFException\nimport java.io.IOException\nimport kotlin.text.Charsets.UTF_8\nimport okio.TestUtil.SEGMENT_SIZE\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.Test\n\n/**\n * Tests solely for the behavior of RealBufferedSource's implementation. For generic\n * BufferedSource behavior use BufferedSourceTest.\n */\nclass BufferedSourceJavaTest {\n  @Test\n  fun inputStreamTracksSegments() {\n    val source = Buffer()\n    source.writeUtf8(\"a\")\n    source.writeUtf8(\"b\".repeat(SEGMENT_SIZE))\n    source.writeUtf8(\"c\")\n    val `in` = (source as Source).buffer().inputStream()\n    assertEquals(0, `in`.available().toLong())\n    assertEquals((SEGMENT_SIZE + 2).toLong(), source.size)\n\n    // Reading one byte buffers a full segment.\n    assertEquals('a'.code.toLong(), `in`.read().toLong())\n    assertEquals((SEGMENT_SIZE - 1).toLong(), `in`.available().toLong())\n    assertEquals(2, source.size)\n\n    // Reading as much as possible reads the rest of that buffered segment.\n    val data = ByteArray(SEGMENT_SIZE * 2)\n    assertEquals((SEGMENT_SIZE - 1).toLong(), `in`.read(data, 0, data.size).toLong())\n    assertEquals(\"b\".repeat(SEGMENT_SIZE - 1), String(data, 0, SEGMENT_SIZE - 1, UTF_8))\n    assertEquals(2, source.size)\n\n    // Continuing to read buffers the next segment.\n    assertEquals('b'.code.toLong(), `in`.read().toLong())\n    assertEquals(1, `in`.available().toLong())\n    assertEquals(0, source.size)\n\n    // Continuing to read reads from the buffer.\n    assertEquals('c'.code.toLong(), `in`.read().toLong())\n    assertEquals(0, `in`.available().toLong())\n    assertEquals(0, source.size)\n\n    // Once we've exhausted the source, we're done.\n    assertEquals(-1, `in`.read().toLong())\n    assertEquals(0, source.size)\n  }\n\n  @Test\n  fun inputStreamCloses() {\n    val source = (Buffer() as Source).buffer()\n    val inputStream = source.inputStream()\n    inputStream.close()\n    try {\n      source.require(1)\n      fail()\n    } catch (e: IllegalStateException) {\n      assertEquals(\"closed\", e.message)\n    }\n  }\n\n  @Test\n  fun indexOfStopsReadingAtLimit() {\n    val buffer = Buffer().writeUtf8(\"abcdef\")\n    val bufferedSource = object : ForwardingSource(buffer) {\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        return super.read(sink, Math.min(1, byteCount))\n      }\n    }.buffer()\n    assertEquals(6, buffer.size)\n    assertEquals(-1, bufferedSource.indexOf('e'.code.toByte(), 0, 4))\n    assertEquals(2, buffer.size)\n  }\n\n  @Test\n  fun requireTracksBufferFirst() {\n    val source = Buffer()\n    source.writeUtf8(\"bb\")\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.buffer.writeUtf8(\"aa\")\n    bufferedSource.require(2)\n    assertEquals(2, bufferedSource.buffer.size)\n    assertEquals(2, source.size)\n  }\n\n  @Test\n  fun requireIncludesBufferBytes() {\n    val source = Buffer()\n    source.writeUtf8(\"b\")\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.buffer.writeUtf8(\"a\")\n    bufferedSource.require(2)\n    assertEquals(\"ab\", bufferedSource.buffer.readUtf8(2))\n  }\n\n  @Test\n  fun requireInsufficientData() {\n    val source = Buffer()\n    source.writeUtf8(\"a\")\n    val bufferedSource = (source as Source).buffer()\n    try {\n      bufferedSource.require(2)\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun requireReadsOneSegmentAtATime() {\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(SEGMENT_SIZE))\n    source.writeUtf8(\"b\".repeat(SEGMENT_SIZE))\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.require(2)\n    assertEquals(SEGMENT_SIZE.toLong(), source.size)\n    assertEquals(SEGMENT_SIZE.toLong(), bufferedSource.buffer.size)\n  }\n\n  @Test\n  fun skipReadsOneSegmentAtATime() {\n    val source = Buffer()\n    source.writeUtf8(\"a\".repeat(SEGMENT_SIZE))\n    source.writeUtf8(\"b\".repeat(SEGMENT_SIZE))\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.skip(2)\n    assertEquals(SEGMENT_SIZE.toLong(), source.size)\n    assertEquals((SEGMENT_SIZE - 2).toLong(), bufferedSource.buffer.size)\n  }\n\n  @Test\n  fun skipTracksBufferFirst() {\n    val source = Buffer()\n    source.writeUtf8(\"bb\")\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.buffer.writeUtf8(\"aa\")\n    bufferedSource.skip(2)\n    assertEquals(0, bufferedSource.buffer.size)\n    assertEquals(2, source.size)\n  }\n\n  @Test\n  fun operationsAfterClose() {\n    val source = Buffer()\n    val bufferedSource = (source as Source).buffer()\n    bufferedSource.close()\n\n    // Test a sample set of methods.\n    try {\n      bufferedSource.indexOf(1.toByte())\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n    try {\n      bufferedSource.skip(1)\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n    try {\n      bufferedSource.readByte()\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n    try {\n      bufferedSource.readByteString(10)\n      fail()\n    } catch (expected: IllegalStateException) {\n    }\n\n    // Test a sample set of methods on the InputStream.\n    val inputStream = bufferedSource.inputStream()\n    try {\n      inputStream.read()\n      fail()\n    } catch (expected: IOException) {\n    }\n    try {\n      inputStream.read(ByteArray(10))\n      fail()\n    } catch (expected: IOException) {\n    }\n  }\n\n  /**\n   * We don't want readAll to buffer an unbounded amount of data. Instead it\n   * should buffer a segment, write it, and repeat.\n   */\n  @Test\n  fun readAllReadsOneSegmentAtATime() {\n    val write1 = Buffer().writeUtf8(\"a\".repeat(SEGMENT_SIZE))\n    val write2 = Buffer().writeUtf8(\"b\".repeat(SEGMENT_SIZE))\n    val write3 = Buffer().writeUtf8(\"c\".repeat(SEGMENT_SIZE))\n    val source = Buffer().writeUtf8(\n      \"\" +\n        \"a\".repeat(SEGMENT_SIZE) +\n        \"b\".repeat(SEGMENT_SIZE) +\n        \"c\".repeat(SEGMENT_SIZE),\n    )\n    val mockSink = MockSink()\n    val bufferedSource = (source as Source).buffer()\n    assertEquals((SEGMENT_SIZE * 3).toLong(), bufferedSource.readAll(mockSink))\n    mockSink.assertLog(\n      \"write(\" + write1 + \", \" + write1.size + \")\",\n      \"write(\" + write2 + \", \" + write2.size + \")\",\n      \"write(\" + write3 + \", \" + write3.size + \")\",\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/BufferedSourceTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isTrue\nimport java.io.ByteArrayInputStream\nimport java.io.ByteArrayOutputStream\nimport java.io.EOFException\nimport java.nio.ByteBuffer\nimport java.nio.charset.Charset\nimport java.util.Arrays\nimport kotlin.text.Charsets.US_ASCII\nimport kotlin.text.Charsets.UTF_8\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.Options.Companion.of\nimport okio.TestUtil.SEGMENT_SIZE\nimport okio.TestUtil.assertByteArrayEquals\nimport okio.TestUtil.assertByteArraysEquals\nimport okio.TestUtil.randomBytes\nimport okio.TestUtil.segmentSizes\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Assume.assumeTrue\nimport org.junit.Test\n\n@Burst\nclass BufferedSourceTest(\n  private val factory: Factory,\n) {\n  enum class Factory {\n    NewBuffer {\n      override fun pipe(): Pipe {\n        val buffer = Buffer()\n        return Pipe(buffer, buffer)\n      }\n\n      override val isOneByteAtATime: Boolean get() = false\n    },\n\n    SourceBuffer {\n      override fun pipe(): Pipe {\n        val buffer = Buffer()\n        return Pipe(\n          sink = buffer,\n          source = (buffer as Source).buffer(),\n        )\n      }\n\n      override val isOneByteAtATime: Boolean get() = false\n    },\n\n    /**\n     * A factory deliberately written to create buffers whose internal segments are always 1 byte\n     * long. We like testing with these segments because are likely to trigger bugs!\n     */\n    OneByteAtATimeSource {\n      override fun pipe(): Pipe {\n        val buffer = Buffer()\n        return Pipe(\n          sink = buffer,\n          source = object : ForwardingSource(buffer) {\n            override fun read(sink: Buffer, byteCount: Long): Long {\n              // Read one byte into a new buffer, then clone it so that the segment is shared.\n              // Shared segments cannot be compacted so we'll get a long chain of short segments.\n              val box = Buffer()\n              val result = super.read(box, Math.min(byteCount, 1L))\n              if (result > 0L) sink.write(box.clone(), result)\n              return result\n            }\n          }.buffer(),\n        )\n      }\n\n      override val isOneByteAtATime: Boolean get() = true\n    },\n\n    OneByteAtATimeSink {\n      override fun pipe(): Pipe {\n        val buffer = Buffer()\n        val sink = object : ForwardingSink(buffer) {\n          override fun write(source: Buffer, byteCount: Long) {\n            // Write each byte into a new buffer, then clone it so that the segments are shared.\n            // Shared segments cannot be compacted so we'll get a long chain of short segments.\n            for (i in 0 until byteCount) {\n              val box = Buffer()\n              box.write(source, 1)\n              super.write(box.clone(), 1)\n            }\n          }\n        }.buffer()\n        return Pipe(\n          sink = sink,\n          source = buffer,\n        )\n      }\n\n      override val isOneByteAtATime: Boolean get() = true\n    },\n\n    PeekSource {\n      override fun pipe(): Pipe {\n        val buffer = Buffer()\n        return Pipe(\n          sink = buffer,\n          source = buffer.peek(),\n        )\n      }\n\n      override val isOneByteAtATime: Boolean get() = false\n    },\n\n    PeekBufferedSource {\n      override fun pipe(): Pipe {\n        val buffer = Buffer()\n        return Pipe(\n          sink = buffer,\n          source = (buffer as Source).buffer().peek(),\n        )\n      }\n\n      override val isOneByteAtATime: Boolean get() = false\n    },\n    ;\n\n    abstract fun pipe(): Pipe\n    abstract val isOneByteAtATime: Boolean\n  }\n\n  class Pipe(\n    var sink: BufferedSink,\n    var source: BufferedSource,\n  )\n\n  private val pipe = factory.pipe()\n  private val sink: BufferedSink = pipe.sink\n  private val source: BufferedSource = pipe.source\n\n  @Test\n  fun readBytes() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte()))\n    sink.emit()\n    assertEquals(0xab, (source.readByte().toInt() and 0xff).toLong())\n    assertEquals(0xcd, (source.readByte().toInt() and 0xff).toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readByteTooShortThrows() {\n    try {\n      source.readByte()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readShort() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x01.toByte()))\n    sink.emit()\n    assertEquals(0xabcd.toShort().toLong(), source.readShort().toLong())\n    assertEquals(0xef01.toShort().toLong(), source.readShort().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readShortLe() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x10.toByte()))\n    sink.emit()\n    assertEquals(0xcdab.toShort().toLong(), source.readShortLe().toLong())\n    assertEquals(0x10ef.toShort().toLong(), source.readShortLe().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readShortSplitAcrossMultipleSegments() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 1))\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte()))\n    sink.emit()\n    source.skip((SEGMENT_SIZE - 1).toLong())\n    assertEquals(0xabcd.toShort().toLong(), source.readShort().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readShortTooShortThrows() {\n    sink.writeShort(Short.MAX_VALUE.toInt())\n    sink.emit()\n    source.readByte()\n    try {\n      source.readShort()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readShortLeTooShortThrows() {\n    sink.writeShortLe(Short.MAX_VALUE.toInt())\n    sink.emit()\n    source.readByte()\n    try {\n      source.readShortLe()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readInt() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x01.toByte(), 0x87.toByte(), 0x65.toByte(), 0x43.toByte(), 0x21.toByte()))\n    sink.emit()\n    assertEquals(-0x543210ff, source.readInt().toLong())\n    assertEquals(-0x789abcdf, source.readInt().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readIntLe() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x10.toByte(), 0x87.toByte(), 0x65.toByte(), 0x43.toByte(), 0x21.toByte()))\n    sink.emit()\n    assertEquals(0x10efcdab, source.readIntLe().toLong())\n    assertEquals(0x21436587, source.readIntLe().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readIntSplitAcrossMultipleSegments() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 3))\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x01.toByte()))\n    sink.emit()\n    source.skip((SEGMENT_SIZE - 3).toLong())\n    assertEquals(-0x543210ff, source.readInt().toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readIntTooShortThrows() {\n    sink.writeInt(Int.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    try {\n      source.readInt()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readIntLeTooShortThrows() {\n    sink.writeIntLe(Int.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    try {\n      source.readIntLe()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readLong() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x10.toByte(), 0x87.toByte(), 0x65.toByte(), 0x43.toByte(), 0x21.toByte(), 0x36.toByte(), 0x47.toByte(), 0x58.toByte(), 0x69.toByte(), 0x12.toByte(), 0x23.toByte(), 0x34.toByte(), 0x45.toByte()))\n    sink.emit()\n    assertEquals(-0x543210ef789abcdfL, source.readLong())\n    assertEquals(0x3647586912233445L, source.readLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readLongLe() {\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x10.toByte(), 0x87.toByte(), 0x65.toByte(), 0x43.toByte(), 0x21.toByte(), 0x36.toByte(), 0x47.toByte(), 0x58.toByte(), 0x69.toByte(), 0x12.toByte(), 0x23.toByte(), 0x34.toByte(), 0x45.toByte()))\n    sink.emit()\n    assertEquals(0x2143658710efcdabL, source.readLongLe())\n    assertEquals(0x4534231269584736L, source.readLongLe())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readLongSplitAcrossMultipleSegments() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 7))\n    sink.write(byteArrayOf(0xab.toByte(), 0xcd.toByte(), 0xef.toByte(), 0x01.toByte(), 0x87.toByte(), 0x65.toByte(), 0x43.toByte(), 0x21.toByte()))\n    sink.emit()\n    source.skip((SEGMENT_SIZE - 7).toLong())\n    assertEquals(-0x543210fe789abcdfL, source.readLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readLongTooShortThrows() {\n    sink.writeLong(Long.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    try {\n      source.readLong()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readLongLeTooShortThrows() {\n    sink.writeLongLe(Long.MAX_VALUE)\n    sink.emit()\n    source.readByte()\n    try {\n      source.readLongLe()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readAll() {\n    source.buffer.writeUtf8(\"abc\")\n    sink.writeUtf8(\"def\")\n    sink.emit()\n    val sink = Buffer()\n    assertEquals(6, source.readAll(sink))\n    assertEquals(\"abcdef\", sink.readUtf8())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readAllExhausted() {\n    val mockSink = MockSink()\n    assertEquals(0, source.readAll(mockSink))\n    assertTrue(source.exhausted())\n    mockSink.assertLog()\n  }\n\n  @Test\n  fun readExhaustedSource() {\n    val sink = Buffer()\n    sink.writeUtf8(\"a\".repeat(10))\n    assertEquals(-1, source.read(sink, 10))\n    assertEquals(10, sink.size)\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readZeroBytesFromSource() {\n    val sink = Buffer()\n    sink.writeUtf8(\"a\".repeat(10))\n\n    // Either 0 or -1 is reasonable here.\n    val readResult = source.read(sink, 0)\n    assertTrue(readResult == 0L || readResult == -1L)\n    assertEquals(10, sink.size)\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun readFully() {\n    sink.writeUtf8(\"a\".repeat(10000))\n    sink.emit()\n    val sink = Buffer()\n    source.readFully(sink, 9999)\n    assertEquals(\"a\".repeat(9999), sink.readUtf8())\n    assertEquals(\"a\", source.readUtf8())\n  }\n\n  @Test\n  fun readFullyTooShortThrows() {\n    sink.writeUtf8(\"Hi\")\n    sink.emit()\n    val sink = Buffer()\n    try {\n      source.readFully(sink, 5)\n      fail()\n    } catch (ignored: EOFException) {\n    }\n\n    // Verify we read all that we could from the source.\n    assertEquals(\"Hi\", sink.readUtf8())\n  }\n\n  @Test\n  fun readFullyByteArray() {\n    val data = Buffer()\n    data.writeUtf8(\"Hello\").writeUtf8(\"e\".repeat(SEGMENT_SIZE))\n    val expected = data.clone().readByteArray()\n    sink.write(data, data.size)\n    sink.emit()\n    val sink = ByteArray(SEGMENT_SIZE + 5)\n    source.readFully(sink)\n    assertByteArraysEquals(expected, sink)\n  }\n\n  @Test\n  fun readFullyByteArrayTooShortThrows() {\n    sink.writeUtf8(\"Hello\")\n    sink.emit()\n    val array = ByteArray(6)\n    try {\n      source.readFully(array)\n      fail()\n    } catch (ignored: EOFException) {\n    }\n\n    // Verify we read all that we could from the source.\n    assertByteArraysEquals(byteArrayOf('H'.code.toByte(), 'e'.code.toByte(), 'l'.code.toByte(), 'l'.code.toByte(), 'o'.code.toByte(), 0), array)\n  }\n\n  @Test\n  fun readIntoByteArray() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n    val sink = ByteArray(3)\n    val read = source.read(sink)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      val expected = byteArrayOf('a'.code.toByte(), 0, 0)\n      assertByteArraysEquals(expected, sink)\n    } else {\n      assertEquals(3, read.toLong())\n      val expected = byteArrayOf('a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte())\n      assertByteArraysEquals(expected, sink)\n    }\n  }\n\n  @Test\n  fun readIntoByteArrayNotEnough() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n    val sink = ByteArray(5)\n    val read = source.read(sink)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      val expected = byteArrayOf('a'.code.toByte(), 0, 0, 0, 0)\n      assertByteArraysEquals(expected, sink)\n    } else {\n      assertEquals(4, read.toLong())\n      val expected = byteArrayOf('a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte(), 'd'.code.toByte(), 0)\n      assertByteArraysEquals(expected, sink)\n    }\n  }\n\n  @Test\n  fun readIntoByteArrayOffsetAndCount() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n    val sink = ByteArray(7)\n    val read = source.read(sink, 2, 3)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      val expected = byteArrayOf(0, 0, 'a'.code.toByte(), 0, 0, 0, 0)\n      assertByteArraysEquals(expected, sink)\n    } else {\n      assertEquals(3, read.toLong())\n      val expected = byteArrayOf(0, 0, 'a'.code.toByte(), 'b'.code.toByte(), 'c'.code.toByte(), 0, 0)\n      assertByteArraysEquals(expected, sink)\n    }\n  }\n\n  @Test\n  fun readByteArray() {\n    val string = \"abcd\" + \"e\".repeat(SEGMENT_SIZE)\n    sink.writeUtf8(string)\n    sink.emit()\n    assertByteArraysEquals(string.toByteArray(UTF_8), source.readByteArray())\n  }\n\n  @Test\n  fun readByteArrayPartial() {\n    sink.writeUtf8(\"abcd\")\n    sink.emit()\n    assertEquals(\"[97, 98, 99]\", Arrays.toString(source.readByteArray(3)))\n    assertEquals(\"d\", source.readUtf8(1))\n  }\n\n  @Test\n  fun readByteArrayTooShortThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    try {\n      source.readByteArray(4)\n      fail()\n    } catch (expected: EOFException) {\n    }\n    assertEquals(\"abc\", source.readUtf8()) // The read shouldn't consume any data.\n  }\n\n  @Test\n  fun readByteString() {\n    sink.writeUtf8(\"abcd\").writeUtf8(\"e\".repeat(SEGMENT_SIZE))\n    sink.emit()\n    assertEquals(\"abcd\" + \"e\".repeat(SEGMENT_SIZE), source.readByteString().utf8())\n  }\n\n  @Test\n  fun readByteStringPartial() {\n    sink.writeUtf8(\"abcd\").writeUtf8(\"e\".repeat(SEGMENT_SIZE))\n    sink.emit()\n    assertEquals(\"abc\", source.readByteString(3).utf8())\n    assertEquals(\"d\", source.readUtf8(1))\n  }\n\n  @Test\n  fun readByteStringTooShortThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    try {\n      source.readByteString(4)\n      fail()\n    } catch (expected: EOFException) {\n    }\n    assertEquals(\"abc\", source.readUtf8()) // The read shouldn't consume any data.\n  }\n\n  @Test\n  fun readSpecificCharsetPartial() {\n    sink.write(\n      (\n        \"0000007600000259000002c80000006c000000e40000007300000259\" +\n          \"000002cc000000720000006100000070000000740000025900000072\"\n        ).decodeHex(),\n    )\n    sink.emit()\n    assertEquals(\"vəˈläsə\", source.readString((7 * 4).toLong(), Charset.forName(\"utf-32\")))\n  }\n\n  @Test\n  fun readSpecificCharset() {\n    sink.write(\n      (\n        \"0000007600000259000002c80000006c000000e40000007300000259\" +\n          \"000002cc000000720000006100000070000000740000025900000072\"\n        ).decodeHex(),\n    )\n    sink.emit()\n    assertEquals(\"vəˈläsəˌraptər\", source.readString(Charset.forName(\"utf-32\")))\n  }\n\n  @Test\n  fun readStringTooShortThrows() {\n    sink.writeString(\"abc\", US_ASCII)\n    sink.emit()\n    try {\n      source.readString(4, US_ASCII)\n      fail()\n    } catch (expected: EOFException) {\n    }\n    assertEquals(\"abc\", source.readUtf8()) // The read shouldn't consume any data.\n  }\n\n  @Test\n  fun readUtf8SpansSegments() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    sink.emit()\n    source.skip((SEGMENT_SIZE - 1).toLong())\n    assertEquals(\"aa\", source.readUtf8(2))\n  }\n\n  @Test\n  fun readUtf8Segment() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE))\n    sink.emit()\n    assertEquals(\"a\".repeat(SEGMENT_SIZE), source.readUtf8(SEGMENT_SIZE.toLong()))\n  }\n\n  @Test\n  fun readUtf8PartialBuffer() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE + 20))\n    sink.emit()\n    assertEquals(\"a\".repeat(SEGMENT_SIZE + 10), source.readUtf8((SEGMENT_SIZE + 10).toLong()))\n  }\n\n  @Test\n  fun readUtf8EntireBuffer() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2))\n    sink.emit()\n    assertEquals(\"a\".repeat(SEGMENT_SIZE * 2), source.readUtf8())\n  }\n\n  @Test\n  fun readUtf8TooShortThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    try {\n      source.readUtf8(4L)\n      fail()\n    } catch (expected: EOFException) {\n    }\n    assertEquals(\"abc\", source.readUtf8()) // The read shouldn't consume any data.\n  }\n\n  @Test\n  fun skip() {\n    sink.writeUtf8(\"a\")\n    sink.writeUtf8(\"b\".repeat(SEGMENT_SIZE))\n    sink.writeUtf8(\"c\")\n    sink.emit()\n    source.skip(1)\n    assertEquals('b'.code.toLong(), (source.readByte().toInt() and 0xff).toLong())\n    source.skip((SEGMENT_SIZE - 2).toLong())\n    assertEquals('b'.code.toLong(), (source.readByte().toInt() and 0xff).toLong())\n    source.skip(1)\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun skipInsufficientData() {\n    sink.writeUtf8(\"a\")\n    sink.emit()\n    try {\n      source.skip(2)\n      fail()\n    } catch (ignored: EOFException) {\n    }\n  }\n\n  @Test\n  fun indexOf() {\n    // The segment is empty.\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n\n    // The segment has one value.\n    sink.writeUtf8(\"a\") // a\n    sink.emit()\n    assertEquals(0, source.indexOf('a'.code.toByte()))\n    assertEquals(-1, source.indexOf('b'.code.toByte()))\n\n    // The segment has lots of data.\n    sink.writeUtf8(\"b\".repeat(SEGMENT_SIZE - 2)) // ab...b\n    sink.emit()\n    assertEquals(0, source.indexOf('a'.code.toByte()))\n    assertEquals(1, source.indexOf('b'.code.toByte()))\n    assertEquals(-1, source.indexOf('c'.code.toByte()))\n\n    // The segment doesn't start at 0, it starts at 2.\n    source.skip(2) // b...b\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('b'.code.toByte()))\n    assertEquals(-1, source.indexOf('c'.code.toByte()))\n\n    // The segment is full.\n    sink.writeUtf8(\"c\") // b...bc\n    sink.emit()\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('b'.code.toByte()))\n    assertEquals((SEGMENT_SIZE - 3).toLong(), source.indexOf('c'.code.toByte()))\n\n    // The segment doesn't start at 2, it starts at 4.\n    source.skip(2) // b...bc\n    assertEquals(-1, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('b'.code.toByte()))\n    assertEquals((SEGMENT_SIZE - 5).toLong(), source.indexOf('c'.code.toByte()))\n\n    // Two segments.\n    sink.writeUtf8(\"d\") // b...bcd, d is in the 2nd segment.\n    sink.emit()\n    assertEquals((SEGMENT_SIZE - 4).toLong(), source.indexOf('d'.code.toByte()))\n    assertEquals(-1, source.indexOf('e'.code.toByte()))\n  }\n\n  @Test\n  fun indexOfByteWithStartOffset() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(SEGMENT_SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertEquals(-1, source.indexOf('a'.code.toByte(), 1))\n    assertEquals(15, source.indexOf('b'.code.toByte(), 15))\n  }\n\n  @Test\n  fun indexOfByteWithBothOffsets() {\n    if (factory.isOneByteAtATime) {\n      // When run on Travis this causes out-of-memory errors.\n      return\n    }\n    val a = 'a'.code.toByte()\n    val c = 'c'.code.toByte()\n    val size: Int = SEGMENT_SIZE * 5\n    val bytes = ByteArray(size)\n    Arrays.fill(bytes, a)\n\n    // These are tricky places where the buffer\n    // starts, ends, or segments come together.\n    val points = intArrayOf(\n      0, 1, 2,\n      SEGMENT_SIZE - 1, SEGMENT_SIZE, SEGMENT_SIZE + 1,\n      size / 2 - 1, size / 2, size / 2 + 1,\n      size - SEGMENT_SIZE - 1, size - SEGMENT_SIZE, size - SEGMENT_SIZE + 1,\n      size - 3, size - 2, size - 1,\n    )\n\n    // In each iteration, we write c to the known point and then search for it using different\n    // windows. Some of the windows don't overlap with c's position, and therefore a match shouldn't\n    // be found.\n    for (p in points) {\n      bytes[p] = c\n      sink.write(bytes)\n      sink.emit()\n      assertEquals(p.toLong(), source.indexOf(c, 0, size.toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, 0, (p + 1).toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, p.toLong(), size.toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, p.toLong(), (p + 1).toLong()))\n      assertEquals(p.toLong(), source.indexOf(c, (p / 2).toLong(), (p * 2 + 1).toLong()))\n      assertEquals(-1, source.indexOf(c, 0, (p / 2).toLong()))\n      assertEquals(-1, source.indexOf(c, 0, p.toLong()))\n      assertEquals(-1, source.indexOf(c, 0, 0))\n      assertEquals(-1, source.indexOf(c, p.toLong(), p.toLong()))\n\n      // Reset.\n      source.readUtf8()\n      bytes[p] = a\n    }\n  }\n\n  @Test\n  fun indexOfByteInvalidBoundsThrows() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    try {\n      source.indexOf('a'.code.toByte(), -1)\n      fail(\"Expected failure: fromIndex < 0\")\n    } catch (expected: IllegalArgumentException) {\n    }\n    try {\n      source.indexOf('a'.code.toByte(), 10, 0)\n      fail(\"Expected failure: fromIndex > toIndex\")\n    } catch (expected: IllegalArgumentException) {\n    }\n  }\n\n  @Test\n  fun indexOfByteString() {\n    assertEquals(-1, source.indexOf(\"flop\".encodeUtf8()))\n    sink.writeUtf8(\"flip flop\")\n    sink.emit()\n    assertEquals(5, source.indexOf(\"flop\".encodeUtf8()))\n    source.readUtf8() // Clear stream.\n\n    // Make sure we backtrack and resume searching after partial match.\n    sink.writeUtf8(\"hi hi hi hey\")\n    sink.emit()\n    assertEquals(3, source.indexOf(\"hi hi hey\".encodeUtf8()))\n  }\n\n  @Test\n  fun indexOfByteStringAtSegmentBoundary() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 1))\n    sink.writeUtf8(\"bcd\")\n    sink.emit()\n    assertEquals((SEGMENT_SIZE - 3).toLong(), source.indexOf(\"aabc\".encodeUtf8(), (SEGMENT_SIZE - 4).toLong()))\n    assertEquals((SEGMENT_SIZE - 3).toLong(), source.indexOf(\"aabc\".encodeUtf8(), (SEGMENT_SIZE - 3).toLong()))\n    assertEquals((SEGMENT_SIZE - 2).toLong(), source.indexOf(\"abcd\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals((SEGMENT_SIZE - 2).toLong(), source.indexOf(\"abc\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals((SEGMENT_SIZE - 2).toLong(), source.indexOf(\"abc\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals((SEGMENT_SIZE - 2).toLong(), source.indexOf(\"ab\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals((SEGMENT_SIZE - 2).toLong(), source.indexOf(\"a\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals((SEGMENT_SIZE - 1).toLong(), source.indexOf(\"bc\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals((SEGMENT_SIZE - 1).toLong(), source.indexOf(\"b\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals(SEGMENT_SIZE.toLong(), source.indexOf(\"c\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals(SEGMENT_SIZE.toLong(), source.indexOf(\"c\".encodeUtf8(), SEGMENT_SIZE.toLong()))\n    assertEquals((SEGMENT_SIZE + 1).toLong(), source.indexOf(\"d\".encodeUtf8(), (SEGMENT_SIZE - 2).toLong()))\n    assertEquals((SEGMENT_SIZE + 1).toLong(), source.indexOf(\"d\".encodeUtf8(), (SEGMENT_SIZE + 1).toLong()))\n  }\n\n  @Test\n  fun indexOfDoesNotWrapAround() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 1))\n    sink.writeUtf8(\"bcd\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"abcda\".encodeUtf8(), (SEGMENT_SIZE - 3).toLong()))\n  }\n\n  @Test\n  fun indexOfByteStringWithOffset() {\n    assertEquals(-1, source.indexOf(\"flop\".encodeUtf8(), 1))\n    sink.writeUtf8(\"flop flip flop\")\n    sink.emit()\n    assertEquals(10, source.indexOf(\"flop\".encodeUtf8(), 1))\n    source.readUtf8() // Clear stream\n\n    // Make sure we backtrack and resume searching after partial match.\n    sink.writeUtf8(\"hi hi hi hi hey\")\n    sink.emit()\n    assertEquals(6, source.indexOf(\"hi hi hey\".encodeUtf8(), 1))\n  }\n\n  @Test\n  fun indexOfByteStringInvalidArgumentsThrows() {\n    try {\n      source.indexOf(ByteString.of())\n      fail()\n    } catch (e: IllegalArgumentException) {\n      assertEquals(\"byteCount == 0\", e.message)\n    }\n    try {\n      source.indexOf(\"hi\".encodeUtf8(), -1)\n      fail()\n    } catch (e: IllegalArgumentException) {\n      assertEquals(\"fromIndex < 0: -1\", e.message)\n    }\n  }\n\n  /**\n   * With [Factory.OneByteAtATimeSource], this code was extremely slow.\n   * https://github.com/square/okio/issues/171\n   */\n  @Test\n  fun indexOfByteStringAcrossSegmentBoundaries() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 2 - 3))\n    sink.writeUtf8(\"bcdefg\")\n    sink.emit()\n    assertEquals((SEGMENT_SIZE * 2 - 4).toLong(), source.indexOf(\"ab\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 4).toLong(), source.indexOf(\"abc\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 4).toLong(), source.indexOf(\"abcd\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 4).toLong(), source.indexOf(\"abcde\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 4).toLong(), source.indexOf(\"abcdef\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 4).toLong(), source.indexOf(\"abcdefg\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 3).toLong(), source.indexOf(\"bcdefg\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 2).toLong(), source.indexOf(\"cdefg\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 - 1).toLong(), source.indexOf(\"defg\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2).toLong(), source.indexOf(\"efg\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 + 1).toLong(), source.indexOf(\"fg\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE * 2 + 2).toLong(), source.indexOf(\"g\".encodeUtf8()))\n  }\n\n  @Test\n  fun indexOfElement() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(SEGMENT_SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertEquals(0, source.indexOfElement(\"DEFGaHIJK\".encodeUtf8()))\n    assertEquals(1, source.indexOfElement(\"DEFGHIJKb\".encodeUtf8()))\n    assertEquals((SEGMENT_SIZE + 1).toLong(), source.indexOfElement(\"cDEFGHIJK\".encodeUtf8()))\n    assertEquals(1, source.indexOfElement(\"DEFbGHIc\".encodeUtf8()))\n    assertEquals(-1L, source.indexOfElement(\"DEFGHIJK\".encodeUtf8()))\n    assertEquals(-1L, source.indexOfElement(\"\".encodeUtf8()))\n  }\n\n  @Test\n  fun indexOfElementWithOffset() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(SEGMENT_SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertEquals(-1, source.indexOfElement(\"DEFGaHIJK\".encodeUtf8(), 1))\n    assertEquals(15, source.indexOfElement(\"DEFGHIJKb\".encodeUtf8(), 15))\n  }\n\n  @Test\n  fun indexOfByteWithFromIndex() {\n    sink.writeUtf8(\"aaa\")\n    sink.emit()\n    assertEquals(0, source.indexOf('a'.code.toByte()))\n    assertEquals(0, source.indexOf('a'.code.toByte(), 0))\n    assertEquals(1, source.indexOf('a'.code.toByte(), 1))\n    assertEquals(2, source.indexOf('a'.code.toByte(), 2))\n  }\n\n  @Test\n  fun indexOfByteStringWithFromIndex() {\n    sink.writeUtf8(\"aaa\")\n    sink.emit()\n    assertEquals(0, source.indexOf(\"a\".encodeUtf8()))\n    assertEquals(0, source.indexOf(\"a\".encodeUtf8(), 0))\n    assertEquals(1, source.indexOf(\"a\".encodeUtf8(), 1))\n    assertEquals(2, source.indexOf(\"a\".encodeUtf8(), 2))\n  }\n\n  @Test\n  fun indexOfByteStringWithFromIndexAndToIndex() {\n    sink.writeUtf8(\"Don't move! He can't see us if we don't move.\")\n    sink.emit()\n    val move = \"move\".encodeUtf8()\n\n    assertEquals(-1L, source.indexOf(move, 0L, 6L))\n    assertEquals(6L, source.indexOf(move, 0L, 7L))\n    assertEquals(6L, source.indexOf(move, 6L, 7L))\n    assertEquals(-1L, source.indexOf(move, 7L, 40L))\n    assertEquals(40L, source.indexOf(move, 7L, 41L))\n    assertEquals(40L, source.indexOf(move, 40L, 41L))\n    assertEquals(-1L, source.indexOf(move, 41L, 42L))\n  }\n\n  /** In this example we must load 6 bytes to determine the string is not found. */\n  @Test\n  fun indexOfByteStringDocumentationLoadingCase() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"shellxyz\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"hello\".encodeUtf8(), 0, 4))\n    assertEquals(\"shellx\", source.buffer.readUtf8())\n  }\n\n  /** In this example we must load only 4 bytes to determine the string is not found. */\n  @Test\n  fun indexOfByteStringDocumentationNoLoadingCase() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"lookxyz\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"hello\".encodeUtf8(), 0, 4))\n    assertEquals(\"look\", source.buffer.readUtf8())\n  }\n\n  /** This demonstrates that `indexOf()` doesn't load ranges beyond the maximum required. */\n  @Test\n  fun indexOfByteStringLoadsOnlyWhatIsRequiredWhenNotFoundSingleByte() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"X man,\".encodeUtf8(), 0, 1))\n    assertEquals(\"A\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfByteStringLoadsOnlyWhatIsRequiredWhenNotFoundMultipleBytes() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"A Xan,\".encodeUtf8(), 0, 1))\n    assertEquals(\"A m\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfByteStringLoadsOnlyWhatIsRequiredWhenFoundMultipleBytes() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertEquals(0, source.indexOf(\"A man,\".encodeUtf8(), 0, 1))\n    assertEquals(\"A man,\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfByteStringLoadsOnlyWhatIsRequiredWhenNotFoundWithFromIndex() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"A man,\".encodeUtf8(), 1, 2))\n    assertEquals(\"A \", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfByteStringLoadsOnlyWhatIsRequiredWhenFound() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertEquals(9L, source.indexOf(\"plan\".encodeUtf8(), 0L, 10L))\n    assertEquals(\"A man, a plan\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfByteStringFindsResultEdgeCases() {\n    for (i in 1..5) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(0L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 0L, 1L))\n      source.skip(5L)\n    }\n\n    for (i in 1..4) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(1L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 1L, 5L))\n      source.skip(5L)\n    }\n\n    for (i in 1..3) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(2L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 2L, 5L))\n      source.skip(5L)\n    }\n\n    for (i in 1..2) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(3L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 3L, 5L))\n      source.skip(5L)\n    }\n\n    for (i in 1..1) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(4L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 4L, 5L))\n      source.skip(5L)\n    }\n  }\n\n  @Test\n  fun indexOfByteStringEmptySearchRange() {\n    for (i in 1..5) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(-1L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 0L, 0L))\n      source.skip(5L)\n    }\n  }\n\n  @Test\n  fun indexOfByteStringTooLongAtOffset() {\n    for (i in 5..5) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(-1L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 1L, 5L))\n      source.skip(5L)\n    }\n    for (i in 4..5) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(-1L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 2L, 5L))\n      source.skip(5L)\n    }\n    for (i in 3..5) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(-1L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 3L, 5L))\n      source.skip(5L)\n    }\n    for (i in 2..5) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(-1L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 4L, 5L))\n      source.skip(5L)\n    }\n    for (i in 1..5) {\n      sink.writeUtf8(\"aaaaa\")\n      sink.emit()\n      assertEquals(-1L, source.indexOf(\"a\".repeat(i).encodeUtf8(), 5L, 5L))\n      source.skip(5L)\n    }\n  }\n\n  @Test\n  fun indexOfHonorsToIndexWhenAvoidingLoadsAndDoesNotLoad() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    source.require(2) // Source buffer contains 'A '\n    assertEquals(-1L, source.indexOf(\" man\".encodeUtf8(), 0L, 1L))\n    assertEquals(\"A \", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfHonorsFromIndexWhenAvoidingLoads() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertEquals(-1, source.indexOf(\"Panama.\".encodeUtf8(), 25L, 27L))\n    assertEquals(\"A man, a plan, a canal. Pan\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfHonorsToIndexWhenAvoidingLoadsAndLoads() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    source.require(2) // Source buffer contains 'A '\n    assertEquals(0L, source.indexOf(\"A ma\".encodeUtf8(), 0L, 1L))\n    assertEquals(\"A ma\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun indexOfElementWithFromIndex() {\n    sink.writeUtf8(\"aaa\")\n    sink.emit()\n    assertEquals(0, source.indexOfElement(\"a\".encodeUtf8()))\n    assertEquals(0, source.indexOfElement(\"a\".encodeUtf8(), 0))\n    assertEquals(1, source.indexOfElement(\"a\".encodeUtf8(), 1))\n    assertEquals(2, source.indexOfElement(\"a\".encodeUtf8(), 2))\n  }\n\n  @Test\n  fun request() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(SEGMENT_SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    assertTrue(source.request((SEGMENT_SIZE + 2).toLong()))\n    assertFalse(source.request((SEGMENT_SIZE + 3).toLong()))\n  }\n\n  @Test\n  fun require() {\n    sink.writeUtf8(\"a\").writeUtf8(\"b\".repeat(SEGMENT_SIZE)).writeUtf8(\"c\")\n    sink.emit()\n    source.require((SEGMENT_SIZE + 2).toLong())\n    try {\n      source.require((SEGMENT_SIZE + 3).toLong())\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun inputStream() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    val `in` = source.inputStream()\n    val bytes = byteArrayOf('z'.code.toByte(), 'z'.code.toByte(), 'z'.code.toByte())\n    var read = `in`.read(bytes)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      assertByteArrayEquals(\"azz\", bytes)\n      read = `in`.read(bytes)\n      assertEquals(1, read.toLong())\n      assertByteArrayEquals(\"bzz\", bytes)\n      read = `in`.read(bytes)\n      assertEquals(1, read.toLong())\n      assertByteArrayEquals(\"czz\", bytes)\n    } else {\n      assertEquals(3, read.toLong())\n      assertByteArrayEquals(\"abc\", bytes)\n    }\n    assertEquals(-1, `in`.read().toLong())\n  }\n\n  @Test\n  fun inputStreamOffsetCount() {\n    sink.writeUtf8(\"abcde\")\n    sink.emit()\n    val `in` = source.inputStream()\n    val bytes = byteArrayOf('z'.code.toByte(), 'z'.code.toByte(), 'z'.code.toByte(), 'z'.code.toByte(), 'z'.code.toByte())\n    val read = `in`.read(bytes, 1, 3)\n    if (factory.isOneByteAtATime) {\n      assertEquals(1, read.toLong())\n      assertByteArrayEquals(\"zazzz\", bytes)\n    } else {\n      assertEquals(3, read.toLong())\n      assertByteArrayEquals(\"zabcz\", bytes)\n    }\n  }\n\n  @Test\n  fun inputStreamSkip() {\n    sink.writeUtf8(\"abcde\")\n    sink.emit()\n    val `in` = source.inputStream()\n    assertEquals(4, `in`.skip(4))\n    assertEquals('e'.code.toLong(), `in`.read().toLong())\n    sink.writeUtf8(\"abcde\")\n    sink.emit()\n    assertEquals(5, `in`.skip(10)) // Try to skip too much.\n    assertEquals(0, `in`.skip(1)) // Try to skip when exhausted.\n  }\n\n  @Test\n  fun inputStreamCharByChar() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    val `in` = source.inputStream()\n    assertEquals('a'.code.toLong(), `in`.read().toLong())\n    assertEquals('b'.code.toLong(), `in`.read().toLong())\n    assertEquals('c'.code.toLong(), `in`.read().toLong())\n    assertEquals(-1, `in`.read().toLong())\n  }\n\n  @Test\n  fun inputStreamBounds() {\n    sink.writeUtf8(\"a\".repeat(100))\n    sink.emit()\n    val `in` = source.inputStream()\n    try {\n      `in`.read(ByteArray(100), 50, 51)\n      fail()\n    } catch (expected: java.lang.ArrayIndexOutOfBoundsException) {\n    }\n  }\n\n  @Test\n  fun inputStreamTransferTo() {\n    try {\n      ByteArrayInputStream(byteArrayOf(1)).transferTo(ByteArrayOutputStream())\n    } catch (e: NoSuchMethodError) {\n      return // This JDK doesn't have transferTo(). Skip this test.\n    }\n\n    val data = \"a\".repeat(SEGMENT_SIZE * 3 + 1)\n    sink.writeUtf8(data)\n    sink.emit()\n    val inputStream = source.inputStream()\n    val outputStream = ByteArrayOutputStream()\n    inputStream.transferTo(outputStream)\n    assertThat(source.exhausted()).isTrue()\n    assertThat(outputStream.toByteArray().toUtf8String()).isEqualTo(data)\n  }\n\n  @Test\n  fun longHexString() {\n    assertLongHexString(\"8000000000000000\", -0x7fffffffffffffffL - 1L)\n    assertLongHexString(\"fffffffffffffffe\", -0x2L)\n    assertLongHexString(\"FFFFFFFFFFFFFFFe\", -0x2L)\n    assertLongHexString(\"ffffffffffffffff\", -0x1L)\n    assertLongHexString(\"FFFFFFFFFFFFFFFF\", -0x1L)\n    assertLongHexString(\"0000000000000000\", 0x0)\n    assertLongHexString(\"0000000000000001\", 0x1)\n    assertLongHexString(\"7999999999999999\", 0x7999999999999999L)\n    assertLongHexString(\"FF\", 0xFF)\n    assertLongHexString(\"0000000000000001\", 0x1)\n  }\n\n  @Test\n  fun hexStringWithManyLeadingZeros() {\n    assertLongHexString(\"00000000000000001\", 0x1)\n    assertLongHexString(\"0000000000000000ffffffffffffffff\", -0x1L)\n    assertLongHexString(\"00000000000000007fffffffffffffff\", 0x7fffffffffffffffL)\n    assertLongHexString(\"0\".repeat(SEGMENT_SIZE + 1) + \"1\", 0x1)\n  }\n\n  private fun assertLongHexString(s: String, expected: Long) {\n    sink.writeUtf8(s)\n    sink.emit()\n    val actual = source.readHexadecimalUnsignedLong()\n    assertEquals(\"$s --> $expected\", expected, actual)\n  }\n\n  @Test\n  fun longHexStringAcrossSegment() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 8)).writeUtf8(\"FFFFFFFFFFFFFFFF\")\n    sink.emit()\n    source.skip((SEGMENT_SIZE - 8).toLong())\n    assertEquals(-1, source.readHexadecimalUnsignedLong())\n  }\n\n  @Test\n  fun longHexStringTooLongThrows() {\n    try {\n      sink.writeUtf8(\"fffffffffffffffff\")\n      sink.emit()\n      source.readHexadecimalUnsignedLong()\n      fail()\n    } catch (e: NumberFormatException) {\n      assertEquals(\"Number too large: fffffffffffffffff\", e.message)\n    }\n  }\n\n  @Test\n  fun longHexStringTooShortThrows() {\n    try {\n      sink.writeUtf8(\" \")\n      sink.emit()\n      source.readHexadecimalUnsignedLong()\n      fail()\n    } catch (e: NumberFormatException) {\n      assertEquals(\"Expected leading [0-9a-fA-F] character but was 0x20\", e.message)\n    }\n  }\n\n  @Test\n  fun longHexEmptySourceThrows() {\n    try {\n      sink.writeUtf8(\"\")\n      sink.emit()\n      source.readHexadecimalUnsignedLong()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun longDecimalString() {\n    assertLongDecimalString(\"-9223372036854775808\", -9223372036854775807L - 1L)\n    assertLongDecimalString(\"-1\", -1L)\n    assertLongDecimalString(\"0\", 0L)\n    assertLongDecimalString(\"1\", 1L)\n    assertLongDecimalString(\"9223372036854775807\", 9223372036854775807L)\n    assertLongDecimalString(\"00000001\", 1L)\n    assertLongDecimalString(\"-000001\", -1L)\n  }\n\n  private fun assertLongDecimalString(s: String, expected: Long) {\n    sink.writeUtf8(s)\n    sink.writeUtf8(\"zzz\")\n    sink.emit()\n    val actual = source.readDecimalLong()\n    assertEquals(\"$s --> $expected\", expected, actual)\n    assertEquals(\"zzz\", source.readUtf8())\n  }\n\n  @Test\n  fun longDecimalStringAcrossSegment() {\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE - 8)).writeUtf8(\"1234567890123456\")\n    sink.writeUtf8(\"zzz\")\n    sink.emit()\n    source.skip((SEGMENT_SIZE - 8).toLong())\n    assertEquals(1234567890123456L, source.readDecimalLong())\n    assertEquals(\"zzz\", source.readUtf8())\n  }\n\n  @Test\n  fun longDecimalStringTooLongThrows() {\n    try {\n      sink.writeUtf8(\"12345678901234567890\") // Too many digits.\n      sink.emit()\n      source.readDecimalLong()\n      fail()\n    } catch (e: NumberFormatException) {\n      assertEquals(\"Number too large: 12345678901234567890\", e.message)\n    }\n  }\n\n  @Test\n  fun longDecimalStringTooHighThrows() {\n    try {\n      sink.writeUtf8(\"9223372036854775808\") // Right size but cannot fit.\n      sink.emit()\n      source.readDecimalLong()\n      fail()\n    } catch (e: NumberFormatException) {\n      assertEquals(\"Number too large: 9223372036854775808\", e.message)\n    }\n  }\n\n  @Test\n  fun longDecimalStringTooLowThrows() {\n    try {\n      sink.writeUtf8(\"-9223372036854775809\") // Right size but cannot fit.\n      sink.emit()\n      source.readDecimalLong()\n      fail()\n    } catch (e: NumberFormatException) {\n      assertEquals(\"Number too large: -9223372036854775809\", e.message)\n    }\n  }\n\n  @Test\n  fun longDecimalStringTooShortThrows() {\n    try {\n      sink.writeUtf8(\" \")\n      sink.emit()\n      source.readDecimalLong()\n      fail()\n    } catch (e: NumberFormatException) {\n      assertEquals(\"Expected a digit or '-' but was 0x20\", e.message)\n    }\n  }\n\n  @Test\n  fun longDecimalEmptyThrows() {\n    try {\n      sink.writeUtf8(\"\")\n      sink.emit()\n      source.readDecimalLong()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun codePoints() {\n    sink.write(\"7f\".decodeHex())\n    sink.emit()\n    assertEquals(0x7f, source.readUtf8CodePoint().toLong())\n    sink.write(\"dfbf\".decodeHex())\n    sink.emit()\n    assertEquals(0x07ff, source.readUtf8CodePoint().toLong())\n    sink.write(\"efbfbf\".decodeHex())\n    sink.emit()\n    assertEquals(0xffff, source.readUtf8CodePoint().toLong())\n    sink.write(\"f48fbfbf\".decodeHex())\n    sink.emit()\n    assertEquals(0x10ffff, source.readUtf8CodePoint().toLong())\n  }\n\n  @Test\n  fun decimalStringWithManyLeadingZeros() {\n    assertLongDecimalString(\"00000000000000001\", 1)\n    assertLongDecimalString(\"00000000000000009223372036854775807\", 9223372036854775807L)\n    assertLongDecimalString(\"-00000000000000009223372036854775808\", -9223372036854775807L - 1L)\n    assertLongDecimalString(\"0\".repeat(SEGMENT_SIZE + 1) + \"1\", 1)\n  }\n\n  @Test\n  fun select() {\n    val options = of(\n      \"ROCK\".encodeUtf8(),\n      \"SCISSORS\".encodeUtf8(),\n      \"PAPER\".encodeUtf8(),\n    )\n    sink.writeUtf8(\"PAPER,SCISSORS,ROCK\")\n    sink.emit()\n    assertEquals(2, source.select(options).toLong())\n    assertEquals(','.code.toLong(), source.readByte().toLong())\n    assertEquals(1, source.select(options).toLong())\n    assertEquals(','.code.toLong(), source.readByte().toLong())\n    assertEquals(0, source.select(options).toLong())\n    assertTrue(source.exhausted())\n  }\n\n  /** Note that this test crashes the VM on Android.  */\n  @Test\n  fun selectSpanningMultipleSegments() {\n    val commonPrefix = randomBytes(SEGMENT_SIZE + 10)\n    val a = Buffer().write(commonPrefix).writeUtf8(\"a\").readByteString()\n    val bc = Buffer().write(commonPrefix).writeUtf8(\"bc\").readByteString()\n    val bd = Buffer().write(commonPrefix).writeUtf8(\"bd\").readByteString()\n    val options = of(a, bc, bd)\n    sink.write(bd)\n    sink.write(a)\n    sink.write(bc)\n    sink.emit()\n    assertEquals(2, source.select(options).toLong())\n    assertEquals(0, source.select(options).toLong())\n    assertEquals(1, source.select(options).toLong())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun selectNotFound() {\n    val options = of(\n      \"ROCK\".encodeUtf8(),\n      \"SCISSORS\".encodeUtf8(),\n      \"PAPER\".encodeUtf8(),\n    )\n    sink.writeUtf8(\"SPOCK\")\n    sink.emit()\n    assertEquals(-1, source.select(options).toLong())\n    assertEquals(\"SPOCK\", source.readUtf8())\n  }\n\n  @Test\n  fun selectValuesHaveCommonPrefix() {\n    val options = of(\n      \"abcd\".encodeUtf8(),\n      \"abce\".encodeUtf8(),\n      \"abcc\".encodeUtf8(),\n    )\n    sink.writeUtf8(\"abcc\").writeUtf8(\"abcd\").writeUtf8(\"abce\")\n    sink.emit()\n    assertEquals(2, source.select(options).toLong())\n    assertEquals(0, source.select(options).toLong())\n    assertEquals(1, source.select(options).toLong())\n  }\n\n  @Test\n  fun selectLongerThanSource() {\n    val options = of(\n      \"abcd\".encodeUtf8(),\n      \"abce\".encodeUtf8(),\n      \"abcc\".encodeUtf8(),\n    )\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    assertEquals(-1, source.select(options).toLong())\n    assertEquals(\"abc\", source.readUtf8())\n  }\n\n  @Test\n  fun selectReturnsFirstByteStringThatMatches() {\n    val options = of(\n      \"abcd\".encodeUtf8(),\n      \"abc\".encodeUtf8(),\n      \"abcde\".encodeUtf8(),\n    )\n    sink.writeUtf8(\"abcdef\")\n    sink.emit()\n    assertEquals(0, source.select(options).toLong())\n    assertEquals(\"ef\", source.readUtf8())\n  }\n\n  @Test\n  fun selectFromEmptySource() {\n    val options = of(\n      \"abc\".encodeUtf8(),\n      \"def\".encodeUtf8(),\n    )\n    assertEquals(-1, source.select(options).toLong())\n  }\n\n  @Test\n  fun selectNoByteStringsFromEmptySource() {\n    val options = Options.of()\n    assertEquals(-1, source.select(options).toLong())\n  }\n\n  @Test\n  fun peek() {\n    sink.writeUtf8(\"abcdefghi\")\n    sink.emit()\n    assertEquals(\"abc\", source.readUtf8(3))\n    val peek = source.peek()\n    assertEquals(\"def\", peek.readUtf8(3))\n    assertEquals(\"ghi\", peek.readUtf8(3))\n    assertFalse(peek.request(1))\n    assertEquals(\"def\", source.readUtf8(3))\n  }\n\n  @Test\n  fun peekMultiple() {\n    sink.writeUtf8(\"abcdefghi\")\n    sink.emit()\n    assertEquals(\"abc\", source.readUtf8(3))\n    val peek1 = source.peek()\n    val peek2 = source.peek()\n    assertEquals(\"def\", peek1.readUtf8(3))\n    assertEquals(\"def\", peek2.readUtf8(3))\n    assertEquals(\"ghi\", peek2.readUtf8(3))\n    assertFalse(peek2.request(1))\n    assertEquals(\"ghi\", peek1.readUtf8(3))\n    assertFalse(peek1.request(1))\n    assertEquals(\"def\", source.readUtf8(3))\n  }\n\n  @Test\n  fun peekLarge() {\n    sink.writeUtf8(\"abcdef\")\n    sink.writeUtf8(\"g\".repeat(2 * SEGMENT_SIZE))\n    sink.writeUtf8(\"hij\")\n    sink.emit()\n    assertEquals(\"abc\", source.readUtf8(3))\n    val peek = source.peek()\n    assertEquals(\"def\", peek.readUtf8(3))\n    peek.skip((2 * SEGMENT_SIZE).toLong())\n    assertEquals(\"hij\", peek.readUtf8(3))\n    assertFalse(peek.request(1))\n    assertEquals(\"def\", source.readUtf8(3))\n    source.skip((2 * SEGMENT_SIZE).toLong())\n    assertEquals(\"hij\", source.readUtf8(3))\n  }\n\n  @Test\n  fun peekInvalid() {\n    sink.writeUtf8(\"abcdefghi\")\n    sink.emit()\n    assertEquals(\"abc\", source.readUtf8(3))\n    val peek = source.peek()\n    assertEquals(\"def\", peek.readUtf8(3))\n    assertEquals(\"ghi\", peek.readUtf8(3))\n    assertFalse(peek.request(1))\n    assertEquals(\"def\", source.readUtf8(3))\n    try {\n      peek.readUtf8()\n      fail()\n    } catch (e: IllegalStateException) {\n      assertEquals(\"Peek source is invalid because upstream source was used\", e.message)\n    }\n  }\n\n  @Test\n  fun peekSegmentThenInvalid() {\n    sink.writeUtf8(\"abc\")\n    sink.writeUtf8(\"d\".repeat(2 * SEGMENT_SIZE))\n    sink.emit()\n    assertEquals(\"abc\", source.readUtf8(3))\n\n    // Peek a little data and skip the rest of the upstream source\n    val peek = source.peek()\n    assertEquals(\"ddd\", peek.readUtf8(3))\n    source.readAll(blackholeSink())\n\n    // Skip the rest of the buffered data\n    peek.skip(peek.buffer.size)\n    try {\n      peek.readByte()\n      fail()\n    } catch (e: IllegalStateException) {\n      assertEquals(\"Peek source is invalid because upstream source was used\", e.message)\n    }\n  }\n\n  @Test\n  fun peekDoesntReadTooMuch() {\n    // 6 bytes in source's buffer plus 3 bytes upstream.\n    sink.writeUtf8(\"abcdef\")\n    sink.emit()\n    source.require(6L)\n    sink.writeUtf8(\"ghi\")\n    sink.emit()\n    val peek = source.peek()\n\n    // Read 3 bytes. This reads some of the buffered data.\n    assertTrue(peek.request(3))\n    if (source !is Buffer) {\n      assertEquals(6, source.buffer.size)\n      assertEquals(6, peek.buffer.size)\n    }\n    assertEquals(\"abc\", peek.readUtf8(3L))\n\n    // Read 3 more bytes. This exhausts the buffered data.\n    assertTrue(peek.request(3))\n    if (source !is Buffer) {\n      assertEquals(6, source.buffer.size)\n      assertEquals(3, peek.buffer.size)\n    }\n    assertEquals(\"def\", peek.readUtf8(3L))\n\n    // Read 3 more bytes. This draws new bytes.\n    assertTrue(peek.request(3))\n    assertEquals(9, source.buffer.size)\n    assertEquals(3, peek.buffer.size)\n    assertEquals(\"ghi\", peek.readUtf8(3L))\n  }\n\n  @Test\n  fun rangeEquals() {\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertTrue(source.rangeEquals(7, \"a plan\".encodeUtf8()))\n    assertTrue(source.rangeEquals(0, \"A man\".encodeUtf8()))\n    assertTrue(source.rangeEquals(24, \"Panama\".encodeUtf8()))\n    assertFalse(source.rangeEquals(24, \"Panama. Panama. Panama.\".encodeUtf8()))\n  }\n\n  @Test\n  fun rangeEqualsWithOffsetAndCount() {\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertTrue(source.rangeEquals(7, \"aaa plannn\".encodeUtf8(), 2, 6))\n    assertTrue(source.rangeEquals(0, \"AAA mannn\".encodeUtf8(), 2, 5))\n    assertTrue(source.rangeEquals(24, \"PPPanamaaa\".encodeUtf8(), 2, 6))\n  }\n\n  @Test\n  fun rangeEqualsOnlyReadsUntilMismatch() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertFalse(source.rangeEquals(0, \"A man.\".encodeUtf8()))\n    assertEquals(\"A man,\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun rangeEqualsBreaksAfterFirstMismatch() {\n    assumeTrue(factory === Factory.OneByteAtATimeSource) // Other sources read in chunks anyway.\n    sink.writeUtf8(\"A man, a plan, a canal. Panama.\")\n    sink.emit()\n    assertFalse(source.rangeEquals(0, \"X man,\".encodeUtf8()))\n    assertEquals(\"A\", source.buffer.readUtf8())\n  }\n\n  @Test\n  fun rangeEqualsArgumentValidation() {\n    // Negative source offset.\n    assertFalse(source.rangeEquals(-1, \"A\".encodeUtf8()))\n    // Negative bytes offset.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), -1, 1))\n    // Bytes offset longer than bytes length.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 2, 1))\n    // Negative byte count.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 0, -1))\n    // Byte count longer than bytes length.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 0, 2))\n    // Bytes offset plus byte count longer than bytes length.\n    assertFalse(source.rangeEquals(0, \"A\".encodeUtf8(), 1, 1))\n  }\n\n  @Test\n  fun readNioBuffer() {\n    val expected = if (factory.isOneByteAtATime) \"a\" else \"abcdefg\"\n    sink.writeUtf8(\"abcdefg\")\n    sink.emit()\n    val nioByteBuffer = ByteBuffer.allocate(1024)\n    val byteCount = source.read(nioByteBuffer)\n    assertEquals(expected.length.toLong(), byteCount.toLong())\n    assertEquals(expected.length.toLong(), nioByteBuffer.position().toLong())\n    assertEquals(nioByteBuffer.capacity().toLong(), nioByteBuffer.limit().toLong())\n    (nioByteBuffer as java.nio.Buffer).flip() // Cast necessary for Java 8.\n    val data = ByteArray(expected.length)\n    nioByteBuffer[data]\n    assertEquals(expected, data.decodeToString())\n  }\n\n  /** Note that this test crashes the VM on Android.  */\n  @Test\n  fun readLargeNioBufferOnlyReadsOneSegment() {\n    val expected = if (factory.isOneByteAtATime) \"a\" else \"a\".repeat(SEGMENT_SIZE)\n    sink.writeUtf8(\"a\".repeat(SEGMENT_SIZE * 4))\n    sink.emit()\n    val nioByteBuffer = ByteBuffer.allocate(SEGMENT_SIZE * 3)\n    val byteCount = source.read(nioByteBuffer)\n    assertEquals(expected.length.toLong(), byteCount.toLong())\n    assertEquals(expected.length.toLong(), nioByteBuffer.position().toLong())\n    assertEquals(nioByteBuffer.capacity().toLong(), nioByteBuffer.limit().toLong())\n    (nioByteBuffer as java.nio.Buffer).flip() // Cast necessary for Java 8.\n    val data = ByteArray(expected.length)\n    nioByteBuffer[data]\n    assertEquals(expected, data.decodeToString())\n  }\n\n  @Test\n  fun factorySegmentSizes() {\n    sink.writeUtf8(\"abc\")\n    sink.emit()\n    source.require(3)\n    if (factory.isOneByteAtATime) {\n      assertEquals(mutableListOf(1, 1, 1), segmentSizes(source.buffer))\n    } else {\n      assertEquals(listOf(3), segmentSizes(source.buffer))\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ByteStringJavaTest.kt",
    "content": "/*\n * Copyright 2014 Square Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport java.io.ByteArrayInputStream\nimport java.io.ByteArrayOutputStream\nimport java.nio.ByteBuffer\nimport java.util.Random\nimport kotlin.text.Charsets.US_ASCII\nimport kotlin.text.Charsets.UTF_16BE\nimport kotlin.text.Charsets.UTF_32BE\nimport kotlin.text.Charsets.UTF_8\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encode\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.ByteString.Companion.readByteString\nimport okio.ByteString.Companion.toByteString\nimport okio.TestUtil.assertByteArraysEquals\nimport okio.TestUtil.assertEquivalent\nimport okio.TestUtil.makeSegments\nimport okio.TestUtil.reserialize\nimport org.junit.Assert.assertEquals\nimport org.junit.Test\n\n@Burst\nclass ByteStringJavaTest(\n  private val factory: Factory,\n) {\n  enum class Factory {\n    BaseByteString {\n      override fun decodeHex(hex: String): ByteString {\n        return hex.decodeHex()\n      }\n\n      override fun encodeUtf8(s: String): ByteString {\n        return s.encodeUtf8()\n      }\n    },\n    SegmentedByteString {\n      override fun decodeHex(hex: String): ByteString {\n        val buffer = Buffer()\n        buffer.write(hex.decodeHex())\n        return buffer.snapshot()\n      }\n\n      override fun encodeUtf8(s: String): ByteString {\n        val buffer = Buffer()\n        buffer.writeUtf8(s)\n        return buffer.snapshot()\n      }\n    },\n    OneBytePerSegment {\n      override fun decodeHex(hex: String): ByteString {\n        return makeSegments(hex.decodeHex())\n      }\n\n      override fun encodeUtf8(s: String): ByteString {\n        return makeSegments(s.encodeUtf8())\n      }\n    },\n    ;\n\n    abstract fun decodeHex(hex: String): ByteString\n    abstract fun encodeUtf8(s: String): ByteString\n  }\n\n  @Test\n  fun ofByteBuffer() {\n    val bytes = \"Hello, World!\".toByteArray(UTF_8)\n    val byteBuffer = ByteBuffer.wrap(bytes)\n    (byteBuffer as java.nio.Buffer).position(2).limit(11) // Cast necessary for Java 8.\n    val byteString: ByteString = byteBuffer.toByteString()\n    // Verify that the bytes were copied out.\n    byteBuffer.put(4, 'a'.code.toByte())\n    assertEquals(\"llo, Worl\", byteString.utf8())\n  }\n\n  @Test\n  fun read() {\n    val inputStream = ByteArrayInputStream(\"abc\".toByteArray(UTF_8))\n    assertEquals(\"6162\".decodeHex(), inputStream.readByteString(2))\n    assertEquals(\"63\".decodeHex(), inputStream.readByteString(1))\n    assertEquals(ByteString.of(), inputStream.readByteString(0))\n  }\n\n  @Test\n  fun readAndToLowercase() {\n    val inputStream = ByteArrayInputStream(\"ABC\".toByteArray(UTF_8))\n    assertEquals(\"ab\".encodeUtf8(), inputStream.readByteString(2).toAsciiLowercase())\n    assertEquals(\"c\".encodeUtf8(), inputStream.readByteString(1).toAsciiLowercase())\n    assertEquals(ByteString.EMPTY, inputStream.readByteString(0).toAsciiLowercase())\n  }\n\n  @Test\n  fun readAndToUppercase() {\n    val inputStream = ByteArrayInputStream(\"abc\".toByteArray(UTF_8))\n    assertEquals(\"AB\".encodeUtf8(), inputStream.readByteString(2).toAsciiUppercase())\n    assertEquals(\"C\".encodeUtf8(), inputStream.readByteString(1).toAsciiUppercase())\n    assertEquals(ByteString.EMPTY, inputStream.readByteString(0).toAsciiUppercase())\n  }\n\n  @Test\n  fun write() {\n    val out = ByteArrayOutputStream()\n    factory.decodeHex(\"616263\").write(out)\n    assertByteArraysEquals(byteArrayOf(0x61, 0x62, 0x63), out.toByteArray())\n  }\n\n  @Test\n  fun compareToSingleBytes() {\n    val originalByteStrings = listOf(\n      factory.decodeHex(\"00\"),\n      factory.decodeHex(\"01\"),\n      factory.decodeHex(\"7e\"),\n      factory.decodeHex(\"7f\"),\n      factory.decodeHex(\"80\"),\n      factory.decodeHex(\"81\"),\n      factory.decodeHex(\"fe\"),\n      factory.decodeHex(\"ff\"),\n    )\n    val sortedByteStrings = originalByteStrings.toMutableList()\n    sortedByteStrings.shuffle(Random(0))\n    sortedByteStrings.sort()\n    assertEquals(originalByteStrings, sortedByteStrings)\n  }\n\n  @Test\n  fun compareToMultipleBytes() {\n    val originalByteStrings = listOf(\n      factory.decodeHex(\"\"),\n      factory.decodeHex(\"00\"),\n      factory.decodeHex(\"0000\"),\n      factory.decodeHex(\"000000\"),\n      factory.decodeHex(\"00000000\"),\n      factory.decodeHex(\"0000000000\"),\n      factory.decodeHex(\"0000000001\"),\n      factory.decodeHex(\"000001\"),\n      factory.decodeHex(\"00007f\"),\n      factory.decodeHex(\"0000ff\"),\n      factory.decodeHex(\"000100\"),\n      factory.decodeHex(\"000101\"),\n      factory.decodeHex(\"007f00\"),\n      factory.decodeHex(\"00ff00\"),\n      factory.decodeHex(\"010000\"),\n      factory.decodeHex(\"010001\"),\n      factory.decodeHex(\"01007f\"),\n      factory.decodeHex(\"0100ff\"),\n      factory.decodeHex(\"010100\"),\n      factory.decodeHex(\"01010000\"),\n      factory.decodeHex(\"0101000000\"),\n      factory.decodeHex(\"0101000001\"),\n      factory.decodeHex(\"010101\"),\n      factory.decodeHex(\"7f0000\"),\n      factory.decodeHex(\"7f0000ffff\"),\n      factory.decodeHex(\"ffffff\"),\n    )\n    val sortedByteStrings = originalByteStrings.toMutableList()\n    sortedByteStrings.shuffle(Random(0))\n    sortedByteStrings.sort()\n    assertEquals(originalByteStrings, sortedByteStrings)\n  }\n\n  @Test\n  fun javaSerializationTestNonEmpty() {\n    val byteString = factory.encodeUtf8(bronzeHorseman)\n    assertEquivalent(byteString, reserialize(byteString))\n  }\n\n  @Test\n  fun javaSerializationTestEmpty() {\n    val byteString = factory.decodeHex(\"\")\n    assertEquivalent(byteString, reserialize(byteString))\n  }\n\n  @Test\n  fun asByteBuffer() {\n    assertEquals(\n      0x42,\n      ByteString.of(0x41.toByte(), 0x42.toByte(), 0x43.toByte()).asByteBuffer()[1].toLong(),\n    )\n  }\n\n  @Test\n  fun encodeDecodeStringUtf8() {\n    val byteString = bronzeHorseman.encode(UTF_8)\n    assertByteArraysEquals(byteString.toByteArray(), bronzeHorseman.toByteArray(UTF_8))\n    assertEquals(\n      byteString,\n      (\n        \"d09dd0b020d0b1d0b5d180d0b5d0b3d18320d0bfd183d181\" +\n          \"d182d18bd0bdd0bdd18bd18520d0b2d0bed0bbd0bd\"\n        ).decodeHex(),\n    )\n    assertEquals(bronzeHorseman, byteString.string(UTF_8))\n  }\n\n  @Test\n  fun encodeDecodeStringUtf16be() {\n    val byteString = bronzeHorseman.encode(UTF_16BE)\n    assertByteArraysEquals(byteString.toByteArray(), bronzeHorseman.toByteArray(UTF_16BE))\n    assertEquals(\n      byteString,\n      (\n        \"041d043000200431043504400435043304430020043f0443\" +\n          \"04410442044b043d043d044b044500200432043e043b043d\"\n        ).decodeHex(),\n    )\n    assertEquals(bronzeHorseman, byteString.string(UTF_16BE))\n  }\n\n  @Test\n  fun encodeDecodeStringUtf32be() {\n    val byteString: ByteString = bronzeHorseman.encode(UTF_32BE)\n    assertByteArraysEquals(byteString.toByteArray(), bronzeHorseman.toByteArray(UTF_32BE))\n    assertEquals(\n      byteString,\n      (\n        \"0000041d0000043000000020000004310000043500000440\" +\n          \"000004350000043300000443000000200000043f0000044300000441000004420000044b0000043d0000043d\" +\n          \"0000044b0000044500000020000004320000043e0000043b0000043d\"\n        ).decodeHex(),\n    )\n    assertEquals(bronzeHorseman, byteString.string(UTF_32BE))\n  }\n\n  @Test\n  fun encodeDecodeStringAsciiIsLossy() {\n    val byteString: ByteString = bronzeHorseman.encode(US_ASCII)\n    assertByteArraysEquals(byteString.toByteArray(), bronzeHorseman.toByteArray(US_ASCII))\n    assertEquals(\n      byteString,\n      \"3f3f203f3f3f3f3f3f203f3f3f3f3f3f3f3f3f203f3f3f3f\".decodeHex(),\n    )\n    assertEquals(\"?? ?????? ????????? ????\", byteString.string(US_ASCII))\n  }\n\n  @Test\n  fun decodeMalformedStringReturnsReplacementCharacter() {\n    val string = \"04\".decodeHex().string(UTF_16BE)\n    assertEquals(\"\\ufffd\", string)\n  }\n\n  companion object {\n    private val bronzeHorseman = \"На берегу пустынных волн\"\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ByteStringKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport java.io.ByteArrayInputStream\nimport java.nio.ByteBuffer\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport okio.ByteString.Companion.encode\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.ByteString.Companion.readByteString\nimport okio.ByteString.Companion.toByteString\n\nclass ByteStringKotlinTest {\n  @Test fun arrayToByteString() {\n    val actual = byteArrayOf(1, 2, 3, 4).toByteString()\n    val expected = ByteString.of(1, 2, 3, 4)\n    assertEquals(actual, expected)\n  }\n\n  @Test fun arraySubsetToByteString() {\n    val actual = byteArrayOf(1, 2, 3, 4).toByteString(1, 2)\n    val expected = ByteString.of(2, 3)\n    assertEquals(actual, expected)\n  }\n\n  @Test fun byteBufferToByteString() {\n    val actual = ByteBuffer.wrap(byteArrayOf(1, 2, 3, 4)).toByteString()\n    val expected = ByteString.of(1, 2, 3, 4)\n    assertEquals(actual, expected)\n  }\n\n  @Test fun stringEncodeByteStringDefaultCharset() {\n    val actual = \"a\\uD83C\\uDF69c\".encode()\n    val expected = \"a\\uD83C\\uDF69c\".encodeUtf8()\n    assertEquals(actual, expected)\n  }\n\n  @Test fun streamReadByteString() {\n    val stream = ByteArrayInputStream(byteArrayOf(1, 2, 3, 4, 5, 6, 7, 8))\n    val actual = stream.readByteString(4)\n    val expected = ByteString.of(1, 2, 3, 4)\n    assertEquals(actual, expected)\n  }\n\n  @Test fun substring() {\n    val byteString = \"abcdef\".encodeUtf8()\n    assertEquals(byteString.substring(), \"abcdef\".encodeUtf8())\n    assertEquals(byteString.substring(endIndex = 3), \"abc\".encodeUtf8())\n    assertEquals(byteString.substring(beginIndex = 3), \"def\".encodeUtf8())\n    assertEquals(byteString.substring(beginIndex = 1, endIndex = 5), \"bcde\".encodeUtf8())\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/CipherAlgorithm.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage okio\n\nimport javax.crypto.spec.IvParameterSpec\nimport javax.crypto.spec.SecretKeySpec\nimport kotlin.random.Random\n\nenum class CipherAlgorithm(\n  val transformation: String,\n  val padding: Boolean,\n  val keyLength: Int,\n  val ivLength: Int? = null,\n) {\n  AesCbcNopadding(\"AES/CBC/NoPadding\", false, 16, 16),\n  AesCbcPkcs5padding(\"AES/CBC/PKCS5Padding\", true, 16, 16),\n  AesEcbNopadding(\"AES/ECB/NoPadding\", false, 16),\n  AesEcbPkcs5padding(\"AES/ECB/PKCS5Padding\", true, 16),\n  DesCbcNopadding(\"DES/CBC/NoPadding\", false, 8, 8),\n  DesCbcPkcs5padding(\"DES/CBC/PKCS5Padding\", true, 8, 8),\n  DesEcbNopadding(\"DES/ECB/NoPadding\", false, 8),\n  DesEcbPkcs5padding(\"DES/ECB/PKCS5Padding\", true, 8),\n  DesedeCbcNopadding(\"DESede/CBC/NoPadding\", false, 24, 8),\n  DesedeCbcPkcs5padding(\"DESede/CBC/PKCS5Padding\", true, 24, 8),\n  DesedeEcbNopadding(\"DESede/ECB/NoPadding\", false, 24),\n  DesedeEcbPkcs5padding(\"DESede/ECB/PKCS5Padding\", true, 24),\n  ;\n\n  fun createCipherFactory(random: Random): CipherFactory {\n    val key = random.nextBytes(keyLength)\n    val secretKeySpec = SecretKeySpec(key, transformation.substringBefore('/'))\n    return if (ivLength == null) {\n      CipherFactory(transformation) { mode ->\n        init(mode, secretKeySpec)\n      }\n    } else {\n      val iv = random.nextBytes(ivLength)\n      val ivParameterSpec = IvParameterSpec(iv)\n      CipherFactory(transformation) { mode ->\n        init(mode, secretKeySpec, ivParameterSpec)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/CipherFactory.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage okio\n\nimport javax.crypto.Cipher\n\nclass CipherFactory(\n  private val transformation: String,\n  private val init: Cipher.(mode: Int) -> Unit,\n) {\n  val blockSize\n    get() = newCipher().blockSize\n\n  val encrypt: Cipher\n    get() = create(Cipher.ENCRYPT_MODE)\n\n  val decrypt: Cipher\n    get() = create(Cipher.DECRYPT_MODE)\n\n  private fun newCipher(): Cipher = Cipher.getInstance(transformation)\n\n  private fun create(mode: Int): Cipher = newCipher().apply { init(mode) }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/CipherSinkTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport kotlin.random.Random\nimport org.junit.Test\n\n@Burst\nclass CipherSinkTest(\n  private val cipherAlgorithm: CipherAlgorithm,\n) {\n  @Test\n  fun encrypt() {\n    val random = Random(8912860393601532863)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = random.nextBytes(32)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.encrypt)\n    cipherSink.buffer().use { it.write(data) }\n    val actualEncryptedData = buffer.readByteArray()\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun encryptEmpty() {\n    val random = Random(3014415396541767201)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = ByteArray(0)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.encrypt)\n    cipherSink.buffer().close()\n    val actualEncryptedData = buffer.readByteArray()\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun encryptLarge() {\n    val random = Random(4800508322764694019)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = random.nextBytes(Segment.SIZE * 16 + Segment.SIZE / 2)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.encrypt)\n    cipherSink.buffer().use { it.write(data) }\n    val actualEncryptedData = buffer.readByteArray()\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun encryptSingleByteWrite() {\n    val random = Random(4374178522096702290)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = random.nextBytes(32)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.encrypt)\n    cipherSink.buffer().use {\n      data.forEach {\n          byte ->\n        it.writeByte(byte.toInt())\n      }\n    }\n    val actualEncryptedData = buffer.readByteArray()\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  /** Only relevant for algorithms which handle padding. */\n  @Test\n  fun encryptPaddingRequired() {\n    val random = Random(7515202505362968404)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val blockSize = cipherFactory.blockSize\n    val dataSize = blockSize * 4 + if (cipherAlgorithm.padding) blockSize / 2 else 0\n    val data = random.nextBytes(dataSize)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.encrypt)\n    cipherSink.buffer().use { it.write(data) }\n    val actualEncryptedData = buffer.readByteArray()\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun decrypt() {\n    val random = Random(488375923060579687)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = random.nextBytes(32)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.decrypt)\n    cipherSink.buffer().use { it.write(encryptedData) }\n    val actualData = buffer.readByteArray()\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  @Test\n  fun decryptEmpty() {\n    val random = Random(-9063010151894844496)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = ByteArray(0)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.decrypt)\n    cipherSink.buffer().use { it.write(encryptedData) }\n    val actualData = buffer.readByteArray()\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  @Test\n  fun decryptLarge() {\n    val random = Random(993064087526004362)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = random.nextBytes(Segment.SIZE * 16 + Segment.SIZE / 2)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.decrypt)\n    cipherSink.buffer().use { it.write(encryptedData) }\n    val actualData = buffer.readByteArray()\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  @Test\n  fun decryptSingleByteWrite() {\n    val random = Random(2621474675920878975)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = random.nextBytes(32)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.decrypt)\n    cipherSink.buffer().use {\n      encryptedData.forEach { byte ->\n        it.writeByte(byte.toInt())\n      }\n    }\n    val actualData = buffer.readByteArray()\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  /** Only relevant for algorithms which handle padding. */\n  @Test\n  fun decryptPaddingRequired() {\n    val random = Random(7689061926945836562)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val blockSize = cipherFactory.blockSize\n    val dataSize = blockSize * 4 + if (cipherAlgorithm.padding) blockSize / 2 else 0\n    val expectedData = random.nextBytes(dataSize)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer()\n    val cipherSink = buffer.cipherSink(cipherFactory.decrypt)\n    cipherSink.buffer().use { it.write(encryptedData) }\n    val actualData = buffer.readByteArray()\n\n    assertArrayEquals(expectedData, actualData)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/CipherSourceTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc. and others.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport kotlin.random.Random\nimport org.junit.Test\n\n@Burst\nclass CipherSourceTest(\n  private val cipherAlgorithm: CipherAlgorithm,\n) {\n  @Test\n  fun encrypt() {\n    val random = Random(787679144228763091)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = random.nextBytes(32)\n\n    val buffer = Buffer().apply { write(data) }\n    val cipherSource = buffer.cipherSource(cipherFactory.encrypt)\n    val actualEncryptedData = cipherSource.buffer().use { it.readByteArray() }\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun encryptEmpty() {\n    val random = Random(1057830944394705953)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = ByteArray(0)\n\n    val buffer = Buffer()\n    val cipherSource = buffer.cipherSource(cipherFactory.encrypt)\n    val actualEncryptedData = cipherSource.buffer().use { it.readByteArray() }\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun encryptLarge() {\n    val random = Random(8185922876836480815)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = random.nextBytes(Segment.SIZE * 16 + Segment.SIZE / 2)\n\n    val buffer = Buffer().apply { write(data) }\n    val cipherSource = buffer.cipherSource(cipherFactory.encrypt)\n    val actualEncryptedData = cipherSource.buffer().use { it.readByteArray() }\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun encryptSingleByteSource() {\n    val random = Random(6085265142433950622)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val data = random.nextBytes(32)\n\n    val buffer = Buffer().apply { write(data) }\n    val cipherSource = buffer.emitSingleBytes().cipherSource(cipherFactory.encrypt)\n    val actualEncryptedData = cipherSource.buffer().use { it.readByteArray() }\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  /** Only relevant for algorithms which handle padding. */\n  @Test\n  fun encryptPaddingRequired() {\n    val random = Random(4190481737015278225)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val blockSize = cipherFactory.blockSize\n    val dataSize = blockSize * 4 + if (cipherAlgorithm.padding) blockSize / 2 else 0\n    val data = random.nextBytes(dataSize)\n\n    val buffer = Buffer().apply { write(data) }\n    val cipherSource = buffer.cipherSource(cipherFactory.encrypt)\n    val actualEncryptedData = cipherSource.buffer().use { it.readByteArray() }\n\n    val expectedEncryptedData = cipherFactory.encrypt.doFinal(data)\n    assertArrayEquals(expectedEncryptedData, actualEncryptedData)\n  }\n\n  @Test\n  fun decrypt() {\n    val random = Random(8067587635762239433)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = random.nextBytes(32)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer().apply { write(encryptedData) }\n    val cipherSource = buffer.cipherSource(cipherFactory.decrypt)\n    val actualData = cipherSource.buffer().use { it.readByteArray() }\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  @Test\n  fun decryptEmpty() {\n    val random = Random(8722996896871347396)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = ByteArray(0)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer().apply { write(encryptedData) }\n    val cipherSource = buffer.cipherSource(cipherFactory.decrypt)\n    val actualData = cipherSource.buffer().use { it.readByteArray() }\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  @Test\n  fun decryptLarge() {\n    val random = Random(4007116131070653181)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = random.nextBytes(Segment.SIZE * 16 + Segment.SIZE / 2)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer().apply { write(encryptedData) }\n    val cipherSource = buffer.cipherSource(cipherFactory.decrypt)\n    val actualData = cipherSource.buffer().use { it.readByteArray() }\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  @Test\n  fun decryptSingleByteSource() {\n    val random = Random(1555017938547616655)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val expectedData = random.nextBytes(32)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer().apply { write(encryptedData) }\n    val cipherSource = buffer.emitSingleBytes().cipherSource(cipherFactory.decrypt)\n    val actualData = cipherSource.buffer().use {\n      it.readByteArray()\n    }\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  /** Only relevant for algorithms which handle padding. */\n  @Test\n  fun decryptPaddingRequired() {\n    val random = Random(5717921427007554469)\n    val cipherFactory = cipherAlgorithm.createCipherFactory(random)\n    val blockSize = cipherFactory.blockSize\n    val dataSize = blockSize * 4 + if (cipherAlgorithm.padding) blockSize / 2 else 0\n    val expectedData = random.nextBytes(dataSize)\n    val encryptedData = cipherFactory.encrypt.doFinal(expectedData)\n\n    val buffer = Buffer().apply { write(encryptedData) }\n    val cipherSource = buffer.cipherSource(cipherFactory.decrypt)\n    val actualData = cipherSource.buffer().use { it.readByteArray() }\n\n    assertArrayEquals(expectedData, actualData)\n  }\n\n  private fun Source.emitSingleBytes(): Source =\n    SingleByteSource(this)\n\n  private class SingleByteSource(source: Source) : ForwardingSource(source) {\n    override fun read(sink: Buffer, byteCount: Long): Long =\n      delegate.read(sink, 1L)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/DeflateKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport java.util.zip.Deflater\nimport java.util.zip.Inflater\nimport kotlin.test.assertEquals\nimport okio.ByteString.Companion.decodeHex\nimport org.junit.Test\n\nclass DeflateKotlinTest {\n  @Test fun deflate() {\n    val data = Buffer()\n    val deflater = (data as Sink).deflate()\n    deflater.buffer().writeUtf8(\"Hi!\").close()\n    assertEquals(\"789cf3c854040001ce00d3\", data.readByteString().hex())\n  }\n\n  @Test fun deflateWithDeflater() {\n    val data = Buffer()\n    val deflater = (data as Sink).deflate(Deflater(0, true))\n    deflater.buffer().writeUtf8(\"Hi!\").close()\n    assertEquals(\"010300fcff486921\", data.readByteString().hex())\n  }\n\n  @Test fun inflate() {\n    val buffer = Buffer().write(\"789cf3c854040001ce00d3\".decodeHex())\n    val inflated = (buffer as Source).inflate()\n    assertEquals(\"Hi!\", inflated.buffer().readUtf8())\n  }\n\n  @Test fun inflateWithInflater() {\n    val buffer = Buffer().write(\"010300fcff486921\".decodeHex())\n    val inflated = (buffer as Source).inflate(Inflater(true))\n    assertEquals(\"Hi!\", inflated.buffer().readUtf8())\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/DeflaterSinkTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport assertk.all\nimport assertk.assertFailure\nimport assertk.assertions.cause\nimport assertk.assertions.hasMessage\nimport assertk.assertions.isInstanceOf\nimport assertk.assertions.isNotNull\nimport java.util.zip.Deflater\nimport java.util.zip.Inflater\nimport java.util.zip.InflaterInputStream\nimport okio.TestUtil.SEGMENT_SIZE\nimport okio.TestUtil.randomBytes\nimport org.junit.Assert\nimport org.junit.Test\n\nclass DeflaterSinkTest {\n  @Test\n  fun deflateWithClose() {\n    val data = Buffer()\n    val original = \"They're moving in herds. They do move in herds.\"\n    data.writeUtf8(original)\n    val sink = Buffer()\n    val deflaterSink = DeflaterSink(sink, Deflater())\n    deflaterSink.write(data, data.size)\n    deflaterSink.close()\n    val inflated = inflate(sink)\n    Assert.assertEquals(original, inflated.readUtf8())\n  }\n\n  @Test\n  fun deflateWithSyncFlush() {\n    val original = \"Yes, yes, yes. That's why we're taking extreme precautions.\"\n    val data = Buffer()\n    data.writeUtf8(original)\n    val sink = Buffer()\n    val deflaterSink = DeflaterSink(sink, Deflater())\n    deflaterSink.write(data, data.size)\n    deflaterSink.flush()\n    val inflated = inflate(sink)\n    Assert.assertEquals(original, inflated.readUtf8())\n  }\n\n  @Test\n  fun deflateWellCompressed() {\n    val original = \"a\".repeat(1024 * 1024)\n    val data = Buffer()\n    data.writeUtf8(original)\n    val sink = Buffer()\n    val deflaterSink = DeflaterSink(sink, Deflater())\n    deflaterSink.write(data, data.size)\n    deflaterSink.close()\n    val inflated = inflate(sink)\n    Assert.assertEquals(original, inflated.readUtf8())\n  }\n\n  @Test\n  fun deflatePoorlyCompressed() {\n    val original = randomBytes(1024 * 1024)\n    val data = Buffer()\n    data.write(original)\n    val sink = Buffer()\n    val deflaterSink = DeflaterSink(sink, Deflater())\n    deflaterSink.write(data, data.size)\n    deflaterSink.close()\n    val inflated = inflate(sink)\n    Assert.assertEquals(original, inflated.readByteString())\n  }\n\n  @Test\n  fun multipleSegmentsWithoutCompression() {\n    val buffer = Buffer()\n    val deflater = Deflater()\n    deflater.setLevel(Deflater.NO_COMPRESSION)\n    val deflaterSink = DeflaterSink(buffer, deflater)\n    val byteCount = SEGMENT_SIZE * 4\n    deflaterSink.write(Buffer().writeUtf8(\"a\".repeat(byteCount)), byteCount.toLong())\n    deflaterSink.close()\n    Assert.assertEquals(\"a\".repeat(byteCount), inflate(buffer).readUtf8(byteCount.toLong()))\n  }\n\n  @Test\n  fun deflateIntoNonemptySink() {\n    val original = \"They're moving in herds. They do move in herds.\"\n\n    // Exercise all possible offsets for the outgoing segment.\n    for (i in 0 until SEGMENT_SIZE) {\n      val data = Buffer().writeUtf8(original)\n      val sink = Buffer().writeUtf8(\"a\".repeat(i))\n      val deflaterSink = DeflaterSink(sink, Deflater())\n      deflaterSink.write(data, data.size)\n      deflaterSink.close()\n      sink.skip(i.toLong())\n      val inflated = inflate(sink)\n      Assert.assertEquals(original, inflated.readUtf8())\n    }\n  }\n\n  /**\n   * This test deflates a single segment of without compression because that's\n   * the easiest way to force close() to emit a large amount of data to the\n   * underlying sink.\n   */\n  @Test\n  fun closeWithExceptionWhenWritingAndClosing() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(0, IOException(\"first\"))\n    mockSink.scheduleThrow(1, IOException(\"second\"))\n    val deflater = Deflater()\n    deflater.setLevel(Deflater.NO_COMPRESSION)\n    val deflaterSink = DeflaterSink(mockSink, deflater)\n    deflaterSink.write(Buffer().writeUtf8(\"a\".repeat(SEGMENT_SIZE)), SEGMENT_SIZE.toLong())\n    try {\n      deflaterSink.close()\n      Assert.fail()\n    } catch (expected: IOException) {\n      Assert.assertEquals(\"first\", expected.message)\n    }\n    mockSink.assertLogContains(\"close()\")\n  }\n\n  /**\n   * This test confirms that we swallow NullPointerException from Deflater and\n   * rethrow as an IOException.\n   */\n  @Test\n  fun rethrowNullPointerAsIOException() {\n    val deflater = Deflater()\n    // Close to cause an exception.\n    deflater.end()\n\n    val data = Buffer().apply {\n      writeUtf8(\"They're moving in herds. They do move in herds.\")\n    }\n    val deflaterSink = DeflaterSink(Buffer(), deflater)\n\n    assertFailure {\n      deflaterSink.write(data, data.size)\n    }.all {\n      isInstanceOf<IOException>()\n      hasMessage(\"Deflater already closed\")\n      cause().isNotNull()\n    }\n  }\n\n  /**\n   * Uses streaming decompression to inflate `deflated`. The input must\n   * either be finished or have a trailing sync flush.\n   */\n  private fun inflate(deflated: Buffer): Buffer {\n    val deflatedIn = deflated.inputStream()\n    val inflater = Inflater()\n    val inflatedIn = InflaterInputStream(deflatedIn, inflater)\n    val result = Buffer()\n    val buffer = ByteArray(8192)\n    while (!inflater.needsInput() || deflated.size > 0 || deflatedIn.available() > 0) {\n      val count = inflatedIn.read(buffer, 0, buffer.size)\n      if (count != -1) {\n        result.write(buffer, 0, count)\n      }\n    }\n    return result\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/FileHandleFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport com.google.common.jimfs.Configuration\nimport com.google.common.jimfs.Jimfs\nimport java.nio.file.FileSystems\nimport kotlin.time.Clock\nimport okio.FileHandleFileSystemTest.FileHandleTestingFileSystem\nimport okio.FileSystem.Companion.asOkioFileSystem\n\n/**\n * Run a regular file system test, but use [FileHandle] for more file system operations than usual.\n * This is intended to increase test coverage for [FileHandle].\n */\nclass FileHandleFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = FileHandleTestingFileSystem(FileSystem.SYSTEM),\n  windowsLimitations = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.DoesNothing,\n) {\n  /**\n   * A testing-only file system that implements all reading and writing operations with\n   * [FileHandle]. This is intended to increase test coverage for [FileHandle].\n   */\n  class FileHandleTestingFileSystem(delegate: FileSystem) : ForwardingFileSystem(delegate) {\n    override fun source(file: Path): Source {\n      val fileHandle = openReadOnly(file)\n      return fileHandle.source()\n        .also { fileHandle.close() }\n    }\n\n    override fun sink(file: Path, mustCreate: Boolean): Sink {\n      val fileHandle = openReadWrite(file, mustCreate = mustCreate, mustExist = false)\n      fileHandle.resize(0L) // If the file already has data, get rid of it.\n      return fileHandle.sink()\n        .also { fileHandle.close() }\n    }\n\n    override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n      val fileHandle = openReadWrite(file, mustCreate = false, mustExist = mustExist)\n      return fileHandle.appendingSink()\n        .also { fileHandle.close() }\n    }\n  }\n}\n\nclass FileHandleNioJimFileSystemWrapperFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = FileHandleTestingFileSystem(\n    Jimfs\n      .newFileSystem(\n        when (Path.DIRECTORY_SEPARATOR == \"\\\\\") {\n          true -> Configuration.windows()\n          false -> Configuration.unix()\n        },\n      ).asOkioFileSystem(),\n  ),\n  windowsLimitations = false,\n  allowClobberingEmptyDirectories = true,\n  allowAtomicMoveFromFileToDirectory = true,\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.Closes,\n)\n\nclass FileHandleNioDefaultFileSystemWrapperFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = FileHandleTestingFileSystem(\n    FileSystems.getDefault().asOkioFileSystem(),\n  ),\n  windowsLimitations = false,\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  allowRenameWhenTargetIsOpen = Path.DIRECTORY_SEPARATOR != \"\\\\\",\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.Unsupported,\n)\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/FileLeakTest.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc. and others.\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 */\npackage okio\n\nimport java.net.URLClassLoader\nimport java.nio.file.Path\nimport java.util.zip.ZipEntry\nimport java.util.zip.ZipOutputStream\nimport kotlin.io.path.ExperimentalPathApi\nimport kotlin.io.path.Path\nimport kotlin.io.path.exists\nimport kotlin.io.path.isDirectory\nimport kotlin.io.path.isSymbolicLink\nimport kotlin.io.path.readSymbolicLink\nimport kotlin.io.path.walk\nimport kotlin.test.assertEquals\nimport kotlin.test.assertNotNull\nimport kotlin.test.assertTrue\nimport okio.Path.Companion.toPath\nimport okio.fakefilesystem.FakeFileSystem\nimport okio.internal.ResourceFileSystem\nimport org.junit.After\nimport org.junit.Assume.assumeTrue\nimport org.junit.Before\nimport org.junit.Test\n\nprivate const val PROC_SELF_FD = \"/proc/self/fd\"\n\nclass FileLeakTest {\n\n  private lateinit var fakeFileSystem: FakeFileSystem\n  private val fakeZip = \"/test.zip\".toPath()\n  private val fakeEntry = \"some.file\".toPath()\n  private val fakeDirectory = \"/another/\".toPath()\n  private val fakeEntry2 = fakeDirectory / \"another.file\"\n\n  @Before\n  fun setup() {\n    fakeFileSystem = FakeFileSystem()\n    with(fakeFileSystem) {\n      write(fakeZip) {\n        writeZip {\n          putEntry(fakeEntry.name) {\n            writeUtf8(\"FooBar\")\n          }\n          try {\n            putNextEntry(ZipEntry(fakeDirectory.name).apply { time = 0L })\n          } finally {\n            closeEntry()\n          }\n          putEntry(fakeEntry2.toString()) {\n            writeUtf8(\"SomethingElse\")\n          }\n        }\n      }\n    }\n  }\n\n  @After\n  fun tearDown() {\n    fakeFileSystem.checkNoOpenFiles()\n  }\n\n  @Test\n  fun zipFileSystemExistsTest() {\n    val zipFileSystem = fakeFileSystem.openZip(fakeZip)\n    assertTrue(zipFileSystem.exists(fakeEntry))\n  }\n\n  @Test\n  fun zipFileSystemMetadataTest() {\n    val zipFileSystem = fakeFileSystem.openZip(fakeZip)\n    assertNotNull(zipFileSystem.metadataOrNull(fakeEntry))\n  }\n\n  @Test\n  fun zipFileSystemSourceTest() {\n    val zipFileSystem = fakeFileSystem.openZip(fakeZip)\n    zipFileSystem.source(fakeEntry).use { source ->\n      assertEquals(\"FooBar\", source.buffer().readUtf8())\n    }\n  }\n\n  @Test\n  fun zipFileSystemListRecursiveTest() {\n    val zipFileSystem = fakeFileSystem.openZip(fakeZip)\n    zipFileSystem.listRecursively(\"/\".toPath()).toList()\n    fakeFileSystem.delete(fakeZip)\n  }\n\n  @Test\n  fun fileLeakInResourceFileSystemTest() {\n    assumeTrue(\"File descriptor symbolic link available only on Linux\", Path(PROC_SELF_FD).exists())\n    // Create a test file that will be opened and cached by the classloader\n    val zipPath = ZipBuilder(FileSystem.SYSTEM_TEMPORARY_DIRECTORY / randomToken(16))\n      .addEntry(\"test.txt\", \"I'm part of a test!\")\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .build()\n\n    // Create a custom class loader\n    val urlClassLoader = URLClassLoader.newInstance(arrayOf(zipPath.toFile().toURI().toURL()))\n\n    // Create a resource file system using the given a custom class loader\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = urlClassLoader,\n      indexEagerly = false,\n    )\n\n    // Trigger the read of the classloader\n    resourceFileSystem.source(\"test.txt\".toPath()).use { it.buffer().readUtf8() }\n\n    // Classloader needs to be closed in order to close the file descriptor to the JAR file\n    urlClassLoader.close()\n\n    // Ensure the underlying URLConnection to the JAR file was not cached\n    zipPath.toNioPath().assetFileNotOpen()\n  }\n}\n\n/**\n * Writes a ZIP file to a [BufferedSink].\n */\nprivate inline fun <R> BufferedSink.writeZip(action: ZipOutputStream.() -> R): R {\n  return ZipOutputStream(outputStream()).use(action)\n}\n\n/**\n * Adds a new ZIP entry named [name], populates it with [action], and closes the entry.\n */\nprivate inline fun <R> ZipOutputStream.putEntry(name: String, action: BufferedSink.() -> R): R {\n  putNextEntry(ZipEntry(name).apply { time = 0L })\n  val sink = sink().buffer()\n  return try {\n    sink.action()\n  } finally {\n    sink.flush()\n    closeEntry()\n  }\n}\n\n// This is a Linux only test for open file descriptors on the current process\n@OptIn(ExperimentalPathApi::class)\nprivate fun Path.assetFileNotOpen() {\n  val fds = Path(PROC_SELF_FD)\n  if (fds.isDirectory()) {\n    // Linux: verify that path is not open\n    assertTrue(\"Resource remained opened: $this\") {\n      fds.walk()\n        .filter { it.isSymbolicLink() }\n        .map { it.readSymbolicLink() }\n        .none { it == this }\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/FileSystemJavaTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.containsExactly\nimport assertk.assertions.isEmpty\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isFalse\nimport assertk.assertions.isIn\nimport assertk.assertions.isNotNull\nimport assertk.assertions.isNull\nimport assertk.assertions.isTrue\nimport java.io.File\nimport java.nio.file.Paths\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.Path.Companion.toOkioPath\nimport okio.Path.Companion.toPath\nimport okio.fakefilesystem.FakeFileSystem\nimport org.junit.Test\n\nclass FileSystemJavaTest {\n  @Test\n  fun pathApi() {\n    val path = \"/home/jesse/todo.txt\".toPath(false)\n    assertThat(\"/home/jesse\".toPath(false).div(\"todo.txt\")).isEqualTo(path)\n    assertThat(\"/home/jesse/todo.txt\".toPath(false)).isEqualTo(path)\n    assertThat(path.isAbsolute).isTrue()\n    assertThat(path.isRelative).isFalse()\n    assertThat(path.isRoot).isFalse()\n    assertThat(path.name).isEqualTo(\"todo.txt\")\n    assertThat(path.nameBytes).isEqualTo(\"todo.txt\".encodeUtf8())\n    assertThat(path.parent).isEqualTo(\"/home/jesse\".toPath(false))\n    assertThat(path.volumeLetter).isNull()\n  }\n\n  @Test\n  fun directorySeparator() {\n    assertThat(Path.DIRECTORY_SEPARATOR).isIn(\"/\", \"\\\\\")\n  }\n\n  /** Like the same test in JvmTest, but this is using the Java APIs.  */\n  @Test\n  fun javaIoFileToOkioPath() {\n    val string = \"/foo/bar/baz\".replace(\"/\", Path.DIRECTORY_SEPARATOR)\n    val javaIoFile = File(string)\n    val okioPath: Path = string.toPath(false)\n    assertThat(javaIoFile.toOkioPath(false)).isEqualTo(okioPath)\n    assertThat(okioPath.toFile()).isEqualTo(javaIoFile)\n  }\n\n  /** Like the same test in JvmTest, but this is using the Java APIs.  */\n  @Test\n  fun nioPathToOkioPath() {\n    val string = \"/foo/bar/baz\".replace(\"/\", Path.DIRECTORY_SEPARATOR)\n    val nioPath = Paths.get(string)\n    val okioPath: Path = string.toPath(false)\n    assertThat(nioPath.toOkioPath(false)).isEqualTo(okioPath)\n    assertThat(okioPath.toNioPath() as Any).isEqualTo(nioPath)\n  }\n\n  // Just confirm these APIs exist; don't invoke them\n  @Suppress(\"unused\")\n  fun fileSystemApi() {\n    val fileSystem = FileSystem.SYSTEM\n    val pathA: Path = \"a.txt\".toPath()\n    val pathB: Path = \"b.txt\".toPath()\n    fileSystem.canonicalize(pathA)\n    fileSystem.metadata(pathA)\n    fileSystem.metadataOrNull(pathA)\n    fileSystem.exists(pathA)\n    fileSystem.list(pathA)\n    fileSystem.listOrNull(pathA)\n    fileSystem.listRecursively(pathA, false)\n    fileSystem.listRecursively(pathA)\n    fileSystem.openReadOnly(pathA)\n    fileSystem.openReadWrite(pathA, mustCreate = false, mustExist = false)\n    fileSystem.openReadWrite(pathA)\n    fileSystem.source(pathA)\n    // Note that FileSystem.read() isn't available to Java callers.\n    fileSystem.sink(pathA, false)\n    fileSystem.sink(pathA)\n    // Note that FileSystem.write() isn't available to Java callers.\n    fileSystem.appendingSink(pathA, false)\n    fileSystem.appendingSink(pathA)\n    fileSystem.createDirectory(pathA)\n    fileSystem.createDirectories(pathA)\n    fileSystem.atomicMove(pathA, pathB)\n    fileSystem.copy(pathA, pathB)\n    fileSystem.delete(pathA)\n    fileSystem.deleteRecursively(pathA)\n    fileSystem.createSymlink(pathA, pathB)\n  }\n\n  @Test\n  fun fakeFileSystemApi() {\n    val fakeFileSystem = FakeFileSystem()\n    assertThat(fakeFileSystem.clock).isNotNull()\n    assertThat(fakeFileSystem.allPaths).isEmpty()\n    assertThat(fakeFileSystem.openPaths).isEmpty()\n    fakeFileSystem.checkNoOpenFiles()\n  }\n\n  @Test\n  fun forwardingFileSystemApi() {\n    val fakeFileSystem = FakeFileSystem()\n    val log: MutableList<String> = ArrayList()\n    val forwardingFileSystem: ForwardingFileSystem = object : ForwardingFileSystem(fakeFileSystem) {\n      override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n        log.add(\"$functionName($parameterName=$path)\")\n        return path\n      }\n    }\n    forwardingFileSystem.metadataOrNull(\"/\".toPath(false))\n    assertThat(log).containsExactly(\"metadataOrNull(path=/)\")\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/FixedLengthSourceTest.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.hasMessage\nimport assertk.assertions.isEmpty\nimport assertk.assertions.isEqualTo\nimport kotlin.test.fail\nimport okio.internal.FixedLengthSource\nimport org.junit.Test\n\ninternal class FixedLengthSourceTest {\n  @Test\n  fun happyPathWithTruncate() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmnop\")\n    val fixedLengthSource = FixedLengthSource(delegate, 16, truncate = true)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(6L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"klmnop\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(-1L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"\")\n  }\n\n  @Test\n  fun happyPathNoTruncate() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmnop\")\n    val fixedLengthSource = FixedLengthSource(delegate, 16, truncate = false)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(6L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"klmnop\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(-1L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"\")\n  }\n\n  @Test\n  fun delegateTooLongWithTruncate() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmnopqr\")\n    val fixedLengthSource = FixedLengthSource(delegate, 16, truncate = true)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(6L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"klmnop\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(-1L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"\")\n  }\n\n  @Test\n  fun delegateTooLongWithTruncateFencepost() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmnop\")\n    val fixedLengthSource = FixedLengthSource(delegate, 10, truncate = true)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(-1L)\n    assertThat(buffer.readUtf8()).isEmpty()\n  }\n\n  @Test\n  fun delegateTooLongNoTruncate() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmnopqr\")\n    val fixedLengthSource = FixedLengthSource(delegate, 16, truncate = false)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 16 bytes but got 18\")\n      assertThat(buffer.readUtf8()).isEqualTo(\"klmnop\") // Doesn't produce too many bytes!\n    }\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 16 bytes but got 18\")\n      assertThat(buffer.readUtf8()).isEmpty() // Doesn't produce any bytes!\n    }\n  }\n\n  @Test\n  fun delegateTooLongNoTruncateFencepost() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmnop\")\n    val fixedLengthSource = FixedLengthSource(delegate, 10, truncate = false)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 10 bytes but got 16\")\n      assertThat(buffer.readUtf8()).isEmpty() // Doesn't produce too many bytes!\n    }\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 10 bytes but got 16\")\n      assertThat(buffer.readUtf8()).isEmpty() // Doesn't produce any bytes!\n    }\n  }\n\n  @Test\n  fun delegateTooShortWithTruncate() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmn\")\n    val fixedLengthSource = FixedLengthSource(delegate, 16, truncate = true)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(4L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"klmn\")\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 16 bytes but got 14\")\n    }\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 16 bytes but got 14\")\n    }\n  }\n\n  @Test\n  fun delegateTooShortNoTruncate() {\n    val delegate = Buffer().writeUtf8(\"abcdefghijklmn\")\n    val fixedLengthSource = FixedLengthSource(delegate, 16, truncate = false)\n    val buffer = Buffer()\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(10L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"abcdefghij\")\n    assertThat(fixedLengthSource.read(buffer, 10L)).isEqualTo(4L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"klmn\")\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 16 bytes but got 14\")\n    }\n    try {\n      fixedLengthSource.read(buffer, 10L)\n      fail()\n    } catch (e: IOException) {\n      assertThat(e).hasMessage(\"expected 16 bytes but got 14\")\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ForwardingTimeoutKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isNotEqualTo\nimport java.util.concurrent.TimeUnit\nimport org.junit.Test\n\nclass ForwardingTimeoutKotlinTest {\n  @Test fun getAndSetDelegate() {\n    val timeout1 = Timeout()\n    val timeout2 = Timeout()\n\n    val forwardingTimeout = ForwardingTimeout(timeout1)\n    forwardingTimeout.timeout(5, TimeUnit.SECONDS)\n    assertThat(timeout1.timeoutNanos()).isNotEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isEqualTo(0L)\n    forwardingTimeout.clearTimeout()\n    assertThat(timeout1.timeoutNanos()).isEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isEqualTo(0L)\n    assertThat(forwardingTimeout.delegate).isEqualTo(timeout1)\n\n    forwardingTimeout.delegate = timeout2\n    forwardingTimeout.timeout(5, TimeUnit.SECONDS)\n    assertThat(timeout1.timeoutNanos()).isEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isNotEqualTo(0L)\n    forwardingTimeout.clearTimeout()\n    assertThat(timeout1.timeoutNanos()).isEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isEqualTo(0L)\n    assertThat(forwardingTimeout.delegate).isEqualTo(timeout2)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ForwardingTimeoutTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isNotEqualTo\nimport java.util.concurrent.TimeUnit\nimport org.junit.Test\n\nclass ForwardingTimeoutTest {\n  @Test\n  fun getAndSetDelegate() {\n    val timeout1 = Timeout()\n    val timeout2 = Timeout()\n    val forwardingTimeout = ForwardingTimeout(timeout1)\n    forwardingTimeout.timeout(5, TimeUnit.SECONDS)\n    assertThat(timeout1.timeoutNanos()).isNotEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isEqualTo(0L)\n    forwardingTimeout.clearTimeout()\n    assertThat(timeout1.timeoutNanos()).isEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isEqualTo(0L)\n    assertThat(forwardingTimeout.delegate).isEqualTo(timeout1)\n    assertThat(forwardingTimeout.setDelegate(timeout2)).isEqualTo(forwardingTimeout)\n    forwardingTimeout.timeout(5, TimeUnit.SECONDS)\n    assertThat(timeout1.timeoutNanos()).isEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isNotEqualTo(0L)\n    forwardingTimeout.clearTimeout()\n    assertThat(timeout1.timeoutNanos()).isEqualTo(0L)\n    assertThat(timeout2.timeoutNanos()).isEqualTo(0L)\n    assertThat(forwardingTimeout.delegate).isEqualTo(timeout2)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/InflaterSourceTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport assertk.assertThat\nimport assertk.assertions.hasMessage\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isFalse\nimport assertk.assertions.isTrue\nimport java.io.EOFException\nimport java.util.zip.DeflaterOutputStream\nimport java.util.zip.Inflater\nimport okio.ByteString.Companion.decodeBase64\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.TestUtil.SEGMENT_SIZE\nimport okio.TestUtil.randomBytes\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.fail\nimport org.junit.Assume.assumeFalse\nimport org.junit.Test\n\n@Burst\nclass InflaterSourceTest(\n  private val bufferFactory: BufferedSourceFactory,\n) {\n  private lateinit var deflatedSink: BufferedSink\n  private lateinit var deflatedSource: BufferedSource\n\n  init {\n    resetDeflatedSourceAndSink()\n  }\n\n  private fun resetDeflatedSourceAndSink() {\n    val pipe = bufferFactory.pipe()\n    deflatedSink = pipe.sink\n    deflatedSource = pipe.source\n  }\n\n  @Test\n  fun inflate() {\n    decodeBase64(\"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\")\n    val inflated = inflate(deflatedSource)\n    assertEquals(\"God help us, we're in the hands of engineers.\", inflated.readUtf8())\n  }\n\n  @Test\n  fun inflateTruncated() {\n    decodeBase64(\"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CDw==\")\n    try {\n      inflate(deflatedSource)\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun inflateWellCompressed() {\n    decodeBase64(\n      \"eJztwTEBAAAAwqCs61/CEL5AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\" +\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8BtFeWvE=\",\n    )\n    val original = \"a\".repeat(1024 * 1024)\n    deflate(original.encodeUtf8())\n    val inflated = inflate(deflatedSource)\n    assertEquals(original, inflated.readUtf8())\n  }\n\n  @Test\n  fun inflatePoorlyCompressed() {\n    assumeFalse(bufferFactory.isOneByteAtATime) // 8 GiB for 1 byte per segment!\n    val original = randomBytes(1024 * 1024)\n    deflate(original)\n    val inflated = inflate(deflatedSource)\n    assertEquals(original, inflated.readByteString())\n  }\n\n  @Test\n  fun inflateIntoNonemptySink() {\n    for (i in 0 until SEGMENT_SIZE) {\n      resetDeflatedSourceAndSink()\n      val inflated = Buffer().writeUtf8(\"a\".repeat(i))\n      deflate(\"God help us, we're in the hands of engineers.\".encodeUtf8())\n      val source = InflaterSource(deflatedSource, Inflater())\n      while (source.read(inflated, Int.MAX_VALUE.toLong()) != -1L) {\n      }\n      inflated.skip(i.toLong())\n      assertEquals(\"God help us, we're in the hands of engineers.\", inflated.readUtf8())\n    }\n  }\n\n  @Test\n  fun inflateSingleByte() {\n    val inflated = Buffer()\n    decodeBase64(\"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\")\n    val source = InflaterSource(deflatedSource, Inflater())\n    source.read(inflated, 1)\n    source.close()\n    assertEquals(\"G\", inflated.readUtf8())\n    assertEquals(0, inflated.size)\n  }\n\n  @Test\n  fun inflateByteCount() {\n    assumeFalse(bufferFactory.isOneByteAtATime) // This test assumes one step.\n    val inflated = Buffer()\n    decodeBase64(\"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\")\n    val source = InflaterSource(deflatedSource, Inflater())\n    source.read(inflated, 11)\n    source.close()\n    assertEquals(\"God help us\", inflated.readUtf8())\n    assertEquals(0, inflated.size)\n  }\n\n  @Test\n  fun sourceExhaustedPrematurelyOnRead() {\n    // Deflate 0 bytes of data that lacks the in-stream terminator.\n    decodeBase64(\"eJwAAAD//w==\")\n    val inflated = Buffer()\n    val inflater = Inflater()\n    val source = InflaterSource(deflatedSource, inflater)\n    assertThat(deflatedSource.exhausted()).isFalse()\n    try {\n      source.read(inflated, Long.MAX_VALUE)\n      fail()\n    } catch (expected: EOFException) {\n      assertThat(expected).hasMessage(\"source exhausted prematurely\")\n    }\n\n    // Despite the exception, the read() call made forward progress on the underlying stream!\n    assertThat(deflatedSource.exhausted()).isTrue()\n  }\n\n  /**\n   * Confirm that [InflaterSource.readOrInflate] consumes a byte on each call even if it\n   * doesn't produce a byte on every call.\n   */\n  @Test\n  fun readOrInflateMakesByteByByteProgress() {\n    // Deflate 0 bytes of data that lacks the in-stream terminator.\n    decodeBase64(\"eJwAAAD//w==\")\n    val deflatedByteCount = 7\n    val inflated = Buffer()\n    val inflater = Inflater()\n    val source = InflaterSource(deflatedSource, inflater)\n    assertThat(deflatedSource.exhausted()).isFalse()\n    if (bufferFactory.isOneByteAtATime) {\n      for (i in 0 until deflatedByteCount) {\n        assertThat(inflater.bytesRead).isEqualTo(i.toLong())\n        assertThat(source.readOrInflate(inflated, Long.MAX_VALUE)).isEqualTo(0L)\n      }\n    } else {\n      assertThat(source.readOrInflate(inflated, Long.MAX_VALUE)).isEqualTo(0L)\n    }\n    assertThat(inflater.bytesRead).isEqualTo(deflatedByteCount.toLong())\n    assertThat(deflatedSource.exhausted()).isTrue()\n  }\n\n  private fun decodeBase64(s: String) {\n    deflatedSink.write(s.decodeBase64()!!)\n    deflatedSink.flush()\n  }\n\n  /** Use DeflaterOutputStream to deflate source.  */\n  private fun deflate(source: ByteString) {\n    val sink = DeflaterOutputStream(deflatedSink.outputStream()).sink()\n    sink.write(Buffer().write(source), source.size.toLong())\n    sink.close()\n  }\n\n  /** Returns a new buffer containing the inflated contents of `deflated`.  */\n  private fun inflate(deflated: BufferedSource?): Buffer {\n    val result = Buffer()\n    val source = InflaterSource(deflated!!, Inflater())\n    while (source.read(result, Int.MAX_VALUE.toLong()) != -1L) {\n    }\n    return result\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/JimfsOkioRoundTripTest.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport com.google.common.jimfs.Configuration\nimport com.google.common.jimfs.Jimfs\nimport java.nio.file.StandardOpenOption\nimport kotlin.io.path.readText\nimport kotlin.io.path.writeText\nimport kotlin.test.assertEquals\nimport okio.FileSystem.Companion.asOkioFileSystem\nimport org.junit.Test\n\nclass JimfsOkioRoundTripTest {\n  private val temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY\n  private val jimFs = Jimfs.newFileSystem(\n    when (Path.DIRECTORY_SEPARATOR == \"\\\\\") {\n      true -> Configuration.windows()\n      false -> Configuration.unix()\n    }.toBuilder()\n      .setWorkingDirectory(temporaryDirectory.toString())\n      .build(),\n  )\n  private val jimFsRoot = jimFs.rootDirectories.first()\n  private val okioFs = jimFs.asOkioFileSystem()\n\n  @InterceptTest\n  private val baseTestDirectory = TestDirectory(okioFs, temporaryDirectory)\n  private val base: Path get() = baseTestDirectory.path\n\n  @Test\n  fun writeOkioReadJim() {\n    val path = base / \"file-handle-write-okio-and-read-jim\"\n\n    okioFs.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n\n    assertEquals(\"abcdefghijklmnop\", jimFsRoot.resolve(path.toString()).readText(Charsets.UTF_8))\n  }\n\n  @Test\n  fun writeJimReadOkio() {\n    val path = base / \"file-handle-write-jim-and-read-okio\"\n    jimFsRoot.resolve(path.toString()).writeText(\"abcdefghijklmnop\", Charsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.WRITE)\n\n    okioFs.openReadWrite(path).use { handle ->\n      handle.source().buffer().use { source ->\n        assertEquals(\"abcde\", source.readUtf8(5))\n        assertEquals(\"fghijklmnop\", source.readUtf8())\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/JvmSystemFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport com.google.common.jimfs.Configuration\nimport com.google.common.jimfs.Jimfs\nimport java.io.InterruptedIOException\nimport java.nio.file.FileSystems\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.fail\nimport kotlin.time.Clock\nimport okio.FileSystem.Companion.asOkioFileSystem\nimport org.junit.Test\n\n/**\n * This test will run using [NioSystemFileSystem] by default. If [java.nio.file.Files] is not found\n * on the classpath, [JvmSystemFileSystem] will be use instead.\n */\nclass NioSystemFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = FileSystem.SYSTEM,\n  windowsLimitations = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.DoesNothing,\n)\n\nclass JvmSystemFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = JvmSystemFileSystem(),\n  windowsLimitations = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.DoesNothing,\n) {\n\n  @Test fun checkInterruptedBeforeDeleting() {\n    Thread.currentThread().interrupt()\n    try {\n      fileSystem.delete(base)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"interrupted\", expected.message)\n      assertFalse(Thread.interrupted())\n    }\n  }\n}\n\nclass NioJimFileSystemWrappingFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = Jimfs\n    .newFileSystem(\n      when (Path.DIRECTORY_SEPARATOR == \"\\\\\") {\n        true -> Configuration.windows()\n        false -> Configuration.unix()\n      },\n    ).asOkioFileSystem(),\n  windowsLimitations = false,\n  allowClobberingEmptyDirectories = true,\n  allowAtomicMoveFromFileToDirectory = true,\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.Closes,\n)\n\nclass NioDefaultFileSystemWrappingFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = FileSystems.getDefault().asOkioFileSystem(),\n  windowsLimitations = false,\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  allowRenameWhenTargetIsOpen = Path.DIRECTORY_SEPARATOR != \"\\\\\",\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.Unsupported,\n)\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/JvmTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport java.io.File\nimport java.nio.file.Paths\nimport kotlin.test.Test\nimport okio.Path.Companion.toOkioPath\nimport okio.Path.Companion.toPath\n\nclass JvmTest {\n  @Test\n  fun baseDirectoryConsistentWithJavaIoFile() {\n    assertThat(FileSystem.SYSTEM.canonicalize(\".\".toPath()).toString())\n      .isEqualTo(File(\"\").canonicalFile.toString())\n  }\n\n  @Test\n  fun javaIoFileToOkioPath() {\n    val string = \"/foo/bar/baz\".replace(\"/\", Path.DIRECTORY_SEPARATOR)\n    val javaIoFile = File(string)\n    val okioPath = string.toPath()\n    assertThat(javaIoFile.toOkioPath()).isEqualTo(okioPath)\n    assertThat(okioPath.toFile()).isEqualTo(javaIoFile)\n  }\n\n  @Test\n  fun nioPathToOkioPath() {\n    val string = \"/foo/bar/baz\".replace(\"/\", Path.DIRECTORY_SEPARATOR)\n    val nioPath = Paths.get(string)\n    val okioPath = string.toPath()\n    assertThat(nioPath.toOkioPath()).isEqualTo(okioPath)\n    assertThat(okioPath.toNioPath() as Any).isEqualTo(nioPath)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/JvmTesting.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport java.util.TimeZone\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport okio.Path.Companion.toOkioPath\nimport okio.Path.Companion.toPath\n\nactual fun assertRelativeTo(\n  a: Path,\n  b: Path,\n  bRelativeToA: Path,\n  sameAsNio: Boolean,\n) {\n  val actual = b.relativeTo(a)\n  assertEquals(bRelativeToA, actual)\n  assertEquals(b.normalized().withUnixSlashes(), (a / actual).normalized().withUnixSlashes())\n  // Also confirm our behavior is consistent with java.nio.\n  if (sameAsNio) {\n    // On Windows, java.nio will modify slashes to backslashes for relative paths, so we force it.\n    val nioPath = a.toNioPath().relativize(b.toNioPath())\n      .toOkioPath(normalize = true).withUnixSlashes().toPath()\n    assertEquals(bRelativeToA, nioPath)\n  }\n}\n\nactual fun assertRelativeToFails(\n  a: Path,\n  b: Path,\n  sameAsNio: Boolean,\n): IllegalArgumentException {\n  // Check java.nio first.\n  if (sameAsNio) {\n    assertFailsWith<IllegalArgumentException> {\n      a.toNioPath().relativize(b.toNioPath())\n    }\n  }\n  // Return okio.\n  return assertFailsWith { b.relativeTo(a) }\n}\n\nactual fun <T> withUtc(block: () -> T): T {\n  val original = TimeZone.getDefault()\n  TimeZone.setDefault(TimeZone.getTimeZone(\"UTC\"))\n  try {\n    return block()\n  } finally {\n    TimeZone.setDefault(original)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/LargeStreamsTest.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport java.util.concurrent.Executors\nimport java.util.concurrent.Future\nimport java.util.zip.Deflater\nimport java.util.zip.GZIPInputStream\nimport java.util.zip.GZIPOutputStream\nimport okio.ByteString.Companion.decodeHex\nimport okio.HashingSink.Companion.sha256\nimport okio.TestUtil.SEGMENT_SIZE\nimport okio.TestUtil.randomSource\nimport org.junit.Assert.assertEquals\nimport org.junit.Test\n\n/** Slow running tests that run a large amount of data through a stream.  */\nclass LargeStreamsTest {\n  @Test\n  fun test() {\n    val pipe = Pipe((1024 * 1024).toLong())\n    val future = readAllAndCloseAsync(randomSource(FOUR_GIB_PLUS_ONE), pipe.sink)\n    val hashingSink = sha256(blackholeSink())\n    readAllAndClose(pipe.source, hashingSink)\n    assertEquals(FOUR_GIB_PLUS_ONE, future.get() as Long)\n    assertEquals(SHA256_RANDOM_FOUR_GIB_PLUS_1, hashingSink.hash)\n  }\n\n  /** Note that this test hangs on Android.  */\n  @Test\n  fun gzipSource() {\n    val pipe = Pipe(1024L * 1024)\n    val gzipOut = object : GZIPOutputStream(pipe.sink.buffer().outputStream()) {\n      init {\n        // Disable compression to speed up a slow test. Improved from 141s to 33s on one machine.\n        def.setLevel(Deflater.NO_COMPRESSION)\n      }\n    }\n    val future = readAllAndCloseAsync(\n      randomSource(FOUR_GIB_PLUS_ONE),\n      gzipOut.sink(),\n    )\n    val hashingSink = sha256(blackholeSink())\n    val gzipSource = GzipSource(pipe.source)\n    readAllAndClose(gzipSource, hashingSink)\n    assertEquals(FOUR_GIB_PLUS_ONE, future.get() as Long)\n    assertEquals(SHA256_RANDOM_FOUR_GIB_PLUS_1, hashingSink.hash)\n  }\n\n  /** Note that this test hangs on Android.  */\n  @Test\n  fun gzipSink() {\n    val pipe = Pipe(1024L * 1024)\n    val gzipSink = GzipSink(pipe.sink)\n\n    // Disable compression to speed up a slow test. Improved from 141s to 35s on one machine.\n    gzipSink.deflater.setLevel(Deflater.NO_COMPRESSION)\n    val future = readAllAndCloseAsync(randomSource(FOUR_GIB_PLUS_ONE), gzipSink)\n    val hashingSink = sha256(blackholeSink())\n    val gzipIn = GZIPInputStream(pipe.source.buffer().inputStream())\n    readAllAndClose(gzipIn.source(), hashingSink)\n    assertEquals(FOUR_GIB_PLUS_ONE, future.get() as Long)\n    assertEquals(SHA256_RANDOM_FOUR_GIB_PLUS_1, hashingSink.hash)\n  }\n\n  /** Reads all bytes from `source` and writes them to `sink`.  */\n  private fun readAllAndClose(source: Source, sink: Sink): Long {\n    var result = 0L\n    val buffer = Buffer()\n    while (true) {\n      val count = source.read(buffer, SEGMENT_SIZE.toLong())\n      if (count == -1L) break\n      sink.write(buffer, count)\n      result += count\n    }\n    source.close()\n    sink.close()\n    return result\n  }\n\n  /** Calls [readAllAndClose] on a background thread.  */\n  private fun readAllAndCloseAsync(source: Source, sink: Sink): Future<Long> {\n    val executor = Executors.newScheduledThreadPool(0)\n    return try {\n      executor.submit<Long> { readAllAndClose(source, sink) }\n    } finally {\n      executor.shutdown()\n    }\n  }\n\n  companion object {\n    /** 4 GiB plus 1 byte. This is greater than what can be expressed in an unsigned int.  */\n    const val FOUR_GIB_PLUS_ONE = 0x100000001L\n\n    /** SHA-256 of `TestUtil.randomSource(FOUR_GIB_PLUS_ONE)`.  */\n    val SHA256_RANDOM_FOUR_GIB_PLUS_1 =\n      \"9654947a655c5efc445502fd1bf11117d894b7812b7974fde8ca4a02c5066315\".decodeHex()\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/MessageDigestConsistencyTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport java.security.MessageDigest\nimport java.util.Random\nimport kotlin.test.Test\nimport okio.ByteString.Companion.toByteString\nimport okio.internal.HashFunction\nimport okio.internal.Md5\nimport okio.internal.Sha1\nimport okio.internal.Sha256\nimport okio.internal.Sha512\n\n/**\n * Confirm Okio is consistent with the JDK's MessageDigest algorithms for various sizes and slices.\n * This makes repeated calls to update() with byte arrays of various sizes and contents to defend\n * against bugs in batching inputs.\n */\nclass MessageDigestConsistencyTest {\n  @Test fun sha1() {\n    test(\"SHA-1\") { Sha1() }\n  }\n\n  @Test fun sha256() {\n    test(\"SHA-256\") { Sha256() }\n  }\n\n  @Test fun sha512() {\n    test(\"SHA-512\") { Sha512() }\n  }\n\n  @Test fun md5() {\n    test(\"MD5\") { Md5() }\n  }\n\n  private fun test(algorithm: String, newHashFunction: () -> HashFunction) {\n    for (seed in 0L until 1000L) {\n      for (updateCount in 0 until 10) {\n        test(\n          algorithm = algorithm,\n          hashFunction = newHashFunction(),\n          seed = seed,\n          updateCount = updateCount,\n        )\n      }\n    }\n  }\n\n  private fun test(\n    algorithm: String,\n    hashFunction: HashFunction,\n    seed: Long,\n    updateCount: Int,\n  ) {\n    val data = Buffer()\n\n    val random = Random(seed)\n    for (i in 0 until updateCount) {\n      val size = random.nextInt(1000) + 1 // size must be >= 1.\n      val byteArray = ByteArray(size).also { random.nextBytes(it) }\n      val offset = random.nextInt(size)\n      val byteCount = random.nextInt(size - offset)\n\n      hashFunction.update(\n        input = byteArray,\n        offset = offset,\n        byteCount = byteCount,\n      )\n\n      data.write(\n        source = byteArray,\n        offset = offset,\n        byteCount = byteCount,\n      )\n    }\n\n    val okioHash = hashFunction.digest()\n\n    val byteArray = data.readByteArray()\n    val jdkMessageDigest = MessageDigest.getInstance(algorithm)\n    val jdkHash = jdkMessageDigest.digest(byteArray)\n\n    assertThat(okioHash.toByteString()).isEqualTo(jdkHash.toByteString())\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/NioTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport java.nio.ByteBuffer\nimport java.nio.channels.FileChannel\nimport java.nio.channels.ReadableByteChannel\nimport java.nio.channels.WritableByteChannel\nimport java.nio.file.StandardOpenOption\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\nimport kotlin.text.Charsets.UTF_8\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\n\n/** Test interop between our beloved Okio and java.nio.  */\nclass NioTest {\n  @JvmField @Rule\n  var temporaryFolder = TemporaryFolder()\n\n  @Test\n  fun sourceIsOpen() {\n    val source = (Buffer() as Source).buffer()\n    assertTrue(source.isOpen())\n    source.close()\n    assertFalse(source.isOpen())\n  }\n\n  @Test\n  fun sinkIsOpen() {\n    val sink = (Buffer() as Sink).buffer()\n    assertTrue(sink.isOpen)\n    sink.close()\n    assertFalse(sink.isOpen)\n  }\n\n  @Test\n  fun writableChannelNioFile() {\n    val file = temporaryFolder.newFile()\n    val fileChannel = FileChannel.open(file.toPath(), StandardOpenOption.WRITE)\n    testWritableByteChannel(fileChannel)\n    val emitted = file.source().buffer()\n    assertEquals(\"defghijklmnopqrstuvw\", emitted.readUtf8())\n    emitted.close()\n  }\n\n  @Test\n  fun writableChannelBuffer() {\n    val buffer = Buffer()\n    testWritableByteChannel(buffer)\n    assertEquals(\"defghijklmnopqrstuvw\", buffer.readUtf8())\n  }\n\n  @Test\n  fun writableChannelBufferedSink() {\n    val buffer = Buffer()\n    val bufferedSink = (buffer as Sink).buffer()\n    testWritableByteChannel(bufferedSink)\n    assertEquals(\"defghijklmnopqrstuvw\", buffer.readUtf8())\n  }\n\n  @Test\n  fun readableChannelNioFile() {\n    val file = temporaryFolder.newFile()\n    val initialData = file.sink().buffer()\n    initialData.writeUtf8(\"abcdefghijklmnopqrstuvwxyz\")\n    initialData.close()\n    val fileChannel = FileChannel.open(file.toPath(), StandardOpenOption.READ)\n    testReadableByteChannel(fileChannel)\n  }\n\n  @Test\n  fun readableChannelBuffer() {\n    val buffer = Buffer()\n    buffer.writeUtf8(\"abcdefghijklmnopqrstuvwxyz\")\n    testReadableByteChannel(buffer)\n  }\n\n  @Test\n  fun readableChannelBufferedSource() {\n    val buffer = Buffer()\n    val bufferedSource = (buffer as Source).buffer()\n    buffer.writeUtf8(\"abcdefghijklmnopqrstuvwxyz\")\n    testReadableByteChannel(bufferedSource)\n  }\n\n  /**\n   * Does some basic writes to `channel`. We execute this against both Okio's channels and\n   * also a standard implementation from the JDK to confirm that their behavior is consistent.\n   */\n  private fun testWritableByteChannel(channel: WritableByteChannel) {\n    assertTrue(channel.isOpen)\n    val byteBuffer = ByteBuffer.allocate(1024)\n    byteBuffer.put(\"abcdefghijklmnopqrstuvwxyz\".toByteArray(UTF_8))\n    (byteBuffer as java.nio.Buffer).flip() // Cast necessary for Java 8.\n    (byteBuffer as java.nio.Buffer).position(3) // Cast necessary for Java 8.\n    (byteBuffer as java.nio.Buffer).limit(23) // Cast necessary for Java 8.\n    val byteCount = channel.write(byteBuffer)\n    assertEquals(20, byteCount)\n    assertEquals(23, byteBuffer.position())\n    assertEquals(23, byteBuffer.limit())\n    channel.close()\n    assertEquals(channel is Buffer, channel.isOpen) // Buffer.close() does nothing.\n  }\n\n  /**\n   * Does some basic reads from `channel`. We execute this against both Okio's channels and\n   * also a standard implementation from the JDK to confirm that their behavior is consistent.\n   */\n  private fun testReadableByteChannel(channel: ReadableByteChannel) {\n    assertTrue(channel.isOpen)\n    val byteBuffer = ByteBuffer.allocate(1024)\n    (byteBuffer as java.nio.Buffer).position(3) // Cast necessary for Java 8.\n    (byteBuffer as java.nio.Buffer).limit(23) // Cast necessary for Java 8.\n    val byteCount = channel.read(byteBuffer)\n    assertEquals(20, byteCount)\n    assertEquals(23, byteBuffer.position())\n    assertEquals(23, byteBuffer.limit())\n    channel.close()\n    assertEquals(channel is Buffer, channel.isOpen) // Buffer.close() does nothing.\n    (byteBuffer as java.nio.Buffer).flip() // Cast necessary for Java 8.\n    (byteBuffer as java.nio.Buffer).position(3) // Cast necessary for Java 8.\n    val data = ByteArray(byteBuffer.remaining())\n    byteBuffer[data]\n    assertEquals(\"abcdefghijklmnopqrst\", String(data, UTF_8))\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/OkioKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport java.io.ByteArrayInputStream\nimport java.io.ByteArrayOutputStream\nimport java.io.File\nimport java.net.Socket\nimport java.nio.file.StandardOpenOption\nimport java.nio.file.StandardOpenOption.APPEND\nimport org.junit.Ignore\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\n\nclass OkioKotlinTest {\n  @get:Rule val temp = TemporaryFolder()\n\n  @Test fun outputStreamSink() {\n    val baos = ByteArrayOutputStream()\n    val sink = baos.sink()\n    sink.write(Buffer().writeUtf8(\"a\"), 1L)\n    assertThat(baos.toByteArray()).isEqualTo(byteArrayOf(0x61))\n  }\n\n  @Test fun inputStreamSource() {\n    val bais = ByteArrayInputStream(byteArrayOf(0x61))\n    val source = bais.source()\n    val buffer = Buffer()\n    source.read(buffer, 1)\n    assertThat(buffer.readUtf8()).isEqualTo(\"a\")\n  }\n\n  @Test fun fileSink() {\n    val file = temp.newFile()\n    val sink = file.sink()\n    sink.write(Buffer().writeUtf8(\"a\"), 1L)\n    assertThat(file.readText()).isEqualTo(\"a\")\n  }\n\n  @Test fun fileAppendingSink() {\n    val file = temp.newFile()\n    file.writeText(\"a\")\n    val sink = file.sink(append = true)\n    sink.write(Buffer().writeUtf8(\"b\"), 1L)\n    sink.close()\n    assertThat(file.readText()).isEqualTo(\"ab\")\n  }\n\n  @Test fun fileSource() {\n    val file = temp.newFile()\n    file.writeText(\"a\")\n    val source = file.source()\n    val buffer = Buffer()\n    source.read(buffer, 1L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"a\")\n  }\n\n  @Test fun pathSink() {\n    val file = temp.newFile()\n    val sink = file.toPath().sink()\n    sink.write(Buffer().writeUtf8(\"a\"), 1L)\n    assertThat(file.readText()).isEqualTo(\"a\")\n  }\n\n  @Test fun pathSinkWithOptions() {\n    val file = temp.newFile()\n    file.writeText(\"a\")\n    val sink = file.toPath().sink(APPEND)\n    sink.write(Buffer().writeUtf8(\"b\"), 1L)\n    assertThat(file.readText()).isEqualTo(\"ab\")\n  }\n\n  @Test fun pathSource() {\n    val file = temp.newFile()\n    file.writeText(\"a\")\n    val source = file.toPath().source()\n    val buffer = Buffer()\n    source.read(buffer, 1L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"a\")\n  }\n\n  @Ignore(\"Not sure how to test this\")\n  @Test\n  fun pathSourceWithOptions() {\n    val folder = temp.newFolder()\n    val file = File(folder, \"new.txt\")\n    file.toPath().source(StandardOpenOption.CREATE_NEW)\n    // This still throws NoSuchFileException...\n  }\n\n  @Test fun socketSink() {\n    val baos = ByteArrayOutputStream()\n    val socket = object : Socket() {\n      override fun getOutputStream() = baos\n    }\n    val sink = socket.sink()\n    sink.write(Buffer().writeUtf8(\"a\"), 1L)\n    assertThat(baos.toByteArray()).isEqualTo(byteArrayOf(0x61))\n  }\n\n  @Test fun socketSource() {\n    val bais = ByteArrayInputStream(byteArrayOf(0x61))\n    val socket = object : Socket() {\n      override fun getInputStream() = bais\n    }\n    val source = socket.source()\n    val buffer = Buffer()\n    source.read(buffer, 1L)\n    assertThat(buffer.readUtf8()).isEqualTo(\"a\")\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/OkioTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.ByteArrayInputStream\nimport java.io.ByteArrayOutputStream\nimport java.nio.file.Files\nimport kotlin.text.Charsets.UTF_8\nimport okio.TestUtil.SEGMENT_SIZE\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\n\nclass OkioTest {\n  @JvmField\n  @Rule\n  var temporaryFolder = TemporaryFolder()\n\n  @Test\n  fun readWriteFile() {\n    val file = temporaryFolder.newFile()\n    val sink = file.sink().buffer()\n    sink.writeUtf8(\"Hello, java.io file!\")\n    sink.close()\n    assertTrue(file.exists())\n    assertEquals(20, file.length())\n    val source = file.source().buffer()\n    assertEquals(\"Hello, java.io file!\", source.readUtf8())\n    source.close()\n  }\n\n  @Test\n  fun appendFile() {\n    val file = temporaryFolder.newFile()\n    var sink = file.appendingSink().buffer()\n    sink.writeUtf8(\"Hello, \")\n    sink.close()\n    assertTrue(file.exists())\n    assertEquals(7, file.length())\n    sink = file.appendingSink().buffer()\n    sink.writeUtf8(\"java.io file!\")\n    sink.close()\n    assertEquals(20, file.length())\n    val source = file.source().buffer()\n    assertEquals(\"Hello, java.io file!\", source.readUtf8())\n    source.close()\n  }\n\n  @Test\n  fun readWritePath() {\n    val path = temporaryFolder.newFile().toPath()\n    val sink = path.sink().buffer()\n    sink.writeUtf8(\"Hello, java.nio file!\")\n    sink.close()\n    assertTrue(Files.exists(path))\n    assertEquals(21, Files.size(path))\n    val source = path.source().buffer()\n    assertEquals(\"Hello, java.nio file!\", source.readUtf8())\n    source.close()\n  }\n\n  @Test\n  fun sinkFromOutputStream() {\n    val data = Buffer()\n    data.writeUtf8(\"a\")\n    data.writeUtf8(\"b\".repeat(9998))\n    data.writeUtf8(\"c\")\n    val out = ByteArrayOutputStream()\n    val sink = out.sink()\n    sink.write(data, 3)\n    assertEquals(\"abb\", out.toString(\"UTF-8\"))\n    sink.write(data, data.size)\n    assertEquals(\"a\" + \"b\".repeat(9998) + \"c\", out.toString(\"UTF-8\"))\n  }\n\n  @Test\n  fun sourceFromInputStream() {\n    val inputStream = ByteArrayInputStream(\n      (\"a\" + \"b\".repeat(SEGMENT_SIZE * 2) + \"c\").toByteArray(UTF_8),\n    )\n\n    // Source: ab...bc\n    val source = inputStream.source()\n    val sink = Buffer()\n\n    // Source: b...bc. Sink: abb.\n    assertEquals(3, source.read(sink, 3))\n    assertEquals(\"abb\", sink.readUtf8(3))\n\n    // Source: b...bc. Sink: b...b.\n    assertEquals(SEGMENT_SIZE.toLong(), source.read(sink, 20000))\n    assertEquals(\"b\".repeat(SEGMENT_SIZE), sink.readUtf8())\n\n    // Source: b...bc. Sink: b...bc.\n    assertEquals((SEGMENT_SIZE - 1).toLong(), source.read(sink, 20000))\n    assertEquals(\"b\".repeat(SEGMENT_SIZE - 2) + \"c\", sink.readUtf8())\n\n    // Source and sink are empty.\n    assertEquals(-1, source.read(sink, 1))\n  }\n\n  @Test\n  fun sourceFromInputStreamWithSegmentSize() {\n    val inputStream = ByteArrayInputStream(ByteArray(SEGMENT_SIZE))\n    val source = inputStream.source()\n    val sink = Buffer()\n    assertEquals(SEGMENT_SIZE.toLong(), source.read(sink, SEGMENT_SIZE.toLong()))\n    assertEquals(-1, source.read(sink, SEGMENT_SIZE.toLong()))\n    assertNoEmptySegments(sink)\n  }\n\n  @Test\n  fun sourceFromInputStreamBounds() {\n    val source = ByteArrayInputStream(ByteArray(100)).source()\n    try {\n      source.read(Buffer(), -1)\n      fail()\n    } catch (expected: IllegalArgumentException) {\n    }\n  }\n\n  @Test\n  fun blackhole() {\n    val data = Buffer()\n    data.writeUtf8(\"blackhole\")\n    val blackhole = blackholeSink()\n    blackhole.write(data, 5)\n    assertEquals(\"hole\", data.readUtf8())\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/PipeKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport java.io.IOException\nimport java.util.concurrent.CountDownLatch\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.atomic.AtomicBoolean\nimport kotlin.test.assertFailsWith\nimport kotlin.time.Duration.Companion.milliseconds\nimport kotlin.time.Duration.Companion.nanoseconds\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.Timeout as JUnitTimeout\n\nclass PipeKotlinTest {\n  @JvmField @Rule\n  val timeout = JUnitTimeout(5, TimeUnit.SECONDS)\n\n  @InterceptTest\n  private val executorService = TestExecutor(1)\n\n  @Test fun pipe() {\n    val pipe = Pipe(6)\n    pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3L)\n\n    val readBuffer = Buffer()\n    assertEquals(3L, pipe.source.read(readBuffer, 6L))\n    assertEquals(\"abc\", readBuffer.readUtf8())\n\n    pipe.sink.close()\n    assertEquals(-1L, pipe.source.read(readBuffer, 6L))\n\n    pipe.source.close()\n  }\n\n  @Test fun fold() {\n    val pipe = Pipe(128)\n\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"hello\")\n    pipeSink.emit()\n\n    val pipeSource = pipe.source.buffer()\n    assertEquals(\"hello\", pipeSource.readUtf8(5))\n\n    val foldedSinkBuffer = Buffer()\n    var foldedSinkClosed = false\n    val foldedSink = object : ForwardingSink(foldedSinkBuffer) {\n      override fun close() {\n        foldedSinkClosed = true\n        super.close()\n      }\n    }\n    pipe.fold(foldedSink)\n\n    pipeSink.writeUtf8(\"world\")\n    pipeSink.emit()\n    assertEquals(\"world\", foldedSinkBuffer.readUtf8(5))\n\n    assertFailsWith<IllegalStateException> {\n      pipeSource.readUtf8()\n    }\n\n    pipeSink.close()\n    assertTrue(foldedSinkClosed)\n  }\n\n  @Test fun foldWritesPipeContentsToSink() {\n    val pipe = Pipe(128)\n\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"hello\")\n    pipeSink.emit()\n\n    val foldSink = Buffer()\n    pipe.fold(foldSink)\n\n    assertEquals(\"hello\", foldSink.readUtf8(5))\n  }\n\n  @Test fun foldUnblocksBlockedWrite() {\n    val pipe = Pipe(4)\n    val foldSink = Buffer()\n\n    val latch = CountDownLatch(1)\n    executorService.schedule(500.milliseconds) {\n      pipe.fold(foldSink)\n      latch.countDown()\n    }\n\n    val sink = pipe.sink.buffer()\n    sink.writeUtf8(\"abcdefgh\") // Blocks writing 8 bytes to a 4 byte pipe.\n    sink.close()\n\n    latch.await()\n    assertEquals(\"abcdefgh\", foldSink.readUtf8())\n  }\n\n  @Test fun accessSourceAfterFold() {\n    val pipe = Pipe(100L)\n    pipe.fold(Buffer())\n    assertFailsWith<IllegalStateException> {\n      pipe.source.read(Buffer(), 1L)\n    }\n  }\n\n  @Test fun closeWhileFolding() {\n    val pipe = Pipe(100L)\n    val writing = CountDownLatch(1)\n    val closed = CountDownLatch(1)\n    val sinkBuffer = Buffer()\n    val sinkClosed = AtomicBoolean()\n    val data = byteArrayOf(1, 2, 3, 4, 5, 6, 7, 8)\n    pipe.sink.write(Buffer().write(data), data.size.toLong())\n    val foldResult = executorService.submit {\n      val sink = object : Sink {\n        override fun write(source: Buffer, byteCount: Long) {\n          writing.countDown()\n          closed.await()\n          sinkBuffer.write(source, byteCount)\n        }\n\n        override fun flush() {\n          sinkBuffer.flush()\n        }\n\n        override fun timeout(): Timeout {\n          return sinkBuffer.timeout()\n        }\n\n        override fun close() {\n          sinkBuffer.close()\n          sinkClosed.set(true)\n        }\n      }\n      pipe.fold(sink)\n    }\n    writing.await()\n    pipe.sink.close()\n    closed.countDown()\n    foldResult.get()\n\n    assertTrue(sinkClosed.get())\n    assertArrayEquals(data, sinkBuffer.readByteArray())\n  }\n\n  @Test fun honorsPipeSinkTimeoutOnWritingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    underlying.timeout.timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n    pipe.sink.timeout().timeout(smallerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerTimeoutNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertEquals(biggerTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsUnderlyingTimeoutOnWritingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    underlying.timeout.timeout(smallerTimeoutNanos, TimeUnit.NANOSECONDS)\n    pipe.sink.timeout().timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerTimeoutNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertEquals(smallerTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsPipeSinkTimeoutOnFlushingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    underlying.timeout.timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n    pipe.sink.timeout().timeout(smallerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerTimeoutNanos) {\n      pipe.sink.flush()\n    }\n    assertEquals(biggerTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsUnderlyingTimeoutOnFlushingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    underlying.timeout.timeout(smallerTimeoutNanos, TimeUnit.NANOSECONDS)\n    pipe.sink.timeout().timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerTimeoutNanos) {\n      pipe.sink.flush()\n    }\n    assertEquals(smallerTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsPipeSinkTimeoutOnClosingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    underlying.timeout.timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n    pipe.sink.timeout().timeout(smallerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerTimeoutNanos) {\n      pipe.sink.close()\n    }\n    assertEquals(biggerTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsUnderlyingTimeoutOnClosingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    underlying.timeout.timeout(smallerTimeoutNanos, TimeUnit.NANOSECONDS)\n    pipe.sink.timeout().timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerTimeoutNanos) {\n      pipe.sink.close()\n    }\n    assertEquals(smallerTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsPipeSinkTimeoutOnWritingWhenUnderlyingSinkTimeoutIsZero() {\n    val pipeSinkTimeoutNanos = smallerTimeoutNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    pipe.sink.timeout().timeout(pipeSinkTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(pipeSinkTimeoutNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertEquals(0L, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsUnderlyingSinkTimeoutOnWritingWhenPipeSinkTimeoutIsZero() {\n    val underlyingSinkTimeoutNanos = smallerTimeoutNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    underlying.timeout().timeout(underlyingSinkTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(underlyingSinkTimeoutNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertEquals(underlyingSinkTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsPipeSinkTimeoutOnFlushingWhenUnderlyingSinkTimeoutIsZero() {\n    val pipeSinkTimeoutNanos = smallerTimeoutNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    pipe.sink.timeout().timeout(pipeSinkTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(pipeSinkTimeoutNanos) {\n      pipe.sink.flush()\n    }\n    assertEquals(0L, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsUnderlyingSinkTimeoutOnFlushingWhenPipeSinkTimeoutIsZero() {\n    val underlyingSinkTimeoutNanos = smallerTimeoutNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    underlying.timeout().timeout(underlyingSinkTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(underlyingSinkTimeoutNanos) {\n      pipe.sink.flush()\n    }\n    assertEquals(underlyingSinkTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsPipeSinkTimeoutOnClosingWhenUnderlyingSinkTimeoutIsZero() {\n    val pipeSinkTimeoutNanos = smallerTimeoutNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    pipe.sink.timeout().timeout(pipeSinkTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(pipeSinkTimeoutNanos) {\n      pipe.sink.close()\n    }\n    assertEquals(0L, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsUnderlyingSinkTimeoutOnClosingWhenPipeSinkTimeoutIsZero() {\n    val underlyingSinkTimeoutNanos = smallerTimeoutNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    underlying.timeout().timeout(underlyingSinkTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    pipe.fold(underlying)\n\n    assertDuration(underlyingSinkTimeoutNanos) {\n      pipe.sink.close()\n    }\n    assertEquals(underlyingSinkTimeoutNanos, underlying.timeout().timeoutNanos())\n  }\n\n  @Test fun honorsPipeSinkDeadlineOnWritingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + biggerDeadlineNanos\n    underlying.timeout.deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + smallerDeadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerDeadlineNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsPipeSinkDeadlineOnWritingWhenUnderlyingSinkHasNoDeadline() {\n    val deadlineNanos = smallerDeadlineNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    underlying.timeout.clearDeadline()\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + deadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(deadlineNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertFalse(underlying.timeout().hasDeadline())\n  }\n\n  @Test fun honorsUnderlyingSinkDeadlineOnWritingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + smallerDeadlineNanos\n    underlying.timeout.deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + biggerDeadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerDeadlineNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsUnderlyingSinkDeadlineOnWritingWhenPipeSinkHasNoDeadline() {\n    val deadlineNanos = smallerDeadlineNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutWritingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + deadlineNanos\n    underlying.timeout().deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().clearDeadline()\n\n    pipe.fold(underlying)\n\n    assertDuration(deadlineNanos) {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsPipeSinkDeadlineOnFlushingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + biggerDeadlineNanos\n    underlying.timeout.deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + smallerDeadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerDeadlineNanos) {\n      pipe.sink.flush()\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsPipeSinkDeadlineOnFlushingWhenUnderlyingSinkHasNoDeadline() {\n    val deadlineNanos = smallerDeadlineNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    underlying.timeout.clearDeadline()\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + deadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(deadlineNanos) {\n      pipe.sink.flush()\n    }\n    assertFalse(underlying.timeout().hasDeadline())\n  }\n\n  @Test fun honorsUnderlyingSinkDeadlineOnFlushingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + smallerDeadlineNanos\n    underlying.timeout.deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + biggerDeadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerDeadlineNanos) {\n      pipe.sink.flush()\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsUnderlyingSinkDeadlineOnFlushingWhenPipeSinkHasNoDeadline() {\n    val deadlineNanos = smallerDeadlineNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutFlushingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + deadlineNanos\n    underlying.timeout().deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().clearDeadline()\n\n    pipe.fold(underlying)\n\n    assertDuration(deadlineNanos) {\n      pipe.sink.flush()\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsPipeSinkDeadlineOnClosingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + biggerDeadlineNanos\n    underlying.timeout.deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + smallerDeadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerDeadlineNanos) {\n      pipe.sink.close()\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsPipeSinkDeadlineOnClosingWhenUnderlyingSinkHasNoDeadline() {\n    val deadlineNanos = smallerDeadlineNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    underlying.timeout.clearDeadline()\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + deadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(deadlineNanos) {\n      pipe.sink.close()\n    }\n    assertFalse(underlying.timeout().hasDeadline())\n  }\n\n  @Test fun honorsUnderlyingSinkDeadlineOnClosingWhenItIsSmaller() {\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + smallerDeadlineNanos\n    underlying.timeout.deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().deadlineNanoTime(System.nanoTime() + biggerDeadlineNanos)\n\n    pipe.fold(underlying)\n\n    assertDuration(smallerDeadlineNanos) {\n      pipe.sink.close()\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun honorsUnderlyingSinkDeadlineOnClosingWhenPipeSinkHasNoDeadline() {\n    val deadlineNanos = smallerDeadlineNanos\n\n    val pipe = Pipe(4)\n    val underlying = TimeoutClosingSink()\n\n    val underlyingOriginalDeadline = System.nanoTime() + deadlineNanos\n    underlying.timeout().deadlineNanoTime(underlyingOriginalDeadline)\n    pipe.sink.timeout().clearDeadline()\n\n    pipe.fold(underlying)\n\n    assertDuration(deadlineNanos) {\n      pipe.sink.close()\n    }\n    assertEquals(underlyingOriginalDeadline, underlying.timeout().deadlineNanoTime())\n  }\n\n  @Test fun foldingTwiceThrows() {\n    val pipe = Pipe(128)\n    pipe.fold(Buffer())\n    assertFailsWith<IllegalStateException> {\n      pipe.fold(Buffer())\n    }\n  }\n\n  @Test fun sinkWriteThrowsIOExceptionUnblockBlockedWriter() {\n    val pipe = Pipe(4)\n\n    val foldFuture = executorService.schedule(500.milliseconds) {\n      val foldFailure = assertFailsWith<IOException> {\n        pipe.fold(\n          object : ForwardingSink(blackholeSink()) {\n            override fun write(source: Buffer, byteCount: Long) {\n              throw IOException(\"boom\")\n            }\n          },\n        )\n      }\n      assertEquals(\"boom\", foldFailure.message)\n    }\n\n    val writeFailure = assertFailsWith<IOException> {\n      val pipeSink = pipe.sink.buffer()\n      pipeSink.writeUtf8(\"abcdefghij\")\n      pipeSink.emit() // Block writing 10 bytes to a 4 byte pipe.\n    }\n    assertEquals(\"source is closed\", writeFailure.message)\n\n    foldFuture.get() // Confirm no unexpected exceptions.\n  }\n\n  @Test fun foldHoldsNoLocksWhenForwardingWrites() {\n    val pipe = Pipe(4)\n\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"abcd\")\n    pipeSink.emit()\n\n    pipe.fold(object : ForwardingSink(blackholeSink()) {\n      override fun write(source: Buffer, byteCount: Long) {\n        assertFalse(Thread.holdsLock(pipe.buffer))\n      }\n    })\n  }\n\n  /**\n   * Flushing the pipe wasn't causing the sink to be flushed when it was later folded. This was\n   * causing problems because the folded data was stalled.\n   */\n  @Test fun foldFlushesWhenThereIsFoldedData() {\n    val pipe = Pipe(128)\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"hello\")\n    pipeSink.emit()\n\n    val ultimateSink = Buffer()\n    val unnecessaryWrapper = (ultimateSink as Sink).buffer()\n\n    pipe.fold(unnecessaryWrapper)\n\n    // Data should not have been flushed through the wrapper to the ultimate sink.\n    assertEquals(\"hello\", ultimateSink.readUtf8())\n  }\n\n  @Test fun foldDoesNotFlushWhenThereIsNoFoldedData() {\n    val pipe = Pipe(128)\n\n    val ultimateSink = Buffer()\n    val unnecessaryWrapper = (ultimateSink as Sink).buffer()\n    unnecessaryWrapper.writeUtf8(\"hello\")\n\n    pipe.fold(unnecessaryWrapper)\n\n    // Data should not have been flushed through the wrapper to the ultimate sink.\n    assertEquals(\"\", ultimateSink.readUtf8())\n  }\n\n  @Test fun foldingClosesUnderlyingSinkWhenPipeSinkIsClose() {\n    val pipe = Pipe(128)\n\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"world\")\n    pipeSink.close()\n\n    val foldedSinkBuffer = Buffer()\n    var foldedSinkClosed = false\n    val foldedSink = object : ForwardingSink(foldedSinkBuffer) {\n      override fun close() {\n        foldedSinkClosed = true\n        super.close()\n      }\n    }\n\n    pipe.fold(foldedSink)\n    assertEquals(\"world\", foldedSinkBuffer.readUtf8(5))\n    assertTrue(foldedSinkClosed)\n  }\n\n  @Test fun cancelPreventsSinkWrite() {\n    val pipe = Pipe(8)\n    pipe.cancel()\n\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"hello world\")\n\n    try {\n      pipeSink.emit()\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"canceled\", e.message)\n    }\n  }\n\n  @Test fun cancelPreventsSinkFlush() {\n    val pipe = Pipe(8)\n    pipe.cancel()\n\n    try {\n      pipe.sink.flush()\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"canceled\", e.message)\n    }\n  }\n\n  @Test fun sinkCloseAfterCancelDoesNotThrow() {\n    val pipe = Pipe(8)\n    pipe.cancel()\n    pipe.sink.close()\n  }\n\n  @Test fun cancelInterruptsSinkWrite() {\n    val pipe = Pipe(8)\n\n    executorService.schedule(smallerTimeoutNanos.nanoseconds) {\n      pipe.cancel()\n    }\n\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"hello world\")\n\n    assertDuration(smallerTimeoutNanos) {\n      try {\n        pipeSink.emit()\n        fail()\n      } catch (e: IOException) {\n        assertEquals(\"canceled\", e.message)\n      }\n    }\n  }\n\n  @Test fun cancelPreventsSourceRead() {\n    val pipe = Pipe(8)\n    pipe.cancel()\n\n    val pipeSource = pipe.source.buffer()\n\n    try {\n      pipeSource.require(1)\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"canceled\", e.message)\n    }\n  }\n\n  @Test fun sourceCloseAfterCancelDoesNotThrow() {\n    val pipe = Pipe(8)\n    pipe.cancel()\n    pipe.source.close()\n  }\n\n  @Test fun cancelInterruptsSourceRead() {\n    val pipe = Pipe(8)\n\n    executorService.schedule(smallerTimeoutNanos.nanoseconds) {\n      pipe.cancel()\n    }\n\n    val pipeSource = pipe.source.buffer()\n\n    assertDuration(smallerTimeoutNanos) {\n      try {\n        pipeSource.require(1)\n        fail()\n      } catch (e: IOException) {\n        assertEquals(\"canceled\", e.message)\n      }\n    }\n  }\n\n  @Test fun cancelPreventsSinkFold() {\n    val pipe = Pipe(8)\n    pipe.cancel()\n\n    var foldedSinkClosed = false\n    val foldedSink = object : ForwardingSink(Buffer()) {\n      override fun close() {\n        foldedSinkClosed = true\n        super.close()\n      }\n    }\n\n    try {\n      pipe.fold(foldedSink)\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"canceled\", e.message)\n    }\n\n    // But the fold is still performed so close() closes everything.\n    assertFalse(foldedSinkClosed)\n    pipe.sink.close()\n    assertTrue(foldedSinkClosed)\n  }\n\n  @Test fun cancelInterruptsSinkFold() {\n    val pipe = Pipe(128)\n    val pipeSink = pipe.sink.buffer()\n    pipeSink.writeUtf8(\"hello\")\n    pipeSink.emit()\n\n    var foldedSinkClosed = false\n    val foldedSink = object : ForwardingSink(Buffer()) {\n      override fun write(source: Buffer, byteCount: Long) {\n        assertEquals(\"hello\", source.readUtf8(byteCount))\n\n        // Write bytes to the original pipe so the pipe write doesn't complete!\n        pipeSink.writeUtf8(\"more bytes\")\n        pipeSink.emit()\n\n        // Cancel while the pipe is writing.\n        pipe.cancel()\n      }\n\n      override fun close() {\n        foldedSinkClosed = true\n        super.close()\n      }\n    }\n\n    try {\n      pipe.fold(foldedSink)\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"canceled\", e.message)\n    }\n\n    // But the fold is still performed so close() closes everything.\n    assertFalse(foldedSinkClosed)\n    pipe.sink.close()\n    assertTrue(foldedSinkClosed)\n  }\n\n  private fun assertDuration(expected: Long, block: () -> Unit) {\n    val start = System.currentTimeMillis()\n    block()\n    val elapsed = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis() - start)\n\n    assertEquals(\n      expected.toDouble(),\n      elapsed.toDouble(),\n      TimeUnit.MILLISECONDS.toNanos(200).toDouble(),\n    )\n  }\n\n  /** Writes on this sink never complete. They can only time out. */\n  class TimeoutWritingSink : Sink {\n    val timeout = object : AsyncTimeout() {\n      override fun timedOut() {\n        synchronized(this@TimeoutWritingSink) {\n          (this@TimeoutWritingSink as Object).notifyAll()\n        }\n      }\n    }\n\n    override fun write(source: Buffer, byteCount: Long) {\n      timeout.enter()\n      try {\n        synchronized(this) {\n          (this as Object).wait()\n        }\n      } finally {\n        timeout.exit()\n      }\n      source.skip(byteCount)\n    }\n\n    override fun flush() = Unit\n\n    override fun close() = Unit\n\n    override fun timeout() = timeout\n  }\n\n  /** Flushes on this sink never complete. They can only time out. */\n  class TimeoutFlushingSink : Sink {\n    val timeout = object : AsyncTimeout() {\n      override fun timedOut() {\n        synchronized(this@TimeoutFlushingSink) {\n          (this@TimeoutFlushingSink as Object).notifyAll()\n        }\n      }\n    }\n\n    override fun write(source: Buffer, byteCount: Long) = source.skip(byteCount)\n\n    override fun flush() {\n      timeout.enter()\n      try {\n        synchronized(this) {\n          (this as Object).wait()\n        }\n      } finally {\n        timeout.exit()\n      }\n    }\n\n    override fun close() = Unit\n\n    override fun timeout() = timeout\n  }\n\n  /** Closes on this sink never complete. They can only time out. */\n  class TimeoutClosingSink : Sink {\n    val timeout = object : AsyncTimeout() {\n      override fun timedOut() {\n        synchronized(this@TimeoutClosingSink) {\n          (this@TimeoutClosingSink as Object).notifyAll()\n        }\n      }\n    }\n\n    override fun write(source: Buffer, byteCount: Long) = source.skip(byteCount)\n\n    override fun flush() = Unit\n\n    override fun close() {\n      timeout.enter()\n      try {\n        synchronized(this) {\n          (this as Object).wait()\n        }\n      } finally {\n        timeout.exit()\n      }\n    }\n\n    override fun timeout() = timeout\n  }\n\n  companion object {\n    val smallerTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(500L)\n    val biggerTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(1500L)\n\n    val smallerDeadlineNanos = TimeUnit.MILLISECONDS.toNanos(500L)\n    val biggerDeadlineNanos = TimeUnit.MILLISECONDS.toNanos(1500L)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/PipeTest.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport java.io.IOException\nimport java.io.InterruptedIOException\nimport java.util.Random\nimport java.util.concurrent.TimeUnit\nimport java.util.concurrent.atomic.AtomicInteger\nimport kotlin.time.Duration.Companion.milliseconds\nimport okio.ByteString.Companion.decodeHex\nimport okio.HashingSink.Companion.sha1\nimport okio.TestUtil.assumeNotWindows\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Test\n\nclass PipeTest {\n  @InterceptTest\n  private val executorService = TestExecutor(2)\n\n  @Test\n  fun test() {\n    val pipe = Pipe(6)\n    pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3L)\n    val source = pipe.source\n    val readBuffer = Buffer()\n    assertEquals(3L, source.read(readBuffer, 6L))\n    assertEquals(\"abc\", readBuffer.readUtf8())\n    pipe.sink.close()\n    assertEquals(-1L, source.read(readBuffer, 6L))\n    source.close()\n  }\n\n  /**\n   * A producer writes the first 16 MiB of bytes generated by `new Random(0)` to a sink, and a\n   * consumer consumes them. Both compute hashes of their data to confirm that they're as expected.\n   */\n  @Test\n  fun largeDataset() {\n    val pipe = Pipe(1000L) // An awkward size to force producer/consumer exchange.\n    val totalBytes = 16L * 1024L * 1024L\n    val expectedHash = \"7c3b224bea749086babe079360cf29f98d88262d\".decodeHex()\n\n    // Write data to the sink.\n    val sinkHash = executorService.submit<ByteString> {\n      val hashingSink = sha1(pipe.sink)\n      val random = Random(0)\n      val data = ByteArray(8192)\n      val buffer = Buffer()\n      var i = 0L\n      while (i < totalBytes) {\n        random.nextBytes(data)\n        buffer.write(data)\n        hashingSink.write(buffer, buffer.size)\n        i += data.size.toLong()\n      }\n      hashingSink.close()\n      hashingSink.hash\n    }\n\n    // Read data from the source.\n    val sourceHash = executorService.submit<ByteString> {\n      val blackhole = Buffer()\n      val hashingSink = sha1(blackhole)\n      val buffer = Buffer()\n      while (pipe.source.read(buffer, Long.MAX_VALUE) != -1L) {\n        hashingSink.write(buffer, buffer.size)\n        blackhole.clear()\n      }\n      pipe.source.close()\n      hashingSink.hash\n    }\n    assertEquals(expectedHash, sinkHash.get())\n    assertEquals(expectedHash, sourceHash.get())\n  }\n\n  @Test\n  fun sinkTimeout() {\n    assumeNotWindows()\n    val pipe = Pipe(3)\n    pipe.sink.timeout().timeout(1000, TimeUnit.MILLISECONDS)\n    pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3L)\n    val start = now()\n    try {\n      pipe.sink.write(Buffer().writeUtf8(\"def\"), 3L)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n    val readBuffer = Buffer()\n    assertEquals(3L, pipe.source.read(readBuffer, 6L))\n    assertEquals(\"abc\", readBuffer.readUtf8())\n  }\n\n  @Test\n  fun sourceTimeout() {\n    assumeNotWindows()\n    val pipe = Pipe(3L)\n    pipe.source.timeout().timeout(1000, TimeUnit.MILLISECONDS)\n    val start = now()\n    val readBuffer = Buffer()\n    try {\n      pipe.source.read(readBuffer, 6L)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n    assertEquals(0, readBuffer.size)\n  }\n\n  /**\n   * The writer is writing 12 bytes as fast as it can to a 3 byte buffer. The reader alternates\n   * sleeping 1000 ms, then reading 3 bytes. That should make for an approximate timeline like\n   * this:\n   *\n   * ```\n   *    0: writer writes 'abc', blocks 0: reader sleeps until 1000\n   * 1000: reader reads 'abc', sleeps until 2000\n   * 1000: writer writes 'def', blocks\n   * 2000: reader reads 'def', sleeps until 3000\n   * 2000: writer writes 'ghi', blocks\n   * 3000: reader reads 'ghi', sleeps until 4000\n   * 3000: writer writes 'jkl', returns\n   * 4000: reader reads 'jkl', returns\n   * ```\n   *\n   *\n   * Because the writer is writing to a buffer, it finishes before the reader does.\n   */\n  @Test\n  fun sinkBlocksOnSlowReader() {\n    val pipe = Pipe(3L)\n    val position = AtomicInteger()\n\n    executorService.submit {\n      val buffer = Buffer()\n      Thread.sleep(1000L)\n      position.set(1)\n      assertEquals(3, pipe.source.read(buffer, Long.MAX_VALUE))\n      assertEquals(\"abc\", buffer.readUtf8())\n      Thread.sleep(1000L)\n      position.set(2)\n      assertEquals(3, pipe.source.read(buffer, Long.MAX_VALUE))\n      assertEquals(\"def\", buffer.readUtf8())\n      Thread.sleep(1000L)\n      position.set(3)\n      assertEquals(3, pipe.source.read(buffer, Long.MAX_VALUE))\n      assertEquals(\"ghi\", buffer.readUtf8())\n      Thread.sleep(1000L)\n      position.set(4)\n      assertEquals(3, pipe.source.read(buffer, Long.MAX_VALUE))\n      assertEquals(\"jkl\", buffer.readUtf8())\n    }\n\n    pipe.sink.write(Buffer().writeUtf8(\"abcdefghijkl\"), 12)\n    assertEquals(3, position.get())\n  }\n\n  @Test\n  fun sinkWriteFailsByClosedReader() {\n    val pipe = Pipe(3L)\n    executorService.schedule(1000.milliseconds) {\n      pipe.source.close()\n    }\n    val start = now()\n    try {\n      pipe.sink.write(Buffer().writeUtf8(\"abcdef\"), 6)\n      fail()\n    } catch (expected: IOException) {\n      assertEquals(\"source is closed\", expected.message)\n      assertElapsed(1000.0, start)\n    }\n  }\n\n  @Test\n  fun sinkFlushDoesntWaitForReader() {\n    val pipe = Pipe(100L)\n    pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    pipe.sink.flush()\n    val bufferedSource = pipe.source.buffer()\n    assertEquals(\"abc\", bufferedSource.readUtf8(3))\n  }\n\n  @Test\n  fun sinkFlushFailsIfReaderIsClosedBeforeAllDataIsRead() {\n    val pipe = Pipe(100L)\n    pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    pipe.source.close()\n    try {\n      pipe.sink.flush()\n      fail()\n    } catch (expected: IOException) {\n      assertEquals(\"source is closed\", expected.message)\n    }\n  }\n\n  @Test\n  fun sinkCloseFailsIfReaderIsClosedBeforeAllDataIsRead() {\n    val pipe = Pipe(100L)\n    pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    pipe.source.close()\n    try {\n      pipe.sink.close()\n      fail()\n    } catch (expected: IOException) {\n      assertEquals(\"source is closed\", expected.message)\n    }\n  }\n\n  @Test\n  fun sinkClose() {\n    val pipe = Pipe(100L)\n    pipe.sink.close()\n    try {\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n      fail()\n    } catch (expected: IllegalStateException) {\n      assertEquals(\"closed\", expected.message)\n    }\n    try {\n      pipe.sink.flush()\n      fail()\n    } catch (expected: IllegalStateException) {\n      assertEquals(\"closed\", expected.message)\n    }\n  }\n\n  @Test\n  fun sinkMultipleClose() {\n    val pipe = Pipe(100L)\n    pipe.sink.close()\n    pipe.sink.close()\n  }\n\n  @Test\n  fun sinkCloseDoesntWaitForSourceRead() {\n    val pipe = Pipe(100L)\n    pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n    pipe.sink.close()\n    val bufferedSource = pipe.source.buffer()\n    assertEquals(\"abc\", bufferedSource.readUtf8())\n    assertTrue(bufferedSource.exhausted())\n  }\n\n  @Test\n  fun sourceClose() {\n    val pipe = Pipe(100L)\n    pipe.source.close()\n    try {\n      pipe.source.read(Buffer(), 3)\n      fail()\n    } catch (expected: IllegalStateException) {\n      assertEquals(\"closed\", expected.message)\n    }\n  }\n\n  @Test\n  fun sourceMultipleClose() {\n    val pipe = Pipe(100L)\n    pipe.source.close()\n    pipe.source.close()\n  }\n\n  @Test\n  fun sourceReadUnblockedByClosedSink() {\n    val pipe = Pipe(3L)\n    executorService.schedule(1000.milliseconds) {\n      pipe.sink.close()\n    }\n    val start = now()\n    val readBuffer = Buffer()\n    assertEquals(-1, pipe.source.read(readBuffer, Long.MAX_VALUE))\n    assertEquals(0, readBuffer.size)\n    assertElapsed(1000.0, start)\n  }\n\n  /**\n   * The writer has 12 bytes to write. It alternates sleeping 1000 ms, then writing 3 bytes. The\n   * reader is reading as fast as it can. That should make for an approximate timeline like this:\n   *\n   * ```\n   *    0: writer sleeps until 1000\n   *    0: reader blocks\n   * 1000: writer writes 'abc', sleeps until 2000\n   * 1000: reader reads 'abc'\n   * 2000: writer writes 'def', sleeps until 3000\n   * 2000: reader reads 'def'\n   * 3000: writer writes 'ghi', sleeps until 4000\n   * 3000: reader reads 'ghi'\n   * 4000: writer writes 'jkl', returns\n   * 4000: reader reads 'jkl', returns\n   * ```\n   */\n  @Test\n  fun sourceBlocksOnSlowWriter() {\n    val pipe = Pipe(100L)\n    val position = AtomicInteger()\n\n    executorService.submit {\n      Thread.sleep(1000L)\n      position.set(1)\n      pipe.sink.write(Buffer().writeUtf8(\"abc\"), 3)\n      Thread.sleep(1000L)\n      position.set(2)\n      pipe.sink.write(Buffer().writeUtf8(\"def\"), 3)\n      Thread.sleep(1000L)\n      position.set(3)\n      pipe.sink.write(Buffer().writeUtf8(\"ghi\"), 3)\n      Thread.sleep(1000L)\n      position.set(4)\n      pipe.sink.write(Buffer().writeUtf8(\"jkl\"), 3)\n    }\n\n    val readBuffer = Buffer()\n    assertEquals(3, pipe.source.read(readBuffer, Long.MAX_VALUE))\n    assertEquals(\"abc\", readBuffer.readUtf8())\n    assertEquals(1, position.get())\n\n    assertEquals(3, pipe.source.read(readBuffer, Long.MAX_VALUE))\n    assertEquals(\"def\", readBuffer.readUtf8())\n    assertEquals(2, position.get())\n\n    assertEquals(3, pipe.source.read(readBuffer, Long.MAX_VALUE))\n    assertEquals(\"ghi\", readBuffer.readUtf8())\n    assertEquals(3, position.get())\n\n    assertEquals(3, pipe.source.read(readBuffer, Long.MAX_VALUE))\n    assertEquals(\"jkl\", readBuffer.readUtf8())\n    assertEquals(4, position.get())\n  }\n\n  /** Returns the nanotime in milliseconds as a double for measuring timeouts. */\n  private fun now(): Double {\n    return System.nanoTime() / 1000000.0\n  }\n\n  /**\n   * Fails the test unless the time from start until now is duration, accepting differences in\n   * -50..+450 milliseconds.\n   */\n  private fun assertElapsed(duration: Double, start: Double) {\n    assertEquals(duration, now() - start - 200.0, 250.0)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ReadUtf8LineTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport java.io.EOFException\nimport okio.TestUtil.SEGMENT_SIZE\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertNull\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Test\n\n@Burst\nclass ReadUtf8LineTest(\n  factory: Factory,\n) {\n  enum class Factory {\n    BasicBuffer {\n      override fun create(data: Buffer) = data\n    },\n    Buffered {\n      override fun create(data: Buffer): BufferedSource = RealBufferedSource(data)\n    },\n    SlowBuffered {\n      override fun create(data: Buffer): BufferedSource {\n        return RealBufferedSource(\n          object : ForwardingSource(data) {\n            override fun read(sink: Buffer, byteCount: Long): Long {\n              return super.read(sink, 1L.coerceAtMost(byteCount))\n            }\n          },\n        )\n      }\n    },\n    ;\n\n    abstract fun create(data: Buffer): BufferedSource\n  }\n\n  private val data: Buffer = Buffer()\n  private val source: BufferedSource = factory.create(data)\n\n  @Test\n  fun readLines() {\n    data.writeUtf8(\"abc\\ndef\\n\")\n    assertEquals(\"abc\", source.readUtf8LineStrict())\n    assertEquals(\"def\", source.readUtf8LineStrict())\n    try {\n      source.readUtf8LineStrict()\n      fail()\n    } catch (expected: EOFException) {\n      assertEquals(\"\\\\n not found: limit=0 content=…\", expected.message)\n    }\n  }\n\n  @Test\n  fun readUtf8LineStrictWithLimits() {\n    val lens = intArrayOf(1, SEGMENT_SIZE - 2, SEGMENT_SIZE - 1, SEGMENT_SIZE, SEGMENT_SIZE * 10)\n    for (len in lens) {\n      data.writeUtf8(\"a\".repeat(len)).writeUtf8(\"\\n\")\n      assertEquals(len.toLong(), source.readUtf8LineStrict(len.toLong()).length.toLong())\n      source.readUtf8()\n      data.writeUtf8(\"a\".repeat(len)).writeUtf8(\"\\n\").writeUtf8(\"a\".repeat(len))\n      assertEquals(len.toLong(), source.readUtf8LineStrict(len.toLong()).length.toLong())\n      source.readUtf8()\n      data.writeUtf8(\"a\".repeat(len)).writeUtf8(\"\\r\\n\")\n      assertEquals(len.toLong(), source.readUtf8LineStrict(len.toLong()).length.toLong())\n      source.readUtf8()\n      data.writeUtf8(\"a\".repeat(len)).writeUtf8(\"\\r\\n\").writeUtf8(\"a\".repeat(len))\n      assertEquals(len.toLong(), source.readUtf8LineStrict(len.toLong()).length.toLong())\n      source.readUtf8()\n    }\n  }\n\n  @Test\n  fun readUtf8LineStrictNoBytesConsumedOnFailure() {\n    data.writeUtf8(\"abc\\n\")\n    try {\n      source.readUtf8LineStrict(2)\n      fail()\n    } catch (expected: EOFException) {\n      assertTrue(expected.message!!.startsWith(\"\\\\n not found: limit=2 content=61626\"))\n    }\n    assertEquals(\"abc\", source.readUtf8LineStrict(3))\n  }\n\n  @Test\n  fun readUtf8LineStrictEmptyString() {\n    data.writeUtf8(\"\\r\\nabc\")\n    assertEquals(\"\", source.readUtf8LineStrict(0))\n    assertEquals(\"abc\", source.readUtf8())\n  }\n\n  @Test\n  fun readUtf8LineStrictNonPositive() {\n    data.writeUtf8(\"\\r\\n\")\n    try {\n      source.readUtf8LineStrict(-1)\n      fail(\"Expected failure: limit must be greater than 0\")\n    } catch (expected: IllegalArgumentException) {\n    }\n  }\n\n  @Test\n  fun eofExceptionProvidesLimitedContent() {\n    data.writeUtf8(\"aaaaaaaabbbbbbbbccccccccdddddddde\")\n    try {\n      source.readUtf8LineStrict()\n      fail()\n    } catch (expected: EOFException) {\n      assertEquals(\n        \"\\\\n not found: limit=33 content=616161616161616162626262626262626363636363636363\" +\n          \"6464646464646464…\",\n        expected.message,\n      )\n    }\n  }\n\n  @Test\n  fun newlineAtEnd() {\n    data.writeUtf8(\"abc\\n\")\n    assertEquals(\"abc\", source.readUtf8LineStrict(3))\n    assertTrue(source.exhausted())\n    data.writeUtf8(\"abc\\r\\n\")\n    assertEquals(\"abc\", source.readUtf8LineStrict(3))\n    assertTrue(source.exhausted())\n    data.writeUtf8(\"abc\\r\")\n    try {\n      source.readUtf8LineStrict(3)\n      fail()\n    } catch (expected: EOFException) {\n      assertEquals(\"\\\\n not found: limit=3 content=6162630d…\", expected.message)\n    }\n    source.readUtf8()\n    data.writeUtf8(\"abc\")\n    try {\n      source.readUtf8LineStrict(3)\n      fail()\n    } catch (expected: EOFException) {\n      assertEquals(\"\\\\n not found: limit=3 content=616263…\", expected.message)\n    }\n  }\n\n  @Test\n  fun emptyLines() {\n    data.writeUtf8(\"\\n\\n\\n\")\n    assertEquals(\"\", source.readUtf8LineStrict())\n    assertEquals(\"\", source.readUtf8LineStrict())\n    assertEquals(\"\", source.readUtf8LineStrict())\n    assertTrue(source.exhausted())\n  }\n\n  @Test\n  fun crDroppedPrecedingLf() {\n    data.writeUtf8(\"abc\\r\\ndef\\r\\nghi\\rjkl\\r\\n\")\n    assertEquals(\"abc\", source.readUtf8LineStrict())\n    assertEquals(\"def\", source.readUtf8LineStrict())\n    assertEquals(\"ghi\\rjkl\", source.readUtf8LineStrict())\n  }\n\n  @Test\n  fun bufferedReaderCompatible() {\n    data.writeUtf8(\"abc\\ndef\")\n    assertEquals(\"abc\", source.readUtf8Line())\n    assertEquals(\"def\", source.readUtf8Line())\n    assertNull(source.readUtf8Line())\n  }\n\n  @Test\n  fun bufferedReaderCompatibleWithTrailingNewline() {\n    data.writeUtf8(\"abc\\ndef\\n\")\n    assertEquals(\"abc\", source.readUtf8Line())\n    assertEquals(\"def\", source.readUtf8Line())\n    assertNull(source.readUtf8Line())\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/SegmentSharingTest.kt",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.TestUtil.assertEquivalent\nimport okio.TestUtil.bufferWithSegments\nimport okio.TestUtil.takeAllPoolSegments\nimport org.junit.Test\n\n/** Tests behavior optimized by sharing segments between buffers and byte strings.  */\nclass SegmentSharingTest {\n  @Test fun snapshotOfEmptyBuffer() {\n    val snapshot = Buffer().snapshot()\n    assertEquivalent(snapshot, ByteString.EMPTY)\n  }\n\n  @Test fun snapshotsAreEquivalent() {\n    val byteString = bufferWithSegments(xs, ys, zs).snapshot()\n    assertEquivalent(byteString, bufferWithSegments(xs, ys + zs).snapshot())\n    assertEquivalent(byteString, bufferWithSegments(xs + ys + zs).snapshot())\n    assertEquivalent(byteString, (xs + ys + zs).encodeUtf8())\n  }\n\n  @Test fun snapshotGetByte() {\n    val byteString = bufferWithSegments(xs, ys, zs).snapshot()\n    assertEquals('x', byteString[0].toInt().toChar())\n    assertEquals('x', byteString[xs.length - 1].toInt().toChar())\n    assertEquals('y', byteString[xs.length].toInt().toChar())\n    assertEquals('y', byteString[xs.length + ys.length - 1].toInt().toChar())\n    assertEquals('z', byteString[xs.length + ys.length].toInt().toChar())\n    assertEquals('z', byteString[xs.length + ys.length + zs.length - 1].toInt().toChar())\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString[-1]\n    }\n\n    assertFailsWith<IndexOutOfBoundsException> {\n      byteString[xs.length + ys.length + zs.length]\n    }\n  }\n\n  @Test fun snapshotWriteToOutputStream() {\n    val byteString = bufferWithSegments(xs, ys, zs).snapshot()\n    val out = Buffer()\n    byteString.write(out.outputStream())\n    assertEquals(xs + ys + zs, out.readUtf8())\n  }\n\n  /**\n   * Snapshots share their backing byte arrays with the source buffers. Those byte arrays must not\n   * be recycled, otherwise the new writer could corrupt the segment.\n   */\n  @Test fun snapshotSegmentsAreNotRecycled() {\n    val buffer = bufferWithSegments(xs, ys, zs)\n    val snapshot = buffer.snapshot()\n    assertEquals(xs + ys + zs, snapshot.utf8())\n\n    // Confirm that clearing the buffer doesn't release its segments.\n    val bufferHead = buffer.head\n    takeAllPoolSegments() // Make room for new segments.\n    buffer.clear()\n    assertTrue(bufferHead !in takeAllPoolSegments())\n  }\n\n  /**\n   * Clones share their backing byte arrays with the source buffers. Those byte arrays must not\n   * be recycled, otherwise the new writer could corrupt the segment.\n   */\n  @Test fun cloneSegmentsAreNotRecycled() {\n    val buffer = bufferWithSegments(xs, ys, zs)\n    val clone = buffer.clone()\n\n    // While locking the pool, confirm that clearing the buffer doesn't release its segments.\n    val bufferHead = buffer.head!!\n    takeAllPoolSegments() // Make room for new segments.\n    buffer.clear()\n    assertTrue(bufferHead !in takeAllPoolSegments())\n\n    val cloneHead = clone.head!!\n    takeAllPoolSegments() // Make room for new segments.\n    clone.clear()\n    assertTrue(cloneHead !in takeAllPoolSegments())\n  }\n\n  @Test fun snapshotJavaSerialization() {\n    val byteString = bufferWithSegments(xs, ys, zs).snapshot()\n    assertEquivalent(byteString, TestUtil.reserialize(byteString))\n  }\n\n  @Test fun clonesAreEquivalent() {\n    val bufferA = bufferWithSegments(xs, ys, zs)\n    val bufferB = bufferA.clone()\n    assertEquivalent(bufferA, bufferB)\n    assertEquivalent(bufferA, bufferWithSegments(xs + ys, zs))\n  }\n\n  /** Even though some segments are shared, clones can be mutated independently.  */\n  @Test fun mutateAfterClone() {\n    val bufferA = Buffer()\n    bufferA.writeUtf8(\"abc\")\n    val bufferB = bufferA.clone()\n    bufferA.writeUtf8(\"def\")\n    bufferB.writeUtf8(\"DEF\")\n    assertEquals(\"abcdef\", bufferA.readUtf8())\n    assertEquals(\"abcDEF\", bufferB.readUtf8())\n  }\n\n  @Test fun concatenateSegmentsCanCombine() {\n    val bufferA = Buffer().writeUtf8(ys).writeUtf8(us)\n    assertEquals(ys, bufferA.readUtf8(ys.length.toLong()))\n    val bufferB = Buffer().writeUtf8(vs).writeUtf8(ws)\n    val bufferC = bufferA.clone()\n    bufferA.write(bufferB, vs.length.toLong())\n    bufferC.writeUtf8(xs)\n\n    assertEquals(us + vs, bufferA.readUtf8())\n    assertEquals(ws, bufferB.readUtf8())\n    assertEquals(us + xs, bufferC.readUtf8())\n  }\n\n  @Test fun shareAndSplit() {\n    val bufferA = Buffer().writeUtf8(\"xxxx\")\n    val snapshot = bufferA.snapshot() // Share the segment.\n    val bufferB = Buffer()\n    bufferB.write(bufferA, 2) // Split the shared segment in two.\n    bufferB.writeUtf8(\"yy\") // Append to the first half of the shared segment.\n    assertEquals(\"xxxx\", snapshot.utf8())\n  }\n\n  @Test fun appendSnapshotToEmptyBuffer() {\n    val bufferA = bufferWithSegments(xs, ys)\n    val snapshot = bufferA.snapshot()\n    val bufferB = Buffer()\n    bufferB.write(snapshot)\n    assertEquivalent(bufferB, bufferA)\n  }\n\n  @Test fun appendSnapshotToNonEmptyBuffer() {\n    val bufferA = bufferWithSegments(xs, ys)\n    val snapshot = bufferA.snapshot()\n    val bufferB = Buffer().writeUtf8(us)\n    bufferB.write(snapshot)\n    assertEquivalent(bufferB, Buffer().writeUtf8(us + xs + ys))\n  }\n\n  @Test fun copyToSegmentSharing() {\n    val bufferA = bufferWithSegments(ws, xs + \"aaaa\", ys, \"bbbb$zs\")\n    val bufferB = bufferWithSegments(us)\n    bufferA.copyTo(bufferB, (ws.length + xs.length).toLong(), (4 + ys.length + 4).toLong())\n    assertEquivalent(bufferB, Buffer().writeUtf8(us + \"aaaa\" + ys + \"bbbb\"))\n  }\n}\n\nprivate val us = \"u\".repeat(Segment.SIZE / 2 - 2)\nprivate val vs = \"v\".repeat(Segment.SIZE / 2 - 1)\nprivate val ws = \"w\".repeat(Segment.SIZE / 2)\nprivate val xs = \"x\".repeat(Segment.SIZE / 2 + 1)\nprivate val ys = \"y\".repeat(Segment.SIZE / 2 + 2)\nprivate val zs = \"z\".repeat(Segment.SIZE / 2 + 3)\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/SocketTest.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport assertk.assertThat\nimport assertk.assertions.isBetween\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isFalse\nimport assertk.assertions.isTrue\nimport java.io.InterruptedIOException\nimport java.net.InetAddress\nimport java.net.InetSocketAddress\nimport java.net.ServerSocket\nimport java.net.SocketException\nimport java.util.concurrent.CompletableFuture\nimport java.util.concurrent.TimeUnit\nimport javax.net.SocketFactory\nimport kotlin.concurrent.thread\nimport kotlin.test.assertFailsWith\nimport kotlin.time.Duration.Companion.milliseconds\nimport kotlin.time.measureTime\nimport okio.internal.DefaultSocket\nimport org.junit.After\nimport org.junit.Before\nimport org.junit.Test\n\n@Burst\nclass SocketTest(val factory: Factory = Factory.Default) {\n  private lateinit var socket: Socket\n  private lateinit var peerSocket: Socket\n  private lateinit var peer: AsyncSocket\n\n  @Before\n  fun setUp() {\n    val socketPair = factory.createSocketPair()\n    this.socket = socketPair[0]\n    this.peerSocket = socketPair[1]\n    this.peer = AsyncSocket(peerSocket)\n  }\n\n  @After\n  fun tearDown() {\n    peer.close()\n    socket.source.close()\n    try {\n      socket.sink.close()\n    } catch (_: IOException) {\n      // Ignore exception if data was left in 'sink'.\n    }\n  }\n\n  @Test\n  fun happyPath() {\n    val bufferedSource = socket.source.buffer()\n    val bufferedSink = socket.sink.buffer()\n\n    peer.write(\"one\")\n    assertThat(bufferedSource.readUtf8LineStrict()).isEqualTo(\"one\")\n\n    bufferedSink.writeUtf8(\"two\\n\")\n    bufferedSink.flush()\n    assertThat(peer.read()).isEqualTo(\"two\")\n\n    peer.write(\"three\")\n    assertThat(bufferedSource.readUtf8LineStrict()).isEqualTo(\"three\")\n\n    bufferedSink.writeUtf8(\"four\\n\")\n    bufferedSink.flush()\n    assertThat(peer.read()).isEqualTo(\"four\")\n  }\n\n  @Test\n  fun sourceIsReadableAfterSinkIsClosed() {\n    peer.closeSource()\n    socket.sink.close()\n\n    peer.write(\"Hello\")\n    assertThat(socket.source.buffer().readUtf8Line()).isEqualTo(\"Hello\")\n\n    socket.source.close()\n    peer.closeSink()\n  }\n\n  @Test\n  fun sinkIsWritableAfterSourceIsClosed() {\n    peer.closeSink()\n    socket.source.close()\n\n    val bufferedSink = socket.sink.buffer()\n    bufferedSink.writeUtf8(\"Hello\\n\")\n    bufferedSink.flush()\n    assertThat(peer.read()).isEqualTo(\"Hello\")\n\n    socket.sink.close()\n    peer.closeSource()\n  }\n\n  @Test\n  fun localCancelCausesSubsequentReadToFail() {\n    peer.write(\"Hello\")\n\n    socket.cancel()\n\n    assertFailsWith<IOException> {\n      socket.source.buffer().readUtf8Line()\n    }\n  }\n\n  @Test\n  fun localCancelCausesSubsequentWriteToFail() {\n    socket.cancel()\n\n    val bufferedSink = socket.sink.buffer()\n    bufferedSink.writeUtf8(\"Hello\\n\")\n    assertFailsWith<IOException> {\n      bufferedSink.flush()\n    }\n  }\n\n  @Test\n  fun peerCloseCausesSubsequentLocalReadToFail() {\n    peer.closeSink()\n\n    val bufferedSource = socket.source.buffer()\n    assertFailsWith<IOException> {\n      bufferedSource.readUtf8LineStrict()\n    }\n  }\n\n  @Test\n  fun peerCancelCausesSubsequentLocalReadToFail() {\n    peerSocket.cancel()\n\n    val bufferedSource = socket.source.buffer()\n    assertFailsWith<IOException> {\n      bufferedSource.readUtf8LineStrict()\n    }\n  }\n\n  @Test\n  fun readTimeout() {\n    val bufferedSource = socket.source.buffer()\n    bufferedSource.timeout().timeout(500, TimeUnit.MILLISECONDS)\n\n    val duration = measureTime {\n      assertFailsWith<InterruptedIOException> {\n        bufferedSource.readUtf8Line()\n      }\n    }\n\n    assertThat(duration).isBetween(250.milliseconds, 750.milliseconds)\n  }\n\n  /** Make a large-enough write to saturate the outgoing write buffer. */\n  @Test\n  fun writeTimeout() {\n    val bufferedSink = socket.sink.buffer()\n    bufferedSink.timeout().timeout(500, TimeUnit.MILLISECONDS)\n\n    val duration = measureTime {\n      assertFailsWith<InterruptedIOException> {\n        bufferedSink.write(ByteArray(1024 * 1024 * 16))\n      }\n    }\n\n    assertThat(duration).isBetween(250.milliseconds, 750.milliseconds)\n  }\n\n  @Test\n  fun closeSourceDoesNotCloseJavaNetSocket() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n\n    socket.source.close()\n    assertThat(javaNetSocket.isInputShutdown).isTrue()\n    assertThat(javaNetSocket.isOutputShutdown).isFalse()\n    assertThat(javaNetSocket.isClosed).isFalse()\n  }\n\n  @Test\n  fun closeSinkDoesNotCloseJavaNetSocket() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n\n    socket.sink.close()\n    assertThat(javaNetSocket.isInputShutdown).isFalse()\n    assertThat(javaNetSocket.isOutputShutdown).isTrue()\n    assertThat(javaNetSocket.isClosed).isFalse()\n  }\n\n  @Test\n  fun closeSourceThenSinkClosesJavaNetSocket() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n\n    socket.source.close()\n    socket.sink.close()\n    assertThat(javaNetSocket.isClosed).isTrue()\n  }\n\n  @Test\n  fun closeSinkThenSourceClosesJavaNetSocket() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n\n    socket.sink.close()\n    socket.source.close()\n    assertThat(javaNetSocket.isClosed).isTrue()\n  }\n\n  @Test\n  fun closeSinkThenSourceClosesJavaNetSocketEvenIfStreamsAlreadyClosed() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n    javaNetSocket.shutdownInput()\n    javaNetSocket.shutdownOutput()\n    assertThat(javaNetSocket.isClosed).isFalse()\n\n    socket.sink.close()\n    socket.source.close()\n    assertThat(javaNetSocket.isClosed).isTrue()\n  }\n\n  @Test\n  fun closeSourceIsIdempotent() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n\n    socket.source.close()\n    assertThat(javaNetSocket.isInputShutdown).isTrue()\n    assertThat(javaNetSocket.isClosed).isFalse()\n    socket.source.close()\n    assertThat(javaNetSocket.isInputShutdown).isTrue()\n    assertThat(javaNetSocket.isClosed).isFalse()\n  }\n\n  @Test\n  fun closeSinkIsIdempotent() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n\n    socket.sink.close()\n    assertThat(javaNetSocket.isOutputShutdown).isTrue()\n    assertThat(javaNetSocket.isClosed).isFalse()\n    socket.sink.close()\n    assertThat(javaNetSocket.isOutputShutdown).isTrue()\n    assertThat(javaNetSocket.isClosed).isFalse()\n  }\n\n  @Test\n  fun cannotCreateOkioSocketFromClosedJavaNetSocket() {\n    val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return\n    javaNetSocket.close()\n\n    assertFailsWith<SocketException> {\n      javaNetSocket.asOkioSocket()\n    }\n  }\n\n  @Test\n  fun cannotCreateOkioSocketFromUnconnectedJavaNetSocket() {\n    val unconnected = SocketFactory.getDefault().createSocket()\n    assertFailsWith<SocketException> {\n      unconnected.asOkioSocket()\n    }\n  }\n\n  @Suppress(\"ktlint:trailing-comma-on-declaration-site\")\n  enum class Factory {\n    /** Implements an okio.Socket using the `java.net.Socket` API on OS sockets. */\n    Default {\n      override fun createSocketPair(): Array<Socket> {\n        val localhost = InetAddress.getByName(\"localhost\")\n\n        val serverSocket = ServerSocket()\n        serverSocket.bind(InetSocketAddress(localhost, 0))\n\n        val socketBFuture = CompletableFuture<java.net.Socket>()\n        thread(name = \"createSocketPair\") {\n          socketBFuture.complete(serverSocket.accept())\n        }\n\n        val socketA = SocketFactory.getDefault().createSocket()\n        socketA.connect(InetSocketAddress(localhost, serverSocket.localPort))\n\n        val socketB = socketBFuture.get()\n        return arrayOf(socketA.asOkioSocket(), socketB.asOkioSocket())\n      }\n    },\n\n    Pipes {\n      override fun createSocketPair() = inMemorySocketPair(1024)\n    };\n\n    /** Returns two mutually-connected sockets. */\n    abstract fun createSocketPair(): Array<Socket>\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/SocketTimeoutTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.EOFException\nimport java.io.IOException\nimport java.io.InputStream\nimport java.io.OutputStream\nimport java.net.InetAddress\nimport java.net.ServerSocket\nimport java.net.Socket\nimport java.net.SocketTimeoutException\nimport java.util.concurrent.TimeUnit\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Test\n\nclass SocketTimeoutTest {\n  @Test\n  fun readWithoutTimeout() {\n    val socket = socket(ONE_MB, 0)\n    val source = socket.source().buffer()\n    source.timeout().timeout(5000, TimeUnit.MILLISECONDS)\n    source.require(ONE_MB.toLong())\n    socket.close()\n  }\n\n  @Test\n  fun readWithTimeout() {\n    val socket = socket(0, 0)\n    val source = socket.source().buffer()\n    source.timeout().timeout(250, TimeUnit.MILLISECONDS)\n    try {\n      source.require(ONE_MB.toLong())\n      fail()\n    } catch (expected: SocketTimeoutException) {\n    }\n    socket.close()\n  }\n\n  @Test\n  fun writeWithoutTimeout() {\n    val socket = socket(0, ONE_MB)\n    val sink: Sink = socket.sink().buffer()\n    sink.timeout().timeout(500, TimeUnit.MILLISECONDS)\n    val data = ByteArray(ONE_MB)\n    sink.write(Buffer().write(data), data.size.toLong())\n    sink.flush()\n    socket.close()\n  }\n\n  @Test\n  fun writeWithTimeout() {\n    val socket = socket(0, 0)\n    val sink = socket.sink()\n    sink.timeout().timeout(500, TimeUnit.MILLISECONDS)\n    val data = ByteArray(ONE_MB)\n    val start = System.nanoTime()\n    try {\n      sink.write(Buffer().write(data), data.size.toLong())\n      sink.flush()\n      fail()\n    } catch (expected: SocketTimeoutException) {\n    }\n    val elapsed = System.nanoTime() - start\n    socket.close()\n    assertTrue(\"elapsed: $elapsed\", TimeUnit.NANOSECONDS.toMillis(elapsed) >= 500)\n    assertTrue(\"elapsed: $elapsed\", TimeUnit.NANOSECONDS.toMillis(elapsed) <= 750)\n  }\n\n  companion object {\n    // The size of the socket buffers to use. Less than half the data transferred during tests to\n    // ensure send and receive buffers are flooded and any necessary blocking behavior takes place.\n    private const val SOCKET_BUFFER_SIZE = 256 * 1024\n    private const val ONE_MB = 1024 * 1024\n\n    /**\n     * Returns a socket that can read `readableByteCount` incoming bytes and\n     * will accept `writableByteCount` written bytes. The socket will idle\n     * for 5 seconds when the required data has been read and written.\n     */\n    fun socket(readableByteCount: Int, writableByteCount: Int): Socket {\n      val inetAddress = InetAddress.getByName(\"localhost\")\n      val serverSocket = ServerSocket(0, 50, inetAddress)\n      serverSocket.reuseAddress = true\n      serverSocket.receiveBufferSize = SOCKET_BUFFER_SIZE\n      val peer: Thread = object : Thread(\"peer\") {\n        override fun run() {\n          var socket: Socket? = null\n          try {\n            socket = serverSocket.accept()\n            socket.sendBufferSize = SOCKET_BUFFER_SIZE\n            writeFully(socket.getOutputStream(), readableByteCount)\n            readFully(socket.getInputStream(), writableByteCount)\n            sleep(5000) // Sleep 5 seconds so the peer can close the connection.\n          } catch (ignored: Exception) {\n          } finally {\n            try {\n              socket?.close()\n            } catch (ignored: IOException) {\n            }\n          }\n        }\n      }\n      peer.start()\n      val socket = Socket(serverSocket.inetAddress, serverSocket.localPort)\n      socket.receiveBufferSize = SOCKET_BUFFER_SIZE\n      socket.sendBufferSize = SOCKET_BUFFER_SIZE\n      return socket\n    }\n\n    private fun writeFully(out: OutputStream, byteCount: Int) {\n      out.write(ByteArray(byteCount))\n      out.flush()\n    }\n\n    private fun readFully(`in`: InputStream, byteCount: Int): ByteArray {\n      var count = 0\n      val result = ByteArray(byteCount)\n      while (count < byteCount) {\n        val read = `in`.read(result, count, result.size - count)\n        if (read == -1) throw EOFException()\n        count += read\n      }\n      return result\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/Stopwatch.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isCloseTo\n\n/** Stopwatch for asserting elapsed time during unit tests. */\ninternal class Stopwatch {\n  private val start = System.nanoTime() / 1e9\n  private var offset = 0.0\n\n  /**\n   * Fails the test unless the time from the last assertion until now is `elapsed`, accepting\n   * differences in -200..+200 milliseconds.\n   */\n  fun assertElapsed(elapsed: Double) {\n    offset += elapsed\n    assertThat(System.nanoTime() / 1e9 - start).isCloseTo(offset, 0.2)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/TestUtil.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.IOException\nimport java.io.ObjectInputStream\nimport java.io.ObjectOutputStream\nimport java.io.Serializable\nimport java.util.Locale\nimport java.util.Random\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.encodeUtf8\nimport org.junit.Assume\n\nobject TestUtil {\n  // Necessary to make an internal member visible to Java.\n  @JvmField val SEGMENT_POOL_MAX_SIZE = SegmentPool.MAX_SIZE\n  const val SEGMENT_SIZE = Segment.SIZE\n  const val REPLACEMENT_CODE_POINT: Int = okio.REPLACEMENT_CODE_POINT\n\n  @JvmStatic fun segmentPoolByteCount() = SegmentPool.byteCount\n\n  @JvmStatic\n  fun segmentSizes(buffer: Buffer): List<Int> = okio.segmentSizes(buffer)\n\n  @JvmStatic\n  fun assertByteArraysEquals(a: ByteArray, b: ByteArray) {\n    assertEquals(a.contentToString(), b.contentToString())\n  }\n\n  @JvmStatic\n  fun assertByteArrayEquals(expectedUtf8: String, b: ByteArray) {\n    assertEquals(expectedUtf8, b.toString(Charsets.UTF_8))\n  }\n\n  @JvmStatic\n  fun randomBytes(length: Int): ByteString {\n    val random = Random(0)\n    val randomBytes = ByteArray(length)\n    random.nextBytes(randomBytes)\n    return ByteString.of(*randomBytes)\n  }\n\n  @JvmStatic\n  fun randomSource(size: Long): Source {\n    return object : Source {\n      internal var random = Random(0)\n      internal var bytesLeft = size\n      internal var closed: Boolean = false\n\n      @Throws(IOException::class)\n      override fun read(sink: Buffer, byteCount: Long): Long {\n        var byteCount = byteCount\n        if (closed) throw IllegalStateException(\"closed\")\n        if (bytesLeft == 0L) return -1L\n        if (byteCount > bytesLeft) byteCount = bytesLeft\n\n        // If we can read a full segment we can save a copy.\n        if (byteCount >= Segment.SIZE) {\n          val segment = sink.writableSegment(Segment.SIZE)\n          random.nextBytes(segment.data)\n          segment.limit += Segment.SIZE\n          sink.size += Segment.SIZE.toLong()\n          bytesLeft -= Segment.SIZE.toLong()\n          return Segment.SIZE.toLong()\n        } else {\n          val data = ByteArray(byteCount.toInt())\n          random.nextBytes(data)\n          sink.write(data)\n          bytesLeft -= byteCount\n          return byteCount\n        }\n      }\n\n      override fun timeout() = Timeout.NONE\n\n      @Throws(IOException::class)\n      override fun close() {\n        closed = true\n      }\n    }\n  }\n\n  @JvmStatic\n  fun assertEquivalent(b1: ByteString, b2: ByteString) {\n    // Equals.\n    assertTrue(b1 == b2)\n    assertTrue(b1 == b1)\n    assertTrue(b2 == b1)\n\n    // Hash code.\n    assertEquals(b1.hashCode().toLong(), b2.hashCode().toLong())\n    assertEquals(b1.hashCode().toLong(), b1.hashCode().toLong())\n    assertEquals(b1.toString(), b2.toString())\n\n    // Content.\n    assertEquals(b1.size.toLong(), b2.size.toLong())\n    val b2Bytes = b2.toByteArray()\n    for (i in b2Bytes.indices) {\n      val b = b2Bytes[i]\n      assertEquals(b.toLong(), b1[i].toLong())\n    }\n    assertByteArraysEquals(b1.toByteArray(), b2Bytes)\n\n    // Doesn't equal a different byte string.\n    assertFalse(b1 == null)\n    assertFalse(b1 == Any())\n    if (b2Bytes.size > 0) {\n      val b3Bytes = b2Bytes.clone()\n      b3Bytes[b3Bytes.size - 1]++\n      val b3 = ByteString(b3Bytes)\n      assertFalse(b1 == b3)\n      assertFalse(b1.hashCode() == b3.hashCode())\n    } else {\n      val b3 = \"a\".encodeUtf8()\n      assertFalse(b1 == b3)\n      assertFalse(b1.hashCode() == b3.hashCode())\n    }\n  }\n\n  @JvmStatic\n  fun assertEquivalent(b1: Buffer, b2: Buffer) {\n    // Equals.\n    assertTrue(b1 == b2)\n    assertTrue(b1 == b1)\n    assertTrue(b2 == b1)\n\n    // Hash code.\n    assertEquals(b1.hashCode().toLong(), b2.hashCode().toLong())\n    assertEquals(b1.hashCode().toLong(), b1.hashCode().toLong())\n    assertEquals(b1.toString(), b2.toString())\n\n    // Content.\n    assertEquals(b1.size, b2.size)\n    val buffer = Buffer()\n    b2.copyTo(buffer, 0, b2.size)\n    val b2Bytes = b2.readByteArray()\n    for (i in b2Bytes.indices) {\n      val b = b2Bytes[i]\n      assertEquals(b.toLong(), b1[i.toLong()].toLong())\n    }\n\n    // Doesn't equal a different buffer.\n    assertFalse(b1 == Any())\n    if (b2Bytes.size > 0) {\n      val b3Bytes = b2Bytes.clone()\n      b3Bytes[b3Bytes.size - 1]++\n      val b3 = Buffer().write(b3Bytes)\n      assertFalse(b1 == b3)\n      assertFalse(b1.hashCode() == b3.hashCode())\n    } else {\n      val b3 = Buffer().writeUtf8(\"a\")\n      assertFalse(b1 == b3)\n      assertFalse(b1.hashCode() == b3.hashCode())\n    }\n  }\n\n  /** Serializes original to bytes, then deserializes those bytes and returns the result.  */\n  // Assume serialization doesn't change types.\n  @Suppress(\"UNCHECKED_CAST\")\n  @Throws(Exception::class)\n  @JvmStatic\n  fun <T : Serializable> reserialize(original: T): T {\n    val buffer = Buffer()\n    val out = ObjectOutputStream(buffer.outputStream())\n    out.writeObject(original)\n    val input = ObjectInputStream(buffer.inputStream())\n    return input.readObject() as T\n  }\n\n  /**\n   * Returns a new buffer containing the data in `data` and a segment\n   * layout determined by `dice`.\n   */\n  @Throws(IOException::class)\n  @JvmStatic\n  fun bufferWithRandomSegmentLayout(dice: Random, data: ByteArray): Buffer {\n    val result = Buffer()\n\n    // Writing to result directly will yield packed segments. Instead, write to\n    // other buffers, then write those buffers to result.\n    var pos = 0\n    var byteCount: Int\n    while (pos < data.size) {\n      byteCount = Segment.SIZE / 2 + dice.nextInt(Segment.SIZE / 2)\n      if (byteCount > data.size - pos) byteCount = data.size - pos\n      val offset = dice.nextInt(Segment.SIZE - byteCount)\n\n      val segment = Buffer()\n      segment.write(ByteArray(offset))\n      segment.write(data, pos, byteCount)\n      segment.skip(offset.toLong())\n\n      result.write(segment, byteCount.toLong())\n      pos += byteCount\n    }\n\n    return result\n  }\n\n  /**\n   * Returns a new buffer containing the contents of `segments`, attempting to isolate each\n   * string to its own segment in the returned buffer. This clones buffers so that segments are\n   * shared, preventing compaction from occurring.\n   */\n  @Throws(Exception::class)\n  @JvmStatic\n  fun bufferWithSegments(vararg segments: String): Buffer {\n    val result = Buffer()\n    for (s in segments) {\n      val offsetInSegment = if (s.length < Segment.SIZE) (Segment.SIZE - s.length) / 2 else 0\n      val buffer = Buffer()\n      buffer.writeUtf8(\"_\".repeat(offsetInSegment))\n      buffer.writeUtf8(s)\n      buffer.skip(offsetInSegment.toLong())\n      result.write(buffer.clone(), buffer.size)\n    }\n    return result\n  }\n\n  @JvmStatic\n  fun makeSegments(source: ByteString): ByteString {\n    val buffer = Buffer()\n    for (i in 0 until source.size) {\n      val segment = buffer.writableSegment(SEGMENT_SIZE)\n      segment.data[segment.pos] = source[i]\n      segment.limit++\n      buffer.size++\n    }\n    return buffer.snapshot()\n  }\n\n  /** Remove all segments from the pool and return them as a list. */\n  @JvmStatic\n  internal fun takeAllPoolSegments(): List<Segment> {\n    val result = mutableListOf<Segment>()\n    while (SegmentPool.byteCount > 0) {\n      result += SegmentPool.take()\n    }\n    return result\n  }\n\n  /** Returns a copy of `buffer` with no segments with `original`.  */\n  @JvmStatic\n  fun deepCopy(original: Buffer): Buffer {\n    val result = Buffer()\n    if (original.size == 0L) return result\n\n    result.head = original.head!!.unsharedCopy()\n    result.head!!.prev = result.head\n    result.head!!.next = result.head!!.prev\n    var s = original.head!!.next\n    while (s !== original.head) {\n      result.head!!.prev!!.push(s!!.unsharedCopy())\n      s = s.next\n    }\n    result.size = original.size\n\n    return result\n  }\n\n  @JvmStatic\n  fun Int.reverseBytes(): Int {\n    /* ktlint-disable no-multi-spaces indent */\n    return (this and -0x1000000 ushr 24) or\n      (this and 0x00ff0000 ushr  8) or\n      (this and 0x0000ff00  shl  8) or\n      (this and 0x000000ff  shl 24)\n    /* ktlint-enable no-multi-spaces indent */\n  }\n\n  @JvmStatic\n  fun Short.reverseBytes(): Short {\n    val i = toInt() and 0xffff\n    /* ktlint-disable no-multi-spaces indent */\n    val reversed = (i and 0xff00 ushr 8) or\n      (i and 0x00ff  shl 8)\n    /* ktlint-enable no-multi-spaces indent */\n    return reversed.toShort()\n  }\n\n  fun assumeNotWindows() = Assume.assumeFalse(System.getProperty(\"os.name\").lowercase(Locale.getDefault()).contains(\"win\"))\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ThrottlerTakeTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isGreaterThan\nimport java.util.concurrent.TimeUnit\nimport org.junit.Test\n\nclass ThrottlerTakeTest {\n  private var nowNanos = 0L\n  private var elapsedNanos = 0L\n  private val throttler = Throttler(allocatedUntil = nowNanos)\n\n  @Test fun takeByByteCount() {\n    throttler.bytesPerSecond(bytesPerSecond = 20, waitByteCount = 5, maxByteCount = 10)\n\n    // We get the first 10 bytes immediately (that's maxByteCount).\n    assertThat(take(100L)).isEqualTo(10L)\n    assertElapsed(0L)\n\n    // Wait a quarter second for each subsequent 5 bytes (that's waitByteCount).\n    assertThat(take(100L)).isEqualTo(5L)\n    assertElapsed(250L)\n\n    assertThat(take(100L)).isEqualTo(5L)\n    assertElapsed(250L)\n\n    // Wait three quarters of a second to build up 15 bytes of potential.\n    // Since maxByteCount = 10, there will only be 10 bytes of potential.\n    sleep(750L)\n    assertElapsed(750L)\n\n    // We get 10 bytes immediately (that's maxByteCount again).\n    assertThat(take(100L)).isEqualTo(10L)\n    assertElapsed(0L)\n\n    // Wait a quarter second for each subsequent 5 bytes (that's waitByteCount again).\n    assertThat(take(100L)).isEqualTo(5L)\n    assertElapsed(250L)\n  }\n\n  @Test fun takeFullyTimeElapsed() {\n    throttler.bytesPerSecond(bytesPerSecond = 20, waitByteCount = 5, maxByteCount = 10)\n\n    // We write the first 10 bytes immediately (that's maxByteCount again).\n    takeFully(10L)\n    assertElapsed(0L)\n\n    // Wait a quarter second for each subsequent 5 bytes (that's waitByteCount).\n    takeFully(5L)\n    assertElapsed(250L)\n\n    // Wait a half second for 10 bytes.\n    takeFully(10L)\n    assertElapsed(500L)\n\n    // Wait a three quarters of a second to build up 15 bytes of potential.\n    // Since maxByteCount = 10, there will only be 10 bytes of potential.\n    sleep(750L)\n    assertElapsed(750L)\n\n    // We write the first 10 bytes immediately (that's maxByteCount again).\n    // Wait a quarter second for each subsequent 5 bytes (that's waitByteCount again).\n    takeFully(15L)\n    assertElapsed(250L)\n  }\n\n  @Test fun takeFullyWhenSaturated() {\n    throttler.bytesPerSecond(400L, 5L, 10L)\n\n    // Saturate the throttler.\n    assertThat(take(10L)).isEqualTo(10L)\n    assertElapsed(0L)\n\n    // At 400 bytes per second it takes 250 ms to read 100 bytes.\n    takeFully(100L)\n    assertElapsed(250L)\n  }\n\n  @Test fun takeFullyNoLimit() {\n    throttler.bytesPerSecond(0L, 5L, 10L)\n    takeFully(100L)\n    assertElapsed(0L)\n  }\n\n  /**\n   * We had a bug where integer division truncation would cause us to call wait() for 0 nanos. We\n   * fixed it by minimizing integer division generally, and by handling that case specifically.\n   */\n  @Test fun infiniteWait() {\n    throttler.bytesPerSecond(3, maxByteCount = 4, waitByteCount = 4)\n    takeFully(7)\n    assertElapsed(1000L)\n  }\n\n  /** Take at least the minimum and up to `byteCount` bytes, sleeping once if necessary. */\n  private fun take(byteCount: Long): Long {\n    val byteCountOrWaitNanos = throttler.byteCountOrWaitNanos(nowNanos, byteCount)\n    if (byteCountOrWaitNanos >= 0L) return byteCountOrWaitNanos\n\n    nowNanos += -byteCountOrWaitNanos\n\n    val resultAfterWait = throttler.byteCountOrWaitNanos(nowNanos, byteCount)\n    assertThat(resultAfterWait).isGreaterThan(0L)\n    return resultAfterWait\n  }\n\n  /** Take all of `byteCount` bytes, advancing the clock until they're all taken. */\n  private fun takeFully(byteCount: Long) {\n    var remaining = byteCount\n    while (remaining > 0L) {\n      val byteCountOrWaitNanos = throttler.byteCountOrWaitNanos(nowNanos, remaining)\n      if (byteCountOrWaitNanos >= 0L) {\n        remaining -= byteCountOrWaitNanos\n      } else {\n        nowNanos += -byteCountOrWaitNanos\n      }\n    }\n  }\n\n  private fun assertElapsed(millis: Long) {\n    elapsedNanos += TimeUnit.MILLISECONDS.toNanos(millis)\n    assertThat(nowNanos).isEqualTo(elapsedNanos)\n  }\n\n  private fun sleep(millis: Long) {\n    nowNanos += TimeUnit.MILLISECONDS.toNanos(millis)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ThrottlerTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport kotlin.test.Ignore\nimport okio.TestUtil.randomSource\nimport org.junit.Before\nimport org.junit.Test\n\n@Ignore(\"These tests are flaky and fail on slower hardware, need to be improved\")\nclass ThrottlerTest {\n  private val size = 1024L * 80L // 80 KiB\n  private val source = randomSource(size)\n\n  private val throttler = Throttler()\n  private val throttlerSlow = Throttler()\n\n  private val threads = 4\n\n  @InterceptTest\n  private val executorService = TestExecutor(threads)\n  private var stopwatch = Stopwatch()\n\n  @Before fun setup() {\n    throttler.bytesPerSecond(4 * size, 4096, 8192)\n    throttlerSlow.bytesPerSecond(2 * size, 4096, 8192)\n    stopwatch = Stopwatch()\n  }\n\n  @Test fun source() {\n    throttler.source(source).buffer().readAll(blackholeSink())\n    stopwatch.assertElapsed(0.25)\n  }\n\n  @Test fun sink() {\n    source.buffer().readAll(throttler.sink(blackholeSink()))\n    stopwatch.assertElapsed(0.25)\n  }\n\n  @Test fun doubleSourceThrottle() {\n    throttler.source(throttler.source(source)).buffer().readAll(blackholeSink())\n    stopwatch.assertElapsed(0.5)\n  }\n\n  @Test fun doubleSinkThrottle() {\n    source.buffer().readAll(throttler.sink(throttler.sink(blackholeSink())))\n    stopwatch.assertElapsed(0.5)\n  }\n\n  @Test fun singleSourceMultiThrottleSlowerThenSlow() {\n    source.buffer().readAll(throttler.sink(throttlerSlow.sink(blackholeSink())))\n    stopwatch.assertElapsed(0.5)\n  }\n\n  @Test fun singleSourceMultiThrottleSlowThenSlower() {\n    source.buffer().readAll(throttlerSlow.sink(throttler.sink(blackholeSink())))\n    stopwatch.assertElapsed(0.5)\n  }\n\n  @Test fun slowSourceSlowerSink() {\n    throttler.source(source).buffer().readAll(throttlerSlow.sink(blackholeSink()))\n    stopwatch.assertElapsed(0.5)\n  }\n\n  @Test fun slowSinkSlowerSource() {\n    throttlerSlow.source(source).buffer().readAll(throttler.sink(blackholeSink()))\n    stopwatch.assertElapsed(0.5)\n  }\n\n  @Test fun parallel() {\n    val futures = List(threads) {\n      executorService.submit {\n        val source = randomSource(size)\n        source.buffer().readAll(throttler.sink(blackholeSink()))\n      }\n    }\n    for (future in futures) {\n      future.get()\n    }\n    stopwatch.assertElapsed(1.0)\n  }\n\n  @Test fun parallelFastThenSlower() {\n    val futures = List(threads) {\n      executorService.submit {\n        val source = randomSource(size)\n        source.buffer().readAll(throttler.sink(blackholeSink()))\n      }\n    }\n    Thread.sleep(500)\n    throttler.bytesPerSecond(2 * size)\n    for (future in futures) {\n      future.get()\n    }\n    stopwatch.assertElapsed(1.5)\n  }\n\n  @Test fun parallelSlowThenFaster() {\n    val futures = List(threads) {\n      executorService.submit {\n        val source = randomSource(size)\n        source.buffer().readAll(throttlerSlow.sink(blackholeSink()))\n      }\n    }\n    Thread.sleep(1_000)\n    throttlerSlow.bytesPerSecond(4 * size)\n    for (future in futures) {\n      future.get()\n    }\n    stopwatch.assertElapsed(1.5)\n  }\n\n  @Test fun parallelIndividualThrottle() {\n    val futures = List(threads) {\n      executorService.submit {\n        val throttlerLocal = Throttler()\n        throttlerLocal.bytesPerSecond(4 * size, maxByteCount = 8192)\n\n        val source = randomSource(size)\n        source.buffer().readAll(throttlerLocal.sink(blackholeSink()))\n      }\n    }\n    for (future in futures) {\n      future.get()\n    }\n    stopwatch.assertElapsed(0.25)\n  }\n\n  @Test fun parallelGroupAndIndividualThrottle() {\n    val futures = List(threads) {\n      executorService.submit {\n        val throttlerLocal = Throttler()\n        throttlerLocal.bytesPerSecond(4 * size, maxByteCount = 8192)\n\n        val source = randomSource(size)\n        source.buffer().readAll(throttler.sink(throttlerLocal.sink(blackholeSink())))\n      }\n    }\n    for (future in futures) {\n      future.get()\n    }\n    stopwatch.assertElapsed(1.0)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/TimeoutFactory.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nenum class TimeoutFactory {\n  Base {\n    override fun newTimeout() = Timeout()\n  },\n\n  Forwarding {\n    override fun newTimeout() = ForwardingTimeout(Base.newTimeout())\n  },\n\n  Async {\n    override fun newTimeout() = AsyncTimeout()\n  },\n  ;\n\n  abstract fun newTimeout(): Timeout\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/TimeoutTest.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport java.util.concurrent.TimeUnit\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.Timeout as JUnitTimeout\n\nclass TimeoutTest {\n  @JvmField @Rule\n  val timeout = JUnitTimeout(5, TimeUnit.SECONDS)\n\n  @Test fun intersectWithReturnsAValue() {\n    val timeoutA = Timeout()\n    val timeoutB = Timeout()\n\n    val s = timeoutA.intersectWith(timeoutB) { \"hello\" }\n    assertEquals(\"hello\", s)\n  }\n\n  @Test fun intersectWithPrefersSmallerTimeout() {\n    val timeoutA = Timeout()\n    timeoutA.timeout(smallerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    val timeoutB = Timeout()\n    timeoutB.timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    timeoutA.intersectWith(timeoutB) {\n      assertEquals(smallerTimeoutNanos, timeoutA.timeoutNanos())\n      assertEquals(biggerTimeoutNanos, timeoutB.timeoutNanos())\n    }\n    timeoutB.intersectWith(timeoutA) {\n      assertEquals(smallerTimeoutNanos, timeoutA.timeoutNanos())\n      assertEquals(smallerTimeoutNanos, timeoutB.timeoutNanos())\n    }\n    assertEquals(smallerTimeoutNanos, timeoutA.timeoutNanos())\n    assertEquals(biggerTimeoutNanos, timeoutB.timeoutNanos())\n  }\n\n  @Test fun intersectWithPrefersNonZeroTimeout() {\n    val timeoutA = Timeout()\n\n    val timeoutB = Timeout()\n    timeoutB.timeout(biggerTimeoutNanos, TimeUnit.NANOSECONDS)\n\n    timeoutA.intersectWith(timeoutB) {\n      assertEquals(biggerTimeoutNanos, timeoutA.timeoutNanos())\n      assertEquals(biggerTimeoutNanos, timeoutB.timeoutNanos())\n    }\n    timeoutB.intersectWith(timeoutA) {\n      assertEquals(0L, timeoutA.timeoutNanos())\n      assertEquals(biggerTimeoutNanos, timeoutB.timeoutNanos())\n    }\n    assertEquals(0L, timeoutA.timeoutNanos())\n    assertEquals(biggerTimeoutNanos, timeoutB.timeoutNanos())\n  }\n\n  @Test fun intersectWithPrefersSmallerDeadline() {\n    val timeoutA = Timeout()\n    timeoutA.deadlineNanoTime(smallerDeadlineNanos)\n\n    val timeoutB = Timeout()\n    timeoutB.deadlineNanoTime(biggerDeadlineNanos)\n\n    timeoutA.intersectWith(timeoutB) {\n      assertEquals(smallerDeadlineNanos, timeoutA.deadlineNanoTime())\n      assertEquals(biggerDeadlineNanos, timeoutB.deadlineNanoTime())\n    }\n    timeoutB.intersectWith(timeoutA) {\n      assertEquals(smallerDeadlineNanos, timeoutA.deadlineNanoTime())\n      assertEquals(smallerDeadlineNanos, timeoutB.deadlineNanoTime())\n    }\n    assertEquals(smallerDeadlineNanos, timeoutA.deadlineNanoTime())\n    assertEquals(biggerDeadlineNanos, timeoutB.deadlineNanoTime())\n  }\n\n  @Test fun intersectWithPrefersNonZeroDeadline() {\n    val timeoutA = Timeout()\n\n    val timeoutB = Timeout()\n    timeoutB.deadlineNanoTime(biggerDeadlineNanos)\n\n    timeoutA.intersectWith(timeoutB) {\n      assertEquals(biggerDeadlineNanos, timeoutA.deadlineNanoTime())\n      assertEquals(biggerDeadlineNanos, timeoutB.deadlineNanoTime())\n    }\n    timeoutB.intersectWith(timeoutA) {\n      assertFalse(timeoutA.hasDeadline())\n      assertEquals(biggerDeadlineNanos, timeoutB.deadlineNanoTime())\n    }\n    assertFalse(timeoutA.hasDeadline())\n    assertEquals(biggerDeadlineNanos, timeoutB.deadlineNanoTime())\n  }\n\n  companion object {\n    val smallerTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(500L)\n    val biggerTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(1500L)\n\n    val smallerDeadlineNanos = TimeUnit.MILLISECONDS.toNanos(500L)\n    val biggerDeadlineNanos = TimeUnit.MILLISECONDS.toNanos(1500L)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/Utf8Test.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport java.io.EOFException\nimport kotlin.text.Charsets.UTF_8\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.of\nimport okio.TestUtil.SEGMENT_SIZE\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertFalse\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Test\n\nclass Utf8Test {\n  @Test\n  fun oneByteCharacters() {\n    assertEncoded(\"00\", 0x00) // Smallest 1-byte character.\n    assertEncoded(\"20\", ' '.code)\n    assertEncoded(\"7e\", '~'.code)\n    assertEncoded(\"7f\", 0x7f) // Largest 1-byte character.\n  }\n\n  @Test\n  fun twoByteCharacters() {\n    assertEncoded(\"c280\", 0x0080) // Smallest 2-byte character.\n    assertEncoded(\"c3bf\", 0x00ff)\n    assertEncoded(\"c480\", 0x0100)\n    assertEncoded(\"dfbf\", 0x07ff) // Largest 2-byte character.\n  }\n\n  @Test\n  fun threeByteCharacters() {\n    assertEncoded(\"e0a080\", 0x0800) // Smallest 3-byte character.\n    assertEncoded(\"e0bfbf\", 0x0fff)\n    assertEncoded(\"e18080\", 0x1000)\n    assertEncoded(\"e1bfbf\", 0x1fff)\n    assertEncoded(\"ed8080\", 0xd000)\n    assertEncoded(\"ed9fbf\", 0xd7ff) // Largest character lower than the min surrogate.\n    assertEncoded(\"ee8080\", 0xe000) // Smallest character greater than the max surrogate.\n    assertEncoded(\"eebfbf\", 0xefff)\n    assertEncoded(\"ef8080\", 0xf000)\n    assertEncoded(\"efbfbf\", 0xffff) // Largest 3-byte character.\n  }\n\n  @Test\n  fun fourByteCharacters() {\n    assertEncoded(\"f0908080\", 0x010000) // Smallest surrogate pair.\n    assertEncoded(\"f48fbfbf\", 0x10ffff) // Largest code point expressible by UTF-16.\n  }\n\n  @Test\n  fun danglingHighSurrogate() {\n    assertStringEncoded(\"3f\", \"\\ud800\") // \"?\"\n  }\n\n  @Test\n  fun lowSurrogateWithoutHighSurrogate() {\n    assertStringEncoded(\"3f\", \"\\udc00\") // \"?\"\n  }\n\n  @Test\n  fun highSurrogateFollowedByNonSurrogate() {\n    assertStringEncoded(\"3f61\", \"\\ud800\\u0061\") // \"?a\": Following character is too low.\n    assertStringEncoded(\"3fee8080\", \"\\ud800\\ue000\") // \"?\\ue000\": Following character is too high.\n  }\n\n  @Test\n  fun doubleLowSurrogate() {\n    assertStringEncoded(\"3f3f\", \"\\udc00\\udc00\") // \"??\"\n  }\n\n  @Test\n  fun doubleHighSurrogate() {\n    assertStringEncoded(\"3f3f\", \"\\ud800\\ud800\") // \"??\"\n  }\n\n  @Test\n  fun highSurrogateLowSurrogate() {\n    assertStringEncoded(\"3f3f\", \"\\udc00\\ud800\") // \"??\"\n  }\n\n  @Test\n  fun multipleSegmentString() {\n    val a = \"a\".repeat(SEGMENT_SIZE + SEGMENT_SIZE + 1)\n    val encoded = Buffer().writeUtf8(a)\n    val expected = Buffer().write(a.toByteArray(UTF_8))\n    assertEquals(expected, encoded)\n  }\n\n  @Test\n  fun stringSpansSegments() {\n    val buffer = Buffer()\n    val a = \"a\".repeat(SEGMENT_SIZE - 1)\n    val b = \"bb\"\n    val c = \"c\".repeat(SEGMENT_SIZE - 1)\n    buffer.writeUtf8(a)\n    buffer.writeUtf8(b)\n    buffer.writeUtf8(c)\n    assertEquals(a + b + c, buffer.readUtf8())\n  }\n\n  @Test\n  fun readEmptyBufferThrowsEofException() {\n    val buffer = Buffer()\n    try {\n      buffer.readUtf8CodePoint()\n      fail()\n    } catch (expected: EOFException) {\n    }\n  }\n\n  @Test\n  fun readLeadingContinuationByteReturnsReplacementCharacter() {\n    val buffer = Buffer()\n    buffer.writeByte(0xbf)\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertTrue(buffer.exhausted())\n  }\n\n  @Test\n  fun readMissingContinuationBytesThrowsEofException() {\n    val buffer = Buffer()\n    buffer.writeByte(0xdf)\n    try {\n      buffer.readUtf8CodePoint()\n      fail()\n    } catch (expected: EOFException) {\n    }\n    assertFalse(buffer.exhausted()) // Prefix byte wasn't consumed.\n  }\n\n  @Test\n  fun readTooLargeCodepointReturnsReplacementCharacter() {\n    // 5-byte and 6-byte code points are not supported.\n    val buffer = Buffer()\n    buffer.write(\"f888808080\".decodeHex())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertTrue(buffer.exhausted())\n  }\n\n  @Test\n  fun readNonContinuationBytesReturnsReplacementCharacter() {\n    // Use a non-continuation byte where a continuation byte is expected.\n    val buffer = Buffer()\n    buffer.write(\"df20\".decodeHex())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertEquals(0x20, buffer.readUtf8CodePoint().toLong()) // Non-continuation character not consumed.\n    assertTrue(buffer.exhausted())\n  }\n\n  @Test\n  fun readCodePointBeyondUnicodeMaximum() {\n    // A 4-byte encoding with data above the U+10ffff Unicode maximum.\n    val buffer = Buffer()\n    buffer.write(\"f4908080\".decodeHex())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertTrue(buffer.exhausted())\n  }\n\n  @Test\n  fun readSurrogateCodePoint() {\n    val buffer = Buffer()\n    buffer.write(\"eda080\".decodeHex())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertTrue(buffer.exhausted())\n    buffer.write(\"edbfbf\".decodeHex())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertTrue(buffer.exhausted())\n  }\n\n  @Test\n  fun readOverlongCodePoint() {\n    // Use 2 bytes to encode data that only needs 1 byte.\n    val buffer = Buffer()\n    buffer.write(\"c080\".decodeHex())\n    assertEquals(REPLACEMENT_CODE_POINT.toLong(), buffer.readUtf8CodePoint().toLong())\n    assertTrue(buffer.exhausted())\n  }\n\n  @Test\n  fun writeSurrogateCodePoint() {\n    assertStringEncoded(\"ed9fbf\", \"\\ud7ff\") // Below lowest surrogate is okay.\n    assertStringEncoded(\"3f\", \"\\ud800\") // Lowest surrogate gets '?'.\n    assertStringEncoded(\"3f\", \"\\udfff\") // Highest surrogate gets '?'.\n    assertStringEncoded(\"ee8080\", \"\\ue000\") // Above highest surrogate is okay.\n  }\n\n  @Test\n  fun writeCodePointBeyondUnicodeMaximum() {\n    val buffer = Buffer()\n    try {\n      buffer.writeUtf8CodePoint(0x110000)\n      fail()\n    } catch (expected: IllegalArgumentException) {\n      assertEquals(\"Unexpected code point: 0x110000\", expected.message)\n    }\n  }\n\n  @Test\n  fun size() {\n    assertEquals(0, \"\".utf8Size())\n    assertEquals(3, \"abc\".utf8Size())\n    assertEquals(16, \"təˈranəˌsôr\".utf8Size())\n  }\n\n  @Test\n  fun sizeWithBounds() {\n    assertEquals(0, \"\".utf8Size(0, 0))\n    assertEquals(0, \"abc\".utf8Size(0, 0))\n    assertEquals(1, \"abc\".utf8Size(1, 2))\n    assertEquals(2, \"abc\".utf8Size(0, 2))\n    assertEquals(3, \"abc\".utf8Size(0, 3))\n    assertEquals(16, \"təˈranəˌsôr\".utf8Size(0, 11))\n    assertEquals(5, \"təˈranəˌsôr\".utf8Size(3, 7))\n  }\n\n  @Test\n  fun sizeBoundsCheck() {\n    try {\n      null!!.utf8Size(0, 0)\n      fail()\n    } catch (expected: NullPointerException) {\n    }\n    try {\n      \"abc\".utf8Size(-1, 2)\n      fail()\n    } catch (expected: IllegalArgumentException) {\n    }\n    try {\n      \"abc\".utf8Size(2, 1)\n      fail()\n    } catch (expected: IllegalArgumentException) {\n    }\n    try {\n      \"abc\".utf8Size(1, 4)\n      fail()\n    } catch (expected: IllegalArgumentException) {\n    }\n  }\n\n  private fun assertEncoded(hex: String, vararg codePoints: Int) {\n    assertCodePointEncoded(hex, *codePoints)\n    assertCodePointDecoded(hex, *codePoints)\n    assertStringEncoded(hex, String(codePoints, 0, codePoints.size))\n  }\n\n  private fun assertCodePointEncoded(hex: String, vararg codePoints: Int) {\n    val buffer = Buffer()\n    for (codePoint in codePoints) {\n      buffer.writeUtf8CodePoint(codePoint)\n    }\n    assertEquals(buffer.readByteString(), hex.decodeHex())\n  }\n\n  private fun assertCodePointDecoded(hex: String, vararg codePoints: Int) {\n    val buffer = Buffer().write(hex.decodeHex())\n    for (codePoint in codePoints) {\n      assertEquals(codePoint.toLong(), buffer.readUtf8CodePoint().toLong())\n    }\n    assertTrue(buffer.exhausted())\n  }\n\n  private fun assertStringEncoded(hex: String, string: String) {\n    val expectedUtf8 = hex.decodeHex()\n\n    // Confirm our expectations are consistent with the platform.\n    val platformUtf8 = of(*string.toByteArray(charset(\"UTF-8\")))\n    assertEquals(expectedUtf8, platformUtf8)\n\n    // Confirm our implementation matches those expectations.\n    val actualUtf8 = Buffer().writeUtf8(string).readByteString()\n    assertEquals(expectedUtf8, actualUtf8)\n\n    // Confirm we are consistent when writing one code point at a time.\n    val bufferUtf8 = Buffer()\n    var i = 0\n    while (i < string.length) {\n      val c = string.codePointAt(i)\n      bufferUtf8.writeUtf8CodePoint(c)\n      i += Character.charCount(c)\n    }\n    assertEquals(expectedUtf8, bufferUtf8.readByteString())\n\n    // Confirm we are consistent when measuring lengths.\n    assertEquals(expectedUtf8.size.toLong(), string.utf8Size())\n    assertEquals(expectedUtf8.size.toLong(), string.utf8Size(0, string.length))\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/WaitUntilNotifiedTest.kt",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.Burst\nimport app.cash.burst.InterceptTest\nimport java.io.InterruptedIOException\nimport java.util.concurrent.TimeUnit\nimport kotlin.time.Duration.Companion.milliseconds\nimport okio.TestUtil.assumeNotWindows\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertTrue\nimport org.junit.Assert.fail\nimport org.junit.Test\n\n@Burst\nclass WaitUntilNotifiedTest(\n  factory: TimeoutFactory,\n) {\n  private val timeout = factory.newTimeout()\n\n  @InterceptTest\n  private val testExecutor = TestExecutor(0)\n\n  @Test\n  @Synchronized\n  fun notified() {\n    timeout.timeout(5000, TimeUnit.MILLISECONDS)\n    val start = now()\n    testExecutor.schedule(1000.milliseconds) {\n      synchronized(this@WaitUntilNotifiedTest) {\n        (this as Object).notify()\n      }\n    }\n    timeout.waitUntilNotified(this)\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun timeout() {\n    assumeNotWindows()\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.waitUntilNotified(this)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun deadline() {\n    assumeNotWindows()\n    timeout.deadline(1000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.waitUntilNotified(this)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun deadlineBeforeTimeout() {\n    assumeNotWindows()\n    timeout.timeout(5000, TimeUnit.MILLISECONDS)\n    timeout.deadline(1000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.waitUntilNotified(this)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun timeoutBeforeDeadline() {\n    assumeNotWindows()\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.deadline(5000, TimeUnit.MILLISECONDS)\n    val start = now()\n    try {\n      timeout.waitUntilNotified(this)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun deadlineAlreadyReached() {\n    assumeNotWindows()\n    timeout.deadlineNanoTime(System.nanoTime())\n    val start = now()\n    try {\n      timeout.waitUntilNotified(this)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(0.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun threadInterrupted() {\n    assumeNotWindows()\n    val start = now()\n    Thread.currentThread().interrupt()\n    try {\n      timeout.waitUntilNotified(this)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"interrupted\", expected.message)\n      assertTrue(Thread.interrupted())\n    }\n    assertElapsed(0.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun threadInterruptedOnThrowIfReached() {\n    assumeNotWindows()\n    Thread.currentThread().interrupt()\n    try {\n      timeout.throwIfReached()\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"interrupted\", expected.message)\n      assertTrue(Thread.interrupted())\n    }\n  }\n\n  @Test\n  @Synchronized\n  fun cancelBeforeWaitDoesNothing() {\n    assumeNotWindows()\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.cancel()\n    val start = now()\n    try {\n      timeout.waitUntilNotified(this)\n      fail()\n    } catch (expected: InterruptedIOException) {\n      assertEquals(\"timeout\", expected.message)\n    }\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun canceledTimeoutDoesNotThrowWhenNotNotifiedOnTime() {\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.cancelLater(500)\n\n    val start = now()\n    timeout.waitUntilNotified(this) // Returns early but doesn't throw.\n    assertElapsed(1000.0, start)\n  }\n\n  @Test\n  @Synchronized\n  fun multipleCancelsAreIdempotent() {\n    timeout.timeout(1000, TimeUnit.MILLISECONDS)\n    timeout.cancelLater(250)\n    timeout.cancelLater(500)\n    timeout.cancelLater(750)\n\n    val start = now()\n    timeout.waitUntilNotified(this) // Returns early but doesn't throw.\n    assertElapsed(1000.0, start)\n  }\n\n  /** Returns the nanotime in milliseconds as a double for measuring timeouts.  */\n  private fun now(): Double {\n    return System.nanoTime() / 1000000.0\n  }\n\n  /**\n   * Fails the test unless the time from start until now is duration, accepting differences in\n   * -50..+450 milliseconds.\n   */\n  private fun assertElapsed(duration: Double, start: Double) {\n    assertEquals(duration, now() - start - 200.0, 250.0)\n  }\n\n  private fun Timeout.cancelLater(delay: Long) {\n    testExecutor.schedule(delay.milliseconds) {\n      cancel()\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ZipBuilder.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport org.junit.Assume.assumeTrue\n\n/**\n * Execute the `zip` command line program to create reference zip files for testing.\n *\n * Unfortunately the `zip` command line is limited in its ability to create exactly the zip files\n * we want for testing. In particular, the only way it will create zip64 archives is if the input\n * file is received from a UNIX pipe. (In such cases the file length is unknown in advance, and so\n * the tool uses zip64 for the possibility of a very large file.) Files received from a pipe are\n * always named `-`.\n */\nclass ZipBuilder(\n  private val directory: Path,\n) {\n  private val fileSystem = FileSystem.SYSTEM\n\n  private val entries = mutableListOf<Entry>()\n  private val options = mutableListOf<String>()\n  private var archiveComment: String = \"\"\n\n  @JvmOverloads\n  fun addEntry(\n    path: String,\n    content: String? = null,\n    directory: Boolean = false,\n    comment: String = \"\",\n    modifiedAt: String? = null,\n    accessedAt: String? = null,\n    zip64: Boolean = false,\n  ) = apply {\n    entries += Entry(path, content, directory, comment, modifiedAt, accessedAt, zip64)\n  }\n\n  fun addOption(option: String) = apply { options += option }\n\n  fun archiveComment(archiveComment: String) = apply { this.archiveComment = archiveComment }\n\n  fun build(): Path {\n    assumeTrue(\"ZipBuilder doesn't work on Windows\", Path.DIRECTORY_SEPARATOR == \"/\")\n\n    val archive = directory / \"${randomToken(16)}.zip\"\n    val anyZip64 = entries.any { it.zip64 }\n\n    require(!anyZip64 || entries.size == 1) {\n      \"ZipBuilder permits at most one zip64 entry\"\n    }\n    require(!anyZip64 || archiveComment.isEmpty()) {\n      \"Cannot combine archiveComment with zip64\"\n    }\n\n    val promptForComments = entries.any { it.comment.isNotEmpty() }\n    if (promptForComments) {\n      options += \"--entry-comments\"\n    }\n    if (archiveComment.isNotEmpty()) {\n      options += \"--archive-comment\"\n    }\n\n    val command = mutableListOf<String>()\n    command += \"zip\"\n    command += options\n    command += archive.toString()\n\n    for (entry in entries) {\n      if (!entry.zip64) {\n        val absolutePath = directory / entry.path\n        fileSystem.createDirectories(absolutePath.parent!!)\n\n        if (entry.directory) {\n          fileSystem.createDirectories(absolutePath)\n        } else {\n          fileSystem.write(absolutePath) {\n            writeUtf8(entry.content!!)\n          }\n        }\n\n        if (entry.modifiedAt != null) {\n          touch(\"-m\", absolutePath, entry.modifiedAt)\n        }\n        if (entry.accessedAt != null) {\n          touch(\"-a\", absolutePath, entry.accessedAt)\n        }\n      }\n      command += entry.path\n    }\n\n    val process = ProcessBuilder()\n      .command(command)\n      .directory(directory.toFile())\n      .redirectOutput(ProcessBuilder.Redirect.INHERIT)\n      .redirectError(ProcessBuilder.Redirect.INHERIT)\n      .start()\n\n    process.outputStream.sink().buffer().use { sink ->\n      if (anyZip64) {\n        sink.writeUtf8(entries.single().content!!)\n      }\n      if (promptForComments) {\n        for (entry in entries) {\n          sink.writeUtf8(entry.comment)\n          sink.writeUtf8(\"\\n\")\n          sink.flush()\n        }\n      }\n      sink.writeUtf8(archiveComment)\n    }\n\n    val result = process.waitFor()\n    require(result == 0) { \"process failed: $command\" }\n\n    return archive\n  }\n\n  private fun touch(option: String, absolutePath: Path, date: String) {\n    val exitCode = ProcessBuilder()\n      .command(\"touch\", option, \"-t\", date, absolutePath.toString())\n      .apply { environment()[\"TZ\"] = \"UTC\" }\n      .start()\n      .waitFor()\n    require(exitCode == 0)\n  }\n\n  private class Entry(\n    val path: String,\n    val content: String?,\n    val directory: Boolean,\n    val comment: String,\n    val modifiedAt: String?,\n    val accessedAt: String?,\n    val zip64: Boolean,\n  ) {\n    init {\n      require(directory != (content != null)) { \"must be a directory or have content\" }\n      if (zip64) {\n        require(path == \"-\") { \"zip64 file name must be '-'\" }\n        require(comment == \"\") { \"zip64 must not have comments\" }\n        require(modifiedAt == null) { \"zip64 must not have modifiedAt\" }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/ZipFileSystemJavaTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport okio.Path.Companion.toPath\nimport org.junit.Test\n\nclass ZipFileSystemJavaTest {\n  private val fileSystem = FileSystem.SYSTEM\n\n  @InterceptTest\n  private val baseTestDirectory = TestDirectory(fileSystem)\n  private val base: Path get() = baseTestDirectory.path\n\n  @Test\n  fun zipFileSystemApi() {\n    val zipPath = ZipBuilder(base)\n      .addEntry(\"hello.txt\", \"Hello World\")\n      .build()\n    val zipFileSystem = fileSystem.openZip(zipPath)\n    zipFileSystem.source(\"hello.txt\".toPath(false)).buffer().use { source ->\n      val content = source.readUtf8()\n      assertThat(content).isEqualTo(\"Hello World\")\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/internal/HmacTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio.internal\n\nimport app.cash.burst.Burst\nimport javax.crypto.Mac\nimport javax.crypto.spec.SecretKeySpec\nimport kotlin.random.Random\nimport okio.ByteString\nimport org.junit.Assert\nimport org.junit.Test\n\n/**\n * Check the [Hmac] implementation against the reference [Mac] JVM implementation.\n */\n@Burst\nclass HmacTest(\n  keySize: KeySize,\n  dataSize: DataSize,\n  algorithm: Algorithm,\n) {\n  private val random = Random(682741861446)\n  private val key = random.nextBytes(keySize.size)\n  private val bytes = random.nextBytes(dataSize.size)\n  private val mac = algorithm.HmacFactory(ByteString(key))\n  private val expected = hmac(algorithm.algorithmName, key, bytes)\n\n  @Test\n  fun hmac() {\n    mac.update(bytes)\n    val hmacValue = mac.digest()\n\n    Assert.assertArrayEquals(expected, hmacValue)\n  }\n\n  @Test\n  fun hmacBytes() {\n    for (byte in bytes) {\n      mac.update(byteArrayOf(byte))\n    }\n    val hmacValue = mac.digest()\n\n    Assert.assertArrayEquals(expected, hmacValue)\n  }\n}\n\nenum class KeySize(val size: Int) {\n  K8(8), K32(32), K48(48), K64(64), K128(128), K256(256),\n}\n\nenum class DataSize(val size: Int) {\n  V0(0), V32(32), V64(64), V128(128), V256(256), V512(512),\n}\n\nenum class Algorithm(\n  val algorithmName: String,\n  internal val HmacFactory: (key: ByteString) -> Hmac,\n) {\n  Sha1(\"HmacSha1\", Hmac.Companion::sha1),\n  Sha256(\"HmacSha256\", Hmac.Companion::sha256),\n  Sha512(\"HmacSha512\", Hmac.Companion::sha512),\n}\n\nprivate fun hmac(algorithm: String, key: ByteArray, bytes: ByteArray) =\n  Mac.getInstance(algorithm).apply { init(SecretKeySpec(key, algorithm)) }.doFinal(bytes)\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/internal/PriorityQueueTest.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.internal\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport java.lang.Integer.numberOfTrailingZeros\nimport java.util.concurrent.TimeUnit\nimport kotlin.time.Duration.Companion.nanoseconds\nimport okio.AsyncTimeout\nimport okio.PriorityQueue\nimport org.junit.Test\n\nclass PriorityQueueTest {\n  private val TIME_UNIT = TimeUnit.NANOSECONDS\n  val now = 0L\n\n  @Test\n  fun insertedElementIsSmallerThanItsAncestors() {\n    val before = \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21............\n      |\"\"\".toHeap()\n\n    before.add(AsyncTimeout(2))\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............2................\n      |......10...............5........\n      |..28......29......21......20....\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun insertedElementWithSmallerTimeoutButLargerTimeoutAtIsLargerThanItsAncestors() {\n    val before = \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21............\n      |\"\"\".toHeap()\n\n    AsyncTimeout(2, false)\n      .apply { setTimeoutAt(now + 28.nanoseconds.inWholeNanoseconds) }\n      .let { before.add(it) }\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21......30....\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun insertedElementWithLargerTimeoutButSmallerTimeoutAtIsSmallerThanItsAncestors() {\n    val before = \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21............\n      |\"\"\".toHeap()\n\n    // now=-30, timeoutNanos=30, timeoutAt=0\n    AsyncTimeout(30, false)\n      .apply { setTimeoutAt(now - 30.nanoseconds.inWholeNanoseconds) }\n      .let { before.add(it) }\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............0................\n      |......10...............5........\n      |..28......29......21......20....\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun insertedElementIsSmallerThanParent() {\n    val before = \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21............\n      |\"\"\".toHeap()\n\n    before.add(AsyncTimeout(15))\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............5................\n      |......10..............15........\n      |..28......29......21......20....\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun lastElementIsGreaterThanOneOfRemovedElementChildren() {\n    val before = \"\"\"\n      |...............5................\n      |......10..............20........\n      |..11......12......21......22....\n      |\"\"\".toHeap()\n\n    before.remove(before[10])\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............5................\n      |......11..............20........\n      |..22......12......21............\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun insertedElementIsLargerThanBothItsParent() {\n    val before = \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21............\n      |\"\"\".toHeap()\n\n    before.add(AsyncTimeout(24))\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21......24....\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun lastElementIsGreaterThanRemovedElement() {\n    val before = \"\"\"\n      |...............5................\n      |......10..............20........\n      |..28......29......21......22....\n      |\"\"\".toHeap()\n\n    before.remove(before[10])\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............5................\n      |......22..............20........\n      |..28......29......21............\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun lastElementIsLessThanRemovedElement() {\n    val before = \"\"\"\n      |...............5................\n      |......20..............10........\n      |..21......22......11......12....\n      |\"\"\".toHeap()\n\n    before.remove(before[20])\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............5................\n      |......12..............10........\n      |..21......22......11............\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  @Test\n  fun lastElementIsLessThanRemovedElementParent() {\n    val before = \"\"\"\n      |...............................5................................\n      |..............10..............................20................\n      |......11..............12..............21..............22........\n      |..13......14....................................................\n      |\"\"\".toHeap()\n\n    before.remove(before[21])\n\n    assertThat(before.toDebugString()).isEqualTo(\n      \"\"\"\n      |...............................5................................\n      |..............10..............................14................\n      |......11..............12..............20..............22........\n      |..13............................................................\n      |\n      \"\"\".trimMargin(),\n    )\n  }\n\n  private fun AsyncTimeout(value: Long, setTimeoutAt: Boolean = true) = AsyncTimeout().apply {\n    timeout(value, TIME_UNIT)\n    if (setTimeoutAt) setTimeoutAt(now)\n  }\n\n  private fun String.toHeap(): PriorityQueue {\n    val nodeValues = trimMargin()\n      .replace(\".\", \" \")\n      .trim()\n      .split(Regex(\"\\\\s+\", RegexOption.MULTILINE))\n      .map { it.toLong() }\n\n    val result = PriorityQueue()\n\n    for (i in nodeValues) {\n      AsyncTimeout(i).let { result.add(it) }\n    }\n\n    val formattedBack = result.toDebugString()\n    assertThat(formattedBack, \"input is well-formatted\").isEqualTo(this.trimMargin())\n\n    return result\n  }\n\n  private operator fun PriorityQueue.get(value: Long): AsyncTimeout {\n    return array.single { it?.timeoutNanos() == TIME_UNIT.toNanos(value) }!!\n  }\n\n  /**\n   * Returns a string like this:\n   *\n   * ```\n   * ...............5................\n   * ......12..............10........\n   * ..21......22......11............\n   * ```\n   */\n  private fun PriorityQueue.toDebugString() = buildString {\n    val nodeWidth = 4\n    val height = numberOfTrailingZeros(Integer.highestOneBit(size)) + 1\n    val width = (1 shl height) - 1\n    var index = 1 // Heap's first element is at 1!\n    for (row in 0 until height) {\n      val printAt = height - row - 1\n      for (column in 1..width) {\n        if (\n          numberOfTrailingZeros(column) != printAt ||\n          index >= array.size ||\n          array[index] == null\n        ) {\n          append(\".\".repeat(nodeWidth))\n        } else {\n          val nodeValue = array[index++]!!.timeoutAt.toString()\n          append(\".\".repeat(nodeWidth - nodeValue.length))\n          append(nodeValue)\n        }\n      }\n      append(\".\".repeat(nodeWidth))\n      append(\"\\n\")\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/internal/ResourceFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio.internal\n\nimport app.cash.burst.InterceptTest\nimport assertk.assertThat\nimport assertk.assertions.containsAtLeast\nimport assertk.assertions.containsExactly\nimport assertk.assertions.containsExactlyInAnyOrder\nimport assertk.assertions.hasMessage\nimport assertk.assertions.isEmpty\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isFalse\nimport assertk.assertions.isGreaterThan\nimport assertk.assertions.isNotNull\nimport assertk.assertions.isNull\nimport assertk.assertions.isTrue\nimport java.net.URL\nimport java.net.URLClassLoader\nimport java.util.Enumeration\nimport kotlin.reflect.KClass\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.fail\nimport okio.BufferedSource\nimport okio.ByteString\nimport okio.FileNotFoundException\nimport okio.FileSystem\nimport okio.ForwardingFileSystem\nimport okio.IOException\nimport okio.Path\nimport okio.Path.Companion.toPath\nimport okio.TestDirectory\nimport okio.ZipBuilder\nimport org.junit.Test\n\nclass ResourceFileSystemTest {\n  private val fileSystem = FileSystem.RESOURCES as ResourceFileSystem\n\n  @InterceptTest\n  private val baseTestDirectory = TestDirectory(FileSystem.SYSTEM)\n  private val base: Path get() = baseTestDirectory.path\n\n  @Test\n  fun testResourceA() {\n    val path = \"okio/resourcefilesystem/a.txt\".toPath()\n\n    val metadata = fileSystem.metadataOrNull(path)!!\n\n    assertThat(metadata.size).isEqualTo(1L)\n    assertThat(metadata.isRegularFile).isTrue()\n    assertThat(metadata.isDirectory).isFalse()\n\n    val content = fileSystem.read(path) { readUtf8() }\n    assertThat(fileSystem.metadata(path).isRegularFile).isTrue()\n\n    assertThat(content).isEqualTo(\"a\")\n  }\n\n  @Test\n  fun testResourceB() {\n    val path = \"okio/resourcefilesystem/b/b.txt\".toPath()\n\n    val metadata = fileSystem.metadataOrNull(path)!!\n\n    assertThat(metadata.size).isEqualTo(3L)\n    assertThat(metadata.isRegularFile).isTrue()\n    assertThat(metadata.isDirectory).isFalse()\n\n    val content = fileSystem.read(path) { readUtf8() }\n    assertThat(fileSystem.metadata(path).isRegularFile).isTrue()\n\n    assertThat(content).isEqualTo(\"b/b\")\n  }\n\n  @Test\n  fun testSingleArchive() {\n    val zipPath = ZipBuilder(base)\n      .addEntry(\"hello.txt\", \"Hello World\")\n      .addEntry(\"directory/subdirectory/child.txt\", \"Another file!\")\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .build()\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(arrayOf(zipPath.toFile().toURI().toURL()), null),\n      indexEagerly = false,\n    )\n\n    assertThat(resourceFileSystem.read(\"hello.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Hello World\")\n    assertThat(\n      resourceFileSystem.metadata(\"hello.txt\".toPath()).isRegularFile,\n    ).isTrue()\n\n    assertThat(resourceFileSystem.read(\"directory/subdirectory/child.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Another file!\")\n    assertThat(\n      resourceFileSystem.metadata(\"directory/subdirectory/child.txt\".toPath()).isRegularFile,\n    ).isTrue()\n\n    assertThat(resourceFileSystem.list(\"/\".toPath())).containsExactlyInAnyOrder(\n      \"/META-INF\".toPath(),\n      \"/hello.txt\".toPath(),\n      \"/directory\".toPath(),\n    )\n    assertThat(resourceFileSystem.list(\"/directory\".toPath()))\n      .containsExactly(\"/directory/subdirectory\".toPath())\n    assertThat(resourceFileSystem.list(\"/directory/subdirectory\".toPath()))\n      .containsExactly(\"/directory/subdirectory/child.txt\".toPath())\n\n    val metadata = resourceFileSystem.metadata(\".\".toPath())\n    assertThat(metadata.isDirectory).isTrue()\n  }\n\n  @Test\n  fun testDirectoryAndJarOverlap() {\n    val filesAPath = base / \"filesA\"\n    FileSystem.SYSTEM.createDirectories(filesAPath / \"colors\")\n    FileSystem.SYSTEM.write(filesAPath / \"colors\" / \"red.txt\") { writeUtf8(\"Apples are red\") }\n    FileSystem.SYSTEM.write(filesAPath / \"colors\" / \"green.txt\") { writeUtf8(\"Grass is green\") }\n    val zipBPath = ZipBuilder(base)\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .addEntry(\"colors/blue.txt\", \"The sky is blue\")\n      .addEntry(\"colors/green.txt\", \"Limes are green\")\n      .build()\n\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(\n        arrayOf(\n          filesAPath.toFile().toURI().toURL(),\n          zipBPath.toFile().toURI().toURL(),\n        ),\n        null,\n      ),\n      indexEagerly = false,\n    )\n\n    assertThat(resourceFileSystem.read(\"/colors/red.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Apples are red\")\n    assertThat(resourceFileSystem.read(\"/colors/green.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Grass is green\")\n    assertThat(resourceFileSystem.read(\"/colors/blue.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"The sky is blue\")\n\n    assertThat(resourceFileSystem.metadata(\"/colors/red.txt\".toPath()).isRegularFile).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors/green.txt\".toPath()).isRegularFile).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors/blue.txt\".toPath()).isRegularFile).isTrue()\n\n    assertThat(resourceFileSystem.list(\"/\".toPath())).containsExactlyInAnyOrder(\n      \"/META-INF\".toPath(),\n      \"/colors\".toPath(),\n    )\n    assertThat(resourceFileSystem.list(\"/colors\".toPath())).containsExactlyInAnyOrder(\n      \"/colors/red.txt\".toPath(),\n      \"/colors/green.txt\".toPath(),\n      \"/colors/blue.txt\".toPath(),\n    )\n\n    assertThat(resourceFileSystem.metadata(\"/\".toPath()).isDirectory).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors\".toPath()).isDirectory).isTrue()\n  }\n\n  @Test\n  fun testDirectoryAndDirectoryOverlap() {\n    val filesAPath = base / \"filesA\"\n    FileSystem.SYSTEM.createDirectories(filesAPath / \"colors\")\n    FileSystem.SYSTEM.write(filesAPath / \"colors\" / \"red.txt\") { writeUtf8(\"Apples are red\") }\n    FileSystem.SYSTEM.write(filesAPath / \"colors\" / \"green.txt\") { writeUtf8(\"Grass is green\") }\n    val filesBPath = base / \"filesB\"\n    FileSystem.SYSTEM.createDirectories(filesBPath / \"colors\")\n    FileSystem.SYSTEM.write(filesBPath / \"colors\" / \"blue.txt\") { writeUtf8(\"The sky is blue\") }\n    FileSystem.SYSTEM.write(filesBPath / \"colors\" / \"green.txt\") { writeUtf8(\"Limes are green\") }\n\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(\n        arrayOf(\n          filesAPath.toFile().toURI().toURL(),\n          filesBPath.toFile().toURI().toURL(),\n        ),\n        null,\n      ),\n      indexEagerly = false,\n    )\n\n    assertThat(resourceFileSystem.read(\"/colors/red.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Apples are red\")\n    assertThat(resourceFileSystem.read(\"/colors/green.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Grass is green\")\n    assertThat(resourceFileSystem.read(\"/colors/blue.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"The sky is blue\")\n\n    assertThat(resourceFileSystem.metadata(\"/colors/red.txt\".toPath()).isRegularFile).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors/green.txt\".toPath()).isRegularFile).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors/blue.txt\".toPath()).isRegularFile).isTrue()\n\n    assertThat(resourceFileSystem.list(\"/\".toPath())).containsExactlyInAnyOrder(\n      \"/colors\".toPath(),\n    )\n    assertThat(resourceFileSystem.list(\"/colors\".toPath())).containsExactlyInAnyOrder(\n      \"/colors/red.txt\".toPath(),\n      \"/colors/green.txt\".toPath(),\n      \"/colors/blue.txt\".toPath(),\n    )\n\n    assertThat(resourceFileSystem.metadata(\"/\".toPath()).isDirectory).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors\".toPath()).isDirectory).isTrue()\n  }\n\n  @Test\n  fun testJarAndJarOverlap() {\n    val zipAPath = ZipBuilder(base)\n      .addEntry(\"colors/red.txt\", \"Apples are red\")\n      .addEntry(\"colors/green.txt\", \"Grass is green\")\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .build()\n    val zipBPath = ZipBuilder(base)\n      .addEntry(\"colors/blue.txt\", \"The sky is blue\")\n      .addEntry(\"colors/green.txt\", \"Limes are green\")\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .build()\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(\n        arrayOf(\n          zipAPath.toFile().toURI().toURL(),\n          zipBPath.toFile().toURI().toURL(),\n        ),\n        null,\n      ),\n      indexEagerly = false,\n    )\n\n    assertThat(resourceFileSystem.read(\"/colors/red.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Apples are red\")\n    assertThat(resourceFileSystem.read(\"/colors/green.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Grass is green\")\n    assertThat(resourceFileSystem.read(\"/colors/blue.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"The sky is blue\")\n\n    assertThat(resourceFileSystem.metadata(\"/colors/red.txt\".toPath()).isRegularFile).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors/green.txt\".toPath()).isRegularFile).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors/blue.txt\".toPath()).isRegularFile).isTrue()\n\n    assertThat(resourceFileSystem.list(\"/\".toPath())).containsExactlyInAnyOrder(\n      \"/META-INF\".toPath(),\n      \"/colors\".toPath(),\n    )\n    assertThat(resourceFileSystem.list(\"/colors\".toPath())).containsExactlyInAnyOrder(\n      \"/colors/red.txt\".toPath(),\n      \"/colors/green.txt\".toPath(),\n      \"/colors/blue.txt\".toPath(),\n    )\n\n    assertThat(resourceFileSystem.metadata(\"/\".toPath()).isDirectory).isTrue()\n    assertThat(resourceFileSystem.metadata(\"/colors\".toPath()).isDirectory).isTrue()\n  }\n\n  @Test\n  fun testResourceMissing() {\n    val path = \"okio/resourcefilesystem/b/c.txt\".toPath()\n\n    assertThat(fileSystem.metadataOrNull(path)).isNull()\n\n    try {\n      fileSystem.read(path) { readUtf8() }\n      fail()\n    } catch (ioe: IOException) {\n      assertThat(ioe.message).isEqualTo(\"file not found: okio/resourcefilesystem/b/c.txt\")\n    }\n  }\n\n  @Test\n  fun testProjectIsListable() {\n    val path = \"okio/resourcefilesystem/b/\".toPath()\n\n    val metadata = fileSystem.metadataOrNull(path)!!\n\n    assertThat(metadata.isDirectory).isTrue()\n    assertThat(metadata.createdAtMillis).isNotNull().isGreaterThan(1L)\n\n    assertThat(fileSystem.list(path).map { it.name }).containsExactly(\"b.txt\")\n  }\n\n  @Test\n  fun testResourceFromJar() {\n    val path = \"LICENSE-junit.txt\".toPath()\n\n    val metadata = fileSystem.metadataOrNull(path)!!\n\n    assertThat(metadata.size).isNotNull().isGreaterThan(10000L)\n    assertThat(metadata.isRegularFile).isTrue()\n    assertThat(metadata.isDirectory).isFalse()\n\n    val content = fileSystem.read(path) { readUtf8Line() }\n\n    assertThat(content).isEqualTo(\"JUnit\")\n  }\n\n  @Test\n  fun testClassFilesOmittedFromJar() {\n    assertThat(fileSystem.list(\"/org/junit/rules\".toPath())).isEmpty()\n    assertThat(fileSystem.metadataOrNull(\"/org/junit/Test.class\".toPath())).isNull()\n  }\n\n  @Test\n  fun testClassFilesOmittedFromDirectory() {\n    val filesPath = base / \"files\"\n    val packagePath = filesPath / \"com\" / \"example\" / \"project\"\n    FileSystem.SYSTEM.createDirectories(packagePath)\n    FileSystem.SYSTEM.write(packagePath / \"Hello.class\") { writeUtf8(\"cafebabe\") }\n\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(\n        arrayOf(filesPath.toFile().toURI().toURL()),\n        null,\n      ),\n      indexEagerly = false,\n    )\n\n    assertThat(resourceFileSystem.list(\"/com/example/project\".toPath())).isEmpty()\n    assertThat(resourceFileSystem.metadataOrNull(\"/com/example/project/Hello.class\".toPath()))\n      .isNull()\n    assertFailsWith<FileNotFoundException> {\n      resourceFileSystem.source(\"/com/example/project/Hello.class\".toPath())\n    }\n  }\n\n  @Test\n  fun testDirectoryFromJar() {\n    val path = \"org/junit/\".toPath()\n\n    val metadata = fileSystem.metadataOrNull(path)\n    assertThat(metadata?.isDirectory).isNotNull().isTrue()\n\n    val files = fileSystem.list(path).map { it.name }\n    assertThat(files).containsAtLeast(\"matchers\", \"rules\")\n    assertThat(files.filter { it.endsWith(\".class\") }).isEmpty()\n  }\n\n  @Test\n  fun packagePath() {\n    val path = ByteString::class.java.`package`.toPath()\n\n    assertThat((path / \"a.txt\").toString())\n      .isEqualTo(\"okio${Path.DIRECTORY_SEPARATOR}a.txt\")\n  }\n\n  @Test\n  fun classResource() {\n    val path = ByteString::class.packagePath!!\n\n    assertThat((path / \"a.txt\").toString())\n      .isEqualTo(\"okio${Path.DIRECTORY_SEPARATOR}a.txt\")\n  }\n\n  /**\n   * Confirm that class loaders aren't accessed until the file system is used. This should save\n   * resources so that zip files aren't decoded if they're unused.\n   */\n  @Test\n  fun testIndexLazily() {\n    val classLoader = object : ClassLoader() {\n      override fun findResources(name: String?): Enumeration<URL> {\n        throw Exception(\"finding a resource\")\n      }\n    }\n\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = classLoader,\n      indexEagerly = false,\n    )\n\n    assertThat(\n      assertFailsWith<Exception> {\n        resourceFileSystem.list(\"/\".toPath())\n      },\n    ).hasMessage(\"finding a resource\")\n  }\n\n  @Test\n  fun testIndexEagerly() {\n    val classLoader = object : ClassLoader() {\n      override fun findResources(name: String?): Enumeration<URL> {\n        throw Exception(\"finding a resource\")\n      }\n    }\n\n    assertThat(\n      assertFailsWith<Exception> {\n        ResourceFileSystem(\n          classLoader = classLoader,\n          indexEagerly = true,\n        )\n      },\n    ).hasMessage(\"finding a resource\")\n  }\n\n  /** Confirm we can read individual files without triggering indexing. */\n  @Test\n  fun testSourceDoesntTriggerIndexing() {\n    val processedPaths = mutableSetOf<Path>()\n    val recordingFileSystem = object : ForwardingFileSystem(FileSystem.SYSTEM) {\n      override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n        processedPaths += path\n        return super.onPathParameter(path, functionName, parameterName)\n      }\n    }\n\n    val zipAPath = ZipBuilder(base)\n      .addEntry(\"colors/red.txt\", \"Apples are red\")\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .build()\n    val zipBPath = ZipBuilder(base)\n      .addEntry(\"colors/blue.txt\", \"The sky is blue\")\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .build()\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(\n        arrayOf(\n          zipAPath.toFile().toURI().toURL(),\n          zipBPath.toFile().toURI().toURL(),\n        ),\n        null,\n      ),\n      indexEagerly = false,\n      systemFileSystem = recordingFileSystem,\n    )\n\n    // Reading paths with source() or read() doesn't index zips.\n    assertThat(\n      resourceFileSystem.read(\"/colors/red.txt\".toPath()) { readUtf8() },\n    ).isEqualTo(\"Apples are red\")\n    assertThat(\n      resourceFileSystem.read(\"/colors/blue.txt\".toPath()) { readUtf8() },\n    ).isEqualTo(\"The sky is blue\")\n    assertThat(processedPaths).isEmpty()\n\n    // Calling list() does though.\n    assertThat(resourceFileSystem.list(\"/colors\".toPath())).containsExactlyInAnyOrder(\n      \"/colors/red.txt\".toPath(),\n      \"/colors/blue.txt\".toPath(),\n    )\n    assertThat(processedPaths).containsExactlyInAnyOrder(\n      zipAPath,\n      zipBPath,\n    )\n  }\n\n  /**\n   * Our resource file system uses [URLClassLoader] internally, which means we need to go back and\n   * forth between [File], [URL], and [URI] models for component paths. This is a big hazard for\n   * escaping special characters and it's likely that some file paths won't survive the round trip!\n   */\n  @Test\n  fun fileNameWithSpaceInPath() {\n    val zipPath = ZipBuilder(base / \"space in directory name\")\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .addEntry(\"hello.txt\", \"Hello World\")\n      .build()\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(arrayOf(zipPath.toFile().toURI().toURL()), null),\n      indexEagerly = false,\n    )\n\n    assertThat(resourceFileSystem.read(\"hello.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Hello World\")\n    assertThat(resourceFileSystem.metadata(\"hello.txt\".toPath())).isNotNull()\n  }\n\n  @Test\n  fun missingResourceSilentlyIgnored() {\n    val zipAPath = ZipBuilder(base)\n      .addEntry(\"META-INF/MANIFEST.MF\", \"Manifest-Version: 1.0\\n\")\n      .addEntry(\"hello.txt\", \"Hello World\")\n      .build()\n    val resourceFileSystem = ResourceFileSystem(\n      classLoader = URLClassLoader(\n        arrayOf(\n          zipAPath.toFile().toURI().toURL(),\n          (base / \"missing.zip\").toFile().toURI().toURL(),\n        ),\n        null,\n      ),\n      indexEagerly = false,\n    )\n\n    assertThat(resourceFileSystem.read(\"hello.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Hello World\")\n  }\n\n  @Test\n  fun listSpecialCharacterNamedFiles() {\n    val path = \"okio/resourcefilesystem/non-ascii\".toPath()\n\n    assertThat(fileSystem.listRecursively(path).toList()).containsExactly(\n      \"/okio/resourcefilesystem/non-ascii/ギリシア神話\".toPath(),\n      \"/okio/resourcefilesystem/non-ascii/ギリシア神話/Ἰλιάς\".toPath(),\n    )\n\n    val content = fileSystem.read(\n      \"/okio/resourcefilesystem/non-ascii/ギリシア神話/Ἰλιάς\".toPath(),\n      BufferedSource::readUtf8,\n    )\n    assertEquals(\"Chante, ô déesse, le courroux du Péléide Achille,\\n\", content)\n  }\n\n  private fun Package.toPath(): Path = name.replace(\".\", \"/\").toPath()\n\n  private val KClass<*>.packagePath: Path?\n    get() = qualifiedName?.replace(\".\", \"/\")?.toPath()?.parent\n}\n"
  },
  {
    "path": "okio/src/jvmTest/kotlin/okio/internal/SetBitsOrZeroTest.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.internal\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport java.util.concurrent.atomic.AtomicInteger\nimport org.junit.Test\n\nclass SetBitsOrZeroTest {\n  @Test\n  fun happyPath() {\n    val value = AtomicInteger(0)\n    assertThat(value.setBitsOrZero(1)).isEqualTo(1)\n    assertThat(value.setBitsOrZero(1)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(2)).isEqualTo(1 or 2)\n    assertThat(value.setBitsOrZero(2)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(8)).isEqualTo(1 or 2 or 8)\n    assertThat(value.setBitsOrZero(8)).isEqualTo(0)\n  }\n\n  @Test\n  fun multipleBits() {\n    val value = AtomicInteger(0)\n    assertThat(value.setBitsOrZero(1 or 4)).isEqualTo(1 or 4)\n    assertThat(value.setBitsOrZero(1)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(4)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(1 or 4)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(1 or 8)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(4 or 8)).isEqualTo(0)\n\n    assertThat(value.setBitsOrZero(8 or 32)).isEqualTo(1 or 4 or 8 or 32)\n    assertThat(value.setBitsOrZero(1)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(4)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(8)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(32)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(8 or 32)).isEqualTo(0)\n    assertThat(value.setBitsOrZero(1 or 32)).isEqualTo(0)\n  }\n}\n"
  },
  {
    "path": "okio/src/jvmTest/resources/okio/resourcefilesystem/a.txt",
    "content": "a"
  },
  {
    "path": "okio/src/jvmTest/resources/okio/resourcefilesystem/b/b.txt",
    "content": "b/b"
  },
  {
    "path": "okio/src/jvmTest/resources/okio/resourcefilesystem/non-ascii/ギリシア神話/Ἰλιάς",
    "content": "Chante, ô déesse, le courroux du Péléide Achille,\n"
  },
  {
    "path": "okio/src/linuxMain/headers/README.md",
    "content": "# Linux User API\n\nThis directory includes files from the Linux kernel user API, used as symbols to build Okio against.\nThe license 'GPL-2.0 WITH Linux-syscall-note' permits us to build against these symbols without\nbeing a derived work.\n\nhttps://github.com/torvalds/linux/blob/master/LICENSES/preferred/GPL-2.0\nhttps://github.com/torvalds/linux/blob/master/LICENSES/exceptions/Linux-syscall-note\n"
  },
  {
    "path": "okio/src/linuxMain/headers/include/uapi/linux/stat.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */\n#ifndef _UAPI_LINUX_STAT_H\n#define _UAPI_LINUX_STAT_H\n\n#include <linux/types.h>\n\n#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)\n\n#define S_IFMT  00170000\n#define S_IFSOCK 0140000\n#define S_IFLNK\t 0120000\n#define S_IFREG  0100000\n#define S_IFBLK  0060000\n#define S_IFDIR  0040000\n#define S_IFCHR  0020000\n#define S_IFIFO  0010000\n#define S_ISUID  0004000\n#define S_ISGID  0002000\n#define S_ISVTX  0001000\n\n#define S_ISLNK(m)\t(((m) & S_IFMT) == S_IFLNK)\n#define S_ISREG(m)\t(((m) & S_IFMT) == S_IFREG)\n#define S_ISDIR(m)\t(((m) & S_IFMT) == S_IFDIR)\n#define S_ISCHR(m)\t(((m) & S_IFMT) == S_IFCHR)\n#define S_ISBLK(m)\t(((m) & S_IFMT) == S_IFBLK)\n#define S_ISFIFO(m)\t(((m) & S_IFMT) == S_IFIFO)\n#define S_ISSOCK(m)\t(((m) & S_IFMT) == S_IFSOCK)\n\n#define S_IRWXU 00700\n#define S_IRUSR 00400\n#define S_IWUSR 00200\n#define S_IXUSR 00100\n\n#define S_IRWXG 00070\n#define S_IRGRP 00040\n#define S_IWGRP 00020\n#define S_IXGRP 00010\n\n#define S_IRWXO 00007\n#define S_IROTH 00004\n#define S_IWOTH 00002\n#define S_IXOTH 00001\n\n#endif\n\n/*\n * Timestamp structure for the timestamps in struct statx.\n *\n * tv_sec holds the number of seconds before (negative) or after (positive)\n * 00:00:00 1st January 1970 UTC.\n *\n * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.\n *\n * __reserved is held in case we need a yet finer resolution.\n */\nstruct statx_timestamp {\n\t__s64\ttv_sec;\n\t__u32\ttv_nsec;\n\t__s32\t__reserved;\n};\n\n/*\n * Structures for the extended file attribute retrieval system call\n * (statx()).\n *\n * The caller passes a mask of what they're specifically interested in as a\n * parameter to statx().  What statx() actually got will be indicated in\n * st_mask upon return.\n *\n * For each bit in the mask argument:\n *\n * - if the datum is not supported:\n *\n *   - the bit will be cleared, and\n *\n *   - the datum will be set to an appropriate fabricated value if one is\n *     available (eg. CIFS can take a default uid and gid), otherwise\n *\n *   - the field will be cleared;\n *\n * - otherwise, if explicitly requested:\n *\n *   - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is\n *     set or if the datum is considered out of date, and\n *\n *   - the field will be filled in and the bit will be set;\n *\n * - otherwise, if not requested, but available in approximate form without any\n *   effort, it will be filled in anyway, and the bit will be set upon return\n *   (it might not be up to date, however, and no attempt will be made to\n *   synchronise the internal state first);\n *\n * - otherwise the field and the bit will be cleared before returning.\n *\n * Items in STATX_BASIC_STATS may be marked unavailable on return, but they\n * will have values installed for compatibility purposes so that stat() and\n * co. can be emulated in userspace.\n */\nstruct statx {\n\t/* 0x00 */\n\t/* What results were written [uncond] */\n\t__u32\tstx_mask;\n\n\t/* Preferred general I/O size [uncond] */\n\t__u32\tstx_blksize;\n\n\t/* Flags conveying information about the file [uncond] */\n\t__u64\tstx_attributes;\n\n\t/* 0x10 */\n\t/* Number of hard links */\n\t__u32\tstx_nlink;\n\n\t/* User ID of owner */\n\t__u32\tstx_uid;\n\n\t/* Group ID of owner */\n\t__u32\tstx_gid;\n\n\t/* File mode */\n\t__u16\tstx_mode;\n\t__u16\t__spare0[1];\n\n\t/* 0x20 */\n\t/* Inode number */\n\t__u64\tstx_ino;\n\n\t/* File size */\n\t__u64\tstx_size;\n\n\t/* Number of 512-byte blocks allocated */\n\t__u64\tstx_blocks;\n\n\t/* Mask to show what's supported in stx_attributes */\n\t__u64\tstx_attributes_mask;\n\n\t/* 0x40 */\n\t/* Last access time */\n\tstruct statx_timestamp\tstx_atime;\n\n\t/* File creation time */\n\tstruct statx_timestamp\tstx_btime;\n\n\t/* Last attribute change time */\n\tstruct statx_timestamp\tstx_ctime;\n\n\t/* Last data modification time */\n\tstruct statx_timestamp\tstx_mtime;\n\n\t/* 0x80 */\n\t/* Device ID of special file [if bdev/cdev] */\n\t__u32\tstx_rdev_major;\n\t__u32\tstx_rdev_minor;\n\n\t/* ID of device containing file [uncond] */\n\t__u32\tstx_dev_major;\n\t__u32\tstx_dev_minor;\n\n\t/* 0x90 */\n\t__u64\tstx_mnt_id;\n\n\t/* Memory buffer alignment for direct I/O */\n\t__u32\tstx_dio_mem_align;\n\n\t/* File offset alignment for direct I/O */\n\t__u32\tstx_dio_offset_align;\n\n\t/* 0xa0 */\n\t/* Subvolume identifier */\n\t__u64\tstx_subvol;\n\n\t/* Min atomic write unit in bytes */\n\t__u32\tstx_atomic_write_unit_min;\n\n\t/* Max atomic write unit in bytes */\n\t__u32\tstx_atomic_write_unit_max;\n\n\t/* 0xb0 */\n\t/* Max atomic write segment count */\n\t__u32   stx_atomic_write_segments_max;\n\n\t/* File offset alignment for direct I/O reads */\n\t__u32\tstx_dio_read_offset_align;\n\n\t/* Optimised max atomic write unit in bytes */\n\t__u32\tstx_atomic_write_unit_max_opt;\n\t__u32\t__spare2[1];\n\n\t/* 0xc0 */\n\t__u64\t__spare3[8];\t/* Spare space for future expansion */\n\n\t/* 0x100 */\n};\n\n/*\n * Flags to be stx_mask\n *\n * Query request/result mask for statx() and struct statx::stx_mask.\n *\n * These bits should be set in the mask argument of statx() to request\n * particular items when calling statx().\n */\n#define STATX_TYPE\t\t0x00000001U\t/* Want/got stx_mode & S_IFMT */\n#define STATX_MODE\t\t0x00000002U\t/* Want/got stx_mode & ~S_IFMT */\n#define STATX_NLINK\t\t0x00000004U\t/* Want/got stx_nlink */\n#define STATX_UID\t\t0x00000008U\t/* Want/got stx_uid */\n#define STATX_GID\t\t0x00000010U\t/* Want/got stx_gid */\n#define STATX_ATIME\t\t0x00000020U\t/* Want/got stx_atime */\n#define STATX_MTIME\t\t0x00000040U\t/* Want/got stx_mtime */\n#define STATX_CTIME\t\t0x00000080U\t/* Want/got stx_ctime */\n#define STATX_INO\t\t0x00000100U\t/* Want/got stx_ino */\n#define STATX_SIZE\t\t0x00000200U\t/* Want/got stx_size */\n#define STATX_BLOCKS\t\t0x00000400U\t/* Want/got stx_blocks */\n#define STATX_BASIC_STATS\t0x000007ffU\t/* The stuff in the normal stat struct */\n#define STATX_BTIME\t\t0x00000800U\t/* Want/got stx_btime */\n#define STATX_MNT_ID\t\t0x00001000U\t/* Got stx_mnt_id */\n#define STATX_DIOALIGN\t\t0x00002000U\t/* Want/got direct I/O alignment info */\n#define STATX_MNT_ID_UNIQUE\t0x00004000U\t/* Want/got extended stx_mount_id */\n#define STATX_SUBVOL\t\t0x00008000U\t/* Want/got stx_subvol */\n#define STATX_WRITE_ATOMIC\t0x00010000U\t/* Want/got atomic_write_* fields */\n#define STATX_DIO_READ_ALIGN\t0x00020000U\t/* Want/got dio read alignment info */\n\n#define STATX__RESERVED\t\t0x80000000U\t/* Reserved for future struct statx expansion */\n\n#ifndef __KERNEL__\n/*\n * This is deprecated, and shall remain the same value in the future.  To avoid\n * confusion please use the equivalent (STATX_BASIC_STATS | STATX_BTIME)\n * instead.\n */\n#define STATX_ALL\t\t0x00000fffU\n#endif\n\n/*\n * Attributes to be found in stx_attributes and masked in stx_attributes_mask.\n *\n * These give information about the features or the state of a file that might\n * be of use to ordinary userspace programs such as GUIs or ls rather than\n * specialised tools.\n *\n * Note that the flags marked [I] correspond to the FS_IOC_SETFLAGS flags\n * semantically.  Where possible, the numerical value is picked to correspond\n * also.  Note that the DAX attribute indicates that the file is in the CPU\n * direct access state.  It does not correspond to the per-inode flag that\n * some filesystems support.\n *\n */\n#define STATX_ATTR_COMPRESSED\t\t0x00000004 /* [I] File is compressed by the fs */\n#define STATX_ATTR_IMMUTABLE\t\t0x00000010 /* [I] File is marked immutable */\n#define STATX_ATTR_APPEND\t\t0x00000020 /* [I] File is append-only */\n#define STATX_ATTR_NODUMP\t\t0x00000040 /* [I] File is not to be dumped */\n#define STATX_ATTR_ENCRYPTED\t\t0x00000800 /* [I] File requires key to decrypt in fs */\n#define STATX_ATTR_AUTOMOUNT\t\t0x00001000 /* Dir: Automount trigger */\n#define STATX_ATTR_MOUNT_ROOT\t\t0x00002000 /* Root of a mount */\n#define STATX_ATTR_VERITY\t\t0x00100000 /* [I] Verity protected file */\n#define STATX_ATTR_DAX\t\t\t0x00200000 /* File is currently in DAX state */\n#define STATX_ATTR_WRITE_ATOMIC\t\t0x00400000 /* File supports atomic write operations */\n\n\n#endif /* _UAPI_LINUX_STAT_H */\n"
  },
  {
    "path": "okio/src/linuxMain/headers/okio_statx.h",
    "content": "/*\n * Symbols to call statx() via syscall().\n *\n * Using constant values from Chromium.\n * https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md\n */\n#ifdef __x86_64__\n#define __NR_statx 332\n#elif defined(__arm__)\n#define __NR_statx 397\n#elif defined(__aarch64__)\n#define __NR_statx 291\n#elif defined(__i386__)\n#define __NR_statx 383\n#else\n#error \"unexpected arch for __NR_statx\"\n#endif\n\n#define AT_FDCWD -100\n#define AT_SYMLINK_NOFOLLOW\t0x100\n"
  },
  {
    "path": "okio/src/linuxMain/kotlin/okio/LinuxPosixVariant.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.UnsafeNumber\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.ptr\nimport okio.internal.linux.AT_FDCWD\nimport okio.internal.linux.AT_SYMLINK_NOFOLLOW\nimport okio.internal.linux.STATX_BASIC_STATS\nimport okio.internal.linux.STATX_BTIME\nimport okio.internal.linux.S_IFDIR\nimport okio.internal.linux.S_IFMT\nimport okio.internal.linux.S_IFREG\nimport okio.internal.linux.__NR_statx\nimport okio.internal.linux.statx\nimport okio.internal.linux.statx_timestamp\nimport platform.posix.ENOENT\nimport platform.posix.ENOSYS\nimport platform.posix.errno\nimport platform.posix.lstat\nimport platform.posix.stat\nimport platform.posix.syscall\n\n/**\n * Prefer `statx()` if it's available. Fall back to `stat()` which doesn't have a field for\n * `createdAt`.\n */\ninternal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? {\n  memScoped {\n    val statx = alloc<statx>()\n    val result = syscall(\n      __NR_statx.toLong(),\n      AT_FDCWD,\n      path.toString(),\n      AT_SYMLINK_NOFOLLOW,\n      STATX_BASIC_STATS or STATX_BTIME,\n      statx.ptr,\n    )\n    if (result == 0L) {\n      return FileMetadata(\n        isRegularFile = statx.stx_mode.toInt() and S_IFMT == S_IFREG,\n        isDirectory = statx.stx_mode.toInt() and S_IFMT == S_IFDIR,\n        symlinkTarget = symlinkTarget(statx.stx_mode.toInt(), path),\n        size = statx.stx_size.toLong(),\n        createdAtMillis = when {\n          statx.stx_mask and STATX_BTIME != 0U -> statx.stx_btime.epochMillis\n          else -> statx.stx_mtime.epochMillis\n        },\n        lastModifiedAtMillis = statx.stx_mtime.epochMillis,\n        lastAccessedAtMillis = statx.stx_atime.epochMillis,\n      )\n    }\n\n    // Recover if statx() isn't available. It first appeared in Linux in 4.11 (2017-04-30) and\n    // Android in API 30 (2020-09-08).\n    if (errno == ENOSYS) {\n      val stat = alloc<stat>()\n      if (lstat(path.toString(), stat.ptr) == 0) {\n        return FileMetadata(\n          isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG,\n          isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR,\n          symlinkTarget = symlinkTarget(stat.st_mode.toInt(), path),\n          size = stat.st_size,\n          createdAtMillis = stat.st_mtim.epochMillis,\n          lastModifiedAtMillis = stat.st_mtim.epochMillis,\n          lastAccessedAtMillis = stat.st_atim.epochMillis,\n        )\n      }\n    }\n\n    if (errno == ENOENT) return null\n    throw errnoToIOException(errno)\n  }\n}\n\n@OptIn(UnsafeNumber::class)\ninternal val statx_timestamp.epochMillis: Long\n  get() = tv_sec * 1000L + tv_nsec.toLong() / 1_000_000L\n"
  },
  {
    "path": "okio/src/macosX64Main/kotlin/okio/MacosX64PosixVariant.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.ptr\nimport platform.posix.ENOENT\nimport platform.posix.S_IFDIR\nimport platform.posix.S_IFMT\nimport platform.posix.S_IFREG\nimport platform.posix.errno\nimport platform.posix.lstat64\nimport platform.posix.stat64\n\n/** MacosX64 uses `stat64`; other Apple platforms use `stat`. */\ninternal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? {\n  return memScoped {\n    val stat = alloc<stat64>()\n    if (lstat64(path.toString(), stat.ptr) != 0) {\n      if (errno == ENOENT) return null\n      throw errnoToIOException(errno)\n    }\n    return@memScoped FileMetadata(\n      isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG,\n      isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR,\n      symlinkTarget = symlinkTarget(stat.st_mode.toInt(), path),\n      size = stat.st_size,\n      createdAtMillis = stat.st_birthtimespec.epochMillis,\n      lastModifiedAtMillis = stat.st_mtimespec.epochMillis,\n      lastAccessedAtMillis = stat.st_atimespec.epochMillis,\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/mingwX64Main/kotlin/okio/Windows.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.ByteVarOf\nimport kotlinx.cinterop.allocArray\nimport kotlinx.cinterop.memScoped\nimport platform.windows.DWORD\nimport platform.windows.ERROR_FILE_NOT_FOUND\nimport platform.windows.ERROR_PATH_NOT_FOUND\nimport platform.windows.FORMAT_MESSAGE_FROM_SYSTEM\nimport platform.windows.FORMAT_MESSAGE_IGNORE_INSERTS\nimport platform.windows.FormatMessageA\nimport platform.windows.GetLastError\nimport platform.windows.LANG_NEUTRAL\nimport platform.windows.SUBLANG_DEFAULT\n\ninternal fun lastErrorToIOException(): IOException {\n  val lastError = GetLastError()\n  return when (lastError.toInt()) {\n    ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND -> FileNotFoundException(lastErrorString(lastError))\n    else -> IOException(lastErrorString(lastError))\n  }\n}\n\ninternal fun lastErrorString(lastError: DWORD): String {\n  memScoped {\n    val messageMaxSize = 2048\n    val message = allocArray<ByteVarOf<Byte>>(messageMaxSize)\n    FormatMessageA(\n      dwFlags = (FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS).toUInt(),\n      lpSource = null,\n      dwMessageId = lastError,\n      dwLanguageId = (SUBLANG_DEFAULT * 1024 + LANG_NEUTRAL).toUInt(), // MAKELANGID macro.\n      lpBuffer = message,\n      nSize = messageMaxSize.toUInt(),\n      Arguments = null,\n    )\n    return Buffer().writeNullTerminated(message).readUtf8().trim()\n  }\n}\n"
  },
  {
    "path": "okio/src/mingwX64Main/kotlin/okio/WindowsFileHandle.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.CValuesRef\nimport kotlinx.cinterop.IntVar\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.ptr\nimport kotlinx.cinterop.usePinned\nimport kotlinx.cinterop.value\nimport platform.windows.CloseHandle\nimport platform.windows.ERROR_HANDLE_EOF\nimport platform.windows.FILE_BEGIN\nimport platform.windows.FlushFileBuffers\nimport platform.windows.GetFileSizeEx\nimport platform.windows.GetLastError\nimport platform.windows.HANDLE\nimport platform.windows.LARGE_INTEGER\nimport platform.windows.ReadFile\nimport platform.windows.SetEndOfFile\nimport platform.windows.SetFilePointer\nimport platform.windows.WriteFile\nimport platform.windows._OVERLAPPED\n\ninternal class WindowsFileHandle(\n  readWrite: Boolean,\n  private val file: HANDLE?,\n) : FileHandle(readWrite) {\n  override fun protectedSize(): Long {\n    memScoped {\n      val result = alloc<LARGE_INTEGER>()\n      if (GetFileSizeEx(file, result.ptr) == 0) {\n        throw lastErrorToIOException()\n      }\n      return result.toLong()\n    }\n  }\n\n  override fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    val bytesRead = if (array.isNotEmpty()) {\n      array.usePinned { pinned ->\n        variantPread(pinned.addressOf(arrayOffset), byteCount, fileOffset)\n      }\n    } else {\n      0\n    }\n    if (bytesRead == 0) return -1\n    return bytesRead\n  }\n\n  fun variantPread(\n    target: CValuesRef<*>,\n    byteCount: Int,\n    offset: Long,\n  ): Int {\n    memScoped {\n      val overlapped = alloc<_OVERLAPPED>()\n      overlapped.Offset = offset.toUInt()\n      overlapped.OffsetHigh = (offset ushr 32).toUInt()\n      val readFileResult = ReadFile(\n        hFile = file,\n        lpBuffer = target.getPointer(this),\n        nNumberOfBytesToRead = byteCount.toUInt(),\n        lpNumberOfBytesRead = null,\n        lpOverlapped = overlapped.ptr,\n      )\n      if (readFileResult == 0 && GetLastError().toInt() != ERROR_HANDLE_EOF) {\n        throw lastErrorToIOException()\n      }\n      return overlapped.InternalHigh.toInt()\n    }\n  }\n\n  override fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    val bytesWritten = if (array.isNotEmpty()) {\n      array.usePinned { pinned ->\n        variantPwrite(pinned.addressOf(arrayOffset), byteCount, fileOffset)\n      }\n    } else {\n      0\n    }\n    if (bytesWritten != byteCount) throw IOException(\"bytesWritten=$bytesWritten\")\n  }\n\n  fun variantPwrite(\n    source: CValuesRef<*>,\n    byteCount: Int,\n    offset: Long,\n  ): Int {\n    memScoped {\n      val overlapped = alloc<_OVERLAPPED>()\n      overlapped.Offset = offset.toUInt()\n      overlapped.OffsetHigh = (offset ushr 32).toUInt()\n      val writeFileResult = WriteFile(\n        hFile = file,\n        lpBuffer = source.getPointer(this),\n        nNumberOfBytesToWrite = byteCount.toUInt(),\n        lpNumberOfBytesWritten = null,\n        lpOverlapped = overlapped.ptr,\n      )\n      if (writeFileResult == 0) {\n        throw lastErrorToIOException()\n      }\n      return overlapped.InternalHigh.toInt()\n    }\n  }\n\n  override fun protectedFlush() {\n    if (FlushFileBuffers(file) == 0) {\n      throw lastErrorToIOException()\n    }\n  }\n\n  override fun protectedResize(size: Long) {\n    memScoped {\n      val distanceToMoveHigh = alloc<IntVar>()\n      distanceToMoveHigh.value = (size ushr 32).toInt()\n      val movePointerResult = SetFilePointer(\n        hFile = file,\n        lDistanceToMove = size.toInt(),\n        lpDistanceToMoveHigh = distanceToMoveHigh.ptr,\n        dwMoveMethod = FILE_BEGIN.toUInt(),\n      )\n      if (movePointerResult == 0U) {\n        throw lastErrorToIOException()\n      }\n      if (SetEndOfFile(file) == 0) {\n        throw lastErrorToIOException()\n      }\n    }\n  }\n\n  override fun protectedClose() {\n    if (CloseHandle(file) == 0) {\n      throw lastErrorToIOException()\n    }\n  }\n\n  private fun LARGE_INTEGER.toLong(): Long {\n    return (HighPart.toLong() shl 32) + (LowPart.toLong() and 0xffffffffL)\n  }\n}\n"
  },
  {
    "path": "okio/src/mingwX64Main/kotlin/okio/WindowsPosixVariant.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.ptr\nimport kotlinx.cinterop.toKString\nimport okio.Path.Companion.toPath\nimport platform.posix.EACCES\nimport platform.posix.ENOENT\nimport platform.posix.FILE\nimport platform.posix.PATH_MAX\nimport platform.posix.S_IFDIR\nimport platform.posix.S_IFMT\nimport platform.posix.S_IFREG\nimport platform.posix._fullpath\nimport platform.posix._stat64\nimport platform.posix.errno\nimport platform.posix.fopen\nimport platform.posix.free\nimport platform.posix.getenv\nimport platform.posix.mkdir\nimport platform.posix.remove\nimport platform.posix.rmdir\nimport platform.windows.CREATE_NEW\nimport platform.windows.CreateFileA\nimport platform.windows.FILE_ATTRIBUTE_NORMAL\nimport platform.windows.FILE_SHARE_WRITE\nimport platform.windows.GENERIC_READ\nimport platform.windows.GENERIC_WRITE\nimport platform.windows.INVALID_HANDLE_VALUE\nimport platform.windows.MOVEFILE_REPLACE_EXISTING\nimport platform.windows.MoveFileExA\nimport platform.windows.OPEN_ALWAYS\nimport platform.windows.OPEN_EXISTING\n\ninternal actual val PLATFORM_TEMPORARY_DIRECTORY: Path\n  get() {\n    // Windows' built-in APIs check the TEMP, TMP, and USERPROFILE environment variables in order.\n    // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha?redirectedfrom=MSDN\n    val temp = getenv(\"TEMP\")\n    if (temp != null) return temp.toKString().toPath()\n\n    val tmp = getenv(\"TMP\")\n    if (tmp != null) return tmp.toKString().toPath()\n\n    val userProfile = getenv(\"USERPROFILE\")\n    if (userProfile != null) return userProfile.toKString().toPath()\n\n    return \"\\\\Windows\\\\TEMP\".toPath()\n  }\n\ninternal actual val PLATFORM_DIRECTORY_SEPARATOR = \"\\\\\"\n\ninternal actual fun PosixFileSystem.variantDelete(path: Path, mustExist: Boolean) {\n  val pathString = path.toString()\n\n  if (remove(pathString) == 0) return\n\n  // If remove failed with EACCES, it might be a directory. Try that.\n  if (errno == EACCES) {\n    if (rmdir(pathString) == 0) return\n  }\n  if (errno == ENOENT) {\n    if (mustExist) {\n      throw FileNotFoundException(\"no such file: $path\")\n    } else {\n      return\n    }\n  }\n\n  throw errnoToIOException(EACCES)\n}\n\ninternal actual fun PosixFileSystem.variantMkdir(dir: Path): Int {\n  return mkdir(dir.toString())\n}\n\ninternal actual fun PosixFileSystem.variantCanonicalize(path: Path): Path {\n  // Note that _fullpath() returns normally if the file doesn't exist.\n  val fullpath = _fullpath(null, path.toString(), PATH_MAX.toULong())\n    ?: throw errnoToIOException(errno)\n  try {\n    val pathString = Buffer().writeNullTerminated(fullpath).readUtf8()\n    if (platform.posix.access(pathString, 0) != 0 && errno == ENOENT) {\n      throw FileNotFoundException(\"no such file\")\n    }\n    return pathString.toPath()\n  } finally {\n    free(fullpath)\n  }\n}\n\ninternal actual fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata? {\n  return memScoped {\n    val stat = alloc<_stat64>()\n    if (_stat64(path.toString(), stat.ptr) != 0) {\n      if (errno == ENOENT) return null\n      throw errnoToIOException(errno)\n    }\n    return@memScoped FileMetadata(\n      isRegularFile = stat.st_mode.toInt() and S_IFMT == S_IFREG,\n      isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR,\n      symlinkTarget = null,\n      size = stat.st_size,\n      createdAtMillis = stat.st_ctime * 1000L,\n      lastModifiedAtMillis = stat.st_mtime * 1000L,\n      lastAccessedAtMillis = stat.st_atime * 1000L,\n    )\n  }\n}\n\ninternal actual fun PosixFileSystem.variantMove(source: Path, target: Path) {\n  if (MoveFileExA(source.toString(), target.toString(), MOVEFILE_REPLACE_EXISTING.toUInt()) == 0) {\n    throw lastErrorToIOException()\n  }\n}\n\ninternal actual fun PosixFileSystem.variantSource(file: Path): Source {\n  val openFile: CPointer<FILE> = fopen(file.toString(), \"rb\")\n    ?: throw errnoToIOException(errno)\n  return FileSource(openFile)\n}\n\ninternal actual fun PosixFileSystem.variantSink(file: Path, mustCreate: Boolean): Sink {\n  // We're non-atomically checking file existence because Windows errors if we use the `x` flag along with `w`.\n  if (mustCreate && exists(file)) throw IOException(\"$file already exists.\")\n  val openFile: CPointer<FILE> = fopen(file.toString(), \"wb\")\n    ?: throw errnoToIOException(errno)\n  return FileSink(openFile)\n}\n\ninternal actual fun PosixFileSystem.variantAppendingSink(file: Path, mustExist: Boolean): Sink {\n  // There is a `r+` flag which we could have used to force existence of [file] but this flag\n  // doesn't allow opening for appending, and we don't currently have a way to move the cursor to\n  // the end of the file. We are then forcing existence non-atomically.\n  if (mustExist && !exists(file)) throw IOException(\"$file doesn't exist.\")\n  val openFile: CPointer<FILE> = fopen(file.toString(), \"ab\")\n    ?: throw errnoToIOException(errno)\n  return FileSink(openFile)\n}\n\ninternal actual fun PosixFileSystem.variantOpenReadOnly(file: Path): FileHandle {\n  val openFile = CreateFileA(\n    lpFileName = file.toString(),\n    dwDesiredAccess = GENERIC_READ,\n    dwShareMode = FILE_SHARE_WRITE.toUInt(),\n    lpSecurityAttributes = null,\n    dwCreationDisposition = OPEN_EXISTING.toUInt(),\n    dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL.toUInt(),\n    hTemplateFile = null,\n  )\n  if (openFile == INVALID_HANDLE_VALUE) {\n    throw lastErrorToIOException()\n  }\n  return WindowsFileHandle(false, openFile)\n}\n\ninternal actual fun PosixFileSystem.variantOpenReadWrite(\n  file: Path,\n  mustCreate: Boolean,\n  mustExist: Boolean,\n): FileHandle {\n  require(!mustCreate || !mustExist) {\n    \"Cannot require mustCreate and mustExist at the same time.\"\n  }\n\n  val creationDisposition = when {\n    mustCreate -> CREATE_NEW.toUInt()\n    mustExist -> OPEN_EXISTING.toUInt()\n    else -> OPEN_ALWAYS.toUInt()\n  }\n\n  val openFile = CreateFileA(\n    lpFileName = file.toString(),\n    dwDesiredAccess = GENERIC_READ or GENERIC_WRITE.toUInt(),\n    dwShareMode = FILE_SHARE_WRITE.toUInt(),\n    lpSecurityAttributes = null,\n    dwCreationDisposition = creationDisposition,\n    dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL.toUInt(),\n    hTemplateFile = null,\n  )\n  if (openFile == INVALID_HANDLE_VALUE) {\n    throw lastErrorToIOException()\n  }\n  return WindowsFileHandle(true, openFile)\n}\n\ninternal actual fun PosixFileSystem.variantCreateSymlink(source: Path, target: Path) {\n  throw IOException(\"Not supported\")\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/Cinterop.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.ByteVarOf\nimport kotlinx.cinterop.COpaquePointer\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.get\nimport kotlinx.cinterop.readBytes\nimport kotlinx.cinterop.set\nimport okio.ByteString.Companion.EMPTY\nimport platform.posix.ENOENT\nimport platform.posix.strerror\n\n/** Copy [count] bytes from the memory at this pointer into a [ByteString]. */\nfun COpaquePointer.readByteString(count: Int): ByteString {\n  return if (count == 0) EMPTY else ByteString(readBytes(count))\n}\n\ninternal fun Buffer.writeNullTerminated(bytes: CPointer<ByteVarOf<Byte>>): Buffer = apply {\n  var pos = 0\n  while (true) {\n    val byte = bytes[pos++].toInt()\n    if (byte == 0) {\n      break\n    } else {\n      writeByte(byte)\n    }\n  }\n}\n\ninternal fun Buffer.write(\n  source: CPointer<ByteVarOf<Byte>>,\n  offset: Int = 0,\n  byteCount: Int,\n): Buffer = apply {\n  for (i in offset until offset + byteCount) {\n    writeByte(source[i].toInt())\n  }\n}\n\ninternal fun Buffer.read(\n  sink: CPointer<ByteVarOf<Byte>>,\n  offset: Int = 0,\n  byteCount: Int,\n): Buffer = apply {\n  for (i in offset until offset + byteCount) {\n    sink[i] = readByte()\n  }\n}\n\ninternal fun errnoToIOException(errno: Int): IOException {\n  val message = strerror(errno)\n  val messageString = if (message != null) {\n    Buffer().writeNullTerminated(message).readUtf8()\n  } else {\n    \"errno: $errno\"\n  }\n  return when (errno) {\n    ENOENT -> FileNotFoundException(messageString)\n    else -> IOException(messageString)\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/DataProcessor.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nprivate val emptyByteArray = byteArrayOf()\n\n/**\n * Transform a stream of source bytes into a stream of target bytes, one segment at a time. The\n * relationship between input byte count and output byte count is arbitrary: a sequence of input\n * bytes may produce zero output bytes, or many segments of output bytes.\n *\n * To use:\n *\n *  1. Create an instance.\n *\n *  2. Populate [source] with input data. Set [sourcePos] and [sourceLimit] to a readable slice of\n *     this array.\n *\n *  3. Populate [target] with a destination for output data. Set [targetPos] and [targetLimit] to a\n *     writable slice of this array.\n *\n *  4. Call [process] to read input data from [source] and write output to [target]. This function\n *     advances [sourcePos] if input data was read and [targetPos] if compressed output was written.\n *     If the input array is exhausted (`sourcePos == sourceLimit`) or the output array is full\n *     (`targetPos == targetLimit`), make an adjustment and call [process] again.\n *\n *  5. Repeat steps 2 through 4 until the input data is completely exhausted.\n *\n *  6. Close the processor.\n *\n * See also, the [zlib manual](https://www.zlib.net/manual.html).\n */\ninternal abstract class DataProcessor : Closeable {\n  var source: ByteArray = emptyByteArray\n  var sourcePos: Int = 0\n  var sourceLimit: Int = 0\n\n  var target: ByteArray = emptyByteArray\n  var targetPos: Int = 0\n  var targetLimit: Int = 0\n\n  var closed: Boolean = false\n    protected set\n\n  /** True if the content is self-terminating and has reached the end of the stream. */\n  var finished: Boolean = false\n    internal set\n\n  /**\n   * Returns true if no further calls to [process] are required to complete the operation.\n   * Otherwise, make space available in [target] and call this again.\n   */\n  @Throws(ProtocolException::class)\n  abstract fun process(): Boolean\n\n  /** True if calling [process] may produce more output without more input. */\n  private var callProcess = false\n\n  /**\n   * Consume [sourceExactByteCount] bytes from [source], writing any amount of output to [target].\n   *\n   * Note that 0 is a valid number of bytes to process, and this will cause flush and finish blocks\n   * to be written. For such 0-byte writes [source] may be null.\n   */\n  @Throws(IOException::class)\n  fun writeBytesFromSource(\n    source: Buffer?,\n    sourceExactByteCount: Long,\n    target: BufferedSink,\n  ) {\n    check(!closed) { \"closed\" }\n\n    var byteCount = 0\n    while (true) {\n      val sourceHead = prepareSource(source, sourceExactByteCount - byteCount)\n      val targetTail = prepareTarget(target)\n      try {\n        callProcess = !process()\n      } finally {\n        byteCount += updateSource(source, sourceHead)\n        updateTarget(target, targetTail)\n      }\n\n      // If we've produced a full segment, emit it. This blocks writing to the target.\n      target.emitCompleteSegments()\n\n      // Keep going until we've consumed the required byte count.\n      if (byteCount < sourceExactByteCount) continue\n\n      // More output is available without consuming more input. Produce it.\n      if (callProcess) continue\n\n      break\n    }\n  }\n\n  /**\n   * Produce up to [targetMaxByteCount] bytes to target, reading any number of bytes from [source].\n   *\n   * @return the total number of bytes produced to [target], or -1L if no bytes were produced.\n   */\n  @Throws(IOException::class)\n  fun readBytesToTarget(\n    source: BufferedSource,\n    targetMaxByteCount: Long,\n    target: Buffer,\n  ): Long {\n    check(!closed) { \"closed\" }\n\n    var byteCount = 0L\n    while (true) {\n      // Make sure we have input to process. This blocks reading the source.\n      val sourceExhausted = when {\n        !callProcess && byteCount == 0L -> finished || source.exhausted()\n        else -> false\n      }\n\n      val sourceHead = prepareSource(source.buffer)\n      val targetTail = prepareTarget(target, targetMaxByteCount - byteCount)\n      try {\n        callProcess = !process()\n      } finally {\n        updateSource(source.buffer, sourceHead)\n        byteCount += updateTarget(target, targetTail)\n      }\n\n      // Keep going until either we produce 1+ byte of output, or we exhaust the stream.\n      if (!sourceExhausted && byteCount == 0L) continue\n\n      // More output is available without consuming more input. Produce it.\n      if (callProcess && byteCount < targetMaxByteCount) continue\n\n      break\n    }\n\n    return when {\n      byteCount > 0L -> byteCount\n      else -> -1L\n    }\n  }\n\n  /** Tell the processor to read up to [maxByteCount] bytes from the source's first segment. */\n  private fun prepareSource(\n    source: Buffer?,\n    maxByteCount: Long = Long.MAX_VALUE,\n  ): Segment? {\n    val head = source?.buffer?.head\n    if (maxByteCount == 0L || head == null) {\n      sourcePos = 0\n      sourceLimit = 0\n      return null\n    }\n\n    val toProcess = minOf(maxByteCount, head.limit - head.pos).toInt()\n    this.source = head.data\n    this.sourcePos = head.pos\n    this.sourceLimit = head.pos + toProcess\n    return head\n  }\n\n  /**\n   * Track what was consumed from the source, if anything.\n   *\n   * Returns the number of consumed bytes.\n   */\n  private fun updateSource(\n    source: Buffer?,\n    sourceHead: Segment?,\n  ): Int {\n    if (sourceLimit == 0) return 0\n\n    source!!\n    val consumedByteCount = sourcePos - sourceHead!!.pos\n    sourceHead.pos = sourcePos\n    source.size -= consumedByteCount\n\n    // If we used up the head segment, recycle it.\n    if (sourceHead.pos == sourceHead.limit) {\n      source.head = sourceHead.pop()\n      SegmentPool.recycle(sourceHead)\n    }\n\n    this.source = emptyByteArray\n    this.sourcePos = 0\n    this.sourceLimit = 0\n\n    return consumedByteCount\n  }\n\n  /** Tell the processor to write to the target's last segment. */\n  private fun prepareTarget(\n    target: BufferedSink,\n    maxByteCount: Long = Long.MAX_VALUE,\n  ): Segment {\n    val tail = target.buffer.writableSegment(1)\n    val toProcess = minOf(maxByteCount, tail.data.size - tail.limit).toInt()\n    this.target = tail.data\n    this.targetPos = tail.limit\n    this.targetLimit = tail.limit + toProcess\n    return tail\n  }\n\n  /**\n   * Track what was produced on the target, if anything, and emit the bytes to the target stream.\n   *\n   * Returns the number of produced bytes.\n   */\n  private fun updateTarget(\n    target: BufferedSink,\n    tail: Segment,\n  ): Int {\n    val producedByteCount = targetPos - tail.limit\n\n    if (producedByteCount == 0 && tail.pos == tail.limit) {\n      // We allocated a tail segment, but didn't end up needing it. Recycle!\n      target.buffer.head = tail.pop()\n      SegmentPool.recycle(tail)\n    } else {\n      tail.limit = targetPos\n      target.buffer.size += producedByteCount\n    }\n\n    this.target = emptyByteArray\n    this.targetPos = 0\n    this.targetLimit = 0\n\n    return producedByteCount\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/Deflater.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.UnsafeNumber\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.free\nimport kotlinx.cinterop.nativeHeap\nimport kotlinx.cinterop.ptr\nimport kotlinx.cinterop.usePinned\nimport platform.zlib.Z_DEFAULT_COMPRESSION\nimport platform.zlib.Z_DEFAULT_STRATEGY\nimport platform.zlib.Z_DEFLATED\nimport platform.zlib.Z_FINISH\nimport platform.zlib.Z_NO_FLUSH\nimport platform.zlib.Z_OK\nimport platform.zlib.Z_STREAM_END\nimport platform.zlib.Z_STREAM_ERROR\nimport platform.zlib.Z_SYNC_FLUSH\nimport platform.zlib.deflate\nimport platform.zlib.deflateEnd\nimport platform.zlib.deflateInit2\nimport platform.zlib.z_stream_s\n\n/**\n * Deflate using Kotlin/Native's built-in zlib bindings. This uses the raw deflate format and omits\n * the zlib header and trailer, and does not compute a check value.\n *\n * Note that you must set [flush] to [Z_FINISH] before the last call to [process]. (It is okay to\n * call process() when the source is exhausted.)\n *\n * See also, the [zlib manual](https://www.zlib.net/manual.html).\n */\nactual class Deflater actual constructor(\n  level: Int,\n  nowrap: Boolean,\n) {\n  private val zStream: z_stream_s = nativeHeap.alloc<z_stream_s> {\n    zalloc = null\n    zfree = null\n    opaque = null\n    check(\n      deflateInit2(\n        strm = ptr,\n        level = level,\n        method = Z_DEFLATED,\n        windowBits = if (nowrap) -15 else 15, // Negative for raw deflate.\n        memLevel = 8, // Default value.\n        strategy = Z_DEFAULT_STRATEGY,\n      ) == Z_OK,\n    )\n  }\n\n  /** Probably [Z_NO_FLUSH], [Z_FINISH], or [Z_SYNC_FLUSH]. */\n  var flush: Int = Z_NO_FLUSH\n\n  actual constructor() : this(Z_DEFAULT_COMPRESSION, false)\n\n  internal val dataProcessor: DataProcessor = object : DataProcessor() {\n    override fun process(): Boolean {\n      check(!closed) { \"closed\" }\n      require(0 <= sourcePos && sourcePos <= sourceLimit && sourceLimit <= source.size)\n      require(0 <= targetPos && targetPos <= targetLimit && targetLimit <= target.size)\n\n      source.asUByteArray().usePinned { pinnedSource ->\n        target.asUByteArray().usePinned { pinnedTarget ->\n          val sourceByteCount = sourceLimit - sourcePos\n          zStream.next_in = when {\n            sourceByteCount > 0 -> pinnedSource.addressOf(sourcePos)\n            else -> null\n          }\n          zStream.avail_in = sourceByteCount.toUInt()\n\n          val targetByteCount = targetLimit - targetPos\n          zStream.next_out = when {\n            targetByteCount > 0 -> pinnedTarget.addressOf(targetPos)\n            else -> null\n          }\n          zStream.avail_out = targetByteCount.toUInt()\n\n          // One of Z_OK, Z_STREAM_END, Z_STREAM_ERROR, or Z_BUF_ERROR.\n          val deflateResult = deflate(zStream.ptr, flush)\n          check(deflateResult != Z_STREAM_ERROR)\n\n          sourcePos += sourceByteCount - zStream.avail_in.toInt()\n          targetPos += targetByteCount - zStream.avail_out.toInt()\n\n          return when (deflateResult) {\n            Z_STREAM_END -> true\n            else -> targetPos < targetLimit\n          }\n        }\n      }\n    }\n\n    override fun close() {\n      if (closed) return\n      closed = true\n\n      deflateEnd(zStream.ptr)\n      nativeHeap.free(zStream)\n    }\n  }\n\n  @OptIn(UnsafeNumber::class)\n  actual fun getBytesRead(): Long {\n    check(!dataProcessor.closed) { \"closed\" }\n    return zStream.total_in.toLong()\n  }\n\n  actual fun end() {\n    dataProcessor.close()\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/DeflaterSink.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport platform.zlib.Z_FINISH\nimport platform.zlib.Z_NO_FLUSH\nimport platform.zlib.Z_SYNC_FLUSH\n\nactual class DeflaterSink internal actual constructor(\n  private val sink: BufferedSink,\n  internal val deflater: Deflater,\n) : Sink {\n  actual constructor(\n    sink: Sink,\n    deflater: Deflater,\n  ) : this(sink.buffer(), deflater)\n\n  @Throws(IOException::class)\n  actual override fun write(source: Buffer, byteCount: Long) {\n    checkOffsetAndCount(source.size, 0, byteCount)\n\n    deflater.flush = Z_NO_FLUSH\n    deflater.dataProcessor.writeBytesFromSource(\n      source = source,\n      sourceExactByteCount = byteCount,\n      target = sink,\n    )\n  }\n\n  @Throws(IOException::class)\n  actual override fun flush() {\n    deflater.flush = Z_SYNC_FLUSH\n    deflater.dataProcessor.writeBytesFromSource(\n      source = null,\n      sourceExactByteCount = 0L,\n      target = sink,\n    )\n\n    sink.flush()\n  }\n\n  actual override fun timeout(): Timeout {\n    return sink.timeout()\n  }\n\n  @Throws(IOException::class)\n  internal actual fun finishDeflate() {\n    deflater.flush = Z_FINISH\n    deflater.dataProcessor.writeBytesFromSource(\n      source = null,\n      sourceExactByteCount = 0L,\n      target = sink,\n    )\n  }\n\n  @Throws(IOException::class)\n  actual override fun close() {\n    if (deflater.dataProcessor.closed) return\n\n    // We must close the deflater and the target, even if flushing fails. Otherwise, we'll leak\n    // resources! (And we re-throw whichever exception we catch first.)\n    var thrown: Throwable? = null\n\n    try {\n      finishDeflate()\n    } catch (e: Throwable) {\n      thrown = e\n    }\n\n    deflater.dataProcessor.close()\n\n    try {\n      sink.close()\n    } catch (e: Throwable) {\n      if (thrown == null) thrown = e\n    }\n\n    if (thrown != null) throw thrown\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/FileSink.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.usePinned\nimport okio.Buffer.UnsafeCursor\nimport platform.posix.FILE\nimport platform.posix.errno\nimport platform.posix.fclose\nimport platform.posix.fflush\n\n/** Writes bytes to a file as a sink. */\ninternal class FileSink(\n  private val file: CPointer<FILE>,\n) : Sink {\n  private val unsafeCursor = UnsafeCursor()\n  private var closed = false\n\n  override fun write(\n    source: Buffer,\n    byteCount: Long,\n  ) {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    require(source.size >= byteCount) { \"source.size=${source.size} < byteCount=$byteCount\" }\n    check(!closed) { \"closed\" }\n\n    var byteCount = byteCount\n    while (byteCount > 0) {\n      // Get the first segment, which we will read a contiguous range of bytes from.\n      val cursor = source.readUnsafe(unsafeCursor)\n      val segmentReadableByteCount = cursor.next()\n      val attemptCount = minOf(byteCount, segmentReadableByteCount.toLong()).toInt()\n\n      // Copy bytes from that segment into the file.\n      val bytesWritten = cursor.data!!.usePinned { pinned ->\n        variantFwrite(pinned.addressOf(cursor.start), attemptCount.toUInt(), file).toLong()\n      }\n\n      // Consume the bytes from the segment.\n      cursor.close()\n      source.skip(bytesWritten)\n      byteCount -= bytesWritten\n\n      // If the write was shorter than expected, some I/O failed.\n      if (bytesWritten < attemptCount) {\n        throw errnoToIOException(errno)\n      }\n    }\n  }\n\n  override fun flush() {\n    if (fflush(file) != 0) {\n      throw errnoToIOException(errno)\n    }\n  }\n\n  override fun timeout(): Timeout = Timeout.NONE\n\n  override fun close() {\n    if (closed) return\n    closed = true\n    if (fclose(file) != 0) {\n      throw errnoToIOException(errno)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/FileSource.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.usePinned\nimport okio.Buffer.UnsafeCursor\nimport platform.posix.FILE\nimport platform.posix.errno\nimport platform.posix.fclose\nimport platform.posix.feof\nimport platform.posix.ferror\n\n/** Reads the bytes of a file as a source. */\ninternal class FileSource(\n  private val file: CPointer<FILE>,\n) : Source {\n  private val unsafeCursor = UnsafeCursor()\n  private var closed = false\n\n  override fun read(\n    sink: Buffer,\n    byteCount: Long,\n  ): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    check(!closed) { \"closed\" }\n    val sinkInitialSize = sink.size\n\n    // Request a writable segment in `sink`. We request at least 1024 bytes, unless the request is\n    // for smaller than that, in which case we request only that many bytes.\n    val cursor = sink.readAndWriteUnsafe(unsafeCursor)\n    val addedCapacityCount = cursor.expandBuffer(minByteCount = minOf(byteCount, 1024L).toInt())\n\n    // Now that we have a writable segment, figure out how many bytes to read. This is the smaller\n    // of the user's requested byte count, and the segment's writable capacity.\n    val attemptCount = minOf(byteCount, addedCapacityCount)\n\n    // Copy bytes from the file to the segment.\n    val bytesRead = cursor.data!!.usePinned { pinned ->\n      variantFread(pinned.addressOf(cursor.start), attemptCount.toUInt(), file).toLong()\n    }\n\n    // Remove new capacity that was added but not used.\n    cursor.resizeBuffer(sinkInitialSize + bytesRead)\n    cursor.close()\n\n    return when {\n      bytesRead == attemptCount -> bytesRead\n      feof(file) != 0 -> if (bytesRead == 0L) -1L else bytesRead\n      ferror(file) != 0 -> throw errnoToIOException(errno)\n      else -> bytesRead\n    }\n  }\n\n  override fun timeout(): Timeout = Timeout.NONE\n\n  override fun close() {\n    if (closed) return\n    closed = true\n    fclose(file)\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/FileSystem.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport kotlin.contracts.InvocationKind\nimport kotlin.contracts.contract\nimport okio.internal.commonCopy\nimport okio.internal.commonCreateDirectories\nimport okio.internal.commonDeleteRecursively\nimport okio.internal.commonExists\nimport okio.internal.commonListRecursively\nimport okio.internal.commonMetadata\n\nactual abstract class FileSystem : Closeable {\n  @Throws(IOException::class)\n  actual abstract fun canonicalize(path: Path): Path\n\n  @Throws(IOException::class)\n  actual fun metadata(path: Path): FileMetadata = commonMetadata(path)\n\n  @Throws(IOException::class)\n  actual abstract fun metadataOrNull(path: Path): FileMetadata?\n\n  @Throws(IOException::class)\n  actual fun exists(path: Path): Boolean = commonExists(path)\n\n  @Throws(IOException::class)\n  actual abstract fun list(dir: Path): List<Path>\n\n  actual abstract fun listOrNull(dir: Path): List<Path>?\n\n  actual open fun listRecursively(dir: Path, followSymlinks: Boolean): Sequence<Path> =\n    commonListRecursively(dir, followSymlinks)\n\n  @Throws(IOException::class)\n  actual abstract fun openReadOnly(file: Path): FileHandle\n\n  @Throws(IOException::class)\n  actual abstract fun openReadWrite(\n    file: Path,\n    mustCreate: Boolean,\n    mustExist: Boolean,\n  ): FileHandle\n\n  @Throws(IOException::class)\n  actual abstract fun source(file: Path): Source\n\n  @Throws(IOException::class)\n  actual inline fun <T> read(file: Path, readerAction: BufferedSource.() -> T): T {\n    contract {\n      callsInPlace(readerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return source(file).buffer().use {\n      it.readerAction()\n    }\n  }\n\n  @Throws(IOException::class)\n  actual abstract fun sink(file: Path, mustCreate: Boolean): Sink\n\n  @Throws(IOException::class)\n  actual inline fun <T> write(\n    file: Path,\n    mustCreate: Boolean,\n    writerAction: BufferedSink.() -> T,\n  ): T {\n    contract {\n      callsInPlace(writerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return sink(file, mustCreate).buffer().use {\n      it.writerAction()\n    }\n  }\n\n  @Throws(IOException::class)\n  actual abstract fun appendingSink(file: Path, mustExist: Boolean): Sink\n\n  @Throws(IOException::class)\n  actual abstract fun createDirectory(dir: Path, mustCreate: Boolean)\n\n  @Throws(IOException::class)\n  actual fun createDirectories(dir: Path, mustCreate: Boolean): Unit =\n    commonCreateDirectories(dir, mustCreate)\n\n  @Throws(IOException::class)\n  actual abstract fun atomicMove(source: Path, target: Path)\n\n  @Throws(IOException::class)\n  actual open fun copy(source: Path, target: Path): Unit = commonCopy(source, target)\n\n  @Throws(IOException::class)\n  actual abstract fun delete(path: Path, mustExist: Boolean)\n\n  @Throws(IOException::class)\n  actual open fun deleteRecursively(fileOrDirectory: Path, mustExist: Boolean): Unit =\n    commonDeleteRecursively(fileOrDirectory, mustExist)\n\n  @Throws(IOException::class)\n  actual abstract fun createSymlink(source: Path, target: Path)\n\n  @Throws(IOException::class)\n  actual override fun close() {\n  }\n\n  actual companion object {\n    /**\n     * The current process's host file system. Use this instance directly, or dependency inject a\n     * [FileSystem] to make code testable.\n     */\n    val SYSTEM: FileSystem = PosixFileSystem\n\n    actual val SYSTEM_TEMPORARY_DIRECTORY: Path = PLATFORM_TEMPORARY_DIRECTORY\n  }\n}\n\n/*\n * JVM and native platforms do offer a [SYSTEM] [FileSystem], however we cannot refine an 'expect' companion object.\n * Therefore an extension property is provided, which on respective platforms (here JVM) will be shadowed by the\n * original implementation.\n */\n@Suppress(\"EXTENSION_SHADOWED_BY_MEMBER\")\nactual inline val FileSystem.Companion.SYSTEM: FileSystem\n  get() = SYSTEM\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/Inflater.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.UnsafeNumber\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.free\nimport kotlinx.cinterop.nativeHeap\nimport kotlinx.cinterop.ptr\nimport kotlinx.cinterop.usePinned\nimport platform.zlib.Z_BUF_ERROR\nimport platform.zlib.Z_DATA_ERROR\nimport platform.zlib.Z_NO_FLUSH\nimport platform.zlib.Z_OK\nimport platform.zlib.Z_STREAM_END\nimport platform.zlib.inflateEnd\nimport platform.zlib.inflateInit2\nimport platform.zlib.z_stream_s\n\n/**\n * Inflate using Kotlin/Native's built-in zlib bindings.\n */\nactual class Inflater actual constructor(\n  nowrap: Boolean,\n) {\n  private val zStream: z_stream_s = nativeHeap.alloc<z_stream_s> {\n    zalloc = null\n    zfree = null\n    opaque = null\n    check(\n      inflateInit2(\n        strm = ptr,\n        windowBits = if (nowrap) -15 else 15, // Negative for raw deflate.\n      ) == Z_OK,\n    )\n  }\n\n  internal val dataProcessor: DataProcessor = object : DataProcessor() {\n    @Throws(ProtocolException::class)\n    override fun process(): Boolean {\n      check(!closed) { \"closed\" }\n      require(0 <= sourcePos && sourcePos <= sourceLimit && sourceLimit <= source.size)\n      require(0 <= targetPos && targetPos <= targetLimit && targetLimit <= target.size)\n\n      source.asUByteArray().usePinned { pinnedSource ->\n        target.asUByteArray().usePinned { pinnedTarget ->\n          val sourceByteCount = sourceLimit - sourcePos\n          zStream.next_in = when {\n            sourceByteCount > 0 -> pinnedSource.addressOf(sourcePos)\n            else -> null\n          }\n          zStream.avail_in = sourceByteCount.toUInt()\n\n          val targetByteCount = targetLimit - targetPos\n          zStream.next_out = when {\n            targetByteCount > 0 -> pinnedTarget.addressOf(targetPos)\n            else -> null\n          }\n          zStream.avail_out = targetByteCount.toUInt()\n\n          val inflateResult = platform.zlib.inflate(zStream.ptr, Z_NO_FLUSH)\n\n          sourcePos += sourceByteCount - zStream.avail_in.toInt()\n          targetPos += targetByteCount - zStream.avail_out.toInt()\n\n          when (inflateResult) {\n            Z_OK, Z_BUF_ERROR -> {\n              return targetPos < targetLimit\n            }\n\n            Z_STREAM_END -> {\n              finished = true\n              return true\n            }\n\n            Z_DATA_ERROR -> throw ProtocolException(\"Z_DATA_ERROR\")\n\n            // One of Z_NEED_DICT, Z_STREAM_ERROR, Z_MEM_ERROR.\n            else -> throw ProtocolException(\"unexpected inflate result: $inflateResult\")\n          }\n        }\n      }\n    }\n\n    override fun close() {\n      if (closed) return\n      closed = true\n\n      inflateEnd(zStream.ptr)\n      nativeHeap.free(zStream)\n    }\n  }\n\n  actual constructor() : this(false)\n\n  @OptIn(UnsafeNumber::class)\n  actual fun getBytesWritten(): Long {\n    check(!dataProcessor.closed) { \"closed\" }\n    return zStream.total_out.toLong()\n  }\n\n  actual fun end() {\n    dataProcessor.close()\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/InflaterSource.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nactual class InflaterSource internal actual constructor(\n  internal val source: BufferedSource,\n  internal val inflater: Inflater,\n) : Source {\n  actual constructor(\n    source: Source,\n    inflater: Inflater,\n  ) : this(source.buffer(), inflater)\n\n  @Throws(IOException::class)\n  actual override fun read(sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n\n    return inflater.dataProcessor.readBytesToTarget(\n      source = source,\n      targetMaxByteCount = byteCount,\n      target = sink,\n    )\n  }\n\n  actual override fun timeout(): Timeout {\n    return source.timeout()\n  }\n\n  actual override fun close() {\n    if (inflater.dataProcessor.closed) return\n\n    inflater.dataProcessor.close()\n\n    source.close()\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/PosixFileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.get\nimport okio.Path.Companion.toPath\nimport okio.internal.toPath\nimport platform.posix.EEXIST\nimport platform.posix.closedir\nimport platform.posix.dirent\nimport platform.posix.errno\nimport platform.posix.opendir\nimport platform.posix.readdir\nimport platform.posix.set_posix_errno\n\ninternal object PosixFileSystem : FileSystem() {\n  private val SELF_DIRECTORY_ENTRY = \".\".toPath()\n  private val PARENT_DIRECTORY_ENTRY = \"..\".toPath()\n\n  override fun canonicalize(path: Path) = variantCanonicalize(path)\n\n  override fun metadataOrNull(path: Path) = variantMetadataOrNull(path)\n\n  override fun list(dir: Path): List<Path> = list(dir, throwOnFailure = true)!!\n\n  override fun listOrNull(dir: Path): List<Path>? = list(dir, throwOnFailure = false)\n\n  private fun list(dir: Path, throwOnFailure: Boolean): List<Path>? {\n    val opendir = opendir(dir.toString())\n      ?: if (throwOnFailure) throw errnoToIOException(errno) else return null\n\n    try {\n      val result = mutableListOf<Path>()\n      val buffer = Buffer()\n\n      set_posix_errno(0) // If readdir() returns null it's either the end or an error.\n      while (true) {\n        val dirent: CPointer<dirent> = readdir(opendir) ?: break\n        val childPath = buffer.writeNullTerminated(\n          bytes = dirent[0].d_name,\n        ).toPath(normalize = true)\n\n        if (childPath == SELF_DIRECTORY_ENTRY || childPath == PARENT_DIRECTORY_ENTRY) {\n          continue // exclude '.' and '..' from the results.\n        }\n\n        result += dir / childPath\n      }\n\n      if (errno != 0) {\n        if (throwOnFailure) {\n          throw errnoToIOException(errno)\n        } else {\n          return null\n        }\n      }\n\n      result.sort()\n      return result\n    } finally {\n      closedir(opendir) // Ignore errno from closedir.\n    }\n  }\n\n  override fun openReadOnly(file: Path) = variantOpenReadOnly(file)\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    return variantOpenReadWrite(file, mustCreate = mustCreate, mustExist = mustExist)\n  }\n\n  override fun source(file: Path) = variantSource(file)\n\n  override fun sink(file: Path, mustCreate: Boolean) = variantSink(file, mustCreate)\n\n  override fun appendingSink(file: Path, mustExist: Boolean) = variantAppendingSink(file, mustExist)\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    val result = variantMkdir(dir)\n    if (result != 0) {\n      if (errno == EEXIST && !mustCreate) return // Already exists.\n      throw errnoToIOException(errno)\n    }\n  }\n\n  override fun atomicMove(\n    source: Path,\n    target: Path,\n  ) {\n    variantMove(source, target)\n  }\n\n  override fun delete(path: Path, mustExist: Boolean) {\n    variantDelete(path, mustExist)\n  }\n\n  override fun createSymlink(source: Path, target: Path) = variantCreateSymlink(source, target)\n\n  override fun toString() = \"PosixSystemFileSystem\"\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/PosixVariant.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\ninternal expect val PLATFORM_TEMPORARY_DIRECTORY: Path\n\ninternal expect fun PosixFileSystem.variantDelete(path: Path, mustExist: Boolean)\n\ninternal expect fun PosixFileSystem.variantMkdir(dir: Path): Int\n\ninternal expect fun PosixFileSystem.variantCanonicalize(path: Path): Path\n\ninternal expect fun PosixFileSystem.variantMetadataOrNull(path: Path): FileMetadata?\n\ninternal expect fun PosixFileSystem.variantMove(source: Path, target: Path)\n\ninternal expect fun PosixFileSystem.variantSource(file: Path): Source\n\ninternal expect fun PosixFileSystem.variantSink(file: Path, mustCreate: Boolean): Sink\n\ninternal expect fun PosixFileSystem.variantAppendingSink(file: Path, mustExist: Boolean): Sink\n\ninternal expect fun PosixFileSystem.variantOpenReadOnly(file: Path): FileHandle\n\ninternal expect fun PosixFileSystem.variantOpenReadWrite(\n  file: Path,\n  mustCreate: Boolean,\n  mustExist: Boolean,\n): FileHandle\n\ninternal expect fun PosixFileSystem.variantCreateSymlink(source: Path, target: Path)\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/SizetVariant.kt",
    "content": "/*\n* Copyright (C) 2020 Square, Inc.\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*/\npackage okio\n\nimport kotlinx.cinterop.ByteVar\nimport kotlinx.cinterop.ByteVarOf\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.UnsafeNumber\nimport kotlinx.cinterop.convert\nimport platform.posix.FILE\nimport platform.posix.fread\nimport platform.posix.fwrite\n\n@OptIn(UnsafeNumber::class)\ninternal fun variantFread(\n  target: CPointer<ByteVarOf<Byte>>,\n  byteCount: UInt,\n  file: CPointer<FILE>,\n): UInt = fread(target, 1u, byteCount.convert(), file).convert()\n\n@OptIn(UnsafeNumber::class)\ninternal fun variantFwrite(\n  source: CPointer<ByteVar>,\n  byteCount: UInt,\n  file: CPointer<FILE>,\n): UInt = fwrite(source, 1u, byteCount.convert(), file).convert()\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/internal/-ZlibNative.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.internal\n\ninternal actual val DEFAULT_COMPRESSION: Int = platform.zlib.Z_DEFAULT_COMPRESSION\n\n/**\n * Roll our own date math because Kotlin doesn't include a built-in date math API, and the\n * kotlinx.datetime library doesn't offer a stable release at this time.\n *\n * Also, we don't necessarily want to take on that dependency for Okio.\n *\n * This implementation assumes UTC.\n *\n * This code is broken for years before 1970. It doesn't implement subtraction for leap years.\n *\n * This code is broken for out-of-range values. For example, it doesn't correctly implement leap\n * year offsets when the month is -24 or when the day is -365.\n */\ninternal actual fun datePartsToEpochMillis(\n  year: Int,\n  month: Int,\n  day: Int,\n  hour: Int,\n  minute: Int,\n  second: Int,\n): Long {\n  // Make sure month is in 1..12, adding or subtracting years as necessary.\n  val rawMonth = month\n  val month = (month - 1).mod(12) + 1\n  val year = year + (rawMonth - month) / 12\n\n  // Start with the cumulative number of days elapsed preceding the current year.\n  var dayCount = (year - 1970) * 365L\n\n  // Adjust by leap years. Years that divide 4 are leap years, unless they divide 100 but not 400.\n  val leapYear = if (month > 2) year else year - 1\n  dayCount += (leapYear - 1968) / 4 - (leapYear - 1900) / 100 + (leapYear - 1600) / 400\n\n  // Add the cumulative number of days elapsed preceding the current month.\n  dayCount += when (month) {\n    1 -> 0\n    2 -> 31\n    3 -> 59\n    4 -> 90\n    5 -> 120\n    6 -> 151\n    7 -> 181\n    8 -> 212\n    9 -> 243\n    10 -> 273\n    11 -> 304\n    else -> 334\n  }\n\n  // Add the cumulative number of days that precede the current day.\n  dayCount += (day - 1)\n\n  // Add hours + minutes + seconds for the current day.\n  val hourCount = dayCount * 24 + hour\n  val minuteCount = hourCount * 60 + minute\n  val secondCount = minuteCount * 60 + second\n  return secondCount * 1_000L\n}\n"
  },
  {
    "path": "okio/src/nativeMain/kotlin/okio/internal/CRC32.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.internal\n\nimport kotlinx.cinterop.CValuesRef\nimport kotlinx.cinterop.UnsafeNumber\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.usePinned\nimport platform.zlib.crc32\nimport platform.zlib.uBytefVar\n\n@OptIn(UnsafeNumber::class)\nactual class CRC32 {\n  private var crc = crc32(0u, null, 0u)\n\n  actual fun update(content: ByteArray, offset: Int, byteCount: Int) {\n    content.usePinned {\n      crc = crc32(crc, it.addressOf(offset) as CValuesRef<uBytefVar>, byteCount.toUInt())\n    }\n  }\n\n  actual fun update(content: ByteArray) {\n    update(content, 0, content.size)\n  }\n\n  actual fun getValue(): Long {\n    return crc.toLong()\n  }\n\n  actual fun reset() {\n    crc = crc32(0u, null, 0u)\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeTest/kotlin/okio/ByteStringCinteropTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertSame\nimport kotlinx.cinterop.allocArray\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.plus\nimport kotlinx.cinterop.value\nimport okio.ByteString.Companion.EMPTY\nimport okio.ByteString.Companion.encodeUtf8\nimport platform.posix.uint8_tVar\n\nclass ByteStringCinteropTest {\n  @Test fun pointerToByteStringZeroDoesNotRead() = memScoped {\n    val pointer = allocArray<uint8_tVar>(0)\n    val bytes = pointer.readByteString(0)\n    // Can't find a way to determine that readBytes was not called, so assume that if EMPTY was\n    // returned there was a short-circuit.\n    assertSame(EMPTY, bytes)\n  }\n\n  @Test fun pointerToByteString() = memScoped {\n    val pointer = allocArray<uint8_tVar>(26L) { index ->\n      value = ('a'.code + index).toUByte()\n    }\n    val bytes = pointer.plus(5)!!.readByteString(15)\n    assertEquals(\"fghijklmnopqrst\".encodeUtf8(), bytes)\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeTest/kotlin/okio/DeflaterSinkTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertTrue\n\nclass DeflaterSinkTest {\n  @Test\n  fun deflateIntoSinkThatThrowsOnWrite() {\n    val throwingSink = ThrowingSink()\n\n    val content = randomBytes(1024 * 32)\n    val source = Buffer().write(content)\n\n    val deflaterSink = throwingSink.deflate()\n\n    throwingSink.nextException = IOException(\"boom\")\n    assertFailsWith<IOException> {\n      deflaterSink.write(source, source.size)\n    }\n\n    // We didn't lose any data. This isn't how real programs recover in practice, but it\n    // demonstrates that no segments are unaccounted for after an exception\n    deflaterSink.write(source, source.size)\n    deflaterSink.close()\n\n    assertEquals(content, inflate(throwingSink.data))\n  }\n\n  @Test\n  fun deflateIntoSinkThatThrowsOnFlush() {\n    val throwingSink = ThrowingSink()\n\n    val content = randomBytes(1024 * 32)\n    val source = Buffer().write(content)\n\n    val deflaterSink = throwingSink.deflate()\n    deflaterSink.write(source, source.size)\n\n    throwingSink.nextException = IOException(\"boom\")\n    assertFailsWith<IOException> {\n      deflaterSink.flush()\n    }\n\n    deflaterSink.close()\n\n    assertEquals(content, inflate(throwingSink.data))\n  }\n\n  @Test\n  fun deflateIntoSinkThatThrowsOnClose() {\n    val throwingSink = ThrowingSink()\n\n    val content = randomBytes(1024 * 32)\n    val source = Buffer().write(content)\n\n    val deflaterSink = throwingSink.deflate()\n    deflaterSink.write(source, source.size)\n\n    throwingSink.nextException = IOException(\"boom\")\n    assertFailsWith<IOException> {\n      deflaterSink.close()\n    }\n\n    assertTrue(deflaterSink.deflater.dataProcessor.closed)\n    assertTrue(throwingSink.closed)\n  }\n\n  class ThrowingSink : Sink {\n    val data = Buffer()\n    var nextException: Throwable? = null\n    var closed = false\n\n    override fun write(source: Buffer, byteCount: Long) {\n      nextException?.let { nextException = null; throw it }\n      data.write(source, byteCount)\n    }\n\n    override fun flush() {\n      nextException?.let { nextException = null; throw it }\n      data.flush()\n    }\n\n    override fun timeout() = Timeout.NONE\n\n    override fun close() {\n      closed = true\n      nextException?.let { nextException = null; throw it }\n    }\n  }\n\n  private fun inflate(deflated: Buffer): ByteString {\n    return deflated.inflate().buffer().use { inflaterSource ->\n      inflaterSource.readByteString()\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeTest/kotlin/okio/DeflaterTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.decodeBase64\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.ByteString.Companion.toByteString\nimport platform.zlib.Z_BEST_COMPRESSION\nimport platform.zlib.Z_FINISH\nimport platform.zlib.Z_NO_FLUSH\nimport platform.zlib.Z_SYNC_FLUSH\n\nclass DeflaterTest {\n  @Test\n  fun happyPath() {\n    val content = \"God help us, we're in the hands of engineers.\"\n    val deflater = Deflater()\n    deflater.dataProcessor.apply {\n      source = content.encodeUtf8().toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      deflater.flush = Z_FINISH\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      assertTrue(process())\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals(content.length.toLong(), deflater.getBytesRead())\n      val deflated = target.toByteString(0, targetPos)\n\n      // Golden compressed output.\n      assertEquals(\n        \"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\".decodeBase64(),\n        deflated,\n      )\n\n      deflater.end()\n    }\n  }\n\n  @Test\n  fun happyPathNoWrap() {\n    val content = \"God help us, we're in the hands of engineers.\"\n    val deflater = Deflater(nowrap = true)\n    deflater.dataProcessor.apply {\n      source = content.encodeUtf8().toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      deflater.flush = Z_FINISH\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      assertTrue(process())\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals(content.length.toLong(), deflater.getBytesRead())\n      val deflated = target.toByteString(0, targetPos)\n\n      // Golden compressed output.\n      assertEquals(\n        \"c89PUchIzSlQKC3WUShPVS9KVcjMUyjJSFXISMxLKVbIT1NIzUvPzEtNLSrWAwA=\".decodeBase64(),\n        deflated,\n      )\n\n      deflater.end()\n    }\n  }\n\n  @Test\n  fun deflateInParts() {\n    val contentA = \"God help us, we're in the hands\"\n    val contentB = \" of engineers.\"\n    val deflater = Deflater()\n    deflater.dataProcessor.apply {\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      source = contentA.encodeUtf8().toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      assertTrue(process())\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals(contentA.length.toLong(), deflater.getBytesRead())\n\n      source = contentB.encodeUtf8().toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      deflater.flush = Z_FINISH\n      assertTrue(process())\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals((contentA + contentB).length.toLong(), deflater.getBytesRead())\n\n      val deflated = target.toByteString(0, targetPos)\n\n      // Golden compressed output.\n      assertEquals(\n        \"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\".decodeBase64(),\n        deflated,\n      )\n\n      deflater.end()\n    }\n  }\n\n  @Test\n  fun deflateInsufficientSpaceInTargetWithoutSourceFinished() {\n    val targetBuffer = Buffer()\n\n    val content = \"God help us, we're in the hands of engineers.\"\n    val deflater = Deflater()\n    deflater.dataProcessor.apply {\n      source = content.encodeUtf8().toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n\n      target = ByteArray(10)\n      targetPos = 0\n      targetLimit = target.size\n      deflater.flush = Z_SYNC_FLUSH\n      assertFalse(process())\n      assertEquals(targetLimit, targetPos)\n      assertEquals(content.length.toLong(), deflater.getBytesRead())\n      targetBuffer.write(target)\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n      deflater.flush = Z_NO_FLUSH\n      assertTrue(process())\n      assertEquals(sourcePos, sourceLimit)\n      assertEquals(content.length.toLong(), deflater.getBytesRead())\n      targetBuffer.write(target, 0, targetPos)\n\n      deflater.flush = Z_FINISH\n      assertTrue(process())\n\n      // Golden compressed output.\n      assertEquals(\n        \"eJxyz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYD\".decodeBase64(),\n        targetBuffer.readByteString(),\n      )\n\n      deflater.end()\n    }\n  }\n\n  @Test\n  fun deflateInsufficientSpaceInTargetWithSourceFinished() {\n    val targetBuffer = Buffer()\n\n    val content = \"God help us, we're in the hands of engineers.\"\n    val deflater = Deflater()\n    deflater.dataProcessor.apply {\n      source = content.encodeUtf8().toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      deflater.flush = Z_FINISH\n\n      target = ByteArray(10)\n      targetPos = 0\n      targetLimit = target.size\n      assertFalse(process())\n      assertEquals(targetLimit, targetPos)\n      assertEquals(content.length.toLong(), deflater.getBytesRead())\n      targetBuffer.write(target)\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n      assertTrue(process())\n      assertEquals(sourcePos, sourceLimit)\n      assertEquals(content.length.toLong(), deflater.getBytesRead())\n      targetBuffer.write(target, 0, targetPos)\n\n      // Golden compressed output.\n      assertEquals(\n        \"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\".decodeBase64(),\n        targetBuffer.readByteString(),\n      )\n\n      deflater.end()\n    }\n  }\n\n  @Test\n  fun deflateEmptySource() {\n    val deflater = Deflater()\n    deflater.dataProcessor.apply {\n      deflater.flush = Z_FINISH\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      assertTrue(process())\n      assertEquals(0L, deflater.getBytesRead())\n      val deflated = target.toByteString(0, targetPos)\n\n      // Golden compressed output.\n      assertEquals(\n        \"eJwDAAAAAAE=\".decodeBase64(),\n        deflated,\n      )\n\n      deflater.end()\n    }\n  }\n\n  @Test\n  fun cannotDeflateAfterEnd() {\n    val deflater = Deflater()\n    deflater.end()\n\n    assertFailsWith<IllegalStateException> {\n      deflater.dataProcessor.process()\n    }\n  }\n\n  @Test\n  fun cannotGetBytesReadAfterEnd() {\n    val deflater = Deflater()\n    deflater.end()\n\n    assertFailsWith<IllegalStateException> {\n      deflater.getBytesRead()\n    }\n  }\n\n  @Test\n  fun endIsIdemptent() {\n    val deflater = Deflater()\n    deflater.end()\n    deflater.end()\n  }\n\n  private fun Deflater(nowrap: Boolean) = Deflater(Z_BEST_COMPRESSION, nowrap)\n}\n"
  },
  {
    "path": "okio/src/nativeTest/kotlin/okio/InflateDeflateTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.toByteString\nimport platform.zlib.Z_BEST_COMPRESSION\n\nclass InflateDeflateTest {\n  /** The compressed data is 0.1% of the size of the original. */\n  @Test\n  fun deflateInflate_compressionRatio0_01() {\n    deflateInflate(\n      contentList = Array(16) {\n        ByteArray(1024 * 64) { 0 }.toByteString()\n      },\n      goldenCompressedSize = 1_330,\n    )\n  }\n\n  /** The compressed data is 100% of the size of the original. */\n  @Test\n  fun deflateInflate_compressionRatio100_0() {\n    deflateInflate(\n      contentList = Array(16) {\n        randomBytes(1024 * 64, seed = it)\n      },\n      goldenCompressedSize = 1_048_978,\n    )\n  }\n\n  /** The compressed data is 700% of the size of the original. */\n  @Test\n  fun deflateInflate_compressionRatio700_0() {\n    deflateInflate(\n      contentList = Array(1024 * 64) {\n        randomBytes(1, seed = it)\n      },\n      goldenCompressedSize = 458_959,\n    )\n  }\n\n  @Test\n  fun deflateInflateEmpty() {\n    deflateInflate(\n      contentList = arrayOf(),\n      goldenCompressedSize = 2,\n    )\n  }\n\n  private fun deflateInflate(\n    contentList: Array<ByteString>,\n    goldenCompressedSize: Long,\n  ) {\n    val data = Buffer()\n\n    val deflaterSink = DeflaterSink(\n      sink = data,\n      deflater = Deflater(level = Z_BEST_COMPRESSION, nowrap = true),\n    )\n    deflaterSink.buffer().use {\n      for (c in contentList) {\n        it.write(c)\n        it.flush()\n      }\n    }\n\n    assertEquals(goldenCompressedSize, data.size)\n\n    val inflaterSource = InflaterSource(\n      source = data,\n      inflater = Inflater(nowrap = true),\n    )\n    inflaterSource.buffer().use {\n      for (content in contentList) {\n        assertEquals(content, it.readByteString(content.size.toLong()))\n      }\n      assertTrue(it.exhausted())\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeTest/kotlin/okio/InflaterSourceTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertTrue\n\nclass InflaterSourceTest {\n  @Test\n  fun inflateFromSourceThatThrowsOnRead() {\n    val content = randomBytes(1024 * 32)\n\n    val throwingSource = ThrowingSource()\n    deflate(throwingSource.data, content)\n\n    val inflaterSource = throwingSource.inflate()\n\n    val sink = Buffer()\n    throwingSource.nextException = IOException(\"boom\")\n    assertFailsWith<IOException> {\n      inflaterSource.read(sink, Long.MAX_VALUE)\n    }\n    assertEquals(0, sink.size)\n\n    // We didn't lose any data. This isn't how real programs recover in practice, but it\n    // demonstrates that no segments are unaccounted for after an exception\n    assertEquals(content, inflaterSource.buffer().readByteString())\n    inflaterSource.close()\n    assertNoEmptySegments(throwingSource.data)\n    assertNoEmptySegments(sink)\n  }\n\n  @Test\n  fun inflateSourceThrowsOnClose() {\n    val content = randomBytes(1024 * 32)\n\n    val throwingSource = ThrowingSource()\n    deflate(throwingSource.data, content)\n\n    val inflaterSource = throwingSource.inflate()\n    val bufferedInflaterSource = inflaterSource.buffer()\n    assertEquals(content, bufferedInflaterSource.readByteString())\n\n    throwingSource.nextException = IOException(\"boom\")\n    assertFailsWith<IOException> {\n      inflaterSource.close()\n    }\n\n    assertTrue(throwingSource.closed)\n    assertTrue(inflaterSource.inflater.dataProcessor.closed)\n    assertNoEmptySegments(throwingSource.data)\n    assertNoEmptySegments(bufferedInflaterSource.buffer)\n  }\n\n  @Test\n  fun inflateInvalidThrows() {\n    // Half valid deflated data + and half 0xff.\n    val invalidData = Buffer()\n      .apply {\n        val deflatedData = Buffer()\n        deflate(deflatedData, randomBytes(1024 * 32))\n        write(deflatedData, deflatedData.size / 2)\n\n        write(ByteArray(deflatedData.size.toInt() / 2) { -128 })\n      }\n\n    val inflaterSource = invalidData.inflate()\n    val bufferedInflaterSource = inflaterSource.buffer()\n    assertFailsWith<IOException> {\n      bufferedInflaterSource.readByteString()\n    }\n\n    bufferedInflaterSource.close()\n    assertTrue(inflaterSource.inflater.dataProcessor.closed)\n    assertNoEmptySegments(invalidData.buffer)\n    assertNoEmptySegments(bufferedInflaterSource.buffer)\n  }\n\n  /**\n   * Confirm that [InflaterSource.read] doesn't read from its source stream until it's necessary\n   * to do so. (When it does read from the source, it reads a full segment.)\n   */\n  @Test\n  fun readsFromSourceDoNotOccurUntilNecessary() {\n    val deflatedData = Buffer()\n    deflate(deflatedData, randomBytes(1024 * 32, seed = 0))\n\n    val inflaterSource = deflatedData.inflate()\n\n    // These index values discovered experimentally.\n    val sink = Buffer()\n    inflaterSource.read(sink, 8184)\n    assertEquals(24 * 1024 + 16, deflatedData.size)\n\n    inflaterSource.read(sink, 1)\n    assertEquals(24 * 1024 + 16, deflatedData.size)\n\n    inflaterSource.read(sink, 1)\n    assertEquals(16 * 1024 + 16, deflatedData.size)\n\n    inflaterSource.read(sink, 1)\n    assertEquals(16 * 1024 + 16, deflatedData.size)\n  }\n\n  @Test\n  fun readsFromSourceDoNotOccurAfterExhausted() {\n    val content = randomBytes(1024 * 32, seed = 0)\n\n    val throwingSource = ThrowingSource()\n    deflate(throwingSource.data, content)\n\n    val inflaterSource = throwingSource.inflate()\n    val bufferedInflaterSource = inflaterSource.buffer()\n\n    assertEquals(content, bufferedInflaterSource.readByteString())\n\n    throwingSource.nextException = IOException(\"boom\")\n    assertTrue(bufferedInflaterSource.exhausted()) // Doesn't throw!\n    throwingSource.nextException = null\n\n    inflaterSource.close()\n  }\n\n  @Test\n  fun trailingDataIgnored() {\n    val content = randomBytes(1024 * 32)\n\n    val deflatedData = Buffer()\n    deflate(deflatedData, content)\n    deflatedData.write(ByteArray(1024 * 32))\n\n    val inflaterSource = deflatedData.inflate()\n    val bufferedInflaterSource = inflaterSource.buffer()\n\n    assertEquals(content, bufferedInflaterSource.readByteString())\n    assertTrue(bufferedInflaterSource.exhausted())\n    assertEquals(24_592, deflatedData.size) // One trailing segment is consumed.\n\n    inflaterSource.close()\n  }\n\n  class ThrowingSource : Source {\n    val data = Buffer()\n    var nextException: Throwable? = null\n    var closed = false\n\n    override fun read(sink: Buffer, byteCount: Long): Long {\n      nextException?.let { nextException = null; throw it }\n      return data.read(sink, byteCount)\n    }\n\n    override fun timeout() = Timeout.NONE\n\n    override fun close() {\n      closed = true\n      nextException?.let { nextException = null; throw it }\n    }\n  }\n\n  private fun deflate(sink: BufferedSink, content: ByteString) {\n    sink.deflate().buffer().use { deflaterSink ->\n      deflaterSink.write(content)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeTest/kotlin/okio/InflaterTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.decodeBase64\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.toByteString\n\nclass InflaterTest {\n  @Test\n  fun happyPath() {\n    val expected = \"God help us, we're in the hands of engineers.\"\n    val inflater = Inflater()\n    inflater.dataProcessor.apply {\n      source = \"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\"\n        .decodeBase64()!!.toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      assertTrue(process())\n      assertTrue(finished)\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals(expected.length.toLong(), inflater.getBytesWritten())\n\n      val inflated = target.toByteString(0, targetPos)\n      assertEquals(\n        expected,\n        inflated.utf8(),\n      )\n\n      inflater.end()\n    }\n  }\n\n  @Test\n  fun happyPathNoWrap() {\n    val content = \"God help us, we're in the hands of engineers.\"\n    val inflater = Inflater(nowrap = true)\n    inflater.dataProcessor.apply {\n      source = \"c89PUchIzSlQKC3WUShPVS9KVcjMUyjJSFXISMxLKVbIT1NIzUvPzEtNLSrWAwA=\"\n        .decodeBase64()!!.toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      assertTrue(process())\n      assertTrue(finished)\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals(content.length.toLong(), inflater.getBytesWritten())\n\n      val inflated = target.toByteString(0, targetPos)\n      assertEquals(\n        content,\n        inflated.utf8(),\n      )\n\n      inflater.end()\n    }\n  }\n\n  @Test\n  fun inflateInParts() {\n    val content = \"God help us, we're in the hands of engineers.\"\n    val inflater = Inflater()\n    inflater.dataProcessor.apply {\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      source = \"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxT\".decodeBase64()!!.toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      assertTrue(process())\n      assertFalse(finished)\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals(21, inflater.getBytesWritten())\n\n      source = \"KMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\".decodeBase64()!!.toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      assertTrue(process())\n      assertTrue(finished)\n      assertEquals(sourceLimit, sourcePos)\n      assertEquals(content.length.toLong(), inflater.getBytesWritten())\n\n      val inflated = target.toByteString(0, targetPos)\n      assertEquals(\n        content,\n        inflated.utf8(),\n      )\n\n      inflater.end()\n    }\n  }\n\n  @Test\n  fun inflateInsufficientSpaceInTarget() {\n    val targetBuffer = Buffer()\n\n    val content = \"God help us, we're in the hands of engineers.\"\n    val inflater = Inflater()\n    inflater.dataProcessor.apply {\n      source = \"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\"\n        .decodeBase64()!!.toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n\n      target = ByteArray(31)\n      targetPos = 0\n      targetLimit = target.size\n      assertFalse(process())\n      assertFalse(finished)\n      assertEquals(targetLimit, targetPos)\n      targetBuffer.write(target)\n      assertEquals(31, inflater.getBytesWritten())\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n      assertTrue(process())\n      assertTrue(finished)\n      assertEquals(sourcePos, sourceLimit)\n      targetBuffer.write(target, 0, targetPos)\n      assertEquals(content.length.toLong(), inflater.getBytesWritten())\n\n      assertEquals(\n        content,\n        targetBuffer.readUtf8(),\n      )\n\n      inflater.end()\n    }\n  }\n\n  @Test\n  fun inflateEmptyContent() {\n    val inflater = Inflater()\n    inflater.dataProcessor.apply {\n      source = \"eJwDAAAAAAE=\".decodeBase64()!!.toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      assertTrue(process())\n      assertTrue(finished)\n      assertEquals(0L, inflater.getBytesWritten())\n\n      val inflated = target.toByteString(0, targetPos)\n      assertEquals(\n        \"\",\n        inflated.utf8(),\n      )\n\n      inflater.end()\n    }\n  }\n\n  @Test\n  fun inflateInPartsStartingWithEmptySource() {\n    val content = \"God help us, we're in the hands of engineers.\"\n    val inflater = Inflater()\n    val dataProcessor = inflater.dataProcessor\n    dataProcessor.apply {\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      source = ByteArray(256)\n      sourcePos = 0\n      sourceLimit = 0\n      assertTrue(process())\n      assertFalse(finished)\n      assertEquals(0, inflater.getBytesWritten())\n\n      source = \"eJxzz09RyEjNKVAoLdZRKE9VL0pVyMxTKMlIVchIzEspVshPU0jNS8/MS00tKtYDAF6CD5s=\"\n        .decodeBase64()!!.toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      assertTrue(process())\n      assertTrue(finished)\n      assertEquals(content.length.toLong(), inflater.getBytesWritten())\n\n      val inflated = target.toByteString(0, targetPos)\n      assertEquals(\n        content,\n        inflated.utf8(),\n      )\n\n      inflater.end()\n    }\n  }\n\n  @Test\n  fun inflateInvalidData() {\n    val inflater = Inflater()\n    val dataProcessor = inflater.dataProcessor\n    dataProcessor.apply {\n      target = ByteArray(256)\n      targetPos = 0\n      targetLimit = target.size\n\n      source = \"ffffffffffffffff\".decodeHex().toByteArray()\n      sourcePos = 0\n      sourceLimit = source.size\n      val exception = assertFailsWith<ProtocolException> {\n        process()\n      }\n      assertFalse(finished)\n      assertEquals(\"Z_DATA_ERROR\", exception.message)\n      assertEquals(0L, inflater.getBytesWritten())\n\n      inflater.end()\n    }\n  }\n\n  @Test\n  fun cannotInflateAfterEnd() {\n    val inflater = Inflater()\n    inflater.end()\n\n    assertFailsWith<IllegalStateException> {\n      inflater.dataProcessor.process()\n    }\n  }\n\n  @Test\n  fun cannotGetBytesWrittenAfterEnd() {\n    val inflater = Inflater()\n    inflater.end()\n\n    assertFailsWith<IllegalStateException> {\n      inflater.getBytesWritten()\n    }\n  }\n\n  @Test\n  fun endIsIdemptent() {\n    val inflater = Inflater()\n    inflater.end()\n    inflater.end()\n  }\n}\n"
  },
  {
    "path": "okio/src/nativeTest/kotlin/okio/NativeSystemFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.time.Clock\n\nclass NativeSystemFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = FileSystem.SYSTEM,\n  windowsLimitations = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.DoesNothing,\n)\n"
  },
  {
    "path": "okio/src/nonAppleMain/kotlin/okio/ByteString.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport okio.internal.HashFunction\nimport okio.internal.Hmac\nimport okio.internal.Md5\nimport okio.internal.Sha1\nimport okio.internal.Sha256\nimport okio.internal.Sha512\nimport okio.internal.commonBase64\nimport okio.internal.commonBase64Url\nimport okio.internal.commonCompareTo\nimport okio.internal.commonCopyInto\nimport okio.internal.commonDecodeBase64\nimport okio.internal.commonDecodeHex\nimport okio.internal.commonEncodeUtf8\nimport okio.internal.commonEndsWith\nimport okio.internal.commonEquals\nimport okio.internal.commonGetByte\nimport okio.internal.commonGetSize\nimport okio.internal.commonHashCode\nimport okio.internal.commonHex\nimport okio.internal.commonIndexOf\nimport okio.internal.commonInternalArray\nimport okio.internal.commonLastIndexOf\nimport okio.internal.commonOf\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonStartsWith\nimport okio.internal.commonSubstring\nimport okio.internal.commonToAsciiLowercase\nimport okio.internal.commonToAsciiUppercase\nimport okio.internal.commonToByteArray\nimport okio.internal.commonToByteString\nimport okio.internal.commonToString\nimport okio.internal.commonUtf8\nimport okio.internal.commonWrite\n\nactual open class ByteString\ninternal actual constructor(\n  internal actual val data: ByteArray,\n) : Comparable<ByteString> {\n  @Suppress(\"SetterBackingFieldAssignment\")\n  internal actual var hashCode: Int = 0 // 0 if unknown.\n    set(value) {\n      // Do nothing to avoid IllegalImmutabilityException.\n    }\n\n  @Suppress(\"SetterBackingFieldAssignment\")\n  internal actual var utf8: String? = null\n    set(value) {\n      // Do nothing to avoid IllegalImmutabilityException.\n    }\n\n  actual open fun utf8(): String = commonUtf8()\n\n  actual open fun base64(): String = commonBase64()\n\n  actual open fun base64Url(): String = commonBase64Url()\n\n  actual open fun hex(): String = commonHex()\n\n  actual fun md5() = digest(Md5())\n\n  actual fun sha1() = digest(Sha1())\n\n  actual fun sha256() = digest(Sha256())\n\n  actual fun sha512() = digest(Sha512())\n\n  /** Returns the 160-bit SHA-1 HMAC of this byte string.  */\n  actual fun hmacSha1(key: ByteString) = digest(Hmac.sha1(key))\n\n  /** Returns the 256-bit SHA-256 HMAC of this byte string.  */\n  actual fun hmacSha256(key: ByteString) = digest(Hmac.sha256(key))\n\n  /** Returns the 512-bit SHA-512 HMAC of this byte string.  */\n  actual fun hmacSha512(key: ByteString) = digest(Hmac.sha512(key))\n\n  internal open fun digest(hashFunction: HashFunction): ByteString {\n    hashFunction.update(data, 0, size)\n    val digestBytes = hashFunction.digest()\n    return ByteString(digestBytes)\n  }\n\n  actual open fun toAsciiLowercase(): ByteString = commonToAsciiLowercase()\n\n  actual open fun toAsciiUppercase(): ByteString = commonToAsciiUppercase()\n\n  actual open fun substring(beginIndex: Int, endIndex: Int): ByteString =\n    commonSubstring(beginIndex, endIndex)\n\n  internal actual open fun internalGet(pos: Int): Byte {\n    if (pos >= size || pos < 0) throw ArrayIndexOutOfBoundsException(\"size=$size pos=$pos\")\n    return commonGetByte(pos)\n  }\n\n  actual operator fun get(index: Int): Byte = internalGet(index)\n\n  actual val size\n    get() = getSize()\n\n  internal actual open fun getSize() = commonGetSize()\n\n  actual open fun toByteArray() = commonToByteArray()\n\n  internal actual open fun internalArray() = commonInternalArray()\n\n  internal actual open fun write(buffer: Buffer, offset: Int, byteCount: Int) =\n    commonWrite(buffer, offset, byteCount)\n\n  actual open fun rangeEquals(\n    offset: Int,\n    other: ByteString,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  actual open fun rangeEquals(\n    offset: Int,\n    other: ByteArray,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  actual open fun copyInto(\n    offset: Int,\n    target: ByteArray,\n    targetOffset: Int,\n    byteCount: Int,\n  ) = commonCopyInto(offset, target, targetOffset, byteCount)\n\n  actual fun startsWith(prefix: ByteString) = commonStartsWith(prefix)\n\n  actual fun startsWith(prefix: ByteArray) = commonStartsWith(prefix)\n\n  actual fun endsWith(suffix: ByteString) = commonEndsWith(suffix)\n\n  actual fun endsWith(suffix: ByteArray) = commonEndsWith(suffix)\n\n  actual fun indexOf(other: ByteString, fromIndex: Int) = indexOf(other.internalArray(), fromIndex)\n\n  actual open fun indexOf(other: ByteArray, fromIndex: Int) = commonIndexOf(other, fromIndex)\n\n  actual fun lastIndexOf(other: ByteString, fromIndex: Int) = commonLastIndexOf(other, fromIndex)\n\n  actual open fun lastIndexOf(other: ByteArray, fromIndex: Int) = commonLastIndexOf(other, fromIndex)\n\n  actual override fun equals(other: Any?) = commonEquals(other)\n\n  actual override fun hashCode() = commonHashCode()\n\n  actual override fun compareTo(other: ByteString) = commonCompareTo(other)\n\n  /**\n   * Returns a human-readable string that describes the contents of this byte string. Typically this\n   * is a string like `[text=Hello]` or `[hex=0000ffff]`.\n   */\n  actual override fun toString() = commonToString()\n\n  actual companion object {\n    actual val EMPTY: ByteString = ByteString(byteArrayOf())\n\n    actual fun of(vararg data: Byte) = commonOf(data)\n\n    actual fun ByteArray.toByteString(offset: Int, byteCount: Int): ByteString =\n      commonToByteString(offset, byteCount)\n\n    actual fun String.encodeUtf8(): ByteString = commonEncodeUtf8()\n\n    actual fun String.decodeBase64(): ByteString? = commonDecodeBase64()\n\n    actual fun String.decodeHex() = commonDecodeHex()\n  }\n}\n"
  },
  {
    "path": "okio/src/nonAppleMain/kotlin/okio/SegmentedByteString.kt",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\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 */\npackage okio\n\nimport okio.internal.HashFunction\nimport okio.internal.commonCopyInto\nimport okio.internal.commonEquals\nimport okio.internal.commonGetSize\nimport okio.internal.commonHashCode\nimport okio.internal.commonInternalGet\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonSubstring\nimport okio.internal.commonToByteArray\nimport okio.internal.commonWrite\nimport okio.internal.forEachSegment\n\ninternal actual class SegmentedByteString internal actual constructor(\n  internal actual val segments: Array<ByteArray>,\n  internal actual val directory: IntArray,\n) : ByteString(EMPTY.data) {\n\n  override fun base64() = toByteString().base64()\n\n  override fun hex() = toByteString().hex()\n\n  override fun toAsciiLowercase() = toByteString().toAsciiLowercase()\n\n  override fun toAsciiUppercase() = toByteString().toAsciiUppercase()\n\n  override fun base64Url() = toByteString().base64Url()\n\n  override fun substring(beginIndex: Int, endIndex: Int): ByteString =\n    commonSubstring(beginIndex, endIndex)\n\n  override fun internalGet(pos: Int): Byte = commonInternalGet(pos)\n\n  override fun getSize() = commonGetSize()\n\n  override fun toByteArray(): ByteArray = commonToByteArray()\n\n  override fun write(buffer: Buffer, offset: Int, byteCount: Int): Unit =\n    commonWrite(buffer, offset, byteCount)\n\n  override fun rangeEquals(\n    offset: Int,\n    other: ByteString,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  override fun rangeEquals(\n    offset: Int,\n    other: ByteArray,\n    otherOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, other, otherOffset, byteCount)\n\n  override fun copyInto(\n    offset: Int,\n    target: ByteArray,\n    targetOffset: Int,\n    byteCount: Int,\n  ) = commonCopyInto(offset, target, targetOffset, byteCount)\n\n  override fun indexOf(other: ByteArray, fromIndex: Int) = toByteString().indexOf(other, fromIndex)\n\n  override fun lastIndexOf(other: ByteArray, fromIndex: Int) = toByteString().lastIndexOf(\n    other,\n    fromIndex,\n  )\n\n  override fun digest(hashFunction: HashFunction): ByteString {\n    forEachSegment { data, offset, byteCount ->\n      hashFunction.update(data, offset, byteCount)\n    }\n    val digestBytes = hashFunction.digest()\n    return ByteString(digestBytes)\n  }\n\n  /** Returns a copy as a non-segmented byte string.  */\n  private fun toByteString() = ByteString(toByteArray())\n\n  override fun internalArray() = toByteArray()\n\n  override fun equals(other: Any?): Boolean = commonEquals(other)\n\n  override fun hashCode(): Int = commonHashCode()\n\n  override fun toString() = toByteString().toString()\n}\n"
  },
  {
    "path": "okio/src/nonJsMain/kotlin/okio/internal/ByteStringNonJs.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\n@file:JvmName(\"-ByteStringNonJs\") // A leading '-' hides this class from Java.\n\npackage okio.internal\n\nimport kotlin.jvm.JvmName\nimport okio.ByteString\n\n@Suppress(\"NOTHING_TO_INLINE\")\ninternal actual inline fun String.commonDecodeHex(): ByteString {\n  require(length % 2 == 0) { \"Unexpected hex string: $this\" }\n\n  val result = ByteArray(length / 2)\n  for (i in result.indices) {\n    val d1 = decodeHexDigit(this[i * 2]) shl 4\n    val d2 = decodeHexDigit(this[i * 2 + 1])\n    result[i] = (d1 + d2).toByte()\n  }\n  return ByteString(result)\n}\n\nprivate fun decodeHexDigit(c: Char): Int {\n  return when (c) {\n    in '0'..'9' -> c - '0'\n    in 'a'..'f' -> c - 'a' + 10\n    in 'A'..'F' -> c - 'A' + 10\n    else -> throw IllegalArgumentException(\"Unexpected hex digit: $c\")\n  }\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/Buffer.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nimport okio.internal.HashFunction\nimport okio.internal.Hmac\nimport okio.internal.Md5\nimport okio.internal.Sha1\nimport okio.internal.Sha256\nimport okio.internal.Sha512\nimport okio.internal.commonClear\nimport okio.internal.commonClose\nimport okio.internal.commonCompleteSegmentByteCount\nimport okio.internal.commonCopy\nimport okio.internal.commonCopyTo\nimport okio.internal.commonEquals\nimport okio.internal.commonExpandBuffer\nimport okio.internal.commonGet\nimport okio.internal.commonHashCode\nimport okio.internal.commonIndexOf\nimport okio.internal.commonIndexOfElement\nimport okio.internal.commonNext\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonRead\nimport okio.internal.commonReadAll\nimport okio.internal.commonReadAndWriteUnsafe\nimport okio.internal.commonReadByte\nimport okio.internal.commonReadByteArray\nimport okio.internal.commonReadByteString\nimport okio.internal.commonReadDecimalLong\nimport okio.internal.commonReadFully\nimport okio.internal.commonReadHexadecimalUnsignedLong\nimport okio.internal.commonReadInt\nimport okio.internal.commonReadLong\nimport okio.internal.commonReadShort\nimport okio.internal.commonReadUnsafe\nimport okio.internal.commonReadUtf8\nimport okio.internal.commonReadUtf8CodePoint\nimport okio.internal.commonReadUtf8Line\nimport okio.internal.commonReadUtf8LineStrict\nimport okio.internal.commonResizeBuffer\nimport okio.internal.commonSeek\nimport okio.internal.commonSelect\nimport okio.internal.commonSkip\nimport okio.internal.commonSnapshot\nimport okio.internal.commonWritableSegment\nimport okio.internal.commonWrite\nimport okio.internal.commonWriteAll\nimport okio.internal.commonWriteByte\nimport okio.internal.commonWriteDecimalLong\nimport okio.internal.commonWriteHexadecimalUnsignedLong\nimport okio.internal.commonWriteInt\nimport okio.internal.commonWriteLong\nimport okio.internal.commonWriteShort\nimport okio.internal.commonWriteUtf8\nimport okio.internal.commonWriteUtf8CodePoint\n\nactual class Buffer : BufferedSource, BufferedSink {\n  internal actual var head: Segment? = null\n\n  actual var size: Long = 0L\n    internal set\n\n  actual override val buffer: Buffer get() = this\n\n  actual override fun emitCompleteSegments(): Buffer = this // Nowhere to emit to!\n\n  actual override fun emit(): Buffer = this // Nowhere to emit to!\n\n  actual override fun exhausted(): Boolean = size == 0L\n\n  actual override fun require(byteCount: Long) {\n    if (size < byteCount) throw EOFException(null)\n  }\n\n  actual override fun request(byteCount: Long): Boolean = size >= byteCount\n\n  actual override fun peek(): BufferedSource = PeekSource(this).buffer()\n\n  actual fun copyTo(\n    out: Buffer,\n    offset: Long,\n    byteCount: Long,\n  ): Buffer = commonCopyTo(out, offset, byteCount)\n\n  actual fun copyTo(\n    out: Buffer,\n    offset: Long,\n  ): Buffer = copyTo(out, offset, size - offset)\n\n  actual operator fun get(pos: Long): Byte = commonGet(pos)\n\n  actual fun completeSegmentByteCount(): Long = commonCompleteSegmentByteCount()\n\n  actual override fun readByte(): Byte = commonReadByte()\n\n  actual override fun readShort(): Short = commonReadShort()\n\n  actual override fun readInt(): Int = commonReadInt()\n\n  actual override fun readLong(): Long = commonReadLong()\n\n  actual override fun readShortLe(): Short = readShort().reverseBytes()\n\n  actual override fun readIntLe(): Int = readInt().reverseBytes()\n\n  actual override fun readLongLe(): Long = readLong().reverseBytes()\n\n  actual override fun readDecimalLong(): Long = commonReadDecimalLong()\n\n  actual override fun readHexadecimalUnsignedLong(): Long = commonReadHexadecimalUnsignedLong()\n\n  actual override fun readByteString(): ByteString = commonReadByteString()\n\n  actual override fun readByteString(byteCount: Long): ByteString = commonReadByteString(byteCount)\n\n  actual override fun readFully(sink: Buffer, byteCount: Long): Unit = commonReadFully(sink, byteCount)\n\n  actual override fun readAll(sink: Sink): Long = commonReadAll(sink)\n\n  actual override fun readUtf8(): String = readUtf8(size)\n\n  actual override fun readUtf8(byteCount: Long): String = commonReadUtf8(byteCount)\n\n  actual override fun readUtf8Line(): String? = commonReadUtf8Line()\n\n  actual override fun readUtf8LineStrict(): String = readUtf8LineStrict(Long.MAX_VALUE)\n\n  actual override fun readUtf8LineStrict(limit: Long): String = commonReadUtf8LineStrict(limit)\n\n  actual override fun readUtf8CodePoint(): Int = commonReadUtf8CodePoint()\n\n  actual override fun select(options: Options): Int = commonSelect(options)\n\n  actual override fun <T : Any> select(options: TypedOptions<T>): T? = commonSelect(options)\n\n  actual override fun readByteArray(): ByteArray = commonReadByteArray()\n\n  actual override fun readByteArray(byteCount: Long): ByteArray = commonReadByteArray(byteCount)\n\n  actual override fun read(sink: ByteArray): Int = commonRead(sink)\n\n  actual override fun readFully(sink: ByteArray): Unit = commonReadFully(sink)\n\n  actual override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int =\n    commonRead(sink, offset, byteCount)\n\n  actual fun clear(): Unit = commonClear()\n\n  actual override fun skip(byteCount: Long): Unit = commonSkip(byteCount)\n\n  actual override fun write(byteString: ByteString): Buffer = commonWrite(byteString)\n\n  actual override fun write(byteString: ByteString, offset: Int, byteCount: Int) =\n    commonWrite(byteString, offset, byteCount)\n\n  internal actual fun writableSegment(minimumCapacity: Int): Segment =\n    commonWritableSegment(minimumCapacity)\n\n  actual override fun writeUtf8(string: String): Buffer = writeUtf8(string, 0, string.length)\n\n  actual override fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): Buffer =\n    commonWriteUtf8(string, beginIndex, endIndex)\n\n  actual override fun writeUtf8CodePoint(codePoint: Int): Buffer =\n    commonWriteUtf8CodePoint(codePoint)\n\n  actual override fun write(source: ByteArray): Buffer = commonWrite(source)\n\n  actual override fun write(source: ByteArray, offset: Int, byteCount: Int): Buffer =\n    commonWrite(source, offset, byteCount)\n\n  actual override fun writeAll(source: Source): Long = commonWriteAll(source)\n\n  actual override fun write(source: Source, byteCount: Long): Buffer =\n    commonWrite(source, byteCount)\n\n  actual override fun writeByte(b: Int): Buffer = commonWriteByte(b)\n\n  actual override fun writeShort(s: Int): Buffer = commonWriteShort(s)\n\n  actual override fun writeShortLe(s: Int): Buffer = writeShort(s.toShort().reverseBytes().toInt())\n\n  actual override fun writeInt(i: Int): Buffer = commonWriteInt(i)\n\n  actual override fun writeIntLe(i: Int): Buffer = writeInt(i.reverseBytes())\n\n  actual override fun writeLong(v: Long): Buffer = commonWriteLong(v)\n\n  actual override fun writeLongLe(v: Long): Buffer = writeLong(v.reverseBytes())\n\n  actual override fun writeDecimalLong(v: Long): Buffer = commonWriteDecimalLong(v)\n\n  actual override fun writeHexadecimalUnsignedLong(v: Long): Buffer =\n    commonWriteHexadecimalUnsignedLong(v)\n\n  actual override fun write(source: Buffer, byteCount: Long): Unit = commonWrite(source, byteCount)\n\n  actual override fun read(sink: Buffer, byteCount: Long): Long = commonRead(sink, byteCount)\n\n  actual override fun indexOf(b: Byte): Long = indexOf(b, 0, Long.MAX_VALUE)\n\n  actual override fun indexOf(b: Byte, fromIndex: Long): Long = indexOf(b, fromIndex, Long.MAX_VALUE)\n\n  actual override fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(b, fromIndex = fromIndex, toIndex = toIndex)\n\n  actual override fun indexOf(bytes: ByteString): Long = indexOf(bytes, 0)\n\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long): Long =\n    indexOf(bytes, fromIndex, Long.MAX_VALUE)\n\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(bytes, fromIndex = fromIndex, toIndex = toIndex)\n\n  actual override fun indexOfElement(targetBytes: ByteString): Long = indexOfElement(targetBytes, 0L)\n\n  actual override fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long =\n    commonIndexOfElement(targetBytes, fromIndex)\n\n  actual override fun rangeEquals(offset: Long, bytes: ByteString): Boolean =\n    rangeEquals(offset, bytes, 0, bytes.size)\n\n  actual override fun rangeEquals(\n    offset: Long,\n    bytes: ByteString,\n    bytesOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, bytes, bytesOffset, byteCount)\n\n  actual override fun flush() = Unit\n\n  actual override fun close() = Unit\n\n  actual override fun timeout(): Timeout = Timeout.NONE\n\n  override fun equals(other: Any?): Boolean = commonEquals(other)\n\n  override fun hashCode(): Int = commonHashCode()\n\n  /**\n   * Returns a human-readable string that describes the contents of this buffer. Typically this\n   * is a string like `[text=Hello]` or `[hex=0000ffff]`.\n   */\n  override fun toString() = snapshot().toString()\n\n  actual fun copy(): Buffer = commonCopy()\n\n  actual fun snapshot(): ByteString = commonSnapshot()\n\n  actual fun snapshot(byteCount: Int): ByteString = commonSnapshot(byteCount)\n\n  actual fun md5() = digest(Md5())\n\n  actual fun sha1() = digest(Sha1())\n\n  actual fun sha256() = digest(Sha256())\n\n  actual fun sha512() = digest(Sha512())\n\n  /** Returns the 160-bit SHA-1 HMAC of this buffer.  */\n  actual fun hmacSha1(key: ByteString) = digest(Hmac.sha1(key))\n\n  /** Returns the 256-bit SHA-256 HMAC of this buffer.  */\n  actual fun hmacSha256(key: ByteString) = digest(Hmac.sha256(key))\n\n  /** Returns the 512-bit SHA-512 HMAC of this buffer.  */\n  actual fun hmacSha512(key: ByteString) = digest(Hmac.sha512(key))\n\n  private fun digest(hash: HashFunction): ByteString {\n    forEachSegment { segment ->\n      hash.update(segment.data, segment.pos, segment.limit - segment.pos)\n    }\n\n    return ByteString(hash.digest())\n  }\n\n  private fun forEachSegment(action: (Segment) -> Unit) {\n    head?.let { head ->\n      var segment: Segment? = head\n      do {\n        segment?.let(action)\n        segment = segment?.next\n      } while (segment !== head)\n    }\n  }\n\n  actual fun readUnsafe(unsafeCursor: UnsafeCursor): UnsafeCursor = commonReadUnsafe(unsafeCursor)\n\n  actual fun readAndWriteUnsafe(unsafeCursor: UnsafeCursor): UnsafeCursor =\n    commonReadAndWriteUnsafe(unsafeCursor)\n\n  actual class UnsafeCursor : Closeable {\n    actual var buffer: Buffer? = null\n    actual var readWrite: Boolean = false\n\n    internal actual var segment: Segment? = null\n    actual var offset = -1L\n    actual var data: ByteArray? = null\n    actual var start = -1\n    actual var end = -1\n\n    actual fun next(): Int = commonNext()\n\n    actual fun seek(offset: Long): Int = commonSeek(offset)\n\n    actual fun resizeBuffer(newSize: Long): Long = commonResizeBuffer(newSize)\n\n    actual fun expandBuffer(minByteCount: Int): Long = commonExpandBuffer(minByteCount)\n\n    actual override fun close() {\n      commonClose()\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/BufferedSink.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nactual sealed interface BufferedSink : Sink {\n  actual val buffer: Buffer\n\n  actual fun write(byteString: ByteString): BufferedSink\n\n  actual fun write(byteString: ByteString, offset: Int, byteCount: Int): BufferedSink\n\n  actual fun write(source: ByteArray): BufferedSink\n\n  actual fun write(source: ByteArray, offset: Int, byteCount: Int): BufferedSink\n\n  actual fun writeAll(source: Source): Long\n\n  actual fun write(source: Source, byteCount: Long): BufferedSink\n\n  actual fun writeUtf8(string: String): BufferedSink\n\n  actual fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): BufferedSink\n\n  actual fun writeUtf8CodePoint(codePoint: Int): BufferedSink\n\n  actual fun writeByte(b: Int): BufferedSink\n\n  actual fun writeShort(s: Int): BufferedSink\n\n  actual fun writeShortLe(s: Int): BufferedSink\n\n  actual fun writeInt(i: Int): BufferedSink\n\n  actual fun writeIntLe(i: Int): BufferedSink\n\n  actual fun writeLong(v: Long): BufferedSink\n\n  actual fun writeLongLe(v: Long): BufferedSink\n\n  actual fun writeDecimalLong(v: Long): BufferedSink\n\n  actual fun writeHexadecimalUnsignedLong(v: Long): BufferedSink\n\n  actual fun emit(): BufferedSink\n\n  actual fun emitCompleteSegments(): BufferedSink\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/BufferedSource.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nactual sealed interface BufferedSource : Source {\n  actual val buffer: Buffer\n\n  actual fun exhausted(): Boolean\n\n  actual fun require(byteCount: Long)\n\n  actual fun request(byteCount: Long): Boolean\n\n  actual fun readByte(): Byte\n\n  actual fun readShort(): Short\n\n  actual fun readShortLe(): Short\n\n  actual fun readInt(): Int\n\n  actual fun readIntLe(): Int\n\n  actual fun readLong(): Long\n\n  actual fun readLongLe(): Long\n\n  actual fun readDecimalLong(): Long\n\n  actual fun readHexadecimalUnsignedLong(): Long\n\n  actual fun skip(byteCount: Long)\n\n  actual fun readByteString(): ByteString\n\n  actual fun readByteString(byteCount: Long): ByteString\n\n  actual fun select(options: Options): Int\n\n  actual fun <T : Any> select(options: TypedOptions<T>): T?\n\n  actual fun readByteArray(): ByteArray\n\n  actual fun readByteArray(byteCount: Long): ByteArray\n\n  actual fun read(sink: ByteArray): Int\n\n  actual fun readFully(sink: ByteArray)\n\n  actual fun read(sink: ByteArray, offset: Int, byteCount: Int): Int\n\n  actual fun readFully(sink: Buffer, byteCount: Long)\n\n  actual fun readAll(sink: Sink): Long\n\n  actual fun readUtf8(): String\n\n  actual fun readUtf8(byteCount: Long): String\n\n  actual fun readUtf8Line(): String?\n\n  actual fun readUtf8LineStrict(): String\n\n  actual fun readUtf8LineStrict(limit: Long): String\n\n  actual fun readUtf8CodePoint(): Int\n\n  actual fun indexOf(b: Byte): Long\n\n  actual fun indexOf(b: Byte, fromIndex: Long): Long\n\n  actual fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long\n\n  actual fun indexOf(bytes: ByteString): Long\n\n  actual fun indexOf(bytes: ByteString, fromIndex: Long): Long\n\n  actual fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long\n\n  actual fun indexOfElement(targetBytes: ByteString): Long\n\n  actual fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long\n\n  actual fun rangeEquals(offset: Long, bytes: ByteString): Boolean\n\n  actual fun rangeEquals(offset: Long, bytes: ByteString, bytesOffset: Int, byteCount: Int): Boolean\n\n  actual fun peek(): BufferedSource\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/ForwardingSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nactual abstract class ForwardingSource actual constructor(\n  actual val delegate: Source,\n) : Source {\n  // TODO 'Source by delegate' once https://youtrack.jetbrains.com/issue/KT-23935 is fixed.\n\n  @Throws(IOException::class)\n  actual override fun read(sink: Buffer, byteCount: Long): Long = delegate.read(sink, byteCount)\n\n  actual override fun timeout() = delegate.timeout()\n\n  @Throws(IOException::class)\n  actual override fun close() = delegate.close()\n\n  actual override fun toString() = \"${this::class.simpleName}($delegate)\"\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/HashingSink.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport okio.internal.HashFunction\nimport okio.internal.Hmac\nimport okio.internal.Md5\nimport okio.internal.Sha1\nimport okio.internal.Sha256\nimport okio.internal.Sha512\n\nactual class HashingSink internal constructor(\n  private val sink: Sink,\n  private val hashFunction: HashFunction,\n) : Sink {\n\n  actual override fun write(source: Buffer, byteCount: Long) {\n    checkOffsetAndCount(source.size, 0, byteCount)\n\n    // Hash byteCount bytes from the prefix of source.\n    var hashedCount = 0L\n    var s = source.head!!\n    while (hashedCount < byteCount) {\n      val toHash = minOf(byteCount - hashedCount, s.limit - s.pos).toInt()\n      hashFunction.update(s.data, s.pos, toHash)\n      hashedCount += toHash\n      s = s.next!!\n    }\n\n    // Write those bytes to the sink.\n    sink.write(source, byteCount)\n  }\n\n  actual override fun flush() = sink.flush()\n\n  actual override fun timeout(): Timeout = sink.timeout()\n\n  actual override fun close() = sink.close()\n\n  /**\n   * Returns the hash of the bytes accepted thus far and resets the internal state of this sink.\n   *\n   * **Warning:** This method is not idempotent. Each time this method is called its\n   * internal state is cleared. This starts a new hash with zero bytes accepted.\n   */\n  actual val hash: ByteString\n    get() {\n      val result = hashFunction.digest()\n      return ByteString(result)\n    }\n\n  actual companion object {\n\n    /** Returns a sink that uses the obsolete MD5 hash algorithm to produce 128-bit hashes. */\n    actual fun md5(sink: Sink) = HashingSink(sink, Md5())\n\n    /** Returns a sink that uses the obsolete SHA-1 hash algorithm to produce 160-bit hashes. */\n    actual fun sha1(sink: Sink) = HashingSink(sink, Sha1())\n\n    /** Returns a sink that uses the SHA-256 hash algorithm to produce 256-bit hashes. */\n    actual fun sha256(sink: Sink) = HashingSink(sink, Sha256())\n\n    /** Returns a sink that uses the SHA-512 hash algorithm to produce 512-bit hashes. */\n    actual fun sha512(sink: Sink) = HashingSink(sink, Sha512())\n\n    /** Returns a sink that uses the obsolete SHA-1 HMAC algorithm to produce 160-bit hashes. */\n    actual fun hmacSha1(sink: Sink, key: ByteString) = HashingSink(sink, Hmac.sha1(key))\n\n    /** Returns a sink that uses the SHA-256 HMAC algorithm to produce 256-bit hashes. */\n    actual fun hmacSha256(sink: Sink, key: ByteString) = HashingSink(sink, Hmac.sha256(key))\n\n    /** Returns a sink that uses the SHA-512 HMAC algorithm to produce 512-bit hashes. */\n    actual fun hmacSha512(sink: Sink, key: ByteString) = HashingSink(sink, Hmac.sha512(key))\n  }\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/HashingSource.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport okio.internal.HashFunction\nimport okio.internal.Hmac\nimport okio.internal.Md5\nimport okio.internal.Sha1\nimport okio.internal.Sha256\nimport okio.internal.Sha512\n\nactual class HashingSource internal constructor(\n  private val source: Source,\n  private val hashFunction: HashFunction,\n) : Source {\n\n  actual override fun read(sink: Buffer, byteCount: Long): Long {\n    val result = source.read(sink, byteCount)\n\n    if (result != -1L) {\n      var start = sink.size - result\n\n      // Find the first segment that has new bytes.\n      var offset = sink.size\n      var s = sink.head!!\n      while (offset > start) {\n        s = s.prev!!\n        offset -= (s.limit - s.pos).toLong()\n      }\n\n      // Hash that segment and all the rest until the end.\n      while (offset < sink.size) {\n        val pos = (s.pos + start - offset).toInt()\n        hashFunction.update(s.data, pos, s.limit - pos)\n        offset += s.limit - s.pos\n        start = offset\n        s = s.next!!\n      }\n    }\n\n    return result\n  }\n\n  actual override fun timeout(): Timeout =\n    source.timeout()\n\n  actual override fun close() =\n    source.close()\n\n  actual val hash: ByteString\n    get() {\n      val result = hashFunction.digest()\n      return ByteString(result)\n    }\n\n  actual companion object {\n\n    /** Returns a source that uses the obsolete MD5 hash algorithm to produce 128-bit hashes. */\n    actual fun md5(source: Source) = HashingSource(source, Md5())\n\n    /** Returns a source that uses the obsolete SHA-1 hash algorithm to produce 160-bit hashes. */\n    actual fun sha1(source: Source) = HashingSource(source, Sha1())\n\n    /** Returns a source that uses the SHA-256 hash algorithm to produce 256-bit hashes. */\n    actual fun sha256(source: Source) = HashingSource(source, Sha256())\n\n    /** Returns a source that uses the SHA-512 hash algorithm to produce 512-bit hashes. */\n    actual fun sha512(source: Source) = HashingSource(source, Sha512())\n\n    /** Returns a source that uses the obsolete SHA-1 HMAC algorithm to produce 160-bit hashes. */\n    actual fun hmacSha1(source: Source, key: ByteString) = HashingSource(source, Hmac.sha1(key))\n\n    /** Returns a source that uses the SHA-256 HMAC algorithm to produce 256-bit hashes. */\n    actual fun hmacSha256(source: Source, key: ByteString) = HashingSource(source, Hmac.sha256(key))\n\n    /** Returns a source that uses the SHA-512 HMAC algorithm to produce 512-bit hashes. */\n    actual fun hmacSha512(source: Source, key: ByteString) = HashingSource(source, Hmac.sha512(key))\n  }\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/NonJvmPlatform.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.contracts.InvocationKind\nimport kotlin.contracts.contract\nimport okio.internal.commonAsUtf8ToByteArray\nimport okio.internal.commonToUtf8String\n\ninternal expect val PLATFORM_DIRECTORY_SEPARATOR: String\n\ninternal actual fun ByteArray.toUtf8String(): String = commonToUtf8String()\n\ninternal actual fun String.asUtf8ToByteArray(): ByteArray = commonAsUtf8ToByteArray()\n\nactual open class ArrayIndexOutOfBoundsException actual constructor(\n  message: String?,\n) : IndexOutOfBoundsException(message)\n\nactual class Lock {\n  companion object {\n    val instance = Lock()\n  }\n}\n\ninternal actual fun newLock(): Lock = Lock.instance\n\nactual inline fun <T> Lock.withLock(action: () -> T): T {\n  contract {\n    callsInPlace(action, InvocationKind.EXACTLY_ONCE)\n  }\n\n  return action()\n}\n\nactual open class IOException actual constructor(\n  message: String?,\n  cause: Throwable?,\n) : Exception(message, cause) {\n  actual constructor(message: String?) : this(message, null)\n  actual constructor() : this(null, null)\n}\n\nactual class ProtocolException actual constructor(message: String) : IOException(message)\n\nactual open class EOFException actual constructor(message: String?) : IOException(message) {\n  actual constructor() : this(null)\n}\n\nactual open class FileNotFoundException actual constructor(message: String?) : IOException(message)\n\nactual interface Closeable {\n  @Throws(IOException::class)\n  actual fun close()\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/Path.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport okio.internal.commonCompareTo\nimport okio.internal.commonEquals\nimport okio.internal.commonHashCode\nimport okio.internal.commonIsAbsolute\nimport okio.internal.commonIsRelative\nimport okio.internal.commonIsRoot\nimport okio.internal.commonName\nimport okio.internal.commonNameBytes\nimport okio.internal.commonNormalized\nimport okio.internal.commonParent\nimport okio.internal.commonRelativeTo\nimport okio.internal.commonResolve\nimport okio.internal.commonRoot\nimport okio.internal.commonSegments\nimport okio.internal.commonSegmentsBytes\nimport okio.internal.commonToPath\nimport okio.internal.commonToString\nimport okio.internal.commonVolumeLetter\n\nactual class Path internal actual constructor(\n  internal actual val bytes: ByteString,\n) : Comparable<Path> {\n  actual val root: Path?\n    get() = commonRoot()\n\n  actual val segments: List<String>\n    get() = commonSegments()\n\n  actual val segmentsBytes: List<ByteString>\n    get() = commonSegmentsBytes()\n\n  actual val isAbsolute: Boolean\n    get() = commonIsAbsolute()\n\n  actual val isRelative: Boolean\n    get() = commonIsRelative()\n\n  actual val volumeLetter: Char?\n    get() = commonVolumeLetter()\n\n  actual val nameBytes: ByteString\n    get() = commonNameBytes()\n\n  actual val name: String\n    get() = commonName()\n\n  actual val parent: Path?\n    get() = commonParent()\n\n  actual val isRoot: Boolean\n    get() = commonIsRoot()\n\n  actual operator fun div(child: String): Path = commonResolve(child, normalize = false)\n\n  actual operator fun div(child: ByteString): Path = commonResolve(child, normalize = false)\n\n  actual operator fun div(child: Path): Path = commonResolve(child, normalize = false)\n\n  actual fun resolve(child: String, normalize: Boolean): Path =\n    commonResolve(child, normalize = normalize)\n\n  actual fun resolve(child: ByteString, normalize: Boolean): Path =\n    commonResolve(child, normalize = normalize)\n\n  actual fun resolve(child: Path, normalize: Boolean): Path =\n    commonResolve(child = child, normalize = normalize)\n\n  actual fun relativeTo(other: Path): Path = commonRelativeTo(other)\n\n  actual fun normalized(): Path = commonNormalized()\n\n  actual override fun compareTo(other: Path): Int = commonCompareTo(other)\n\n  actual override fun equals(other: Any?): Boolean = commonEquals(other)\n\n  actual override fun hashCode() = commonHashCode()\n\n  actual override fun toString() = commonToString()\n\n  actual companion object {\n    actual val DIRECTORY_SEPARATOR: String = PLATFORM_DIRECTORY_SEPARATOR\n\n    actual fun String.toPath(normalize: Boolean): Path = commonToPath(normalize)\n  }\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/RealBufferedSink.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\n\npackage okio\n\nimport okio.internal.commonClose\nimport okio.internal.commonEmit\nimport okio.internal.commonEmitCompleteSegments\nimport okio.internal.commonFlush\nimport okio.internal.commonTimeout\nimport okio.internal.commonToString\nimport okio.internal.commonWrite\nimport okio.internal.commonWriteAll\nimport okio.internal.commonWriteByte\nimport okio.internal.commonWriteDecimalLong\nimport okio.internal.commonWriteHexadecimalUnsignedLong\nimport okio.internal.commonWriteInt\nimport okio.internal.commonWriteIntLe\nimport okio.internal.commonWriteLong\nimport okio.internal.commonWriteLongLe\nimport okio.internal.commonWriteShort\nimport okio.internal.commonWriteShortLe\nimport okio.internal.commonWriteUtf8\nimport okio.internal.commonWriteUtf8CodePoint\n\ninternal actual class RealBufferedSink actual constructor(\n  actual val sink: Sink,\n) : BufferedSink {\n  actual var closed: Boolean = false\n  actual override val buffer = Buffer()\n\n  actual override fun write(source: Buffer, byteCount: Long) = commonWrite(source, byteCount)\n  actual override fun write(byteString: ByteString) = commonWrite(byteString)\n  actual override fun write(byteString: ByteString, offset: Int, byteCount: Int) =\n    commonWrite(byteString, offset, byteCount)\n  actual override fun writeUtf8(string: String) = commonWriteUtf8(string)\n  actual override fun writeUtf8(string: String, beginIndex: Int, endIndex: Int) =\n    commonWriteUtf8(string, beginIndex, endIndex)\n\n  actual override fun writeUtf8CodePoint(codePoint: Int) = commonWriteUtf8CodePoint(codePoint)\n  actual override fun write(source: ByteArray) = commonWrite(source)\n  actual override fun write(source: ByteArray, offset: Int, byteCount: Int) =\n    commonWrite(source, offset, byteCount)\n\n  actual override fun writeAll(source: Source) = commonWriteAll(source)\n  actual override fun write(source: Source, byteCount: Long): BufferedSink = commonWrite(source, byteCount)\n  actual override fun writeByte(b: Int) = commonWriteByte(b)\n  actual override fun writeShort(s: Int) = commonWriteShort(s)\n  actual override fun writeShortLe(s: Int) = commonWriteShortLe(s)\n  actual override fun writeInt(i: Int) = commonWriteInt(i)\n  actual override fun writeIntLe(i: Int) = commonWriteIntLe(i)\n  actual override fun writeLong(v: Long) = commonWriteLong(v)\n  actual override fun writeLongLe(v: Long) = commonWriteLongLe(v)\n  actual override fun writeDecimalLong(v: Long) = commonWriteDecimalLong(v)\n  actual override fun writeHexadecimalUnsignedLong(v: Long) = commonWriteHexadecimalUnsignedLong(v)\n  actual override fun emitCompleteSegments() = commonEmitCompleteSegments()\n  actual override fun emit() = commonEmit()\n  actual override fun flush() = commonFlush()\n  actual override fun close() = commonClose()\n  actual override fun timeout() = commonTimeout()\n  override fun toString() = commonToString()\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/RealBufferedSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport okio.internal.commonClose\nimport okio.internal.commonExhausted\nimport okio.internal.commonIndexOf\nimport okio.internal.commonIndexOfElement\nimport okio.internal.commonPeek\nimport okio.internal.commonRangeEquals\nimport okio.internal.commonRead\nimport okio.internal.commonReadAll\nimport okio.internal.commonReadByte\nimport okio.internal.commonReadByteArray\nimport okio.internal.commonReadByteString\nimport okio.internal.commonReadDecimalLong\nimport okio.internal.commonReadFully\nimport okio.internal.commonReadHexadecimalUnsignedLong\nimport okio.internal.commonReadInt\nimport okio.internal.commonReadIntLe\nimport okio.internal.commonReadLong\nimport okio.internal.commonReadLongLe\nimport okio.internal.commonReadShort\nimport okio.internal.commonReadShortLe\nimport okio.internal.commonReadUtf8\nimport okio.internal.commonReadUtf8CodePoint\nimport okio.internal.commonReadUtf8Line\nimport okio.internal.commonReadUtf8LineStrict\nimport okio.internal.commonRequest\nimport okio.internal.commonRequire\nimport okio.internal.commonSelect\nimport okio.internal.commonSkip\nimport okio.internal.commonTimeout\nimport okio.internal.commonToString\n\ninternal actual class RealBufferedSource actual constructor(\n  actual val source: Source,\n) : BufferedSource {\n  actual var closed: Boolean = false\n  actual override val buffer: Buffer = Buffer()\n\n  actual override fun read(sink: Buffer, byteCount: Long): Long = commonRead(sink, byteCount)\n  actual override fun exhausted(): Boolean = commonExhausted()\n  actual override fun require(byteCount: Long): Unit = commonRequire(byteCount)\n  actual override fun request(byteCount: Long): Boolean = commonRequest(byteCount)\n  actual override fun readByte(): Byte = commonReadByte()\n  actual override fun readByteString(): ByteString = commonReadByteString()\n  actual override fun readByteString(byteCount: Long): ByteString = commonReadByteString(byteCount)\n  actual override fun select(options: Options): Int = commonSelect(options)\n  actual override fun <T : Any> select(options: TypedOptions<T>): T? = commonSelect(options)\n  actual override fun readByteArray(): ByteArray = commonReadByteArray()\n  actual override fun readByteArray(byteCount: Long): ByteArray = commonReadByteArray(byteCount)\n  actual override fun read(sink: ByteArray): Int = read(sink, 0, sink.size)\n  actual override fun readFully(sink: ByteArray): Unit = commonReadFully(sink)\n  actual override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int =\n    commonRead(sink, offset, byteCount)\n\n  actual override fun readFully(sink: Buffer, byteCount: Long): Unit =\n    commonReadFully(sink, byteCount)\n  actual override fun readAll(sink: Sink): Long = commonReadAll(sink)\n  actual override fun readUtf8(): String = commonReadUtf8()\n  actual override fun readUtf8(byteCount: Long): String = commonReadUtf8(byteCount)\n  actual override fun readUtf8Line(): String? = commonReadUtf8Line()\n  actual override fun readUtf8LineStrict() = readUtf8LineStrict(Long.MAX_VALUE)\n  actual override fun readUtf8LineStrict(limit: Long): String = commonReadUtf8LineStrict(limit)\n  actual override fun readUtf8CodePoint(): Int = commonReadUtf8CodePoint()\n  actual override fun readShort(): Short = commonReadShort()\n  actual override fun readShortLe(): Short = commonReadShortLe()\n  actual override fun readInt(): Int = commonReadInt()\n  actual override fun readIntLe(): Int = commonReadIntLe()\n  actual override fun readLong(): Long = commonReadLong()\n  actual override fun readLongLe(): Long = commonReadLongLe()\n  actual override fun readDecimalLong(): Long = commonReadDecimalLong()\n  actual override fun readHexadecimalUnsignedLong(): Long = commonReadHexadecimalUnsignedLong()\n  actual override fun skip(byteCount: Long): Unit = commonSkip(byteCount)\n  actual override fun indexOf(b: Byte): Long = indexOf(b, 0L, Long.MAX_VALUE)\n  actual override fun indexOf(b: Byte, fromIndex: Long): Long =\n    indexOf(b, fromIndex, Long.MAX_VALUE)\n  actual override fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(b, fromIndex = fromIndex, toIndex = toIndex)\n\n  actual override fun indexOf(bytes: ByteString): Long = indexOf(bytes, 0L)\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long): Long =\n    indexOf(bytes, fromIndex, Long.MAX_VALUE)\n  actual override fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long =\n    commonIndexOf(bytes, fromIndex = fromIndex, toIndex = toIndex)\n  actual override fun indexOfElement(targetBytes: ByteString): Long =\n    indexOfElement(targetBytes, 0L)\n  actual override fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long =\n    commonIndexOfElement(targetBytes, fromIndex)\n\n  actual override fun rangeEquals(offset: Long, bytes: ByteString) = rangeEquals(\n    offset,\n    bytes,\n    0,\n    bytes.size,\n  )\n\n  actual override fun rangeEquals(\n    offset: Long,\n    bytes: ByteString,\n    bytesOffset: Int,\n    byteCount: Int,\n  ): Boolean = commonRangeEquals(offset, bytes, bytesOffset, byteCount)\n\n  actual override fun peek(): BufferedSource = commonPeek()\n  actual override fun close(): Unit = commonClose()\n  actual override fun timeout(): Timeout = commonTimeout()\n  override fun toString(): String = commonToString()\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/SegmentPool.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\ninternal actual object SegmentPool {\n  actual val MAX_SIZE: Int = 0\n\n  actual val byteCount: Int = 0\n\n  actual fun take(): Segment = Segment()\n\n  actual fun recycle(segment: Segment) {\n  }\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/Sink.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nactual interface Sink : Closeable {\n  @Throws(IOException::class)\n  actual fun write(source: Buffer, byteCount: Long)\n\n  @Throws(IOException::class)\n  actual fun flush()\n\n  actual fun timeout(): Timeout\n\n  @Throws(IOException::class)\n  actual override fun close()\n}\n"
  },
  {
    "path": "okio/src/nonJvmMain/kotlin/okio/Timeout.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nactual open class Timeout {\n  actual companion object {\n    actual val NONE = Timeout()\n  }\n}\n"
  },
  {
    "path": "okio/src/nonJvmTest/kotlin/okio/NonJvmTesting.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\n\nactual fun assertRelativeTo(\n  a: Path,\n  b: Path,\n  bRelativeToA: Path,\n  sameAsNio: Boolean,\n) {\n  val actual = b.relativeTo(a)\n  assertEquals(bRelativeToA, actual)\n  assertEquals(b.normalized().withUnixSlashes(), (a / actual).normalized().withUnixSlashes())\n}\n\nactual fun assertRelativeToFails(\n  a: Path,\n  b: Path,\n  sameAsNio: Boolean,\n): IllegalArgumentException {\n  return assertFailsWith { b.relativeTo(a) }\n}\n\nactual fun <T> withUtc(block: () -> T): T {\n  return block()\n}\n"
  },
  {
    "path": "okio/src/nonWasmTest/kotlin/okio/FakeFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.reflect.KClass\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNull\nimport kotlin.test.assertTrue\nimport kotlin.time.Duration.Companion.minutes\nimport okio.Path.Companion.toPath\nimport okio.fakefilesystem.FakeFileSystem\n\nclass FakeWindowsFileSystemTest private constructor(clock: FakeClock) : FakeFileSystemTest(\n  fakeFileSystem = FakeFileSystem(clock = clock).also { it.emulateWindows() },\n  fakeClock = clock,\n  temporaryDirectory = \"C:\\\\\".toPath(),\n) {\n  constructor() : this(FakeClock())\n}\n\nclass FakeUnixFileSystemTest private constructor(clock: FakeClock) : FakeFileSystemTest(\n  fakeFileSystem = FakeFileSystem(clock = clock).also { it.emulateUnix() },\n  fakeClock = clock,\n  temporaryDirectory = \"/\".toPath(),\n) {\n  constructor() : this(FakeClock())\n}\n\nclass StrictFakeFileSystemTest private constructor(clock: FakeClock) : FakeFileSystemTest(\n  fakeFileSystem = FakeFileSystem(clock = clock),\n  fakeClock = clock,\n  temporaryDirectory = \"/\".toPath(),\n) {\n  constructor() : this(FakeClock())\n}\n\nabstract class FakeFileSystemTest internal constructor(\n  private val fakeFileSystem: FakeFileSystem,\n  private val fakeClock: FakeClock,\n  temporaryDirectory: Path,\n) : AbstractFileSystemTest(\n  clock = fakeFileSystem.clock,\n  fileSystem = fakeFileSystem,\n  windowsLimitations = !fakeFileSystem.allowMovingOpenFiles,\n  allowClobberingEmptyDirectories = fakeFileSystem.allowClobberingEmptyDirectories,\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = temporaryDirectory,\n  closeBehavior = CloseBehavior.Closes,\n) {\n\n  @Test\n  fun openPathsIncludesOpenSink() {\n    val openPath = base / \"open-file\"\n    val sink = fileSystem.sink(openPath)\n    assertEquals(openPath, fakeFileSystem.openPaths.single())\n    sink.close()\n    assertTrue(fakeFileSystem.openPaths.isEmpty())\n  }\n\n  @Test\n  fun openPathsIncludesOpenSource() {\n    val openPath = base / \"open-file\"\n    openPath.writeUtf8(\"hello, world!\")\n    assertTrue(fakeFileSystem.openPaths.isEmpty())\n    val source = fileSystem.source(openPath)\n    assertEquals(openPath, fakeFileSystem.openPaths.single())\n    source.close()\n    assertTrue(fakeFileSystem.openPaths.isEmpty())\n  }\n\n  @Test\n  fun openPathsIsOpenOrder() {\n    if (!fakeFileSystem.allowWritesWhileWriting) return\n\n    val fileA = base / \"a\"\n    val fileB = base / \"b\"\n    val fileC = base / \"c\"\n    val fileD = base / \"d\"\n\n    assertEquals(fakeFileSystem.openPaths, listOf())\n    val sinkD = fileSystem.sink(fileD)\n    assertEquals(fakeFileSystem.openPaths, listOf(fileD))\n    val sinkB = fileSystem.sink(fileB)\n    assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB))\n    val sinkC = fileSystem.sink(fileC)\n    assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB, fileC))\n    val sinkA = fileSystem.sink(fileA)\n    assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB, fileC, fileA))\n    val sinkB2 = fileSystem.sink(fileB)\n    assertEquals(fakeFileSystem.openPaths, listOf(fileD, fileB, fileC, fileA, fileB))\n    sinkD.close()\n    assertEquals(fakeFileSystem.openPaths, listOf(fileB, fileC, fileA, fileB))\n    sinkB2.close()\n    assertEquals(fakeFileSystem.openPaths, listOf(fileB, fileC, fileA))\n    sinkB.close()\n    assertEquals(fakeFileSystem.openPaths, listOf(fileC, fileA))\n    sinkC.close()\n    assertEquals(fakeFileSystem.openPaths, listOf(fileA))\n    sinkA.close()\n    assertEquals(fakeFileSystem.openPaths, listOf())\n  }\n\n  @Test\n  fun allPathsIncludesFile() {\n    val file = base / \"all-files-includes-file\"\n    file.writeUtf8(\"hello, world!\")\n    assertEquals(setOf(base, file), fakeFileSystem.allPaths)\n  }\n\n  @Test\n  fun allPathsIsSorted() {\n    val fileA = base / \"a\"\n    val fileB = base / \"b\"\n    val fileC = base / \"c\"\n    val fileD = base / \"d\"\n\n    // Create files in a different order than the sorted order, so a file system that returns files\n    // in creation-order or reverse-creation order won't pass by accident.\n    fileD.writeUtf8(\"fileD\")\n    fileB.writeUtf8(\"fileB\")\n    fileC.writeUtf8(\"fileC\")\n    fileA.writeUtf8(\"fileA\")\n\n    assertEquals(listOf(base, fileA, fileB, fileC, fileD), fakeFileSystem.allPaths.toList())\n  }\n\n  @Test\n  fun allPathsIncludesDirectory() {\n    val dir = base / \"all-files-includes-directory\"\n    fileSystem.createDirectory(dir)\n    assertEquals(setOf(base, dir), fakeFileSystem.allPaths)\n  }\n\n  @Test\n  fun allPathsDoesNotIncludeDeletedFile() {\n    val file = base / \"all-files-does-not-include-deleted-file\"\n    file.writeUtf8(\"hello, world!\")\n    fileSystem.delete(file)\n    assertEquals(setOf(base), fakeFileSystem.allPaths)\n  }\n\n  @Test\n  fun allPathsDoesNotIncludeDeletedOpenFile() {\n    if (windowsLimitations) return // Can't delete open files with Windows' limitations.\n\n    val file = base / \"all-files-does-not-include-deleted-open-file\"\n    val sink = fileSystem.sink(file)\n    assertEquals(setOf(base, file), fakeFileSystem.allPaths)\n    fileSystem.delete(file)\n    assertEquals(setOf(base), fakeFileSystem.allPaths)\n    sink.close()\n  }\n\n  @Test\n  fun fileLastAccessedTime() {\n    val path = base / \"file-last-accessed-time\"\n\n    fakeClock.sleep(1.minutes)\n    path.writeUtf8(\"hello, world!\")\n    val createdAt = clock.now()\n\n    fakeClock.sleep(1.minutes)\n    path.writeUtf8(\"hello again!\")\n    val modifiedAt = clock.now()\n\n    fakeClock.sleep(1.minutes)\n    path.readUtf8()\n    val accessedAt = clock.now()\n\n    val metadata = fileSystem.metadata(path)\n    assertEquals(createdAt, metadata.createdAt)\n    assertEquals(modifiedAt, metadata.lastModifiedAt)\n    assertEquals(accessedAt, metadata.lastAccessedAt)\n  }\n\n  @Test\n  fun directoryLastAccessedTime() {\n    val path = base / \"directory-last-accessed-time\"\n\n    fakeClock.sleep(1.minutes)\n    fileSystem.createDirectory(path)\n    val createdAt = clock.now()\n\n    fakeClock.sleep(1.minutes)\n    (path / \"child\").writeUtf8(\"hello world!\")\n    val modifiedAt = clock.now()\n\n    fakeClock.sleep(1.minutes)\n    fileSystem.list(path)\n    val accessedAt = clock.now()\n\n    val metadata = fileSystem.metadata(path)\n    assertEquals(createdAt, metadata.createdAt)\n    assertEquals(modifiedAt, metadata.lastModifiedAt)\n    assertEquals(accessedAt, metadata.lastAccessedAt)\n  }\n\n  @Test\n  fun checkNoOpenFilesThrowsOnOpenSource() {\n    val path = base / \"check-no-open-files-open-source\"\n    path.writeUtf8(\"hello, world!\")\n    val exception = fileSystem.source(path).use { source ->\n      assertFailsWith<IllegalStateException> {\n        fakeFileSystem.checkNoOpenFiles()\n      }\n    }\n\n    assertEquals(\n      \"\"\"\n      |expected 0 open files, but found:\n      |    $path\n      \"\"\".trimMargin(),\n      exception.message,\n    )\n    assertEquals(\"file opened for READ here\", exception.cause?.message)\n\n    // Now that the source is closed this is safe.\n    fakeFileSystem.checkNoOpenFiles()\n  }\n\n  @Test\n  fun checkNoOpenFilesThrowsOnOpenSink() {\n    val path = base / \"check-no-open-files-open-sink\"\n    val exception = fileSystem.sink(path).use { source ->\n      assertFailsWith<IllegalStateException> {\n        fakeFileSystem.checkNoOpenFiles()\n      }\n    }\n\n    assertEquals(\n      \"\"\"\n      |expected 0 open files, but found:\n      |    $path\n      \"\"\".trimMargin(),\n      exception.message,\n    )\n    assertEquals(\"file opened for WRITE here\", exception.cause?.message)\n\n    // Now that the source is closed this is safe.\n    fakeFileSystem.checkNoOpenFiles()\n  }\n\n  @Test\n  fun createDirectoriesForVolumeLetterRoot() {\n    val path = \"X:\\\\\".toPath()\n    fileSystem.createDirectories(path)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesForChildOfVolumeLetterRoot() {\n    val path = \"X:\\\\path\".toPath()\n    fileSystem.createDirectories(path)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesForUnixRoot() {\n    val path = \"/\".toPath()\n    fileSystem.createDirectories(path)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesForChildOfUnixRoot() {\n    val path = \"/path\".toPath()\n    fileSystem.createDirectories(path)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesForUncRoot() {\n    val path = \"\\\\\\\\server\".toPath()\n    fileSystem.createDirectories(path)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesForChildOfUncRoot() {\n    val path = \"\\\\\\\\server\\\\project\".toPath()\n    fileSystem.createDirectories(path)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun workingDirectoryMustBeAbsolute() {\n    val exception = assertFailsWith<IllegalArgumentException> {\n      fakeFileSystem.workingDirectory = \"some/relative/path\".toPath()\n    }\n    assertEquals(\"expected an absolute path but was some/relative/path\", exception.message)\n  }\n\n  @Test\n  fun metadataForRootsGeneratedOnDemand() {\n    assertTrue(fileSystem.metadata(\"X:\\\\\".toPath()).isDirectory)\n    assertTrue(fileSystem.metadata(\"/\".toPath()).isDirectory)\n    assertTrue(fileSystem.metadata(\"\\\\\\\\server\".toPath()).isDirectory)\n  }\n\n  @Test\n  fun startWriteWhileWritingNotAllowedWhenStrict() {\n    val path = base / \"write-write\"\n    path.writeUtf8(\"hello world!\")\n    fileSystem.sink(path).use {\n      try {\n        fileSystem.sink(path).use {\n        }\n        assertTrue(fakeFileSystem.allowWritesWhileWriting)\n      } catch (_: IOException) {\n        assertFalse(fakeFileSystem.allowWritesWhileWriting)\n      }\n    }\n  }\n\n  @Test\n  fun startReadWhileWritingNotAllowedWhenStrict() {\n    val path = base / \"write-read\"\n    path.writeUtf8(\"hello world!\")\n    fileSystem.sink(path).use {\n      try {\n        fileSystem.source(path).use {\n        }\n        assertTrue(fakeFileSystem.allowReadsWhileWriting)\n      } catch (_: IOException) {\n        assertFalse(fakeFileSystem.allowReadsWhileWriting)\n      }\n    }\n  }\n\n  @Test\n  fun startWriteWhileReadingNotAllowedWhenStrict() {\n    val path = base / \"read-write\"\n    path.writeUtf8(\"hello world!\")\n    fileSystem.source(path).use {\n      try {\n        fileSystem.sink(path).use {\n        }\n        assertTrue(fakeFileSystem.allowReadsWhileWriting)\n      } catch (_: IOException) {\n        assertFalse(fakeFileSystem.allowReadsWhileWriting)\n      }\n    }\n  }\n\n  @Test\n  fun startReadWhileReadingAllowedWhenStrict() {\n    val path = base / \"read-read\"\n    path.writeUtf8(\"hello world!\")\n    fileSystem.source(path).use {\n      fileSystem.source(path).use {\n      }\n    }\n  }\n\n  @Test\n  fun symlinkCanBeUsedAfterSettingAllowSymlinksToFalse() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    fileSystem.createSymlink(source, target)\n    fakeFileSystem.allowSymlinks = false\n    target.writeUtf8(\"I am the target file\")\n    assertEquals(\"I am the target file\", source.readUtf8())\n  }\n\n  @Test\n  fun symlinkCannotBeCreatedAfterSettingAllowSymlinksToFalse() {\n    fakeFileSystem.allowSymlinks = false\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    assertFailsWith<IOException> {\n      fileSystem.createSymlink(source, target)\n    }\n  }\n\n  @Test\n  fun fileExtras() {\n    val path = base / \"a.txt\"\n    path.writeUtf8(\"hello\")\n    fakeFileSystem.setExtra(path, ContentTypeExtra::class, ContentTypeExtra(\"text/plain\"))\n    val metadata = fileSystem.metadata(path)\n    assertEquals(ContentTypeExtra(\"text/plain\"), metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun directoryExtras() {\n    val path = base / \"a.txt\"\n    fileSystem.createDirectory(path)\n    fakeFileSystem.setExtra(path, ContentTypeExtra::class, ContentTypeExtra(\"text/plain\"))\n    val metadata = fileSystem.metadata(path)\n    assertEquals(ContentTypeExtra(\"text/plain\"), metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun symlinkExtras() {\n    if (!supportsSymlink()) return\n\n    val pathA = base / \"a.txt\"\n    val pathB = base / \"b.txt\"\n    fileSystem.createSymlink(pathA, pathB)\n    fakeFileSystem.setExtra(pathA, ContentTypeExtra::class, ContentTypeExtra(\"text/plain\"))\n    val metadata = fileSystem.metadata(pathA)\n    assertEquals(ContentTypeExtra(\"text/plain\"), metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun deleteExtra() {\n    val path = base / \"a.txt\"\n    path.writeUtf8(\"hello\")\n    fakeFileSystem.setExtra(path, ContentTypeExtra::class, ContentTypeExtra(\"text/plain\"))\n    fakeFileSystem.setExtra(path, ContentTypeExtra::class, null)\n    val metadata = fileSystem.metadata(path)\n    assertNull(metadata.extra(ContentTypeExtra::class))\n    assertEquals(mapOf(), metadata.extras)\n  }\n\n  @Test\n  fun extraIsNotCopiedByFileCopy() {\n    val pathA = base / \"a.txt\"\n    val pathB = base / \"b.txt\"\n    pathA.writeUtf8(\"hello\")\n    fakeFileSystem.setExtra(pathA, ContentTypeExtra::class, ContentTypeExtra(\"text/plain\"))\n    fileSystem.copy(pathA, pathB)\n    val metadata = fileSystem.metadata(pathB)\n    assertNull(metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun extraIsMovedByAtomicMove() {\n    val pathA = base / \"a.txt\"\n    val pathB = base / \"b.txt\"\n    pathA.writeUtf8(\"hello\")\n    fakeFileSystem.setExtra(pathA, ContentTypeExtra::class, ContentTypeExtra(\"text/plain\"))\n    fileSystem.atomicMove(pathA, pathB)\n    val metadata = fileSystem.metadata(pathB)\n    assertEquals(ContentTypeExtra(\"text/plain\"), metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun extrasHappyPath() {\n    val metadata = FileMetadata(\n      isRegularFile = true,\n      size = 10L,\n      extras = mapOf(ContentTypeExtra::class to ContentTypeExtra(\"text/plain\")),\n    )\n    assertEquals(ContentTypeExtra(\"text/plain\"), metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun createExtrasDefensiveCopy() {\n    val extras = mutableMapOf<KClass<*>, Any>(\n      ContentTypeExtra::class to ContentTypeExtra(\"text/plain\"),\n    )\n    val metadata = FileMetadata(\n      isRegularFile = true,\n      size = 10L,\n      extras = extras,\n    )\n    extras.clear()\n    assertEquals(ContentTypeExtra(\"text/plain\"), metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun getExtraAbsent() {\n    val metadata = FileMetadata(\n      isRegularFile = true,\n      size = 10L,\n      extras = mapOf(),\n    )\n    assertNull(metadata.extra(ContentTypeExtra::class))\n  }\n\n  @Test\n  fun getExtraWrongType() {\n    val metadata = FileMetadata(\n      isRegularFile = true,\n      size = 10L,\n      extras = mapOf(ContentTypeExtra::class to \"hello\"),\n    )\n    assertFailsWith<ClassCastException> {\n      metadata.extra(ContentTypeExtra::class)\n    }\n  }\n\n  internal data class ContentTypeExtra(\n    val contentType: String,\n  )\n}\n"
  },
  {
    "path": "okio/src/nonWasmTest/kotlin/okio/ForwardingFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertTrue\nimport kotlin.time.Clock\nimport okio.Path.Companion.toPath\nimport okio.fakefilesystem.FakeFileSystem\n\nclass ForwardingFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = object : ForwardingFileSystem(FakeFileSystem().apply { emulateUnix() }) {},\n  windowsLimitations = false,\n  allowClobberingEmptyDirectories = false,\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = \"/\".toPath(),\n  closeBehavior = CloseBehavior.Closes,\n) {\n  @Test\n  fun pathBlocking() {\n    val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {\n      override fun delete(path: Path, mustExist: Boolean) {\n        throw IOException(\"synthetic failure!\")\n      }\n\n      override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n        if (path.name.contains(\"blocked\")) throw IOException(\"blocked path!\")\n        return path\n      }\n    }\n\n    forwardingFileSystem.createDirectory(base / \"okay\")\n    assertFailsWith<IOException> {\n      forwardingFileSystem.createDirectory(base / \"blocked\")\n    }\n  }\n\n  @Test\n  fun operationBlocking() {\n    val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {\n      override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n        if (functionName == \"delete\") throw IOException(\"blocked operation!\")\n        return path\n      }\n    }\n\n    forwardingFileSystem.createDirectory(base / \"operation-blocking\")\n    assertFailsWith<IOException> {\n      forwardingFileSystem.delete(base / \"operation-blocking\")\n    }\n  }\n\n  @Test\n  fun pathMapping() {\n    val prefix = \"/mapped\"\n    val source = base / \"source\"\n    val mappedSource = (prefix + source).toPath()\n    val target = base / \"target\"\n    val mappedTarget = (prefix + target).toPath()\n\n    source.writeUtf8(\"hello, world!\")\n\n    val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {\n      override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n        return path.toString().removePrefix(prefix).toPath()\n      }\n\n      override fun onPathResult(path: Path, functionName: String): Path {\n        return (prefix + path).toPath()\n      }\n    }\n\n    forwardingFileSystem.copy(mappedSource, mappedTarget)\n    assertTrue(target in fileSystem.list(base))\n    assertTrue(mappedTarget in forwardingFileSystem.list(base))\n    assertEquals(\"hello, world!\", source.readUtf8())\n    assertEquals(\"hello, world!\", target.readUtf8())\n  }\n\n  /**\n   * Path mapping might impact the sort order. Confirm that list() returns elements in sorted order\n   * even if that order is different in the delegate file system.\n   */\n  @Test\n  fun pathMappingImpactedBySorting() {\n    val az = base / \"az\"\n    val by = base / \"by\"\n    val cx = base / \"cx\"\n    az.writeUtf8(\"az\")\n    by.writeUtf8(\"by\")\n    cx.writeUtf8(\"cx\")\n\n    val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {\n      override fun onPathResult(path: Path, functionName: String): Path {\n        return path.parent!! / path.name.reversed()\n      }\n    }\n\n    assertEquals(listOf(base / \"az\", base / \"by\", base / \"cx\"), fileSystem.list(base))\n    assertEquals(listOf(base / \"xc\", base / \"yb\", base / \"za\"), forwardingFileSystem.list(base))\n  }\n\n  @Test\n  fun copyIsNotForwarded() {\n    val log = mutableListOf<String>()\n\n    val delegate = object : ForwardingFileSystem(fileSystem) {\n      override fun copy(source: Path, target: Path) {\n        throw AssertionError(\"unexpected call to copy()\")\n      }\n    }\n\n    val forwardingFileSystem = object : ForwardingFileSystem(delegate) {\n      override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n        log += \"$functionName($parameterName=$path)\"\n        return path\n      }\n    }\n\n    val source = base / \"source\"\n    source.writeUtf8(\"hello, world!\")\n    val target = base / \"target\"\n    forwardingFileSystem.copy(source, target)\n    assertTrue(target in fileSystem.list(base))\n    assertEquals(\"hello, world!\", source.readUtf8())\n    assertEquals(\"hello, world!\", target.readUtf8())\n\n    assertEquals(listOf(\"source(file=$source)\", \"sink(file=$target)\"), log)\n  }\n\n  @Test\n  fun metadataForwardsParameterAndSymlinkTarget() {\n    val log = mutableListOf<String>()\n\n    val forwardingFileSystem = object : ForwardingFileSystem(fileSystem) {\n      override fun onPathParameter(path: Path, functionName: String, parameterName: String): Path {\n        log += \"$functionName($parameterName=$path)\"\n        return path\n      }\n\n      override fun onPathResult(path: Path, functionName: String): Path {\n        log += \"$functionName($path)\"\n        return path\n      }\n    }\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n\n    fileSystem.createSymlink(source, target)\n\n    val sourceMetadata = forwardingFileSystem.metadata(source)\n    assertEquals(target, sourceMetadata.symlinkTarget)\n\n    assertEquals(listOf(\"metadataOrNull(path=$source)\", \"metadataOrNull($target)\"), log)\n  }\n\n  /** Closing the ForwardingFileSystem closes the delegate. */\n  @Test\n  fun closeForwards() {\n    val delegate = FakeFileSystem()\n\n    val forwardingFileSystem = object : ForwardingFileSystem(delegate) {\n    }\n\n    forwardingFileSystem.close()\n\n    assertFailsWith<IllegalStateException> {\n      delegate.list(base)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/nonWasmTest/kotlin/okio/UseTest.kt",
    "content": "package okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertNull\nimport okio.Path.Companion.toPath\nimport okio.fakefilesystem.FakeFileSystem\n\nclass UseTest {\n  val fakeFileSystem = FakeFileSystem(clock = FakeClock()).also { it.emulateUnix() }\n\n  val base = \"/cache\".toPath().also {\n    fakeFileSystem.createDirectories(it)\n  }\n\n  @Test\n  fun closesWithUseBlock() {\n    fun testMethodWithUse() {\n      val sink = fakeFileSystem.sink(base / \"all-files-includes-file\")\n\n      sink.use {\n        return@testMethodWithUse\n      }\n    }\n\n    testMethodWithUse()\n\n    fakeFileSystem.checkNoOpenFiles()\n  }\n\n  @Test\n  fun acceptsNullReturn() {\n    val result = object : Closeable {\n      override fun close() {}\n    }.use { null }\n\n    assertNull(result)\n  }\n}\n"
  },
  {
    "path": "okio/src/systemFileSystemMain/kotlin/okio/FileSystem.System.kt",
    "content": "package okio\n\n/*\n * The current process's host file system. Use this instance directly, or dependency inject a\n * [FileSystem] to make code testable.\n */\nexpect val FileSystem.Companion.SYSTEM: FileSystem\n"
  },
  {
    "path": "okio/src/unixMain/kotlin/okio/UnixFileHandle.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.addressOf\nimport kotlinx.cinterop.alloc\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.ptr\nimport kotlinx.cinterop.usePinned\nimport platform.posix.FILE\nimport platform.posix.errno\nimport platform.posix.fclose\nimport platform.posix.fflush\nimport platform.posix.fileno\nimport platform.posix.fstat\nimport platform.posix.ftruncate\nimport platform.posix.stat\n\ninternal class UnixFileHandle(\n  readWrite: Boolean,\n  private val file: CPointer<FILE>,\n) : FileHandle(readWrite) {\n  override fun protectedSize(): Long {\n    memScoped {\n      val stat = alloc<stat>()\n      if (fstat(fileno(file), stat.ptr) != 0) {\n        throw errnoToIOException(errno)\n      }\n      return stat.st_size\n    }\n  }\n\n  override fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    val bytesRead = if (array.isNotEmpty()) {\n      array.usePinned { pinned ->\n        variantPread(file, pinned.addressOf(arrayOffset), byteCount, fileOffset)\n      }\n    } else {\n      0\n    }\n    if (bytesRead == -1) throw errnoToIOException(errno)\n    if (bytesRead == 0) return -1\n    return bytesRead\n  }\n\n  override fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    val bytesWritten = if (array.isNotEmpty()) {\n      array.usePinned { pinned ->\n        variantPwrite(file, pinned.addressOf(arrayOffset), byteCount, fileOffset)\n      }\n    } else {\n      0\n    }\n    if (bytesWritten != byteCount) throw errnoToIOException(errno)\n  }\n\n  override fun protectedFlush() {\n    if (fflush(file) != 0) {\n      throw errnoToIOException(errno)\n    }\n  }\n\n  override fun protectedResize(size: Long) {\n    if (ftruncate(fileno(file), size) == -1) {\n      throw errnoToIOException(errno)\n    }\n  }\n\n  override fun protectedClose() {\n    if (fclose(file) != 0) {\n      throw errnoToIOException(errno)\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/unixMain/kotlin/okio/UnixPosixVariant.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.ByteVar\nimport kotlinx.cinterop.CPointer\nimport kotlinx.cinterop.CValuesRef\nimport kotlinx.cinterop.UnsafeNumber\nimport kotlinx.cinterop.allocArray\nimport kotlinx.cinterop.convert\nimport kotlinx.cinterop.memScoped\nimport kotlinx.cinterop.toKString\nimport okio.Path.Companion.toPath\nimport okio.internal.toPath\nimport platform.posix.DEFFILEMODE\nimport platform.posix.ENOENT\nimport platform.posix.FILE\nimport platform.posix.O_CREAT\nimport platform.posix.O_EXCL\nimport platform.posix.O_RDWR\nimport platform.posix.PATH_MAX\nimport platform.posix.S_IFLNK\nimport platform.posix.S_IFMT\nimport platform.posix.errno\nimport platform.posix.fdopen\nimport platform.posix.fileno\nimport platform.posix.fopen\nimport platform.posix.free\nimport platform.posix.getenv\nimport platform.posix.mkdir\nimport platform.posix.open\nimport platform.posix.pread\nimport platform.posix.pwrite\nimport platform.posix.readlink\nimport platform.posix.realpath\nimport platform.posix.remove\nimport platform.posix.rename\nimport platform.posix.symlink\nimport platform.posix.timespec\n\ninternal actual val PLATFORM_TEMPORARY_DIRECTORY: Path\n  get() {\n    val tmpdir = getenv(\"TMPDIR\")\n    if (tmpdir != null) return tmpdir.toKString().toPath()\n\n    return \"/tmp\".toPath()\n  }\n\ninternal actual val PLATFORM_DIRECTORY_SEPARATOR = \"/\"\n\ninternal actual fun PosixFileSystem.variantDelete(path: Path, mustExist: Boolean) {\n  val result = remove(path.toString())\n  if (result != 0) {\n    if (errno == ENOENT) {\n      if (mustExist) {\n        throw FileNotFoundException(\"no such file: $path\")\n      } else {\n        return\n      }\n    }\n    throw errnoToIOException(errno)\n  }\n}\n\n@OptIn(UnsafeNumber::class)\ninternal actual fun PosixFileSystem.variantMkdir(dir: Path): Int {\n  return mkdir(dir.toString(), 0b111111111u.convert() /* octal 777 */)\n}\n\ninternal actual fun PosixFileSystem.variantCanonicalize(path: Path): Path {\n  // Note that realpath() fails if the file doesn't exist.\n  val fullpath = realpath(path.toString(), null)\n    ?: throw errnoToIOException(errno)\n  try {\n    return Buffer().writeNullTerminated(fullpath).toPath(normalize = true)\n  } finally {\n    free(fullpath)\n  }\n}\n\ninternal actual fun PosixFileSystem.variantMove(\n  source: Path,\n  target: Path,\n) {\n  val result = rename(source.toString(), target.toString())\n  if (result != 0) {\n    throw errnoToIOException(errno)\n  }\n}\n\ninternal actual fun PosixFileSystem.variantSource(file: Path): Source {\n  val openFile: CPointer<FILE> = fopen(file.toString(), \"r\")\n    ?: throw errnoToIOException(errno)\n  return FileSource(openFile)\n}\n\ninternal actual fun PosixFileSystem.variantSink(file: Path, mustCreate: Boolean): Sink {\n  val openFile: CPointer<FILE> = fopen(file.toString(), if (mustCreate) \"wx\" else \"w\")\n    ?: throw errnoToIOException(errno)\n  return FileSink(openFile)\n}\n\ninternal actual fun PosixFileSystem.variantAppendingSink(file: Path, mustExist: Boolean): Sink {\n  // There is a `r+` flag which we could have used to force existence of [file] but this flag\n  // doesn't allow opening for appending, and we don't currently have a way to move the cursor to\n  // the end of the file. We are then forcing existence non-atomically.\n  if (mustExist && !exists(file)) throw IOException(\"$file doesn't exist.\")\n  val openFile: CPointer<FILE> = fopen(file.toString(), \"a\")\n    ?: throw errnoToIOException(errno)\n  return FileSink(openFile)\n}\n\ninternal actual fun PosixFileSystem.variantOpenReadOnly(file: Path): FileHandle {\n  val openFile: CPointer<FILE> = fopen(file.toString(), \"r\")\n    ?: throw errnoToIOException(errno)\n  return UnixFileHandle(false, openFile)\n}\n\ninternal actual fun PosixFileSystem.variantOpenReadWrite(\n  file: Path,\n  mustCreate: Boolean,\n  mustExist: Boolean,\n): FileHandle {\n  // Note that we're using open() followed by fdopen() rather than fopen() because this way we\n  // can pass exactly the flags we want. Note that there's no string mode that opens for reading\n  // and writing that creates if necessary. (\"a+\" has features but can't do random access).\n  val flags = when {\n    mustCreate && mustExist ->\n      throw IllegalArgumentException(\"Cannot require mustCreate and mustExist at the same time.\")\n    mustCreate -> O_RDWR or O_CREAT or O_EXCL\n    mustExist -> O_RDWR\n    else -> O_RDWR or O_CREAT\n  }\n\n  val fid = open(file.toString(), flags, DEFFILEMODE)\n  if (fid == -1) throw errnoToIOException(errno)\n\n  // Use 'r+' to get reading and writing on the FILE, which is all we need.\n  val openFile = fdopen(fid, \"r+\") ?: throw errnoToIOException(errno)\n\n  return UnixFileHandle(true, openFile)\n}\n\ninternal actual fun PosixFileSystem.variantCreateSymlink(source: Path, target: Path) {\n  if (source.parent == null || !exists(source.parent!!)) {\n    throw IOException(\"parent directory does not exist: ${source.parent}\")\n  }\n\n  if (exists(source)) {\n    throw IOException(\"already exists: $source\")\n  }\n\n  val result = symlink(target.toString(), source.toString())\n  if (result != 0) {\n    throw errnoToIOException(errno)\n  }\n}\n\n@OptIn(UnsafeNumber::class)\ninternal fun variantPread(\n  file: CPointer<FILE>,\n  target: CValuesRef<*>,\n  byteCount: Int,\n  offset: Long,\n): Int = pread(fileno(file), target, byteCount.convert(), offset).convert()\n\n@OptIn(UnsafeNumber::class)\ninternal fun variantPwrite(\n  file: CPointer<FILE>,\n  source: CValuesRef<*>,\n  byteCount: Int,\n  offset: Long,\n): Int = pwrite(fileno(file), source, byteCount.convert(), offset).convert()\n\n@OptIn(UnsafeNumber::class)\ninternal val timespec.epochMillis: Long\n  get() = tv_sec * 1000L + tv_nsec / 1_000_000L\n\n@OptIn(UnsafeNumber::class)\ninternal fun symlinkTarget(mode: Int, path: Path): Path? {\n  if (mode and S_IFMT != S_IFLNK) return null\n\n  // `path` is a symlink, let's resolve its target.\n  memScoped {\n    val buffer = allocArray<ByteVar>(PATH_MAX)\n    val byteCount = readlink(path.toString(), buffer, PATH_MAX.convert())\n    if (byteCount.convert<Int>() == -1) {\n      throw errnoToIOException(errno)\n    }\n    return buffer.toKString().toPath()\n  }\n}\n"
  },
  {
    "path": "okio/src/wasmMain/kotlin/okio/FileSystem.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport kotlin.contracts.ExperimentalContracts\nimport kotlin.contracts.InvocationKind\nimport kotlin.contracts.contract\nimport okio.Path.Companion.toPath\nimport okio.internal.commonCopy\nimport okio.internal.commonCreateDirectories\nimport okio.internal.commonDeleteRecursively\nimport okio.internal.commonExists\nimport okio.internal.commonListRecursively\nimport okio.internal.commonMetadata\n\n@OptIn(ExperimentalContracts::class)\nactual abstract class FileSystem : Closeable {\n  actual abstract fun canonicalize(path: Path): Path\n\n  actual fun metadata(path: Path): FileMetadata = commonMetadata(path)\n\n  actual abstract fun metadataOrNull(path: Path): FileMetadata?\n\n  actual fun exists(path: Path): Boolean = commonExists(path)\n\n  actual abstract fun list(dir: Path): List<Path>\n\n  actual abstract fun listOrNull(dir: Path): List<Path>?\n\n  actual open fun listRecursively(dir: Path, followSymlinks: Boolean): Sequence<Path> =\n    commonListRecursively(dir, followSymlinks)\n\n  actual abstract fun openReadOnly(file: Path): FileHandle\n\n  actual abstract fun openReadWrite(\n    file: Path,\n    mustCreate: Boolean,\n    mustExist: Boolean,\n  ): FileHandle\n\n  actual abstract fun source(file: Path): Source\n\n  actual inline fun <T> read(file: Path, readerAction: BufferedSource.() -> T): T {\n    contract {\n      callsInPlace(readerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return source(file).buffer().use {\n      it.readerAction()\n    }\n  }\n\n  actual abstract fun sink(file: Path, mustCreate: Boolean): Sink\n\n  actual inline fun <T> write(\n    file: Path,\n    mustCreate: Boolean,\n    writerAction: BufferedSink.() -> T,\n  ): T {\n    contract {\n      callsInPlace(writerAction, InvocationKind.EXACTLY_ONCE)\n    }\n\n    return sink(file, mustCreate).buffer().use {\n      it.writerAction()\n    }\n  }\n\n  actual abstract fun appendingSink(file: Path, mustExist: Boolean): Sink\n\n  actual abstract fun createDirectory(dir: Path, mustCreate: Boolean)\n\n  actual fun createDirectories(dir: Path, mustCreate: Boolean): Unit = commonCreateDirectories(dir, mustCreate)\n\n  actual abstract fun atomicMove(source: Path, target: Path)\n\n  actual open fun copy(source: Path, target: Path): Unit = commonCopy(source, target)\n\n  actual abstract fun delete(path: Path, mustExist: Boolean)\n\n  actual open fun deleteRecursively(fileOrDirectory: Path, mustExist: Boolean): Unit =\n    commonDeleteRecursively(fileOrDirectory, mustExist)\n\n  actual abstract fun createSymlink(source: Path, target: Path)\n\n  actual override fun close() {\n  }\n\n  actual companion object {\n    actual val SYSTEM_TEMPORARY_DIRECTORY: Path = \"/tmp\".toPath()\n  }\n}\n"
  },
  {
    "path": "okio/src/wasmMain/kotlin/okio/WasmPlatform.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\ninternal actual val PLATFORM_DIRECTORY_SEPARATOR: String\n  get() = \"/\"\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/Deflater.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\n/**\n * @param nowrap true to skip the ZLIB header and checksum.\n */\nexpect class Deflater(\n  level: Int,\n  nowrap: Boolean,\n) {\n  /** Creates a deflater that expects to read a ZLIB header and checksum. */\n  constructor()\n\n  fun getBytesRead(): Long\n\n  fun end()\n}\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/DeflaterSink.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\n\n@file:JvmName(\"-DeflaterSinkExtensions\")\n\npackage okio\n\nimport kotlin.jvm.JvmName\n\n/**\n * A sink that uses [DEFLATE](http://tools.ietf.org/html/rfc1951) to\n * compress data written to another source.\n *\n * ### Sync flush\n *\n * Aggressive flushing of this stream may result in reduced compression. Each\n * call to [flush] immediately compresses all currently-buffered data;\n * this early compression may be less effective than compression performed\n * without flushing.\n *\n * This is equivalent to using [Deflater] with the sync flush option.\n * This class does not offer any partial flush mechanism. For best performance,\n * only call [flush] when application behavior requires it.\n */\nexpect class DeflaterSink\n/**\n * This internal constructor shares a buffer with its trusted caller. In general, we can't share a\n * BufferedSource because the deflater holds input bytes until they are inflated.\n */\ninternal constructor(\n  sink: BufferedSink,\n  deflater: Deflater,\n) : Sink {\n  constructor(sink: Sink, deflater: Deflater)\n\n  internal fun finishDeflate()\n\n  override fun write(source: Buffer, byteCount: Long)\n  override fun flush()\n  override fun timeout(): Timeout\n  override fun close()\n}\n\n/**\n * Returns an [DeflaterSink] that DEFLATE-compresses data to this [Sink] while writing.\n *\n * @see DeflaterSink\n */\ninline fun Sink.deflate(deflater: Deflater = Deflater()): DeflaterSink =\n  DeflaterSink(this, deflater)\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/GzipSink.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\n\n@file:JvmName(\"-GzipSinkExtensions\")\n@file:Suppress(\"NOTHING_TO_INLINE\") // Aliases to public API.\n\npackage okio\n\nimport kotlin.jvm.JvmName\nimport okio.internal.CRC32\nimport okio.internal.DEFAULT_COMPRESSION\n\n/**\n * A sink that uses [GZIP](http://www.ietf.org/rfc/rfc1952.txt) to\n * compress written data to another sink.\n *\n * ### Sync flush\n *\n * Aggressive flushing of this stream may result in reduced compression. Each\n * call to [flush] immediately compresses all currently-buffered data;\n * this early compression may be less effective than compression performed\n * without flushing.\n *\n * This is equivalent to using [Deflater] with the sync flush option.\n * This class does not offer any partial flush mechanism. For best performance,\n * only call [flush] when application behavior requires it.\n */\nclass GzipSink(sink: Sink) : Sink {\n  /** Sink into which the GZIP format is written. */\n  private val sink = RealBufferedSink(sink)\n\n  /** The deflater used to compress the body. */\n  @get:JvmName(\"deflater\")\n  val deflater = Deflater(DEFAULT_COMPRESSION, true /* No wrap */)\n\n  /**\n   * The deflater sink takes care of moving data between decompressed source and\n   * compressed sink buffers.\n   */\n  private val deflaterSink = DeflaterSink(this.sink, deflater)\n\n  private var closed = false\n\n  /** Checksum calculated for the compressed body. */\n  private val crc = CRC32()\n\n  init {\n    // Write the Gzip header directly into the buffer for the sink to avoid handling IOException.\n    this.sink.buffer.apply {\n      writeShort(0x1f8b) // Two-byte Gzip ID.\n      writeByte(0x08) // 8 == Deflate compression method.\n      writeByte(0x00) // No flags.\n      writeInt(0x00) // No modification time.\n      writeByte(0x00) // No extra flags.\n      writeByte(0x00) // No OS.\n    }\n  }\n\n  @Throws(IOException::class)\n  override fun write(source: Buffer, byteCount: Long) {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    if (byteCount == 0L) return\n\n    updateCrc(source, byteCount)\n    deflaterSink.write(source, byteCount)\n  }\n\n  @Throws(IOException::class)\n  override fun flush() = deflaterSink.flush()\n\n  override fun timeout(): Timeout = sink.timeout()\n\n  @Throws(IOException::class)\n  override fun close() {\n    if (closed) return\n\n    // This method delegates to the DeflaterSink for finishing the deflate process\n    // but keeps responsibility for releasing the deflater's resources. This is\n    // necessary because writeFooter needs to query the processed byte count which\n    // only works when the deflater is still open.\n\n    var thrown: Throwable? = null\n    try {\n      deflaterSink.finishDeflate()\n      writeFooter()\n    } catch (e: Throwable) {\n      thrown = e\n    }\n\n    try {\n      deflater.end()\n    } catch (e: Throwable) {\n      if (thrown == null) thrown = e\n    }\n\n    try {\n      sink.close()\n    } catch (e: Throwable) {\n      if (thrown == null) thrown = e\n    }\n\n    closed = true\n\n    if (thrown != null) throw thrown\n  }\n\n  private fun writeFooter() {\n    sink.writeIntLe(crc.getValue().toInt()) // CRC of original data.\n    sink.writeIntLe(deflater.getBytesRead().toInt()) // Length of original data.\n  }\n\n  /** Updates the CRC with the given bytes. */\n  private fun updateCrc(buffer: Buffer, byteCount: Long) {\n    var head = buffer.head!!\n    var remaining = byteCount\n    while (remaining > 0) {\n      val segmentLength = minOf(remaining, head.limit - head.pos).toInt()\n      crc.update(head.data, head.pos, segmentLength)\n      remaining -= segmentLength\n      head = head.next!!\n    }\n  }\n\n  @JvmName(\"-deprecated_deflater\")\n  @Deprecated(\n    message = \"moved to val\",\n    replaceWith = ReplaceWith(expression = \"deflater\"),\n    level = DeprecationLevel.ERROR,\n  )\n  fun deflater() = deflater\n}\n\n/**\n * Returns a [GzipSink] that gzip-compresses to this [Sink] while writing.\n *\n * @see GzipSource\n */\ninline fun Sink.gzip() = GzipSink(this)\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/GzipSource.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\n\n@file:JvmName(\"-GzipSourceExtensions\")\n@file:Suppress(\"NOTHING_TO_INLINE\") // Aliases to public API.\n\npackage okio\n\nimport kotlin.jvm.JvmName\nimport okio.internal.CRC32\n\n/**\n * A source that uses [GZIP](http://www.ietf.org/rfc/rfc1952.txt) to\n * decompress data read from another source.\n */\nclass GzipSource(source: Source) : Source {\n\n  /** The current section. Always progresses forward. */\n  private var section = SECTION_HEADER\n\n  /**\n   * Our source should yield a GZIP header (which we consume directly), followed\n   * by deflated bytes (which we consume via an InflaterSource), followed by a\n   * GZIP trailer (which we also consume directly).\n   */\n  private val source = RealBufferedSource(source)\n\n  /** The inflater used to decompress the deflated body. */\n  private val inflater = Inflater(true)\n\n  /**\n   * The inflater source takes care of moving data between compressed source and\n   * decompressed sink buffers.\n   */\n  private val inflaterSource = InflaterSource(this.source, inflater)\n\n  /** Checksum used to check both the GZIP header and decompressed body. */\n  private val crc = CRC32()\n\n  @Throws(IOException::class)\n  override fun read(sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    if (byteCount == 0L) return 0L\n\n    // If we haven't consumed the header, we must consume it before anything else.\n    if (section == SECTION_HEADER) {\n      consumeHeader()\n      section = SECTION_BODY\n    }\n\n    // Attempt to read at least a byte of the body. If we do, we're done.\n    if (section == SECTION_BODY) {\n      val offset = sink.size\n      val result = inflaterSource.read(sink, byteCount)\n      if (result != -1L) {\n        updateCrc(sink, offset, result)\n        return result\n      }\n      section = SECTION_TRAILER\n    }\n\n    // The body is exhausted; time to read the trailer. We always consume the\n    // trailer before returning a -1 exhausted result; that way if you read to\n    // the end of a GzipSource you guarantee that the CRC has been checked.\n    if (section == SECTION_TRAILER) {\n      consumeTrailer()\n      section = SECTION_DONE\n\n      // Gzip streams self-terminate: they return -1 before their underlying\n      // source returns -1. Here we attempt to force the underlying stream to\n      // return -1 which may trigger it to release its resources. If it doesn't\n      // return -1, then our Gzip data finished prematurely!\n      if (!source.exhausted()) {\n        throw IOException(\"gzip finished without exhausting source\")\n      }\n    }\n\n    return -1\n  }\n\n  @Throws(IOException::class)\n  private fun consumeHeader() {\n    // Read the 10-byte header. We peek at the flags byte first so we know if we\n    // need to CRC the entire header. Then we read the magic ID1ID2 sequence.\n    // We can skip everything else in the first 10 bytes.\n    // +---+---+---+---+---+---+---+---+---+---+\n    // |ID1|ID2|CM |FLG|     MTIME     |XFL|OS | (more-->)\n    // +---+---+---+---+---+---+---+---+---+---+\n    source.require(10)\n    val flags = source.buffer[3].toInt()\n    val fhcrc = flags.getBit(FHCRC)\n    if (fhcrc) updateCrc(source.buffer, 0, 10)\n\n    val id1id2 = source.readShort()\n    checkEqual(\"ID1ID2\", 0x1f8b, id1id2.toInt())\n    source.skip(8)\n\n    // Skip optional extra fields.\n    // +---+---+=================================+\n    // | XLEN  |...XLEN bytes of \"extra field\"...| (more-->)\n    // +---+---+=================================+\n    if (flags.getBit(FEXTRA)) {\n      source.require(2)\n      if (fhcrc) updateCrc(source.buffer, 0, 2)\n      val xlen = (source.buffer.readShortLe().toInt() and 0xffff).toLong()\n      source.require(xlen)\n      if (fhcrc) updateCrc(source.buffer, 0, xlen)\n      source.skip(xlen)\n    }\n\n    // Skip an optional 0-terminated name.\n    // +=========================================+\n    // |...original file name, zero-terminated...| (more-->)\n    // +=========================================+\n    if (flags.getBit(FNAME)) {\n      val index = source.indexOf(0)\n      if (index == -1L) throw EOFException()\n      if (fhcrc) updateCrc(source.buffer, 0, index + 1)\n      source.skip(index + 1)\n    }\n\n    // Skip an optional 0-terminated comment.\n    // +===================================+\n    // |...file comment, zero-terminated...| (more-->)\n    // +===================================+\n    if (flags.getBit(FCOMMENT)) {\n      val index = source.indexOf(0)\n      if (index == -1L) throw EOFException()\n      if (fhcrc) updateCrc(source.buffer, 0, index + 1)\n      source.skip(index + 1)\n    }\n\n    // Confirm the optional header CRC.\n    // +---+---+\n    // | CRC16 |\n    // +---+---+\n    if (fhcrc) {\n      checkEqual(\"FHCRC\", source.readShortLe().toInt(), crc.getValue().toShort().toInt())\n      crc.reset()\n    }\n  }\n\n  @Throws(IOException::class)\n  private fun consumeTrailer() {\n    // Read the eight-byte trailer. Confirm the body's CRC and size.\n    // +---+---+---+---+---+---+---+---+\n    // |     CRC32     |     ISIZE     |\n    // +---+---+---+---+---+---+---+---+\n    checkEqual(\"CRC\", source.readIntLe(), crc.getValue().toInt())\n    checkEqual(\"ISIZE\", source.readIntLe(), inflater.getBytesWritten().toInt())\n  }\n\n  override fun timeout(): Timeout = source.timeout()\n\n  @Throws(IOException::class)\n  override fun close() = inflaterSource.close()\n\n  /** Updates the CRC with the given bytes.  */\n  private fun updateCrc(buffer: Buffer, offset: Long, byteCount: Long) {\n    var offset = offset\n    var byteCount = byteCount\n    // Skip segments that we aren't checksumming.\n    var s = buffer.head!!\n    while (offset >= s.limit - s.pos) {\n      offset -= s.limit - s.pos\n      s = s.next!!\n    }\n\n    // Checksum one segment at a time.\n    while (byteCount > 0) {\n      val pos = (s.pos + offset).toInt()\n      val toUpdate = minOf(s.limit - pos, byteCount).toInt()\n      crc.update(s.data, pos, toUpdate)\n      byteCount -= toUpdate\n      offset = 0\n      s = s.next!!\n    }\n  }\n\n  private fun checkEqual(name: String, expected: Int, actual: Int) {\n    if (actual != expected) {\n      throw IOException(\n        \"$name: \" +\n          \"actual 0x${actual.toHexString().padStart(8, '0')} != \" +\n          \"expected 0x${expected.toHexString().padStart(8, '0')}\",\n      )\n    }\n  }\n}\n\nprivate inline fun Int.getBit(bit: Int) = this shr bit and 1 == 1\n\nprivate const val FHCRC = 1\nprivate const val FEXTRA = 2\nprivate const val FNAME = 3\nprivate const val FCOMMENT = 4\n\nprivate const val SECTION_HEADER: Byte = 0\nprivate const val SECTION_BODY: Byte = 1\nprivate const val SECTION_TRAILER: Byte = 2\nprivate const val SECTION_DONE: Byte = 3\n\n/**\n * Returns a [GzipSource] that gzip-decompresses this [Source] while reading.\n *\n * @see GzipSource\n */\ninline fun Source.gzip() = GzipSource(this)\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/Inflater.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\n/**\n * @param nowrap true to omit the ZLIB header and checksum.\n */\nexpect class Inflater(\n  nowrap: Boolean,\n) {\n  /** Creates an inflater that writes a ZLIB header and checksum. */\n  constructor()\n\n  fun getBytesWritten(): Long\n\n  fun end()\n}\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/InflaterSource.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\n@file:JvmName(\"-InflaterSourceExtensions\")\n\npackage okio\n\nimport kotlin.jvm.JvmName\n\n/**\n * A source that uses [DEFLATE](http://tools.ietf.org/html/rfc1951) to decompress data read from\n * another source.\n */\nexpect class InflaterSource\n/**\n * This internal constructor shares a buffer with its trusted caller. In general, we can't share a\n * `BufferedSource` because the inflater holds input bytes until they are inflated.\n */\ninternal constructor(\n  source: BufferedSource,\n  inflater: Inflater,\n) : Source {\n  constructor(source: Source, inflater: Inflater)\n\n  override fun read(sink: Buffer, byteCount: Long): Long\n  override fun timeout(): Timeout\n  override fun close()\n}\n\n/**\n * Returns an [InflaterSource] that DEFLATE-decompresses this [Source] while reading.\n *\n * @see InflaterSource\n */\ninline fun Source.inflate(inflater: Inflater = Inflater()): InflaterSource =\n  InflaterSource(this, inflater)\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/ZipFileSystem.kt",
    "content": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements.  See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License.  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 */\npackage okio\n\nimport okio.Path.Companion.toPath\nimport okio.internal.COMPRESSION_METHOD_STORED\nimport okio.internal.FixedLengthSource\nimport okio.internal.ZipEntry\nimport okio.internal.readLocalHeader\nimport okio.internal.skipLocalHeader\n\n/**\n * Read only access to a [zip file](https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE_6.2.0.txt)\n * and common [extra fields](https://opensource.apple.com/source/zip/zip-6/unzip/unzip/proginfo/extra.fld).\n */\ninternal class ZipFileSystem internal constructor(\n  private val zipPath: Path,\n  private val fileSystem: FileSystem,\n  private val entries: Map<Path, ZipEntry>,\n  private val comment: String?,\n) : FileSystem() {\n  override fun canonicalize(path: Path): Path {\n    val canonical = canonicalizeInternal(path)\n    if (canonical !in entries) {\n      throw FileNotFoundException(\"$path\")\n    }\n    return canonical\n  }\n\n  /** Don't throw [FileNotFoundException] if the path doesn't identify a file. */\n  private fun canonicalizeInternal(path: Path): Path {\n    return ROOT.resolve(path, normalize = true)\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    val canonicalPath = canonicalizeInternal(path)\n    val centralDirectoryEntry = entries[canonicalPath] ?: return null\n\n    val fullEntry = when {\n      centralDirectoryEntry.offset != -1L -> {\n        fileSystem.openReadOnly(zipPath).use { fileHandle ->\n          return@use fileHandle.source(centralDirectoryEntry.offset).buffer().use { source ->\n            source.readLocalHeader(centralDirectoryEntry)\n          }\n        }\n      }\n\n      else -> centralDirectoryEntry\n    }\n\n    return FileMetadata(\n      isRegularFile = !fullEntry.isDirectory,\n      isDirectory = fullEntry.isDirectory,\n      symlinkTarget = null,\n      size = if (fullEntry.isDirectory) null else fullEntry.size,\n      createdAtMillis = fullEntry.createdAtMillis,\n      lastModifiedAtMillis = fullEntry.lastModifiedAtMillis,\n      lastAccessedAtMillis = fullEntry.lastAccessedAtMillis,\n    )\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    throw UnsupportedOperationException(\"not implemented yet!\")\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    throw IOException(\"zip entries are not writable\")\n  }\n\n  override fun list(dir: Path): List<Path> = list(dir, throwOnFailure = true)!!\n\n  override fun listOrNull(dir: Path): List<Path>? = list(dir, throwOnFailure = false)\n\n  private fun list(dir: Path, throwOnFailure: Boolean): List<Path>? {\n    val canonicalDir = canonicalizeInternal(dir)\n    val entry = entries[canonicalDir]\n      ?: if (throwOnFailure) throw IOException(\"not a directory: $dir\") else return null\n    return entry.children.toList()\n  }\n\n  @Throws(IOException::class)\n  override fun source(file: Path): Source {\n    val canonicalPath = canonicalizeInternal(file)\n    val entry = entries[canonicalPath] ?: throw FileNotFoundException(\"no such file: $file\")\n    val source = fileSystem.openReadOnly(zipPath).use { fileHandle ->\n      fileHandle.source(entry.offset).buffer()\n    }\n    source.skipLocalHeader()\n\n    return when (entry.compressionMethod) {\n      COMPRESSION_METHOD_STORED -> {\n        FixedLengthSource(source, entry.size, truncate = true)\n      }\n      else -> {\n        val inflaterSource = InflaterSource(\n          FixedLengthSource(source, entry.compressedSize, truncate = true),\n          Inflater(true),\n        )\n        FixedLengthSource(inflaterSource, entry.size, truncate = false)\n      }\n    }\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    throw IOException(\"zip file systems are read-only\")\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    throw IOException(\"zip file systems are read-only\")\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean): Unit =\n    throw IOException(\"zip file systems are read-only\")\n\n  override fun atomicMove(source: Path, target: Path): Unit =\n    throw IOException(\"zip file systems are read-only\")\n\n  override fun delete(path: Path, mustExist: Boolean): Unit =\n    throw IOException(\"zip file systems are read-only\")\n\n  override fun createSymlink(source: Path, target: Path): Unit =\n    throw IOException(\"zip file systems are read-only\")\n\n  private companion object {\n    val ROOT = \"/\".toPath()\n  }\n}\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/ZlibOkio.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\n\n@file:JvmMultifileClass\n@file:JvmName(\"Okio\")\n\npackage okio\n\nimport kotlin.jvm.JvmMultifileClass\nimport kotlin.jvm.JvmName\n\n/**\n * Returns a new read-only file system.\n *\n * This function processes the ZIP file's central directory and builds an index of its files and\n * their offsets within the ZIP. If the ZIP file is changed after this function returns, this\n * file system will be broken and may return inconsistent data or crash when it is accessed.\n *\n * Closing the returned file system is not necessary and does nothing.\n */\n@Throws(IOException::class)\nfun FileSystem.openZip(zipPath: Path): FileSystem = okio.internal.openZip(zipPath, this)\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/internal/-Zlib.kt",
    "content": "// ktlint-disable filename\n/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.internal\n\ninternal expect val DEFAULT_COMPRESSION: Int\n\n/**\n * Note that this inherits the local time zone.\n *\n * @param year such as 1970 or 2024\n * @param month a value in the range 1 (January) through 12 (December).\n * @param day a value in the range 1 through 31.\n * @param hour a value in the range 0 through 23.\n * @param minute a value in the range 0 through 59.\n * @param second a value in the range 0 through 59.\n */\ninternal expect fun datePartsToEpochMillis(\n  year: Int,\n  month: Int,\n  day: Int,\n  hour: Int,\n  minute: Int,\n  second: Int,\n): Long\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/internal/CRC32.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.internal\n\nexpect class CRC32() {\n  fun update(content: ByteArray, offset: Int, byteCount: Int)\n  fun update(content: ByteArray)\n  fun getValue(): Long\n  fun reset()\n}\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/internal/FixedLengthSource.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.Buffer\nimport okio.ForwardingSource\nimport okio.IOException\nimport okio.Source\n\n/**\n * A source that returns [size] bytes of [delegate].\n *\n * This throws an [IOException] if the delegate returns fewer than [size] bytes.\n *\n * If [truncate] is true, this truncates to [size] bytes. Otherwise this requires that [delegate]\n * will return exactly [size] bytes, and will throw an [IOException] if it doesn't.\n */\ninternal class FixedLengthSource(\n  delegate: Source,\n  private val size: Long,\n  private val truncate: Boolean,\n) : ForwardingSource(delegate) {\n  private var bytesReceived = 0L\n\n  override fun read(sink: Buffer, byteCount: Long): Long {\n    // Figure out how many bytes to attempt to read.\n    //\n    // If we're truncating, we never attempt to read more than what's remaining.\n    //\n    // Otherwise we expect the underlying source to be exactly the promised size. Read as much as\n    // possible and throw an exception if too many bytes are returned.\n    val toRead = when {\n      bytesReceived > size -> 0L // Already read more than the promised size.\n      truncate -> {\n        val remaining = size - bytesReceived\n        if (remaining == 0L) return -1L // Already read exactly the promised size.\n        minOf(byteCount, remaining)\n      }\n      else -> byteCount\n    }\n\n    val result = super.read(sink, toRead)\n\n    if (result != -1L) bytesReceived += result\n\n    // Throw an exception if we received too few bytes or too many.\n    if ((bytesReceived < size && result == -1L) || bytesReceived > size) {\n      if (result > 0L && bytesReceived > size) {\n        // If we received bytes beyond the limit, don't return them to the caller.\n        sink.truncateToSize(sink.size - (bytesReceived - size))\n      }\n      throw IOException(\"expected $size bytes but got $bytesReceived\")\n    }\n\n    return result\n  }\n\n  private fun Buffer.truncateToSize(newSize: Long) {\n    val scratch = Buffer()\n    scratch.writeAll(this)\n    write(scratch, newSize)\n    scratch.clear()\n  }\n}\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/internal/ZipEntry.kt",
    "content": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements.  See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License.  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 */\npackage okio.internal\n\nimport okio.FileMetadata\nimport okio.Path\n\n/**\n * This class prefers NTFS timestamps, then extended timestamps, then the base ZIP timestamps.\n */\ninternal class ZipEntry(\n  /**\n   * Absolute path of this entry. If the raw name on disk contains relative paths like `..`, they\n   * are not present in this path.\n   */\n  val canonicalPath: Path,\n\n  /** True if this entry is a directory. When encoded directory entries' names end with `/`. */\n  val isDirectory: Boolean = false,\n\n  /** The comment on this entry. Empty if there is no comment. */\n  val comment: String = \"\",\n\n  /** The CRC32 of the uncompressed data, or -1 if not set. */\n  val crc: Long = -1L,\n\n  /** The compressed size in bytes, or -1 if unknown. */\n  val compressedSize: Long = -1L,\n\n  /** The uncompressed size in bytes, or -1 if unknown. */\n  val size: Long = -1L,\n\n  /** Either [COMPRESSION_METHOD_DEFLATED] or [COMPRESSION_METHOD_STORED]. */\n  val compressionMethod: Int = -1,\n\n  val offset: Long = -1L,\n\n  /**\n   * The base ZIP format tracks the [last modified timestamp][FileMetadata.lastModifiedAtMillis]. It\n   * does not track [created timestamps][FileMetadata.createdAtMillis] or [last accessed\n   * timestamps][FileMetadata.lastAccessedAtMillis].\n   *\n   * This format has severe limitations:\n   *\n   *  * Timestamps are 16-bit values stored with 2-second precision. Some zip encoders (WinZip,\n   *    PKZIP) round up to the nearest 2 seconds; other encoders (Java) round down.\n   *\n   *  * Timestamps before 1980-01-01 cannot be represented. They cannot represent dates after\n   *    2107-12-31.\n   *\n   *  * Timestamps are stored in local time with no time zone offset. If the time zone offset\n   *    changes – due to daylight savings time or the zip file being sent to another time zone –\n   *    file times will be incorrect. The file time will be shifted by the difference in time zone\n   *    offsets between the encoder and decoder.\n   */\n  val dosLastModifiedAtDate: Int = -1,\n  val dosLastModifiedAtTime: Int = -1,\n\n  /**\n   * NTFS timestamps (0x000a) support creation time, last access time, and last modified time.\n   * These timestamps are stored with 100-millisecond precision using UTC.\n   */\n  val ntfsLastModifiedAtFiletime: Long? = null,\n  val ntfsLastAccessedAtFiletime: Long? = null,\n  val ntfsCreatedAtFiletime: Long? = null,\n\n  /**\n   * Extended timestamps (0x5455) are stored as signed 32-bit timestamps with 1-second precision.\n   * These cannot express dates beyond 2038-01-19.\n   */\n  val extendedLastModifiedAtSeconds: Int? = null,\n  val extendedLastAccessedAtSeconds: Int? = null,\n  val extendedCreatedAtSeconds: Int? = null,\n) {\n  val children = mutableListOf<Path>()\n\n  internal fun copy(\n    extendedLastModifiedAtSeconds: Int?,\n    extendedLastAccessedAtSeconds: Int?,\n    extendedCreatedAtSeconds: Int?,\n  ) = ZipEntry(\n    canonicalPath = canonicalPath,\n    isDirectory = isDirectory,\n    comment = comment,\n    crc = crc,\n    compressedSize = compressedSize,\n    size = size,\n    compressionMethod = compressionMethod,\n    offset = offset,\n    dosLastModifiedAtDate = dosLastModifiedAtDate,\n    dosLastModifiedAtTime = dosLastModifiedAtTime,\n    ntfsLastModifiedAtFiletime = ntfsLastModifiedAtFiletime,\n    ntfsLastAccessedAtFiletime = ntfsLastAccessedAtFiletime,\n    ntfsCreatedAtFiletime = ntfsCreatedAtFiletime,\n    extendedLastModifiedAtSeconds = extendedLastModifiedAtSeconds,\n    extendedLastAccessedAtSeconds = extendedLastAccessedAtSeconds,\n    extendedCreatedAtSeconds = extendedCreatedAtSeconds,\n  )\n\n  internal val lastAccessedAtMillis: Long?\n    get() = when {\n      ntfsLastAccessedAtFiletime != null -> filetimeToEpochMillis(ntfsLastAccessedAtFiletime)\n      extendedLastAccessedAtSeconds != null -> extendedLastAccessedAtSeconds * 1000L\n      else -> null\n    }\n\n  internal val lastModifiedAtMillis: Long?\n    get() = when {\n      ntfsLastModifiedAtFiletime != null -> filetimeToEpochMillis(ntfsLastModifiedAtFiletime)\n      extendedLastModifiedAtSeconds != null -> extendedLastModifiedAtSeconds * 1000L\n      dosLastModifiedAtTime != -1 -> {\n        dosDateTimeToEpochMillis(dosLastModifiedAtDate, dosLastModifiedAtTime)\n      }\n      else -> null\n    }\n\n  internal val createdAtMillis: Long?\n    get() = when {\n      ntfsCreatedAtFiletime != null -> filetimeToEpochMillis(ntfsCreatedAtFiletime)\n      extendedCreatedAtSeconds != null -> extendedCreatedAtSeconds * 1000L\n      else -> null\n    }\n}\n"
  },
  {
    "path": "okio/src/zlibMain/kotlin/okio/internal/ZipFiles.kt",
    "content": "/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements.  See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License.  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 */\npackage okio.internal\n\nimport okio.BufferedSource\nimport okio.FileSystem\nimport okio.IOException\nimport okio.Path\nimport okio.Path.Companion.toPath\nimport okio.ZipFileSystem\nimport okio.buffer\nimport okio.use\n\nprivate const val LOCAL_FILE_HEADER_SIGNATURE = 0x4034b50\nprivate const val CENTRAL_FILE_HEADER_SIGNATURE = 0x2014b50\nprivate const val END_OF_CENTRAL_DIRECTORY_SIGNATURE = 0x6054b50\nprivate const val ZIP64_LOCATOR_SIGNATURE = 0x07064b50\nprivate const val ZIP64_EOCD_RECORD_SIGNATURE = 0x06064b50\n\ninternal const val COMPRESSION_METHOD_DEFLATED = 8\ninternal const val COMPRESSION_METHOD_STORED = 0\n\n/** General Purpose Bit Flags, Bit 0. Set if the file is encrypted. */\nprivate const val BIT_FLAG_ENCRYPTED = 1 shl 0\n\n/**\n * General purpose bit flags that this implementation handles. Strict enforcement of additional\n * flags may break legitimate use cases.\n */\nprivate const val BIT_FLAG_UNSUPPORTED_MASK = BIT_FLAG_ENCRYPTED\n\n/** Max size of entries and archives without zip64. */\nprivate const val MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE = 0xffffffffL\n\nprivate const val HEADER_ID_ZIP64_EXTENDED_INFO = 0x1\nprivate const val HEADER_ID_NTFS_EXTRA = 0x000a\nprivate const val HEADER_ID_EXTENDED_TIMESTAMP = 0x5455\n\n/**\n * Opens the file at [zipPath] for use as a file system. This uses UTF-8 to comments and names in\n * the zip file.\n *\n * @param predicate a function that returns false for entries that should be omitted from the file\n *     system.\n */\n@Throws(IOException::class)\ninternal fun openZip(\n  zipPath: Path,\n  fileSystem: FileSystem,\n  predicate: (ZipEntry) -> Boolean = { true },\n): ZipFileSystem {\n  fileSystem.openReadOnly(zipPath).use { fileHandle ->\n    // Scan backwards from the end of the file looking for the END_OF_CENTRAL_DIRECTORY_SIGNATURE.\n    // If this file has no comment we'll see it on the first attempt; otherwise we have to go\n    // backwards byte-by-byte until we reach it. (The number of bytes scanned will equal the comment\n    // size).\n    var scanOffset = fileHandle.size() - 22 // end of central directory record size is 22 bytes.\n    if (scanOffset < 0L) {\n      throw IOException(\"not a zip: size=${fileHandle.size()}\")\n    }\n    val stopOffset = maxOf(scanOffset - 65_536L, 0L)\n    val eocdOffset: Long\n    var record: EocdRecord\n    val comment: String\n    while (true) {\n      val source = fileHandle.source(scanOffset).buffer()\n      try {\n        if (source.readIntLe() == END_OF_CENTRAL_DIRECTORY_SIGNATURE) {\n          eocdOffset = scanOffset\n          record = source.readEocdRecord()\n          comment = source.readUtf8(record.commentByteCount.toLong())\n          break\n        }\n      } finally {\n        source.close()\n      }\n\n      scanOffset--\n      if (scanOffset < stopOffset) {\n        throw IOException(\"not a zip: end of central directory signature not found\")\n      }\n    }\n\n    // If this is a zip64, read a zip64 central directory record.\n    val zip64LocatorOffset = eocdOffset - 20 // zip64 end of central directory locator is 20 bytes.\n    if (zip64LocatorOffset > 0L) {\n      fileHandle.source(zip64LocatorOffset).buffer().use { zip64LocatorSource ->\n        if (zip64LocatorSource.readIntLe() == ZIP64_LOCATOR_SIGNATURE) {\n          val diskWithCentralDir = zip64LocatorSource.readIntLe()\n          val zip64EocdRecordOffset = zip64LocatorSource.readLongLe()\n          val numDisks = zip64LocatorSource.readIntLe()\n          if (numDisks != 1 || diskWithCentralDir != 0) {\n            throw IOException(\"unsupported zip: spanned\")\n          }\n          fileHandle.source(zip64EocdRecordOffset).buffer().use { zip64EocdSource ->\n            val zip64EocdSignature = zip64EocdSource.readIntLe()\n            if (zip64EocdSignature != ZIP64_EOCD_RECORD_SIGNATURE) {\n              throw IOException(\n                \"bad zip: expected ${ZIP64_EOCD_RECORD_SIGNATURE.hex} \" +\n                  \"but was ${zip64EocdSignature.hex}\",\n              )\n            }\n            record = zip64EocdSource.readZip64EocdRecord(record)\n          }\n        }\n      }\n    }\n\n    // Seek to the first central directory entry and read all of the entries.\n    val entries = mutableListOf<ZipEntry>()\n    fileHandle.source(record.centralDirectoryOffset).buffer().use { source ->\n      for (i in 0 until record.entryCount) {\n        val entry = source.readCentralDirectoryZipEntry()\n        if (entry.offset >= record.centralDirectoryOffset) {\n          throw IOException(\"bad zip: local file header offset >= central directory offset\")\n        }\n        if (predicate(entry)) {\n          entries += entry\n        }\n      }\n    }\n\n    // Organize the entries into a tree.\n    val index = buildIndex(entries)\n\n    return ZipFileSystem(zipPath, fileSystem, index, comment)\n  }\n}\n\n/**\n * Returns a map containing all of [entries], plus parent entries required so that all entries\n * (other than the file system root `/`) have a parent.\n */\nprivate fun buildIndex(entries: List<ZipEntry>): Map<Path, ZipEntry> {\n  val root = \"/\".toPath()\n  val result = mutableMapOf(\n    root to ZipEntry(canonicalPath = root, isDirectory = true),\n  )\n\n  // Iterate in sorted order so each path is preceded by its parent.\n  for (entry in entries.sortedBy { it.canonicalPath }) {\n    // Note that this may clobber an existing element in the map. For consistency with java.util.zip\n    // and java.nio.file.FileSystem, this prefers the last-encountered element.\n    val replaced = result.put(entry.canonicalPath, entry)\n    if (replaced != null) continue\n\n    // Make sure this parent directories exist all the way up to the file system root.\n    var child = entry\n    while (true) {\n      val parentPath = child.canonicalPath.parent ?: break // child is '/'.\n      var parentEntry = result[parentPath]\n\n      // We've found a parent that already exists! Add the child; we're done.\n      if (parentEntry != null) {\n        parentEntry.children += child.canonicalPath\n        break\n      }\n\n      // A parent is missing! Synthesize one.\n      parentEntry = ZipEntry(\n        canonicalPath = parentPath,\n        isDirectory = true,\n      )\n      result[parentPath] = parentEntry\n      parentEntry.children += child.canonicalPath\n      child = parentEntry\n    }\n  }\n\n  return result\n}\n\n/** When this returns, [this] will be positioned at the start of the next entry. */\n@Throws(IOException::class)\ninternal fun BufferedSource.readCentralDirectoryZipEntry(): ZipEntry {\n  val signature = readIntLe()\n  if (signature != CENTRAL_FILE_HEADER_SIGNATURE) {\n    throw IOException(\n      \"bad zip: expected ${CENTRAL_FILE_HEADER_SIGNATURE.hex} but was ${signature.hex}\",\n    )\n  }\n\n  skip(4) // version made by (2) + version to extract (2).\n  val bitFlag = readShortLe().toInt() and 0xffff\n  if (bitFlag and BIT_FLAG_UNSUPPORTED_MASK != 0) {\n    throw IOException(\"unsupported zip: general purpose bit flag=${bitFlag.hex}\")\n  }\n\n  val compressionMethod = readShortLe().toInt() and 0xffff\n  val dosLastModifiedTime = readShortLe().toInt() and 0xffff\n  val dosLastModifiedDate = readShortLe().toInt() and 0xffff\n\n  // These are 32-bit values in the file, but 64-bit fields in this object.\n  val crc = readIntLe().toLong() and 0xffffffffL\n  var compressedSize = readIntLe().toLong() and 0xffffffffL\n  var size = readIntLe().toLong() and 0xffffffffL\n  val nameSize = readShortLe().toInt() and 0xffff\n  val extraSize = readShortLe().toInt() and 0xffff\n  val commentByteCount = readShortLe().toInt() and 0xffff\n\n  skip(8) // disk number start (2) + internal file attributes (2) + external file attributes (4).\n  var offset = readIntLe().toLong() and 0xffffffffL\n  val name = readUtf8(nameSize.toLong())\n  if ('\\u0000' in name) throw IOException(\"bad zip: filename contains 0x00\")\n\n  val requiredZip64ExtraSize = run {\n    var result = 0L\n    if (size == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) result += 8\n    if (compressedSize == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) result += 8\n    if (offset == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) result += 8\n    return@run result\n  }\n\n  var ntfsLastModifiedAtFiletime: Long? = null\n  var ntfsLastAccessedAtFiletime: Long? = null\n  var ntfsCreatedAtFiletime: Long? = null\n\n  var hasZip64Extra = false\n  readExtra(extraSize) { headerId, dataSize ->\n    when (headerId) {\n      HEADER_ID_ZIP64_EXTENDED_INFO -> {\n        if (hasZip64Extra) {\n          throw IOException(\"bad zip: zip64 extra repeated\")\n        }\n        hasZip64Extra = true\n\n        if (dataSize < requiredZip64ExtraSize) {\n          throw IOException(\"bad zip: zip64 extra too short\")\n        }\n\n        // Read each field if it has a sentinel value in the regular header.\n        size = if (size == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) readLongLe() else size\n        compressedSize = if (compressedSize == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) readLongLe() else 0L\n        offset = if (offset == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) readLongLe() else 0L\n      }\n\n      HEADER_ID_NTFS_EXTRA -> {\n        if (dataSize < 4L) {\n          throw IOException(\"bad zip: NTFS extra too short\")\n        }\n        skip(4L)\n\n        // Reads the NTFS extra metadata. This metadata recursively does a tag and length scheme\n        // inside of ZIP extras' own tag and length scheme. So we do readExtra() again.\n        readExtra((dataSize - 4L).toInt()) { attributeId, attributeSize ->\n          when (attributeId) {\n            0x1 -> {\n              if (ntfsLastModifiedAtFiletime != null) {\n                throw IOException(\"bad zip: NTFS extra attribute tag 0x0001 repeated\")\n              }\n\n              if (attributeSize != 24L) {\n                throw IOException(\"bad zip: NTFS extra attribute tag 0x0001 size != 24\")\n              }\n\n              ntfsLastModifiedAtFiletime = readLongLe()\n              ntfsLastAccessedAtFiletime = readLongLe()\n              ntfsCreatedAtFiletime = readLongLe()\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (requiredZip64ExtraSize > 0L && !hasZip64Extra) {\n    throw IOException(\"bad zip: zip64 extra required but absent\")\n  }\n\n  val comment = readUtf8(commentByteCount.toLong())\n  val canonicalPath = \"/\".toPath() / name\n  val isDirectory = name.endsWith(\"/\")\n\n  return ZipEntry(\n    canonicalPath = canonicalPath,\n    isDirectory = isDirectory,\n    comment = comment,\n    crc = crc,\n    compressedSize = compressedSize,\n    size = size,\n    compressionMethod = compressionMethod,\n    offset = offset,\n    dosLastModifiedAtDate = dosLastModifiedDate,\n    dosLastModifiedAtTime = dosLastModifiedTime,\n    ntfsLastModifiedAtFiletime = ntfsLastModifiedAtFiletime,\n    ntfsLastAccessedAtFiletime = ntfsLastAccessedAtFiletime,\n    ntfsCreatedAtFiletime = ntfsCreatedAtFiletime,\n  )\n}\n\n@Throws(IOException::class)\nprivate fun BufferedSource.readEocdRecord(): EocdRecord {\n  val diskNumber = readShortLe().toInt() and 0xffff\n  val diskWithCentralDir = readShortLe().toInt() and 0xffff\n  val entryCount = (readShortLe().toInt() and 0xffff).toLong()\n  val totalEntryCount = (readShortLe().toInt() and 0xffff).toLong()\n  if (entryCount != totalEntryCount || diskNumber != 0 || diskWithCentralDir != 0) {\n    throw IOException(\"unsupported zip: spanned\")\n  }\n  skip(4) // central directory size.\n  val centralDirectoryOffset = readIntLe().toLong() and 0xffffffffL\n  val commentByteCount = readShortLe().toInt() and 0xffff\n\n  return EocdRecord(\n    entryCount = entryCount,\n    centralDirectoryOffset = centralDirectoryOffset,\n    commentByteCount = commentByteCount,\n  )\n}\n\n@Throws(IOException::class)\nprivate fun BufferedSource.readZip64EocdRecord(regularRecord: EocdRecord): EocdRecord {\n  skip(12) // size of central directory record (8) + version made by (2) + version to extract (2).\n  val diskNumber = readIntLe()\n  val diskWithCentralDirStart = readIntLe()\n  val entryCount = readLongLe()\n  val totalEntryCount = readLongLe()\n  if (entryCount != totalEntryCount || diskNumber != 0 || diskWithCentralDirStart != 0) {\n    throw IOException(\"unsupported zip: spanned\")\n  }\n  skip(8) // central directory size.\n  val centralDirectoryOffset = readLongLe()\n\n  return EocdRecord(\n    entryCount = entryCount,\n    centralDirectoryOffset = centralDirectoryOffset,\n    commentByteCount = regularRecord.commentByteCount,\n  )\n}\n\n/**\n * Read a sequence of 0 or more extra fields. Each field has this structure:\n *\n *  * 2-byte header ID\n *  * 2-byte data size\n *  * variable-byte data value\n *\n * This reads each extra field and calls [block] for each. The parameters are the header ID and\n * data size. It is an error for [block] to process more bytes than the data size.\n */\nprivate fun BufferedSource.readExtra(extraSize: Int, block: (Int, Long) -> Unit) {\n  var remaining = extraSize.toLong()\n  while (remaining != 0L) {\n    if (remaining < 4) {\n      throw IOException(\"bad zip: truncated header in extra field\")\n    }\n    val headerId = readShortLe().toInt() and 0xffff\n    val dataSize = readShortLe().toLong() and 0xffff\n    remaining -= 4\n    if (remaining < dataSize) {\n      throw IOException(\"bad zip: truncated value in extra field\")\n    }\n    require(dataSize)\n    val sizeBefore = buffer.size\n    block(headerId, dataSize)\n    val fieldRemaining = dataSize + buffer.size - sizeBefore\n    when {\n      fieldRemaining < 0 -> {\n        throw IOException(\"unsupported zip: too many bytes processed for $headerId\")\n      }\n      fieldRemaining > 0 -> {\n        buffer.skip(fieldRemaining)\n      }\n    }\n    remaining -= dataSize\n  }\n}\n\ninternal fun BufferedSource.skipLocalHeader() {\n  readOrSkipLocalHeader(null)\n}\n\ninternal fun BufferedSource.readLocalHeader(centralDirectoryZipEntry: ZipEntry): ZipEntry {\n  return readOrSkipLocalHeader(centralDirectoryZipEntry)!!\n}\n\n/**\n * If [centralDirectoryZipEntry] is null this will return null. Otherwise, it will return a new\n * entry which unions [centralDirectoryZipEntry] with information from the local header.\n */\nprivate fun BufferedSource.readOrSkipLocalHeader(\n  centralDirectoryZipEntry: ZipEntry?,\n): ZipEntry? {\n  val signature = readIntLe()\n  if (signature != LOCAL_FILE_HEADER_SIGNATURE) {\n    throw IOException(\n      \"bad zip: expected ${LOCAL_FILE_HEADER_SIGNATURE.hex} but was ${signature.hex}\",\n    )\n  }\n  skip(2) // version to extract.\n  val bitFlag = readShortLe().toInt() and 0xffff\n  if (bitFlag and BIT_FLAG_UNSUPPORTED_MASK != 0) {\n    throw IOException(\"unsupported zip: general purpose bit flag=${bitFlag.hex}\")\n  }\n  skip(18) // compression method (2) + time+date (4) + crc32 (4) + compressed size (4) + size (4).\n  val fileNameLength = readShortLe().toLong() and 0xffff\n  val extraSize = readShortLe().toInt() and 0xffff\n  skip(fileNameLength)\n\n  if (centralDirectoryZipEntry == null) {\n    skip(extraSize.toLong())\n    return null\n  }\n\n  var extendedLastModifiedAtSeconds: Int? = null\n  var extendedLastAccessedAtSeconds: Int? = null\n  var extendedCreatedAtSeconds: Int? = null\n\n  readExtra(extraSize) { headerId, dataSize ->\n    when (headerId) {\n      HEADER_ID_EXTENDED_TIMESTAMP -> {\n        if (dataSize < 1) {\n          throw IOException(\"bad zip: extended timestamp extra too short\")\n        }\n        val flags = readByte().toInt() and 0xff\n\n        val hasLastModifiedAtMillis = (flags and 0x1) == 0x1\n        val hasLastAccessedAtMillis = (flags and 0x2) == 0x2\n        val hasCreatedAtMillis = (flags and 0x4) == 0x4\n        val requiredSize = run {\n          var result = 1L\n          if (hasLastModifiedAtMillis) result += 4L\n          if (hasLastAccessedAtMillis) result += 4L\n          if (hasCreatedAtMillis) result += 4L\n          return@run result\n        }\n        if (dataSize < requiredSize) {\n          throw IOException(\"bad zip: extended timestamp extra too short\")\n        }\n\n        if (hasLastModifiedAtMillis) extendedLastModifiedAtSeconds = readIntLe()\n        if (hasLastAccessedAtMillis) extendedLastAccessedAtSeconds = readIntLe()\n        if (hasCreatedAtMillis) extendedCreatedAtSeconds = readIntLe()\n      }\n    }\n  }\n\n  return centralDirectoryZipEntry.copy(\n    extendedLastModifiedAtSeconds = extendedLastModifiedAtSeconds,\n    extendedLastAccessedAtSeconds = extendedLastAccessedAtSeconds,\n    extendedCreatedAtSeconds = extendedCreatedAtSeconds,\n  )\n}\n\n/**\n * Converts from the Microsoft [filetime] format to the Java epoch millis format.\n *\n *  * Filetime's unit is 100 nanoseconds, and 0 is 1601-01-01T00:00:00Z.\n *  * Java epoch millis' unit is 1 millisecond, and 0 is 1970-01-01T00:00:00Z.\n *\n * See also https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime\n */\ninternal fun filetimeToEpochMillis(filetime: Long): Long {\n  // There's 11,644,473,600,000 milliseconds between 1601-01-01T00:00:00Z and 1970-01-01T00:00:00Z.\n  //   val years = 1_970 − 1_601\n  //   val leapYears = floor(years / 4) − floor(years / 100)\n  //   val days = (years * 365) + leapYears\n  //   val millis = days * 24 * 60 * 60 * 1_000\n  return filetime / 10_000 - 11_644_473_600_000L\n}\n\n/**\n * Converts a 32-bit DOS date+time to milliseconds since epoch. Note that this function interprets\n * a value with no time zone as a value with the local time zone.\n */\ninternal fun dosDateTimeToEpochMillis(date: Int, time: Int): Long? {\n  if (time == -1) {\n    return null\n  }\n\n  return datePartsToEpochMillis(\n    year = 1980 + (date shr 9 and 0x7f),\n    month = date shr 5 and 0xf,\n    day = date and 0x1f,\n    hour = time shr 11 and 0x1f,\n    minute = time shr 5 and 0x3f,\n    second = time and 0x1f shl 1,\n  )\n}\n\nprivate class EocdRecord(\n  val entryCount: Long,\n  val centralDirectoryOffset: Long,\n  val commentByteCount: Int,\n)\n\nprivate val Int.hex: String\n  get() = \"0x${this.toString(16)}\"\n"
  },
  {
    "path": "okio/src/zlibTest/kotlin/okio/GzipKotlinTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\n\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport okio.ByteString.Companion.decodeHex\n\nclass GzipKotlinTest {\n  @Test fun sink() {\n    val data = Buffer()\n    (data as Sink).gzip().buffer().use { gzip ->\n      gzip.writeUtf8(\"Hi!\")\n    }\n    assertEquals(\"1f8b0800000000000000f3c8540400dac59e7903000000\", data.readByteString().hex())\n  }\n\n  @Test fun source() {\n    val buffer = Buffer().write(\"1f8b0800000000000000f3c8540400dac59e7903000000\".decodeHex())\n    (buffer as Source).gzip().buffer().use { gzip ->\n      assertEquals(\"Hi!\", gzip.readUtf8())\n    }\n  }\n\n  @Test fun extraLongXlen() {\n    val xlen = 0xffff\n    val buffer = Buffer()\n      .write(\"1f8b0804000000000000\".decodeHex())\n      .writeShort(xlen)\n      .write(ByteArray(xlen))\n      .write(\"f3c8540400dac59e7903000000\".decodeHex())\n    (buffer as Source).gzip().buffer().use { gzip ->\n      assertEquals(\"Hi!\", gzip.readUtf8())\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/zlibTest/kotlin/okio/GzipSinkTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.fail\n\nclass GzipSinkTest {\n  @Test\n  fun gzipGunzip() {\n    val data = Buffer()\n    val original = \"It's a UNIX system! I know this!\"\n    data.writeUtf8(original)\n    val sink = Buffer()\n    val gzipSink = GzipSink(sink)\n    gzipSink.write(data, data.size)\n    gzipSink.close()\n    val inflated = gunzip(sink)\n    assertEquals(original, inflated.readUtf8())\n  }\n\n  @Test\n  fun closeWithExceptionWhenWritingAndClosing() {\n    val mockSink = MockSink()\n    mockSink.scheduleThrow(0, IOException(\"first\"))\n    mockSink.scheduleThrow(1, IOException(\"second\"))\n    val gzipSink = GzipSink(mockSink)\n    gzipSink.write(Buffer().writeUtf8(\"a\".repeat(Segment.SIZE)), Segment.SIZE.toLong())\n    try {\n      gzipSink.close()\n      fail()\n    } catch (expected: IOException) {\n      assertEquals(\"first\", expected.message)\n    }\n    mockSink.assertLogContains(\"close()\")\n  }\n\n  private fun gunzip(gzipped: Buffer): Buffer {\n    val result = Buffer()\n    val source = GzipSource(gzipped)\n    while (source.read(result, Int.MAX_VALUE.toLong()) != -1L) {\n    }\n    return result\n  }\n}\n"
  },
  {
    "path": "okio/src/zlibTest/kotlin/okio/GzipSourceTest.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFalse\nimport kotlin.test.assertTrue\nimport kotlin.test.fail\nimport okio.ByteString.Companion.decodeHex\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.ByteString.Companion.of\nimport okio.internal.CRC32\n\nclass GzipSourceTest {\n  @Test\n  fun gunzip() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeader)\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer)\n    assertGzipped(gzipped)\n  }\n\n  @Test\n  fun gunzip_withHCRC() {\n    val hcrc = CRC32()\n    val gzipHeader = gzipHeaderWithFlags(0x02.toByte())\n    hcrc.update(gzipHeader.toByteArray())\n    val gzipped = Buffer()\n    gzipped.write(gzipHeader)\n    gzipped.writeShort(hcrc.getValue().toShort().reverseBytes().toInt()) // little endian\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer)\n    assertGzipped(gzipped)\n  }\n\n  @Test\n  fun gunzip_withExtra() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeaderWithFlags(0x04.toByte()))\n    gzipped.writeShort(7.toShort().reverseBytes().toInt()) // little endian extra length\n    gzipped.write(\"blubber\".encodeUtf8().toByteArray(), 0, 7)\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer)\n    assertGzipped(gzipped)\n  }\n\n  @Test\n  fun gunzip_withName() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeaderWithFlags(0x08.toByte()))\n    gzipped.write(\"foo.txt\".encodeUtf8().toByteArray(), 0, 7)\n    gzipped.writeByte(0) // zero-terminated\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer)\n    assertGzipped(gzipped)\n  }\n\n  @Test\n  fun gunzip_withComment() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeaderWithFlags(0x10.toByte()))\n    gzipped.write(\"rubbish\".encodeUtf8().toByteArray(), 0, 7)\n    gzipped.writeByte(0) // zero-terminated\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer)\n    assertGzipped(gzipped)\n  }\n\n  /**\n   * For portability, it is a good idea to export the gzipped bytes and try running gzip.  Ex.\n   * `echo gzipped | base64 --decode | gzip -l -v`\n   */\n  @Test\n  fun gunzip_withAll() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeaderWithFlags(0x1c.toByte()))\n    gzipped.writeShort(7.toShort().reverseBytes().toInt()) // little endian extra length\n    gzipped.write(\"blubber\".encodeUtf8().toByteArray(), 0, 7)\n    gzipped.write(\"foo.txt\".encodeUtf8().toByteArray(), 0, 7)\n    gzipped.writeByte(0) // zero-terminated\n    gzipped.write(\"rubbish\".encodeUtf8().toByteArray(), 0, 7)\n    gzipped.writeByte(0) // zero-terminated\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer)\n    assertGzipped(gzipped)\n  }\n\n  private fun assertGzipped(gzipped: Buffer) {\n    val gunzipped = gunzip(gzipped)\n    assertEquals(\"It's a UNIX system! I know this!\", gunzipped.readUtf8())\n  }\n\n  /**\n   * Note that you cannot test this with old versions of gzip, as they interpret flag bit 1 as\n   * CONTINUATION, not HCRC. For example, this is the case with the default gzip on osx.\n   */\n  @Test\n  fun gunzipWhenHeaderCRCIncorrect() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeaderWithFlags(0x02.toByte()))\n    gzipped.writeShort(0.toShort().toInt()) // wrong HCRC!\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer)\n    try {\n      gunzip(gzipped)\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"FHCRC: actual 0x0000261d != expected 0x00000000\", e.message)\n    }\n  }\n\n  @Test\n  fun gunzipWhenCRCIncorrect() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeader)\n    gzipped.write(deflated)\n    gzipped.writeInt(0x1234567.reverseBytes()) // wrong CRC\n    gzipped.write(gzipTrailer.toByteArray(), 3, 4)\n    try {\n      gunzip(gzipped)\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"CRC: actual 0x37ad8f8d != expected 0x01234567\", e.message)\n    }\n  }\n\n  @Test\n  fun gunzipWhenLengthIncorrect() {\n    val gzipped = Buffer()\n    gzipped.write(gzipHeader)\n    gzipped.write(deflated)\n    gzipped.write(gzipTrailer.toByteArray(), 0, 4)\n    gzipped.writeInt(0x123456.reverseBytes()) // wrong length\n    try {\n      gunzip(gzipped)\n      fail()\n    } catch (e: IOException) {\n      assertEquals(\"ISIZE: actual 0x00000020 != expected 0x00123456\", e.message)\n    }\n  }\n\n  @Test\n  fun gunzipExhaustsSource() {\n    val gzippedSource = Buffer()\n      .write(\"1f8b08000000000000004b4c4a0600c241243503000000\".decodeHex()) // 'abc'\n    val exhaustableSource = ExhaustableSource(gzippedSource)\n    val gunzippedSource = GzipSource(exhaustableSource).buffer()\n    assertEquals('a'.code.toLong(), gunzippedSource.readByte().toLong())\n    assertEquals('b'.code.toLong(), gunzippedSource.readByte().toLong())\n    assertEquals('c'.code.toLong(), gunzippedSource.readByte().toLong())\n    assertFalse(exhaustableSource.exhausted)\n    assertEquals(-1, gunzippedSource.read(Buffer(), 1))\n    assertTrue(exhaustableSource.exhausted)\n  }\n\n  @Test\n  fun gunzipThrowsIfSourceIsNotExhausted() {\n    val gzippedSource = Buffer()\n      .write(\"1f8b08000000000000004b4c4a0600c241243503000000\".decodeHex()) // 'abc'\n    gzippedSource.writeByte('d'.code) // This byte shouldn't be here!\n    val gunzippedSource = GzipSource(gzippedSource).buffer()\n    assertEquals('a'.code.toLong(), gunzippedSource.readByte().toLong())\n    assertEquals('b'.code.toLong(), gunzippedSource.readByte().toLong())\n    assertEquals('c'.code.toLong(), gunzippedSource.readByte().toLong())\n    try {\n      gunzippedSource.readByte()\n      fail()\n    } catch (expected: IOException) {\n    }\n  }\n\n  private fun gzipHeaderWithFlags(flags: Byte): ByteString {\n    val result = gzipHeader.toByteArray()\n    result[3] = flags\n    return of(*result)\n  }\n\n  private val gzipHeader = \"1f8b0800000000000000\".decodeHex()\n\n  // Deflated \"It's a UNIX system! I know this!\"\n  private val deflated = \"f32c512f56485408f5f38c5028ae2c2e49cd5554f054c8cecb2f5728c9c82c560400\".decodeHex()\n  private val gzipTrailer = (\n    \"\" +\n      \"8d8fad37\" + // Checksum of deflated.\n      \"20000000\"\n    ) // 32 in little endian.\n    .decodeHex()\n\n  private fun gunzip(gzipped: Buffer): Buffer {\n    val result = Buffer()\n    val source = GzipSource(gzipped)\n    while (source.read(result, Int.MAX_VALUE.toLong()) != -1L) {\n    }\n    return result\n  }\n\n  /** This source keeps track of whether its read has returned -1.  */\n  internal class ExhaustableSource(private val source: Source) : Source {\n    var exhausted = false\n\n    override fun read(sink: Buffer, byteCount: Long): Long {\n      val result = source.read(sink, byteCount)\n      if (result == -1L) exhausted = true\n      return result\n    }\n\n    override fun timeout(): Timeout {\n      return source.timeout()\n    }\n\n    override fun close() {\n      source.close()\n    }\n  }\n}\n"
  },
  {
    "path": "okio/src/zlibTest/kotlin/okio/ZipFileSystemGoTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.time.Instant\nimport okio.Path.Companion.toPath\n\n/**\n * Test using sample data from Go's test suite.\n *\n * https://github.com/golang/go/blob/6f5d77454e31be8af11a7e2bcda36d200fda07c5/src/archive/zip/reader_test.go\n */\nclass ZipFileSystemGoTest {\n  private val fileSystem = FileSystem.SYSTEM\n  private var base = okioRoot / \"okio-testing-support\" /\n    \"src/commonMain/resources/go/src/archive/zip/testdata\"\n\n  @Test\n  fun timeWinzip() {\n    val zipFileSystem = fileSystem.openZip(base / \"time-winzip.zip\")\n    val fileMetadata = zipFileSystem.metadata(\"test.txt\".toPath())\n    assertEquals(\n      Instant.parse(\"2017-11-01T04:11:57.244Z\"),\n      Instant.fromEpochMilliseconds(fileMetadata.createdAtMillis!!),\n    )\n    assertEquals(\n      Instant.parse(\"2017-11-01T04:11:57.244Z\"),\n      Instant.fromEpochMilliseconds(fileMetadata.lastModifiedAtMillis!!),\n    )\n    assertEquals(\n      Instant.parse(\"2017-11-01T04:13:19.623Z\"),\n      Instant.fromEpochMilliseconds(fileMetadata.lastAccessedAtMillis!!),\n    )\n  }\n}\n"
  },
  {
    "path": "okio/src/zlibTest/kotlin/okio/ZipFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport assertk.assertThat\nimport assertk.assertions.containsExactly\nimport assertk.assertions.containsExactlyInAnyOrder\nimport assertk.assertions.isEmpty\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isFalse\nimport assertk.assertions.isGreaterThan\nimport assertk.assertions.isLessThan\nimport assertk.assertions.isNotNull\nimport assertk.assertions.isNull\nimport assertk.assertions.isTrue\nimport kotlin.test.Test\nimport kotlin.test.assertFailsWith\nimport kotlin.time.Instant\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.Path.Companion.toPath\n\nclass ZipFileSystemTest {\n  private val fileSystem = FileSystem.SYSTEM\n  private var base = okioRoot / \"okio-testing-support/src/commonMain/resources/okio/zipfilesystem\"\n\n  @Test\n  fun emptyZip() {\n    val zipFileSystem = fileSystem.openZip(base / \"emptyZip.zip\")\n    assertThat(zipFileSystem.list(\"/\".toPath())).isEmpty()\n  }\n\n  @Test\n  fun emptyZipWithPrependedData() {\n    val zipFileSystem = fileSystem.openZip(base / \"emptyZipWithPrependedData.zip\")\n    assertThat(zipFileSystem.list(\"/\".toPath())).isEmpty()\n  }\n\n  /**\n   * ```\n   * echo \"Hello World\" > hello.txt\n   *\n   * mkdir -p directory/subdirectory\n   * echo \"Another file!\" > directory/subdirectory/child.txt\n   *\n   * zip \\\n   *   zipWithFiles.zip \\\n   *   hello.txt \\\n   *   directory/subdirectory/child.txt\n   * ```\n   */\n  @Test\n  fun zipWithFiles() {\n    val zipPath = base / \"zipWithFiles.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertThat(zipFileSystem.read(\"hello.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Hello World\")\n\n    assertThat(zipFileSystem.read(\"directory/subdirectory/child.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Another file!\")\n\n    assertThat(zipFileSystem.list(\"/\".toPath()))\n      .containsExactlyInAnyOrder(\"/hello.txt\".toPath(), \"/directory\".toPath())\n    assertThat(zipFileSystem.list(\"/directory\".toPath()))\n      .containsExactly(\"/directory/subdirectory\".toPath())\n    assertThat(zipFileSystem.list(\"/directory/subdirectory\".toPath()))\n      .containsExactly(\"/directory/subdirectory/child.txt\".toPath())\n  }\n\n  /**\n   * Note that the zip tool does not compress files that don't benefit from it. Examples above like\n   * 'Hello World' are stored, not deflated.\n   *\n   * ```\n   * echo \"Android\n   * Android\n   * ... <1000 times>\n   * Android\n   * \" > a.txt\n   *\n   * zip \\\n   *   --compression-method \\\n   *   deflate \\\n   *   zipWithDeflate.zip \\\n   *   a.txt\n   * ```\n   */\n  @Test\n  fun zipWithDeflate() {\n    val content = \"Android\\n\".repeat(1000)\n    val zipPath = base / \"zipWithDeflate.zip\"\n    assertThat(fileSystem.metadata(zipPath).size).isNotNull().isLessThan(content.length.toLong())\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertThat(zipFileSystem.read(\"a.txt\".toPath()) { readUtf8() })\n      .isEqualTo(content)\n  }\n\n  /**\n   * ```\n   * echo \"Android\n   * Android\n   * ... <1000 times>\n   * Android\n   * \" > a.txt\n   *\n   * zip \\\n   *   --compression-method \\\n   *   store \\\n   *   zipWithStore.zip \\\n   *   a.txt\n   * ```\n   */\n  @Test\n  fun zipWithStore() {\n    val content = \"Android\\n\".repeat(1000)\n    val zipPath = base / \"zipWithStore.zip\"\n    assertThat(fileSystem.metadata(zipPath).size).isNotNull().isGreaterThan(content.length.toLong())\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertThat(zipFileSystem.read(\"a.txt\".toPath()) { readUtf8() })\n      .isEqualTo(content)\n  }\n\n  /**\n   * Confirm we can read zip files that have file comments, even if these comments are not exposed\n   * in the public API.\n   *\n   * ```\n   * echo \"Android\" > a.txt\n   *\n   * echo \"Banana\" > b.txt\n   *\n   * zip \\\n   *   --entry-comments \\\n   *   zipWithFileComments.zip \\\n   *   a.txt \\\n   *   b.txt\n   * ```\n   */\n  @Test\n  fun zipWithFileComments() {\n    val zipPath = base / \"zipWithFileComments.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertThat(zipFileSystem.read(\"a.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Android\")\n\n    assertThat(zipFileSystem.read(\"b.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Banana\")\n  }\n\n  /**\n   * ```\n   * echo \"Android\" > a.txt\n   * touch -m -t 200102030405.06 a.txt\n   * touch -a -t 200102030405.07 a.txt\n   *\n   * echo \"Banana\" > b.txt\n   * touch -m -t 200908070605.04 b.txt\n   * touch -a -t 200908070605.03 b.txt\n   *\n   * zip \\\n   *   zipWithFileModifiedDate.zip \\\n   *   a.txt \\\n   *   b.txt\n   * ```\n   */\n  @Test\n  fun zipWithFileModifiedDate() {\n    val zipPath = base / \"zipWithFileModifiedDate.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    zipFileSystem.metadata(\"a.txt\".toPath())\n      .apply {\n        assertThat(isRegularFile).isTrue()\n        assertThat(isDirectory).isFalse()\n        assertThat(size).isEqualTo(7L)\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"2001-02-03T04:05:06Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"2001-02-03T04:05:07Z\".toEpochMillis())\n      }\n\n    zipFileSystem.metadata(\"b.txt\".toPath())\n      .apply {\n        assertThat(isRegularFile).isTrue()\n        assertThat(isDirectory).isFalse()\n        assertThat(size).isEqualTo(6L)\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"2009-08-07T06:05:04Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"2009-08-07T06:05:03Z\".toEpochMillis())\n      }\n  }\n\n  /**\n   * Confirm we suffer UNIX limitations on our date format.\n   *\n   * ```\n   * echo \"Android\" > a.txt\n   * touch -m -t 196912310000.00 a.txt\n   * touch -a -t 196912300000.00 a.txt\n   *\n   * echo \"Banana\" > b.txt\n   * touch -m -t 203801190314.07 b.txt\n   * touch -a -t 203801190314.08 b.txt\n   *\n   * zip \\\n   *   zipWithFileOutOfBoundsModifiedDate.zip \\\n   *   a.txt \\\n   *   b.txt\n   * ```\n   */\n  @Test\n  fun zipWithFileOutOfBoundsModifiedDate() {\n    val zipPath = base / \"zipWithFileOutOfBoundsModifiedDate.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    zipFileSystem.metadata(\"a.txt\".toPath())\n      .apply {\n        assertThat(isRegularFile).isTrue()\n        assertThat(isDirectory).isFalse()\n        assertThat(size).isEqualTo(7L)\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"1969-12-31T00:00:00Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"1969-12-30T00:00:00Z\".toEpochMillis())\n      }\n\n    // Greater than the upper bound wraps around.\n    zipFileSystem.metadata(\"b.txt\".toPath())\n      .apply {\n        assertThat(isRegularFile).isTrue()\n        assertThat(isDirectory).isFalse()\n        assertThat(size).isEqualTo(6L)\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"2038-01-19T03:14:07Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"1901-12-13T20:45:52Z\".toEpochMillis())\n      }\n  }\n\n  /**\n   * Directories are optional in the zip file. But if we want metadata on them they must be stored.\n   * Note that this test adds the directories last; otherwise adding child files to them will cause\n   * their modified at times to change.\n   *\n   * ```\n   * mkdir -p a\n   * echo \"Android\" > a/a.txt\n   * touch -m -t 200102030405.06 a\n   * touch -a -t 200102030405.07 a\n   *\n   * mkdir -p b\n   * echo \"Android\" > b/b.txt\n   * touch -m -t 200908070605.04 b\n   * touch -a -t 200908070605.03 b\n   *\n   * zip \\\n   *   zipWithDirectoryModifiedDate.zip \\\n   *   a/a.txt \\\n   *   a \\\n   *   b/b.txt \\\n   *   b\n   * ```\n   */\n  @Test\n  fun zipWithDirectoryModifiedDate() {\n    val zipPath = base / \"zipWithDirectoryModifiedDate.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    zipFileSystem.metadata(\"a\".toPath())\n      .apply {\n        assertThat(isRegularFile).isFalse()\n        assertThat(isDirectory).isTrue()\n        assertThat(size).isNull()\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"2001-02-03T04:05:06Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"2001-02-03T04:05:07Z\".toEpochMillis())\n      }\n    assertThat(zipFileSystem.list(\"a\".toPath())).containsExactly(\"/a/a.txt\".toPath())\n\n    zipFileSystem.metadata(\"b\".toPath())\n      .apply {\n        assertThat(isRegularFile).isFalse()\n        assertThat(isDirectory).isTrue()\n        assertThat(size).isNull()\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"2009-08-07T06:05:04Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"2009-08-07T06:05:03Z\".toEpochMillis())\n      }\n    assertThat(zipFileSystem.list(\"b\".toPath())).containsExactly(\"/b/b.txt\".toPath())\n  }\n\n  /**\n   * ```\n   * mkdir -p a\n   * echo \"Android\" > a/a.txt\n   * touch -m -t 197001010001.00 a/a.txt\n   * touch -a -t 197001010002.00 a/a.txt\n   *\n   * zip \\\n   *   zipWithModifiedDate.zip \\\n   *   a/a.txt\n   * ```\n   */\n  @Test\n  fun zipWithModifiedDate() {\n    val zipPath = base / \"zipWithModifiedDate.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    zipFileSystem.metadata(\"a/a.txt\".toPath())\n      .apply {\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"1970-01-01T00:01:00Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"1970-01-01T00:02:00Z\".toEpochMillis())\n      }\n  }\n\n  /**\n   * Build a very small zip file with just a single empty directory.\n   *\n   * ```\n   * mkdir -p a\n   * touch -m -t 200102030405.06 a\n   * touch -a -t 200102030405.07 a\n   *\n   * zip \\\n   *   zipWithEmptyDirectory.zip \\\n   *   a\n   * ```\n   */\n  @Test\n  fun zipWithEmptyDirectory() {\n    val zipPath = base / \"zipWithEmptyDirectory.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    zipFileSystem.metadata(\"a\".toPath())\n      .apply {\n        assertThat(isRegularFile).isFalse()\n        assertThat(isDirectory).isTrue()\n        assertThat(size).isNull()\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isEqualTo(\"2001-02-03T04:05:06Z\".toEpochMillis())\n        assertThat(lastAccessedAtMillis).isEqualTo(\"2001-02-03T04:05:07Z\".toEpochMillis())\n      }\n    assertThat(zipFileSystem.list(\"a\".toPath())).isEmpty()\n  }\n\n  /**\n   * The `--no-dir-entries` option causes the zip file to omit the directories from the encoded\n   * file. Our implementation synthesizes these missing directories automatically.\n   *\n   * ```\n   * mkdir -p a\n   * echo \"Android\" > a/a.txt\n   *\n   * mkdir -p b\n   * echo \"Android\" > b/b.txt\n   *\n   * zip \\\n   *   --no-dir-entries \\\n   *   zipWithSyntheticDirectory.zip \\\n   *   a/a.txt \\\n   *   a \\\n   *   b/b.txt \\\n   *   b\n   * ```\n   */\n  @Test\n  fun zipWithSyntheticDirectory() {\n    val zipPath = base / \"zipWithSyntheticDirectory.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    zipFileSystem.metadata(\"a\".toPath())\n      .apply {\n        assertThat(isRegularFile).isFalse()\n        assertThat(isDirectory).isTrue()\n        assertThat(size).isNull()\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isNull()\n        assertThat(lastAccessedAtMillis).isNull()\n      }\n    assertThat(zipFileSystem.list(\"a\".toPath())).containsExactly(\"/a/a.txt\".toPath())\n\n    zipFileSystem.metadata(\"b\".toPath())\n      .apply {\n        assertThat(isRegularFile).isFalse()\n        assertThat(isDirectory).isTrue()\n        assertThat(size).isNull()\n        assertThat(createdAtMillis).isNull()\n        assertThat(lastModifiedAtMillis).isNull()\n        assertThat(lastAccessedAtMillis).isNull()\n      }\n    assertThat(zipFileSystem.list(\"b\".toPath())).containsExactly(\"/b/b.txt\".toPath())\n  }\n\n  /**\n   * Force a file to be encoded with zip64 metadata. We use a pipe to force the zip command to\n   * create a zip64 archive; otherwise we'd need to add a very large file to get this format.\n   *\n   * ```\n   * zip \\\n   *   zip64.zip \\\n   *   -\n   * ```\n   */\n  @Test\n  fun zip64() {\n    val zipPath = base / \"zip64.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertThat(zipFileSystem.read(\"-\".toPath()) { readUtf8() })\n      .isEqualTo(\"Android\")\n  }\n\n  /**\n   * Confirm we can read zip files with a full-archive comment, even if this comment is not surfaced\n   * in our API.\n   *\n   * ```\n   * echo \"Android\" > a.txt\n   *\n   * zip \\\n   *   --archive-comment \\\n   *   zipWithArchiveComment.zip \\\n   *   a.txt\n   * ```\n   */\n  @Test\n  fun zipWithArchiveComment() {\n    val zipPath = base / \"zipWithArchiveComment.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertThat(zipFileSystem.read(\"a.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"Android\")\n  }\n\n  /**\n   * ```\n   * echo \"(...128 KiB...)\" > large_file.txt\n   *\n   * zip \\\n   *   --split-size \\\n   *   64k \\\n   *   cannotReadZipWithSpanning.zip \\\n   *   large_file.txt\n   * ```\n   */\n  @Test\n  fun cannotReadZipWithSpanning() {\n    // Spanned archives must be at least 64 KiB.\n    val zipPath = base / \"cannotReadZipWithSpanning.zip\"\n    assertFailsWith<IOException> {\n      fileSystem.openZip(zipPath)\n    }\n  }\n\n  /**\n   * ```\n   * echo \"Android\" > a.txt\n   *\n   * zip \\\n   *   --password \\\n   *   secret \\\n   *   cannotReadZipWithEncryption.zip \\\n   *   a.txt\n   * ```\n   */\n  @Test\n  fun cannotReadZipWithEncryption() {\n    val zipPath = base / \"cannotReadZipWithEncryption.zip\"\n    assertFailsWith<IOException> {\n      fileSystem.openZip(zipPath)\n    }\n  }\n\n  /**\n   * ```\n   * echo \"Android\" > a.txt\n   *\n   * zip \\\n   *   zipTooShort.zip \\\n   *   a.txt\n   * ```\n   */\n  @Test\n  fun zipTooShort() {\n    val zipPath = base / \"zipTooShort.zip\"\n\n    val prefix = fileSystem.read(zipPath) { readByteString(20) }\n    fileSystem.write(zipPath) { write(prefix) }\n\n    assertFailsWith<IOException> {\n      fileSystem.openZip(zipPath)\n    }\n  }\n\n  /**\n   * The zip format permits multiple files with the same names. For example,\n   * `kotlin-gradle-plugin-1.5.20.jar` contains two copies of\n   * `META-INF/kotlin-gradle-statistics.kotlin_module`.\n   *\n   * We used to crash on duplicates, but they are common in practice so now we prefer the last\n   * entry. This behavior is consistent with both `java.util.zip.ZipFile` and\n   * `java.nio.file.FileSystem`.\n   *\n   * ```\n   * echo \"This is the first hello.txt\" > hello.txt\n   *\n   * echo \"This is the second hello.txt\" > xxxxx.xxx\n   *\n   * zip \\\n   *   filesOverlap.zip \\\n   *   hello.txt \\\n   *   xxxxx.xxx\n   * ```\n   */\n  @Test\n  fun filesOverlap() {\n    val zipPath = base / \"filesOverlap.zip\"\n    val original = fileSystem.read(zipPath) { readByteString() }\n    val rewritten = original.replaceAll(\"xxxxx.xxx\".encodeUtf8(), \"hello.txt\".encodeUtf8())\n    fileSystem.write(zipPath) { write(rewritten) }\n\n    val zipFileSystem = fileSystem.openZip(zipPath)\n    assertThat(zipFileSystem.read(\"hello.txt\".toPath()) { readUtf8() })\n      .isEqualTo(\"This is the second hello.txt\")\n    assertThat(zipFileSystem.list(\"/\".toPath()))\n      .containsExactly(\"/hello.txt\".toPath())\n  }\n\n  /**\n   * ```\n   * echo \"Hello World\" > hello.txt\n   *\n   * mkdir -p directory\n   * echo \"Another file!\" > directory/child.txt\n   *\n   * zip \\\n   *   canonicalizationValid.zip \\\n   *   hello.txt \\\n   *   directory/child.txt\n   * ```\n   */\n  @Test\n  fun canonicalizationValid() {\n    val zipPath = base / \"canonicalizationValid.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertThat(zipFileSystem.canonicalize(\"/\".toPath())).isEqualTo(\"/\".toPath())\n    assertThat(zipFileSystem.canonicalize(\".\".toPath())).isEqualTo(\"/\".toPath())\n    assertThat(zipFileSystem.canonicalize(\"not/a/path/../../..\".toPath())).isEqualTo(\"/\".toPath())\n    assertThat(zipFileSystem.canonicalize(\"hello.txt\".toPath())).isEqualTo(\"/hello.txt\".toPath())\n    assertThat(zipFileSystem.canonicalize(\"stuff/../hello.txt\".toPath())).isEqualTo(\"/hello.txt\".toPath())\n    assertThat(zipFileSystem.canonicalize(\"directory\".toPath())).isEqualTo(\"/directory\".toPath())\n    assertThat(zipFileSystem.canonicalize(\"directory/whevs/..\".toPath())).isEqualTo(\"/directory\".toPath())\n    assertThat(zipFileSystem.canonicalize(\"directory/child.txt\".toPath())).isEqualTo(\"/directory/child.txt\".toPath())\n    assertThat(zipFileSystem.canonicalize(\"directory/whevs/../child.txt\".toPath())).isEqualTo(\"/directory/child.txt\".toPath())\n  }\n\n  /**\n   * ```\n   * echo \"Hello World\" > hello.txt\n   *\n   * mkdir -p directory\n   * echo \"Another file!\" > directory/child.txt\n   *\n   * zip \\\n   *   canonicalizationInvalidThrows.zip \\\n   *   hello.txt \\\n   *   directory/child.txt\n   * ```\n   */\n  @Test\n  fun canonicalizationInvalidThrows() {\n    val zipPath = base / \"canonicalizationInvalidThrows.zip\"\n    val zipFileSystem = fileSystem.openZip(zipPath)\n\n    assertFailsWith<FileNotFoundException> {\n      zipFileSystem.canonicalize(\"not/a/path\".toPath())\n    }\n  }\n}\n\nprivate fun ByteString.replaceAll(a: ByteString, b: ByteString): ByteString {\n  val buffer = Buffer()\n  buffer.write(this)\n  buffer.replace(a, b)\n  return buffer.readByteString()\n}\n\nprivate fun Buffer.replace(a: ByteString, b: ByteString) {\n  val result = Buffer()\n  while (!exhausted()) {\n    val index = indexOf(a)\n    if (index == -1L) {\n      result.writeAll(this)\n    } else {\n      result.write(this, index)\n      result.write(b)\n      skip(a.size.toLong())\n    }\n  }\n  writeAll(result)\n}\n\n/** Decodes this ISO8601 time string. */\nfun String.toEpochMillis() = Instant.parse(this).toEpochMilliseconds()\n"
  },
  {
    "path": "okio/src/zlibTest/kotlin/okio/internal/CRC32Test.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.internal\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass CRC32Test {\n  @Test fun happyPath() {\n    val crc32 = CRC32()\n    crc32.update(\"hello world!\".encodeToByteArray())\n    assertEquals(0x3B4C26D, crc32.getValue())\n  }\n\n  @Test fun multipleUpdates() {\n    val crc32 = CRC32()\n    crc32.update(\"hello \".encodeToByteArray())\n    crc32.update(\"world!\".encodeToByteArray())\n    assertEquals(0x3B4C26D, crc32.getValue())\n  }\n\n  @Test fun resetClearsState() {\n    val crc32 = CRC32()\n    crc32.update(\"unused\".encodeToByteArray())\n    crc32.reset()\n\n    crc32.update(\"hello \".encodeToByteArray())\n    crc32.update(\"world!\".encodeToByteArray())\n    assertEquals(0x3B4C26D, crc32.getValue())\n  }\n\n  @Test fun offsetAndByteCountAreHonored() {\n    val crc32 = CRC32()\n    crc32.update(\"well hello there\".encodeToByteArray(), 5, 6)\n    crc32.update(\"city! world! universe!\".encodeToByteArray(), 6, 6)\n    assertEquals(0x3B4C26D, crc32.getValue())\n  }\n\n  @Test fun emptyInput() {\n    val crc32 = CRC32()\n    assertEquals(0x0, crc32.getValue())\n  }\n}\n"
  },
  {
    "path": "okio/src/zlibTest/kotlin/okio/internal/DatePartsToEpochMillisTest.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.internal\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport okio.withUtc\n\nclass DatePartsToEpochMillisTest {\n  /**\n   * Test every day from 1970-01-01 (epochMillis = 0) until 2200-01-01. Note that this includes the\n   * full range of ZIP DOS dates (1980-01-01 until 2107-12-31).\n   */\n  @Test\n  fun everySingleDay() {\n    val dateTester = DateTester()\n    while (dateTester.year < 2200) {\n      dateTester.addDay()\n      dateTester.check()\n    }\n  }\n\n  /** Test the boundaries of the ZIP DOS date format. */\n  @Test\n  fun dosDateRange() {\n    assertEquals(\n      (365 * 10 + 2) * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1980, month = 1, day = 1),\n    )\n    assertEquals(\n      (365 * 138 + 33) * (24 * 60 * 60 * 1000L) - 1_000L,\n      datePartsToEpochMillisUtc(\n        year = 2107,\n        month = 12,\n        day = 31,\n        hour = 23,\n        minute = 59,\n        second = 59,\n      ),\n    )\n  }\n\n  @Test\n  fun monthOutOfBounds() {\n    // Month -21 is the same as March, 22 months ago.\n    assertEquals(\n      (-365 + -365 + 31 + 28) * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(month = -21, day = 1),\n    )\n\n    // Month -12 is the same as December, 13 months ago.\n    assertEquals(\n      (-365 + -31) * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = -12, day = 1),\n    )\n\n    // Month -11 is the same as January, 12 months ago.\n    assertEquals(\n      -365 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = -11, day = 1),\n    )\n\n    // Month -1 is the same as November, 2 months ago.\n    assertEquals(\n      (-31 + -30) * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = -1, day = 1),\n    )\n\n    // Month 0 is the same as December, 1 month ago.\n    assertEquals(\n      -31 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 0, day = 1),\n    )\n\n    // Month 13 is the same as January, 12 months from now.\n    assertEquals(\n      365 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 13, day = 1),\n    )\n\n    // Month 24 is the same as December, 23 months from now\n    assertEquals(\n      (365 + 365 - 31) * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 24, day = 1),\n    )\n\n    // Month 25 is the same as January, 24 months from now\n    assertEquals(\n      (365 + 365) * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 25, day = 1),\n    )\n  }\n\n  @Test\n  fun dayOutOfBounds() {\n    // Day -364 is the same as January 1 of the previous year.\n    assertEquals(\n      -365 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 1, day = -364),\n    )\n\n    // Day -1 is the same as December 30 of the previous year.\n    assertEquals(\n      -2 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 1, day = -1),\n    )\n\n    // Day 0 is the same as December 31 of the previous year.\n    assertEquals(\n      -1 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 1, day = 0),\n    )\n\n    // Day 32 is the same as February 1.\n    assertEquals(\n      31 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 1, day = 32),\n    )\n\n    // Day 33 is the same as February 2.\n    assertEquals(\n      32 * (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(year = 1970, month = 1, day = 33),\n    )\n  }\n\n  @Test\n  fun hourOutOfBounds() {\n    assertEquals(\n      (-24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(hour = -24),\n    )\n    assertEquals(\n      (-1 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(hour = -1),\n    )\n    assertEquals(\n      (24 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(hour = 24),\n    )\n    assertEquals(\n      (25 * 60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(hour = 25),\n    )\n  }\n\n  @Test\n  fun minuteOutOfBounds() {\n    assertEquals(\n      (-1 * 60 * 1000L),\n      datePartsToEpochMillisUtc(minute = -1),\n    )\n    assertEquals(\n      (60 * 60 * 1000L),\n      datePartsToEpochMillisUtc(minute = 60),\n    )\n    assertEquals(\n      (61 * 60 * 1000L),\n      datePartsToEpochMillisUtc(minute = 61),\n    )\n  }\n\n  @Test\n  fun secondOutOfBounds() {\n    assertEquals(\n      (-1 * 1000L),\n      datePartsToEpochMillisUtc(hour = 0, second = -1),\n    )\n    assertEquals(\n      (60 * 1000L),\n      datePartsToEpochMillisUtc(hour = 0, second = 60),\n    )\n    assertEquals(\n      (61 * 1000L),\n      datePartsToEpochMillisUtc(hour = 0, second = 61),\n    )\n  }\n\n  private class DateTester {\n    var epochMillis = 0L\n    var year = 1970\n    var month = 1\n    var day = 1\n\n    fun addDay() {\n      day++\n      epochMillis += 24L * 60 * 60 * 1000\n\n      val monthSize = when (month) {\n        1 -> 31\n        2 -> {\n          when {\n            year % 400 == 0 -> 29\n            year % 100 == 0 -> 28\n            year % 4 == 0 -> 29\n            else -> 28\n          }\n        }\n\n        3 -> 31\n        4 -> 30\n        5 -> 31\n        6 -> 30\n        7 -> 31\n        8 -> 31\n        9 -> 30\n        10 -> 31\n        11 -> 30\n        12 -> 31\n        else -> error(\"unexpected month $month\")\n      }\n\n      if (day > monthSize) {\n        day -= monthSize\n        month++\n        if (month > 12) {\n          month -= 12\n          year++\n        }\n      }\n    }\n\n    fun check() {\n      assertEquals(\n        expected = epochMillis,\n        actual = datePartsToEpochMillisUtc(\n          year = year,\n          month = month,\n          day = day,\n        ),\n        message = \"y=$year m=$month d=$day\",\n      )\n    }\n  }\n}\n\nfun datePartsToEpochMillisUtc(\n  year: Int = 1970,\n  month: Int = 1,\n  day: Int = 1,\n  hour: Int = 0,\n  minute: Int = 0,\n  second: Int = 0,\n): Long {\n  return withUtc {\n    datePartsToEpochMillis(year, month, day, hour, minute, second)\n  }\n}\n"
  },
  {
    "path": "okio-assetfilesystem/README.md",
    "content": "Okio Asset File System\n----------------------\n\nThis module contains a `FileSystem` implementation for\nan Android application's `assets/` contents.\n"
  },
  {
    "path": "okio-assetfilesystem/api/okio-assetfilesystem.api",
    "content": "public final class okio/assetfilesystem/AssetFileSystemKt {\n\tpublic static final fun asFileSystem (Landroid/content/res/AssetManager;)Lokio/FileSystem;\n}\n\n"
  },
  {
    "path": "okio-assetfilesystem/build.gradle.kts",
    "content": "import com.vanniktech.maven.publish.AndroidSingleVariantLibrary\nimport com.vanniktech.maven.publish.MavenPublishBaseExtension\n\nplugins {\n  id(\"com.android.library\")\n  id(\"org.jetbrains.dokka\")\n  id(\"com.vanniktech.maven.publish.base\")\n  id(\"binary-compatibility-validator\")\n  id(\"build-support\")\n}\n\nandroid {\n  namespace = \"okio.assetfilesystem\"\n  compileSdk = 33\n\n  defaultConfig {\n    minSdk = 14\n\n    testInstrumentationRunner = \"androidx.test.runner.AndroidJUnitRunner\"\n  }\n\n  compileOptions {\n    sourceCompatibility = JavaVersion.VERSION_1_8\n    targetCompatibility = JavaVersion.VERSION_1_8\n  }\n}\n\ndependencies {\n  api(projects.okio)\n\n  androidTestImplementation(libs.androidx.test.runner)\n  androidTestImplementation(libs.kotlin.test)\n  androidTestImplementation(libs.test.assertk)\n}\n\nconfigure<MavenPublishBaseExtension> {\n  configure(\n    AndroidSingleVariantLibrary()\n  )\n}\n"
  },
  {
    "path": "okio-assetfilesystem/src/androidTest/assets/dir/nested.txt",
    "content": "Nested!\n"
  },
  {
    "path": "okio-assetfilesystem/src/androidTest/assets/file.txt",
    "content": "File!\n"
  },
  {
    "path": "okio-assetfilesystem/src/androidTest/assets/moby10b.txt",
    "content": "**The Project Gutenberg Etext of Moby Dick, by Herman Melville**\n#3 in our series by Herman Melville\n\nThis Project Gutenberg version of Moby Dick is based on a combination\nof the etext from the ERIS project at Virginia Tech and another from\nProject Gutenberg's archives, as compared to a public-domain hard copy.\n\nCopyright laws are changing all over the world, be sure to check\nthe copyright laws for your country before posting these files!!\n\nPlease take a look at the important information in this header.\nWe encourage you to keep this file on your own disk, keeping an\nelectronic path open for the next readers.  Do not remove this.\n\n\n**Welcome To The World of Free Plain Vanilla Electronic Texts**\n\n**Etexts Readable By Both Humans and By Computers, Since 1971**\n\n*These Etexts Prepared By Hundreds of Volunteers and Donations*\n\nInformation on contacting Project Gutenberg to get Etexts, and\nfurther information is included below.  We need your donations.\n\n\nTitle:  Moby Dick; or The Whale\n\nAuthor:  Herman Melville\n\nJune, 2001  [Etext #2701]\n\n**The Project Gutenberg Etext of Moby Dick, by Herman Melville**\n******This file should be named moby10b.txt or moby10b.zip******\n\nCorrected EDITIONS of our etexts get a new NUMBER, moby11b.txt\nVERSIONS based on separate sources get new LETTER, moby10c.txt\n\nThis etext was prepared by Daniel Lazarus and Jonesey\n\nProject Gutenberg Etexts are usually created from multiple editions,\nall of which are in the Public Domain in the United States, unless a\ncopyright notice is included.  Therefore, we usually do NOT keep any\nof these books in compliance with any particular paper edition.\n\n\nWe are now trying to release all our books one month in advance\nof the official release dates, leaving time for better editing.\n\nPlease note:  neither this list nor its contents are final till\nmidnight of the last day of the month of any such announcement.\nThe official release date of all Project Gutenberg Etexts is at\nMidnight, Central Time, of the last day of the stated month.  A\npreliminary version may often be posted for suggestion, comment\nand editing by those who wish to do so.  To be sure you have an\nup to date first edition [xxxxx10x.xxx] please check file sizes\nin the first week of the next month.  Since our ftp program has\na bug in it that scrambles the date [tried to fix and failed] a\nlook at the file size will have to do, but we will try to see a\nnew copy has at least one byte more or less.\n\n\nInformation about Project Gutenberg (one page)\n\nWe produce about two million dollars for each hour we work.  The\ntime it takes us, a rather conservative estimate, is fifty hours\nto get any etext selected, entered, proofread, edited, copyright\nsearched and analyzed, the copyright letters written, etc.  This\nprojected audience is one hundred million readers.  If our value\nper text is nominally estimated at one dollar then we produce $2\nmillion dollars per hour this year as we release thirty-six text\nfiles per month, or 432 more Etexts in 1999 for a total of 2000+\nIf these reach just 10% of the computerized population, then the\ntotal should reach over 200 billion Etexts given away this year.\n\nThe Goal of Project Gutenberg is to Give Away One Trillion Etext\nFiles by December 31, 2001.  [10,000 x 100,000,000 = 1 Trillion]\nThis is ten thousand titles each to one hundred million readers,\nwhich is only ~5% of the present number of computer users.\n\nAt our revised rates of production, we will reach only one-third\nof that goal by the end of 2001, or about 3,333 Etexts unless we\nmanage to get some real funding; currently our funding is mostly\nfrom Michael Hart's salary at Carnegie-Mellon University, and an\nassortment of sporadic gifts; this salary is only good for a few\nmore years, so we are looking for something to replace it, as we\ndon't want Project Gutenberg to be so dependent on one person.\n\nWe need your donations more than ever!\n\n\nAll donations should be made to \"Project Gutenberg/CMU\": and are\ntax deductible to the extent allowable by law.  (CMU = Carnegie-\nMellon University).\n\nFor these and other matters, please mail to:\n\nProject Gutenberg\nP. O. Box  2782\nChampaign, IL 61825\n\nWhen all other email fails. . .try our Executive Director:\nMichael S. Hart <hart@pobox.com>\nhart@pobox.com forwards to hart@prairienet.org and archive.org\nif your mail bounces from archive.org, I will still see it, if\nit bounces from prairienet.org, better resend later on. . . .\n\nWe would prefer to send you this information by email.\n\n******\n\nTo access Project Gutenberg etexts, use any Web browser\nto view http://promo.net/pg.  This site lists Etexts by\nauthor and by title, and includes information about how\nto get involved with Project Gutenberg.  You could also\ndownload our past Newsletters, or subscribe here.  This\nis one of our major sites, please email hart@pobox.com,\nfor a more complete list of our various sites.\n\nTo go directly to the etext collections, use FTP or any\nWeb browser to visit a Project Gutenberg mirror (mirror\nsites are available on 7 continents; mirrors are listed\nat http://promo.net/pg).\n\nMac users, do NOT point and click, typing works better.\n\nExample FTP session:\n\nftp sunsite.unc.edu\nlogin: anonymous\npassword: your@login\ncd pub/docs/books/gutenberg\ncd etext90 through etext99\ndir [to see files]\nget or mget [to get files. . .set bin for zip files]\nGET GUTINDEX.??  [to get a year's listing of books, e.g., GUTINDEX.99]\nGET GUTINDEX.ALL [to get a listing of ALL books]\n\n***\n\n**Information prepared by the Project Gutenberg legal advisor**\n\n(Three Pages)\n\n\n***START**THE SMALL PRINT!**FOR PUBLIC DOMAIN ETEXTS**START***\nWhy is this \"Small Print!\" statement here?  You know: lawyers.\nThey tell us you might sue us if there is something wrong with\nyour copy of this etext, even if you got it for free from\nsomeone other than us, and even if what's wrong is not our\nfault.  So, among other things, this \"Small Print!\" statement\ndisclaims most of our liability to you.  It also tells you how\nyou can distribute copies of this etext if you want to.\n\n*BEFORE!* YOU USE OR READ THIS ETEXT\nBy using or reading any part of this PROJECT GUTENBERG-tm\netext, you indicate that you understand, agree to and accept\nthis \"Small Print!\" statement.  If you do not, you can receive\na refund of the money (if any) you paid for this etext by\nsending a request within 30 days of receiving it to the person\nyou got it from.  If you received this etext on a physical\nmedium (such as a disk), you must return it with your request.\n\nABOUT PROJECT GUTENBERG-TM ETEXTS\nThis PROJECT GUTENBERG-tm etext, like most PROJECT GUTENBERG-\ntm etexts, is a \"public domain\" work distributed by Professor\nMichael S. Hart through the Project Gutenberg Association at\nCarnegie-Mellon University (the \"Project\").  Among other\nthings, this means that no one owns a United States copyright\non or for this work, so the Project (and you!) can copy and\ndistribute it in the United States without permission and\nwithout paying copyright royalties.  Special rules, set forth\nbelow, apply if you wish to copy and distribute this etext\nunder the Project's \"PROJECT GUTENBERG\" trademark.\n\nTo create these etexts, the Project expends considerable\nefforts to identify, transcribe and proofread public domain\nworks.  Despite these efforts, the Project's etexts and any\nmedium they may be on may contain \"Defects\".  Among other\nthings, Defects may take the form of incomplete, inaccurate or\ncorrupt data, transcription errors, a copyright or other\nintellectual property infringement, a defective or damaged\ndisk or other etext medium, a computer virus, or computer\ncodes that damage or cannot be read by your equipment.\n\nLIMITED WARRANTY; DISCLAIMER OF DAMAGES\nBut for the \"Right of Replacement or Refund\" described below,\n[1] the Project (and any other party you may receive this\netext from as a PROJECT GUTENBERG-tm etext) disclaims all\nliability to you for damages, costs and expenses, including\nlegal fees, and [2] YOU HAVE NO REMEDIES FOR NEGLIGENCE OR\nUNDER STRICT LIABILITY, OR FOR BREACH OF WARRANTY OR CONTRACT,\nINCLUDING BUT NOT LIMITED TO INDIRECT, CONSEQUENTIAL, PUNITIVE\nOR INCIDENTAL DAMAGES, EVEN IF YOU GIVE NOTICE OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\nIf you discover a Defect in this etext within 90 days of\nreceiving it, you can receive a refund of the money (if any)\nyou paid for it by sending an explanatory note within that\ntime to the person you received it from.  If you received it\non a physical medium, you must return it with your note, and\nsuch person may choose to alternatively give you a replacement\ncopy.  If you received it electronically, such person may\nchoose to alternatively give you a second opportunity to\nreceive it electronically.\n\nTHIS ETEXT IS OTHERWISE PROVIDED TO YOU \"AS-IS\".  NO OTHER\nWARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, ARE MADE TO YOU AS\nTO THE ETEXT OR ANY MEDIUM IT MAY BE ON, INCLUDING BUT NOT\nLIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A\nPARTICULAR PURPOSE.\n\nSome states do not allow disclaimers of implied warranties or\nthe exclusion or limitation of consequential damages, so the\nabove disclaimers and exclusions may not apply to you, and you\nmay have other legal rights.\n\nINDEMNITY\nYou will indemnify and hold the Project, its directors,\nofficers, members and agents harmless from all liability, cost\nand expense, including legal fees, that arise directly or\nindirectly from any of the following that you do or cause:\n[1] distribution of this etext, [2] alteration, modification,\nor addition to the etext, or [3] any Defect.\n\nDISTRIBUTION UNDER \"PROJECT GUTENBERG-tm\"\nYou may distribute copies of this etext electronically, or by\ndisk, book or any other medium if you either delete this\n\"Small Print!\" and all other references to Project Gutenberg,\nor:\n\n[1]  Only give exact copies of it.  Among other things, this\n     requires that you do not remove, alter or modify the\n     etext or this \"small print!\" statement.  You may however,\n     if you wish, distribute this etext in machine readable\n     binary, compressed, mark-up, or proprietary form,\n     including any form resulting from conversion by word pro-\n     cessing or hypertext software, but only so long as\n     *EITHER*:\n\n     [*]  The etext, when displayed, is clearly readable, and\n          does *not* contain characters other than those\n          intended by the author of the work, although tilde\n          (~), asterisk (*) and underline (_) characters may\n          be used to convey punctuation intended by the\n          author, and additional characters may be used to\n          indicate hypertext links; OR\n\n     [*]  The etext may be readily converted by the reader at\n          no expense into plain ASCII, EBCDIC or equivalent\n          form by the program that displays the etext (as is\n          the case, for instance, with most word processors);\n          OR\n\n     [*]  You provide, or agree to also provide on request at\n          no additional cost, fee or expense, a copy of the\n          etext in its original plain ASCII form (or in EBCDIC\n          or other equivalent proprietary form).\n\n[2]  Honor the etext refund and replacement provisions of this\n     \"Small Print!\" statement.\n\n[3]  Pay a trademark license fee to the Project of 20% of the\n     net profits you derive calculated using the method you\n     already use to calculate your applicable taxes.  If you\n     don't derive profits, no royalty is due.  Royalties are\n     payable to \"Project Gutenberg Association/Carnegie-Mellon\n     University\" within the 60 days following each\n     date you prepare (or were legally required to prepare)\n     your annual (or equivalent periodic) tax return.\n\nWHAT IF YOU *WANT* TO SEND MONEY EVEN IF YOU DON'T HAVE TO?\nThe Project gratefully accepts contributions in money, time,\nscanning machines, OCR software, public domain etexts, royalty\nfree copyright licenses, and every other sort of contribution\nyou can think of.  Money should be paid to \"Project Gutenberg\nAssociation / Carnegie-Mellon University\".\n\nWe are planning on making some changes in our donation structure\nin 2000, so you might want to email me, hart@pobox.com beforehand.\n\n\n\n\n*END THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*\n\n\n\n\n\nThis etext was prepared by Daniel Lazarus and Jonesey\n\n\n\n\n\nNotes on this etext of Moby Dick:\n\nThis text is a combination of etexts, one from the now-defunct ERIS\nproject at Virginia Tech and one from Project Gutenberg's archives.\nThe proofreaders of this version are indebted to The University of\nAdelaide Library for preserving the Virginia Tech version.  The\nresulting etext was compared with a public domain hard copy version of\nthe text.\n\nIn chapters 24, 89, and 90, we substituted a capital L for the symbol\nfor the British pound, a unit of currency.\n\n\n\n\n\nMOBY DICK; OR THE WHALE \n\nby Herman Melville\n\n\n\n\nETYMOLOGY.\n\n(Supplied by a Late Consumptive Usher to a Grammar School)\n\nThe pale Usher--threadbare in coat, heart, body, and brain; I see him\nnow.  He was ever dusting his old lexicons and grammars, with a queer\nhandkerchief, mockingly embellished with all the gay flags of all the\nknown nations of the world.  He loved to dust his old grammars; it\nsomehow mildly reminded him of his mortality.\n\n\"While you take in hand to school others, and to teach them by what\nname a whale-fish is to be called in our tongue leaving out, through\nignorance, the letter H, which almost alone maketh the signification\nof the word, you deliver that which is not true.\" --HACKLUYT\n\n\"WHALE. ... Sw. and Dan. HVAL.  This animal is named from roundness\nor rolling; for in Dan. HVALT is arched or vaulted.\" --WEBSTER'S\nDICTIONARY\n\n\"WHALE. ... It is more immediately from the Dut. and Ger. WALLEN;\nA.S. WALW-IAN, to roll, to wallow.\" --RICHARDSON'S DICTIONARY\n\nKETOS,               GREEK.\nCETUS,               LATIN.\nWHOEL,               ANGLO-SAXON.\nHVALT,               DANISH.\nWAL,                 DUTCH.\nHWAL,                SWEDISH.\nWHALE,               ICELANDIC.\nWHALE,               ENGLISH.\nBALEINE,             FRENCH.\nBALLENA,             SPANISH.\nPEKEE-NUEE-NUEE,     FEGEE.\nPEKEE-NUEE-NUEE,     ERROMANGOAN.\n\n\n\n\nEXTRACTS (Supplied by a Sub-Sub-Librarian).\n\nIt will be seen that this mere painstaking burrower and grub-worm of\na poor devil of a Sub-Sub appears to have gone through the long\nVaticans and street-stalls of the earth, picking up whatever random\nallusions to whales he could anyways find in any book whatsoever,\nsacred or profane.  Therefore you must not, in every case at least,\ntake the higgledy-piggledy whale statements, however authentic, in\nthese extracts, for veritable gospel cetology.  Far from it.  As\ntouching the ancient authors generally, as well as the poets here\nappearing, these extracts are solely valuable or entertaining, as\naffording a glancing bird's eye view of what has been promiscuously\nsaid, thought, fancied, and sung of Leviathan, by many nations and\ngenerations, including our own.\n\nSo fare thee well, poor devil of a Sub-Sub, whose commentator I am.\nThou belongest to that hopeless, sallow tribe which no wine of this\nworld will ever warm; and for whom even Pale Sherry would be too\nrosy-strong; but with whom one sometimes loves to sit, and feel\npoor-devilish, too; and grow convivial upon tears; and say to them\nbluntly, with full eyes and empty glasses, and in not altogether\nunpleasant sadness--Give it up, Sub-Subs!  For by how much the more\npains ye take to please the world, by so much the more shall ye for\never go thankless!  Would that I could clear out Hampton Court and\nthe Tuileries for ye!  But gulp down your tears and hie aloft to the\nroyal-mast with your hearts; for your friends who have gone before\nare clearing out the seven-storied heavens, and making refugees of\nlong-pampered Gabriel, Michael, and Raphael, against your coming.\nHere ye strike but splintered hearts together--there, ye shall strike\nunsplinterable glasses!\n\n\nEXTRACTS.\n\n\"And God created great whales.\" --GENESIS.\n\n\"Leviathan maketh a path to shine after him; One would think the deep\nto be hoary.\" --JOB.\n\n\"Now the Lord had prepared a great fish to swallow up Jonah.\"\n--JONAH.\n\n\"There go the ships; there is that Leviathan whom thou hast made to\nplay therein.\" --PSALMS.\n\n\"In that day, the Lord with his sore, and great, and strong sword,\nshall punish Leviathan the piercing serpent, even Leviathan that\ncrooked serpent; and he shall slay the dragon that is in the sea.\"\n--ISAIAH\n\n\"And what thing soever besides cometh within the chaos of this\nmonster's mouth, be it beast, boat, or stone, down it goes all\nincontinently that foul great swallow of his, and perisheth in the\nbottomless gulf of his paunch.\" --HOLLAND'S PLUTARCH'S MORALS.\n\n\"The Indian Sea breedeth the most and the biggest fishes that are:\namong which the Whales and Whirlpooles called Balaene, take up as\nmuch in length as four acres or arpens of land.\" --HOLLAND'S PLINY.\n\n\"Scarcely had we proceeded two days on the sea, when about sunrise a\ngreat many Whales and other monsters of the sea, appeared.  Among the\nformer, one was of a most monstrous size. ...  This came towards us,\nopen-mouthed, raising the waves on all sides, and beating the sea\nbefore him into a foam.\" --TOOKE'S LUCIAN.  \"THE TRUE HISTORY.\"\n\n\"He visited this country also with a view of catching horse-whales,\nwhich had bones of very great value for their teeth, of which he\nbrought some to the king. ...  The best whales were catched in his\nown country, of which some were forty-eight, some fifty yards long.\nHe said that he was one of six who had killed sixty in two days.\"\n--OTHER OR OCTHER'S VERBAL NARRATIVE TAKEN DOWN FROM HIS MOUTH BY\nKING ALFRED, A.D. 890.\n\n\"And whereas all the other things, whether beast or vessel, that\nenter into the dreadful gulf of this monster's (whale's) mouth, are\nimmediately lost and swallowed up, the sea-gudgeon retires into it in\ngreat security, and there sleeps.\" --MONTAIGNE.  --APOLOGY FOR\nRAIMOND SEBOND.\n\n\"Let us fly, let us fly!  Old Nick take me if is not Leviathan\ndescribed by the noble prophet Moses in the life of patient Job.\"\n--RABELAIS.\n\n\"This whale's liver was two cartloads.\" --STOWE'S ANNALS.\n\n\"The great Leviathan that maketh the seas to seethe like boiling\npan.\" --LORD BACON'S VERSION OF THE PSALMS.\n\n\"Touching that monstrous bulk of the whale or ork we have received\nnothing certain.  They grow exceeding fat, insomuch that an\nincredible quantity of oil will be extracted out of one whale.\"\n--IBID.  \"HISTORY OF LIFE AND DEATH.\"\n\n\"The sovereignest thing on earth is parmacetti for an inward bruise.\"\n--KING HENRY.\n\n\"Very like a whale.\" --HAMLET.\n\n\"Which to secure, no skill of leach's art\nMote him availle, but to returne againe\nTo his wound's worker, that with lowly dart,\nDinting his breast, had bred his restless paine,\nLike as the wounded whale to shore flies thro' the maine.\"\n--THE FAERIE QUEEN.\n\n\"Immense as whales, the motion of whose vast bodies can in a peaceful\ncalm trouble the ocean til it boil.\" --SIR WILLIAM DAVENANT.  PREFACE\nTO GONDIBERT.\n\n\"What spermacetti is, men might justly doubt, since the learned\nHosmannus in his work of thirty years, saith plainly, Nescio quid\nsit.\" --SIR T. BROWNE.  OF SPERMA CETI AND THE SPERMA CETI WHALE.\nVIDE HIS V. E.\n\n\"Like Spencer's Talus with his modern flail\nHe threatens ruin with his ponderous tail.\n...\nTheir fixed jav'lins in his side he wears,\nAnd on his back a grove of pikes appears.\" --WALLER'S BATTLE OF THE\nSUMMER ISLANDS.\n\n\"By art is created that great Leviathan, called a Commonwealth or\nState--(in Latin, Civitas) which is but an artificial man.\" --OPENING\nSENTENCE OF HOBBES'S LEVIATHAN.\n\n\"Silly Mansoul swallowed it without chewing, as if it had been a\nsprat in the mouth of a whale.\" --PILGRIM'S PROGRESS.\n\n\"That sea beast\nLeviathan, which God of all his works\nCreated hugest that swim the ocean stream.\" --PARADISE LOST.\n\n---\"There Leviathan,\nHugest of living creatures, in the deep\nStretched like a promontory sleeps or swims,\nAnd seems a moving land; and at his gills\nDraws in, and at his breath spouts out a sea.\" --IBID.\n\n\"The mighty whales which swim in a sea of water, and have a sea of\noil swimming in them.\" --FULLLER'S PROFANE AND HOLY STATE.\n\n\"So close behind some promontory lie\nThe huge Leviathan to attend their prey,\nAnd give no chance, but swallow in the fry,\nWhich through their gaping jaws mistake the way.\"\n--DRYDEN'S ANNUS MIRABILIS.\n\n\"While the whale is floating at the stern of the ship, they cut off\nhis head, and tow it with a boat as near the shore as it will come;\nbut it will be aground in twelve or thirteen feet water.\" --THOMAS\nEDGE'S TEN VOYAGES TO SPITZBERGEN, IN PURCHAS.\n\n\"In their way they saw many whales sporting in the ocean, and in\nwantonness fuzzing up the water through their pipes and vents, which\nnature has placed on their shoulders.\" --SIR T. HERBERT'S VOYAGES\nINTO ASIA AND AFRICA.  HARRIS COLL.\n\n\"Here they saw such huge troops of whales, that they were forced to\nproceed with a great deal of caution for fear they should run their\nship upon them.\" --SCHOUTEN'S SIXTH CIRCUMNAVIGATION.\n\n\"We set sail from the Elbe, wind N.E. in the ship called The\nJonas-in-the-Whale. ...  Some say the whale can't open his mouth, but\nthat is a fable. ...  They frequently climb up the masts to see\nwhether they can see a whale, for the first discoverer has a ducat\nfor his pains. ...  I was told of a whale taken near Shetland, that\nhad above a barrel of herrings in his belly. ...  One of our\nharpooneers told me that he caught once a whale in Spitzbergen that\nwas white all over.\" --A VOYAGE TO GREENLAND, A.D. 1671 HARRIS COLL.\n\n\"Several whales have come in upon this coast (Fife) Anno 1652, one\neighty feet in length of the whale-bone kind came in, which (as I was\ninformed), besides a vast quantity of oil, did afford 500 weight of\nbaleen.  The jaws of it stand for a gate in the garden of Pitferren.\"\n--SIBBALD'S FIFE AND KINROSS.\n\n\"Myself have agreed to try whether I can master and kill this\nSperma-ceti whale, for I could never hear of any of that sort that\nwas killed by any man, such is his fierceness and swiftness.\"\n--RICHARD STRAFFORD'S LETTER FROM THE BERMUDAS.  PHIL. TRANS.  A.D.\n1668.\n\n\"Whales in the sea God's voice obey.\" --N. E. PRIMER.\n\n\"We saw also abundance of large whales, there being more in those\nsouthern seas, as I may say, by a hundred to one; than we have to the\nnorthward of us.\" --CAPTAIN COWLEY'S VOYAGE ROUND THE GLOBE, A.D.\n1729.\n\n\"... and the breath of the whale is frequendy attended with such an\ninsupportable smell, as to bring on a disorder of the brain.\"\n--ULLOA'S SOUTH AMERICA.\n\n\"To fifty chosen sylphs of special note,\nWe trust the important charge, the petticoat.\nOft have we known that seven-fold fence to fail,\nTho' stuffed with hoops and armed with ribs of whale.\" --RAPE\nOF THE LOCK.\n\n\"If we compare land animals in respect to magnitude, with those that\ntake up their abode in the deep, we shall find they will appear\ncontemptible in the comparison.  The whale is doubtless the largest\nanimal in creation.\" --GOLDSMITH, NAT. HIST.\n\n\"If you should write a fable for little fishes, you would make them\nspeak like great wales.\" --GOLDSMITH TO JOHNSON.\n\n\"In the afternoon we saw what was supposed to be a rock, but it was\nfound to be a dead whale, which some Asiatics had killed, and were\nthen towing ashore.  They seemed to endeavor to conceal themselves\nbehind the whale, in order to avoid being seen by us.\" --COOK'S\nVOYAGES.\n\n\"The larger whales, they seldom venture to attack.  They stand in so\ngreat dread of some of them, that when out at sea they are afraid to\nmention even their names, and carry dung, lime-stone, juniper-wood,\nand some other articles of the same nature in their boats, in order\nto terrify and prevent their too near approach.\" --UNO VON TROIL'S\nLETTERS ON BANKS'S AND SOLANDER'S VOYAGE TO ICELAND IN 1772.\n\n\"The Spermacetti Whale found by the Nantuckois, is an active, fierce\nanimal, and requires vast address and boldness in the fishermen.\"\n--THOMAS JEFFERSON'S WHALE MEMORIAL TO THE FRENCH MINISTER IN 1778.\n\n\"And pray, sir, what in the world is equal to it?\" --EDMUND BURKE'S\nREFERENCE IN PARLIAMENT TO THE NANTUCKET WHALE-FISHERY.\n\n\"Spain--a great whale stranded on the shores of Europe.\" --EDMUND\nBURKE. (SOMEWHERE.)\n\n\"A tenth branch of the king's ordinary revenue, said to be grounded\non the consideration of his guarding and protecting the seas from\npirates and robbers, is the right to royal fish, which are whale and\nsturgeon.  And these, when either thrown ashore or caught near the\ncoast, are the property of the king.\" --BLACKSTONE.\n\n\"Soon to the sport of death the crews repair:\nRodmond unerring o'er his head suspends\nThe barbed steel, and every turn attends.\"\n--FALCONER'S SHIPWRECK.\n\n\"Bright shone the roofs, the domes, the spires,\nAnd rockets blew self driven,\nTo hang their momentary fire\nAround the vault of heaven.\n\n\"So fire with water to compare,\nThe ocean serves on high,\nUp-spouted by a whale in air,\nTo express unwieldy joy.\" --COWPER, ON THE QUEEN'S\nVISIT TO LONDON.\n\n\"Ten or fifteen gallons of blood are thrown out of the heart at a\nstroke, with immense velocity.\" --JOHN HUNTER'S ACCOUNT OF THE\nDISSECTION OF A WHALE.  (A SMALL SIZED ONE.)\n\n\"The aorta of a whale is larger in the bore than the main pipe of the\nwater-works at London Bridge, and the water roaring in its passage\nthrough that pipe is inferior in impetus and velocity to the blood\ngushing from the whale's heart.\" --PALEY'S THEOLOGY.\n\n\"The whale is a mammiferous animal without hind feet.\" --BARON\nCUVIER.\n\n\"In 40 degrees south, we saw Spermacetti Whales, but did not take any\ntill the first of May, the sea being then covered with them.\"\n--COLNETT'S VOYAGE FOR THE PURPOSE OF EXTENDING THE SPERMACETI WHALE\nFISHERY.\n\n\"In the free element beneath me swam,\nFloundered and dived, in play, in chace, in battle,\nFishes of every colour, form, and kind;\nWhich language cannot paint, and mariner\nHad never seen; from dread Leviathan\nTo insect millions peopling every wave:\nGather'd in shoals immense, like floating islands,\nLed by mysterious instincts through that waste\nAnd trackless region, though on every side\nAssaulted by voracious enemies,\nWhales, sharks, and monsters, arm'd in front or jaw,\nWith swords, saws, spiral horns, or hooked fangs.\"\n--MONTGOMERY'S WORLD BEFORE THE FLOOD.\n\n\"Io!  Paean!  Io! sing.\nTo the finny people's king.\nNot a mightier whale than this\nIn the vast Atlantic is;\nNot a fatter fish than he,\nFlounders round the Polar Sea.\" --CHARLES LAMB'S TRIUMPH OF THE\nWHALE.\n\n\"In the year 1690 some persons were on a high hill observing the\nwhales spouting and sporting with each other, when one observed:\nthere--pointing to the sea--is a green pasture where our children's\ngrand-children will go for bread.\" --OBED MACY'S HISTORY OF\nNANTUCKET.\n\n\"I built a cottage for Susan and myself and made a gateway in the\nform of a Gothic Arch, by setting up a whale's jaw bones.\"\n--HAWTHORNE'S TWICE TOLD TALES.\n\n\"She came to bespeak a monument for her first love, who had been\nkilled by a whale in the Pacific ocean, no less than forty years\nago.\" --IBID.\n\n\"No, Sir, 'tis a Right Whale,\" answered Tom; \"I saw his sprout; he\nthrew up a pair of as pretty rainbows as a Christian would wish to\nlook at.  He's a raal oil-butt, that fellow!\" --COOPER'S PILOT.\n\n\"The papers were brought in, and we saw in the Berlin Gazette that\nwhales had been introduced on the stage there.\" --ECKERMANN'S\nCONVERSATIONS WITH GOETHE.\n\n\"My God!  Mr. Chace, what is the matter?\"  I answered, \"we have been\nstove by a whale.\" --\"NARRATIVE OF THE SHIPWRECK OF THE WHALE SHIP\nESSEX OF NANTUCKET, WHICH WAS ATTACKED AND FINALLY DESTROYED BY A\nLARGE SPERM WHALE IN THE PACIFIC OCEAN.\"  BY OWEN CHACE OF NANTUCKET,\nFIRST MATE OF SAID VESSEL.  NEW YORK, 1821.\n\n\"A mariner sat in the shrouds one night,\nThe wind was piping free;\nNow bright, now dimmed, was the moonlight pale,\nAnd the phospher gleamed in the wake of the whale,\nAs it floundered in the sea.\" --ELIZABETH OAKES SMITH.\n\n\"The quantity of line withdrawn from the boats engaged in the capture\nof this one whale, amounted altogether to 10,440 yards or nearly six\nEnglish miles. ...\n\n\"Sometimes the whale shakes its tremendous tail in the air, which,\ncracking like a whip, resounds to the distance of three or four\nmiles.\" --SCORESBY.\n\n\"Mad with the agonies he endures from these fresh attacks, the\ninfuriated Sperm Whale rolls over and over; he rears his enormous\nhead, and with wide expanded jaws snaps at everything around him; he\nrushes at the boats with his head; they are propelled before him with\nvast swiftness, and sometimes utterly destroyed. ...  It is a matter\nof great astonishment that the consideration of the habits of so\ninteresting, and, in a commercial point of view, so important an\nanimal (as the Sperm Whale) should have been so entirely neglected,\nor should have excited so little curiosity among the numerous, and\nmany of them competent observers, that of late years, must have\npossessed the most abundant and the most convenient opportunities of\nwitnessing their habitudes.\" --THOMAS BEALE'S HISTORY OF THE SPERM\nWHALE, 1839.\n\n\"The Cachalot\" (Sperm Whale) \"is not only better armed than the True\nWhale\" (Greenland or Right Whale) \"in possessing a formidable weapon\nat either extremity of its body, but also more frequently displays a\ndisposition to employ these weapons offensively and in manner at once\nso artful, bold, and mischievous, as to lead to its being regarded as\nthe most dangerous to attack of all the known species of the whale\ntribe.\" --FREDERICK DEBELL BENNETT'S WHALING VOYAGE ROUND THE GLOBE,\n1840.\n\nOctober 13.  \"There she blows,\" was sung out from the mast-head.\n\"Where away?\" demanded the captain.\n\"Three points off the lee bow, sir.\"\n\"Raise up your wheel.  Steady!\"  \"Steady, sir.\"\n\"Mast-head ahoy!  Do you see that whale now?\"\n\"Ay ay, sir!  A shoal of Sperm Whales!  There she blows!  There she\nbreaches!\"\n\"Sing out! sing out every time!\"\n\"Ay Ay, sir!  There she blows! there--there--THAR she\nblows--bowes--bo-o-os!\"\n\"How far off?\"\n\"Two miles and a half.\"\n\"Thunder and lightning! so near!  Call all hands.\" --J. ROSS BROWNE'S\nETCHINGS OF A WHALING CRUIZE.  1846.\n\n\"The Whale-ship Globe, on board of which vessel occurred the horrid\ntransactions we are about to relate, belonged to the island of\nNantucket.\" --\"NARRATIVE OF THE GLOBE,\" BY LAY AND HUSSEY SURVIVORS.\nA.D. 1828.\n\nBeing once pursued by a whale which he had wounded, he parried the\nassault for some time with a lance; but the furious monster at length\nrushed on the boat; himself and comrades only being preserved by\nleaping into the water when they saw the onset was inevitable.\"\n--MISSIONARY JOURNAL OF TYERMAN AND BENNETT.\n\n\"Nantucket itself,\" said Mr. Webster, \"is a very striking and\npeculiar portion of the National interest.  There is a population of\neight or nine thousand persons living here in the sea, adding largely\nevery year to the National wealth by the boldest and most persevering\nindustry.\" --REPORT OF DANIEL WEBSTER'S SPEECH IN THE U.  S.  SENATE,\nON THE APPLICATION FOR THE ERECTION OF A BREAKWATER AT NANTUCKET.\n1828.\n\n\"The whale fell directly over him, and probably killed him in a\nmoment.\" --\"THE WHALE AND HIS CAPTORS, OR THE WHALEMAN'S ADVENTURES\nAND THE WHALE'S BIOGRAPHY, GATHERED ON THE HOMEWARD CRUISE OF THE\nCOMMODORE PREBLE.\"  BY REV. HENRY T. CHEEVER.\n\n\"If you make the least damn bit of noise,\" replied Samuel, \"I will\nsend you to hell.\" --LIFE OF SAMUEL COMSTOCK (THE MUTINEER), BY HIS\nBROTHER, WILLIAM COMSTOCK.  ANOTHER VERSION OF THE WHALE-SHIP GLOBE\nNARRATIVE.\n\n\"The voyages of the Dutch and English to the Northern Ocean, in\norder, if possible, to discover a passage through it to India, though\nthey failed of their main object, laid-open the haunts of the whale.\"\n--MCCULLOCH'S COMMERCIAL DICTIONARY.\n\n\"These things are reciprocal; the ball rebounds, only to bound\nforward again; for now in laying open the haunts of the whale, the\nwhalemen seem to have indirectly hit upon new clews to that same\nmystic North-West Passage.\" --FROM \"SOMETHING\" UNPUBLISHED.\n\n\"It is impossible to meet a whale-ship on the ocean without being\nstruck by her near appearance.  The vessel under short sail, with\nlook-outs at the mast-heads, eagerly scanning the wide expanse around\nthem, has a totally different air from those engaged in regular\nvoyage.\" --CURRENTS AND WHALING.  U.S. EX. EX.\n\n\"Pedestrians in the vicinity of London and elsewhere may recollect\nhaving seen large curved bones set upright in the earth, either to\nform arches over gateways, or entrances to alcoves, and they may\nperhaps have been told that these were the ribs of whales.\" --TALES\nOF A WHALE VOYAGER TO THE ARCTIC OCEAN.\n\n\"It was not till the boats returned from the pursuit of these whales,\nthat the whites saw their ship in bloody possession of the savages\nenrolled among the crew.\" --NEWSPAPER ACCOUNT OF THE TAKING AND\nRETAKING OF THE WHALE-SHIP HOBOMACK.\n\n\"It is generally well known that out of the crews of Whaling vessels\n(American) few ever return in the ships on board of which they\ndeparted.\" --CRUISE IN A WHALE BOAT.\n\n\"Suddenly a mighty mass emerged from the water, and shot up\nperpendicularly into the air.  It was the while.\" --MIRIAM COFFIN OR\nTHE WHALE FISHERMAN.\n\n\"The Whale is harpooned to be sure; but bethink you, how you would\nmanage a powerful unbroken colt, with the mere appliance of a rope\ntied to the root of his tail.\" --A CHAPTER ON WHALING IN RIBS AND\nTRUCKS.\n\n\"On one occasion I saw two of these monsters (whales) probably male\nand female, slowly swimming, one after the other, within less than a\nstone's throw of the shore\" (Terra Del Fuego), \"over which the beech\ntree extended its branches.\" --DARWIN'S VOYAGE OF A NATURALIST.\n\n\"'Stern all!' exclaimed the mate, as upon turning his head, he saw\nthe distended jaws of a large Sperm Whale close to the head of the\nboat, threatening it with instant destruction;--'Stern all, for your\nlives!'\" --WHARTON THE WHALE KILLER.\n\n\"So be cheery, my lads, let your hearts never fail,\nWhile the bold harpooneer is striking the whale!\" --NANTUCKET SONG.\n\n\"Oh, the rare old Whale, mid storm and gale\nIn his ocean home will be\nA giant in might, where might is right,\nAnd King of the boundless sea.\" --WHALE SONG.\n\n\n\nCHAPTER 1\n\nLoomings.\n\n\nCall me Ishmael.  Some years ago--never mind how long\nprecisely--having little or no money in my purse, and nothing\nparticular to interest me on shore, I thought I would sail about a\nlittle and see the watery part of the world.  It is a way I have of\ndriving off the spleen and regulating the circulation.  Whenever I\nfind myself growing grim about the mouth; whenever it is a damp,\ndrizzly November in my soul; whenever I find myself involuntarily\npausing before coffin warehouses, and bringing up the rear of every\nfuneral I meet; and especially whenever my hypos get such an upper\nhand of me, that it requires a strong moral principle to prevent me\nfrom deliberately stepping into the street, and methodically knocking\npeople's hats off--then, I account it high time to get to sea as soon\nas I can.  This is my substitute for pistol and ball.  With a\nphilosophical flourish Cato throws himself upon his sword; I quietly\ntake to the ship.  There is nothing surprising in this.  If they but\nknew it, almost all men in their degree, some time or other, cherish\nvery nearly the same feelings towards the ocean with me.\n\nThere now is your insular city of the Manhattoes, belted round by\nwharves as Indian isles by coral reefs--commerce surrounds it with\nher surf.  Right and left, the streets take you waterward.  Its\nextreme downtown is the battery, where that noble mole is washed by\nwaves, and cooled by breezes, which a few hours previous were out of\nsight of land.  Look at the crowds of water-gazers there.\n\nCircumambulate the city of a dreamy Sabbath afternoon.  Go from\nCorlears Hook to Coenties Slip, and from thence, by Whitehall,\nnorthward.  What do you see?--Posted like silent sentinels all around\nthe town, stand thousands upon thousands of mortal men fixed in ocean\nreveries.  Some leaning against the spiles; some seated upon the\npier-heads; some looking over the bulwarks of ships from China; some\nhigh aloft in the rigging, as if striving to get a still better\nseaward peep.  But these are all landsmen; of week days pent up in\nlath and plaster--tied to counters, nailed to benches, clinched to\ndesks.  How then is this?  Are the green fields gone?  What do they\nhere?\n\nBut look! here come more crowds, pacing straight for the water, and\nseemingly bound for a dive.  Strange!  Nothing will content them but\nthe extremest limit of the land; loitering under the shady lee of\nyonder warehouses will not suffice.  No.  They must get just as nigh\nthe water as they possibly can without falling in.  And there they\nstand--miles of them--leagues.  Inlanders all, they come from lanes\nand alleys, streets and avenues--north, east, south, and west.  Yet\nhere they all unite.  Tell me, does the magnetic virtue of the\nneedles of the compasses of all those ships attract them thither?\n\nOnce more.  Say you are in the country; in some high land of lakes.\nTake almost any path you please, and ten to one it carries you down\nin a dale, and leaves you there by a pool in the stream.  There is\nmagic in it.  Let the most absent-minded of men be plunged in his\ndeepest reveries--stand that man on his legs, set his feet a-going,\nand he will infallibly lead you to water, if water there be in all\nthat region.  Should you ever be athirst in the great American\ndesert, try this experiment, if your caravan happen to be supplied\nwith a metaphysical professor.  Yes, as every one knows, meditation\nand water are wedded for ever.\n\nBut here is an artist.  He desires to paint you the dreamiest,\nshadiest, quietest, most enchanting bit of romantic landscape in all\nthe valley of the Saco.  What is the chief element he employs?  There\nstand his trees, each with a hollow trunk, as if a hermit and a\ncrucifix were within; and here sleeps his meadow, and there sleep his\ncattle; and up from yonder cottage goes a sleepy smoke.  Deep into\ndistant woodlands winds a mazy way, reaching to overlapping spurs of\nmountains bathed in their hill-side blue.  But though the picture\nlies thus tranced, and though this pine-tree shakes down its sighs\nlike leaves upon this shepherd's head, yet all were vain, unless the\nshepherd's eye were fixed upon the magic stream before him.  Go visit\nthe Prairies in June, when for scores on scores of miles you wade\nknee-deep among Tiger-lilies--what is the one charm\nwanting?--Water--there is not a drop of water there!  Were Niagara\nbut a cataract of sand, would you travel your thousand miles to see\nit?  Why did the poor poet of Tennessee, upon suddenly receiving two\nhandfuls of silver, deliberate whether to buy him a coat, which he\nsadly needed, or invest his money in a pedestrian trip to Rockaway\nBeach?  Why is almost every robust healthy boy with a robust healthy\nsoul in him, at some time or other crazy to go to sea?  Why upon your\nfirst voyage as a passenger, did you yourself feel such a mystical\nvibration, when first told that you and your ship were now out of\nsight of land?  Why did the old Persians hold the sea holy?  Why did\nthe Greeks give it a separate deity, and own brother of Jove?  Surely\nall this is not without meaning.  And still deeper the meaning of\nthat story of Narcissus, who because he could not grasp the\ntormenting, mild image he saw in the fountain, plunged into it and\nwas drowned.  But that same image, we ourselves see in all rivers and\noceans.  It is the image of the ungraspable phantom of life; and this\nis the key to it all.\n\nNow, when I say that I am in the habit of going to sea whenever I\nbegin to grow hazy about the eyes, and begin to be over conscious of\nmy lungs, I do not mean to have it inferred that I ever go to sea as\na passenger.  For to go as a passenger you must needs have a purse,\nand a purse is but a rag unless you have something in it.  Besides,\npassengers get sea-sick--grow quarrelsome--don't sleep of nights--do\nnot enjoy themselves much, as a general thing;--no, I never go as a\npassenger; nor, though I am something of a salt, do I ever go to sea\nas a Commodore, or a Captain, or a Cook.  I abandon the glory and\ndistinction of such offices to those who like them.  For my part, I\nabominate all honourable respectable toils, trials, and tribulations\nof every kind whatsoever.  It is quite as much as I can do to take\ncare of myself, without taking care of ships, barques, brigs,\nschooners, and what not.  And as for going as cook,--though I confess\nthere is considerable glory in that, a cook being a sort of officer\non ship-board--yet, somehow, I never fancied broiling fowls;--though\nonce broiled, judiciously buttered, and judgmatically salted and\npeppered, there is no one who will speak more respectfully, not to\nsay reverentially, of a broiled fowl than I will.  It is out of the\nidolatrous dotings of the old Egyptians upon broiled ibis and roasted\nriver horse, that you see the mummies of those creatures in their\nhuge bake-houses the pyramids.\n\nNo, when I go to sea, I go as a simple sailor, right before the mast,\nplumb down into the forecastle, aloft there to the royal mast-head.\nTrue, they rather order me about some, and make me jump from spar to\nspar, like a grasshopper in a May meadow.  And at first, this sort of\nthing is unpleasant enough.  It touches one's sense of honour,\nparticularly if you come of an old established family in the land,\nthe Van Rensselaers, or Randolphs, or Hardicanutes.  And more than\nall, if just previous to putting your hand into the tar-pot, you have\nbeen lording it as a country schoolmaster, making the tallest boys\nstand in awe of you.  The transition is a keen one, I assure you,\nfrom a schoolmaster to a sailor, and requires a strong decoction of\nSeneca and the Stoics to enable you to grin and bear it.  But even\nthis wears off in time.\n\nWhat of it, if some old hunks of a sea-captain orders me to get a\nbroom and sweep down the decks?  What does that indignity amount to,\nweighed, I mean, in the scales of the New Testament?  Do you think\nthe archangel Gabriel thinks anything the less of me, because I\npromptly and respectfully obey that old hunks in that particular\ninstance?  Who ain't a slave?  Tell me that.  Well, then, however the\nold sea-captains may order me about--however they may thump and punch\nme about, I have the satisfaction of knowing that it is all right;\nthat everybody else is one way or other served in much the same\nway--either in a physical or metaphysical point of view, that is; and\nso the universal thump is passed round, and all hands should rub each\nother's shoulder-blades, and be content.\n\nAgain, I always go to sea as a sailor, because they make a point of\npaying me for my trouble, whereas they never pay passengers a single\npenny that I ever heard of.  On the contrary, passengers themselves\nmust pay.  And there is all the difference in the world between\npaying and being paid.  The act of paying is perhaps the most\nuncomfortable infliction that the two orchard thieves entailed upon\nus.  But BEING PAID,--what will compare with it?  The urbane activity\nwith which a man receives money is really marvellous, considering\nthat we so earnestly believe money to be the root of all earthly\nills, and that on no account can a monied man enter heaven.  Ah! how\ncheerfully we consign ourselves to perdition!\n\nFinally, I always go to sea as a sailor, because of the wholesome\nexercise and pure air of the fore-castle deck.  For as in this world,\nhead winds are far more prevalent than winds from astern (that is, if\nyou never violate the Pythagorean maxim), so for the most part the\nCommodore on the quarter-deck gets his atmosphere at second hand from\nthe sailors on the forecastle.  He thinks he breathes it first; but\nnot so.  In much the same way do the commonalty lead their leaders in\nmany other things, at the same time that the leaders little suspect\nit.  But wherefore it was that after having repeatedly smelt the sea\nas a merchant sailor, I should now take it into my head to go on a\nwhaling voyage; this the invisible police officer of the Fates, who\nhas the constant surveillance of me, and secretly dogs me, and\ninfluences me in some unaccountable way--he can better answer than\nany one else.  And, doubtless, my going on this whaling voyage,\nformed part of the grand programme of Providence that was drawn up a\nlong time ago.  It came in as a sort of brief interlude and solo\nbetween more extensive performances.  I take it that this part of the\nbill must have run something like this:\n\n\n\"GRAND CONTESTED ELECTION FOR THE PRESIDENCY OF THE UNITED STATES.\n\"WHALING VOYAGE BY ONE ISHMAEL.\n\"BLOODY BATTLE IN AFFGHANISTAN.\"\n\n\nThough I cannot tell why it was exactly that those stage managers,\nthe Fates, put me down for this shabby part of a whaling voyage, when\nothers were set down for magnificent parts in high tragedies, and\nshort and easy parts in genteel comedies, and jolly parts in\nfarces--though I cannot tell why this was exactly; yet, now that I\nrecall all the circumstances, I think I can see a little into the\nsprings and motives which being cunningly presented to me under\nvarious disguises, induced me to set about performing the part I did,\nbesides cajoling me into the delusion that it was a choice resulting\nfrom my own unbiased freewill and discriminating judgment.\n\nChief among these motives was the overwhelming idea of the great\nwhale himself.  Such a portentous and mysterious monster roused all\nmy curiosity.  Then the wild and distant seas where he rolled his\nisland bulk; the undeliverable, nameless perils of the whale; these,\nwith all the attending marvels of a thousand Patagonian sights and\nsounds, helped to sway me to my wish.  With other men, perhaps, such\nthings would not have been inducements; but as for me, I am tormented\nwith an everlasting itch for things remote.  I love to sail forbidden\nseas, and land on barbarous coasts.  Not ignoring what is good, I am\nquick to perceive a horror, and could still be social with it--would\nthey let me--since it is but well to be on friendly terms with all\nthe inmates of the place one lodges in.\n\nBy reason of these things, then, the whaling voyage was welcome; the\ngreat flood-gates of the wonder-world swung open, and in the wild\nconceits that swayed me to my purpose, two and two there floated into\nmy inmost soul, endless processions of the whale, and, mid most of\nthem all, one grand hooded phantom, like a snow hill in the air.\n\n\n\nCHAPTER 2\n\nThe Carpet-Bag.\n\n\nI stuffed a shirt or two into my old carpet-bag, tucked it under my\narm, and started for Cape Horn and the Pacific.  Quitting the good\ncity of old Manhatto, I duly arrived in New Bedford.  It was a\nSaturday night in December.  Much was I disappointed upon learning\nthat the little packet for Nantucket had already sailed, and that no\nway of reaching that place would offer, till the following Monday.\n\nAs most young candidates for the pains and penalties of whaling stop\nat this same New Bedford, thence to embark on their voyage, it may as\nwell be related that I, for one, had no idea of so doing.  For my\nmind was made up to sail in no other than a Nantucket craft, because\nthere was a fine, boisterous something about everything connected\nwith that famous old island, which amazingly pleased me.  Besides\nthough New Bedford has of late been gradually monopolising the\nbusiness of whaling, and though in this matter poor old Nantucket is\nnow much behind her, yet Nantucket was her great original--the Tyre\nof this Carthage;--the place where the first dead American whale was\nstranded.  Where else but from Nantucket did those aboriginal\nwhalemen, the Red-Men, first sally out in canoes to give chase to the\nLeviathan?  And where but from Nantucket, too, did that first\nadventurous little sloop put forth, partly laden with imported\ncobblestones--so goes the story--to throw at the whales, in order to\ndiscover when they were nigh enough to risk a harpoon from the\nbowsprit?\n\nNow having a night, a day, and still another night following before\nme in New Bedford, ere I could embark for my destined port, it\nbecame a matter of concernment where I was to eat and sleep\nmeanwhile.  It was a very dubious-looking, nay, a very dark and\ndismal night, bitingly cold and cheerless.  I knew no one in the\nplace.  With anxious grapnels I had sounded my pocket, and only\nbrought up a few pieces of silver,--So, wherever you go, Ishmael,\nsaid I to myself, as I stood in the middle of a dreary street\nshouldering my bag, and comparing the gloom towards the north with\nthe darkness towards the south--wherever in your wisdom you may\nconclude to lodge for the night, my dear Ishmael, be sure to inquire\nthe price, and don't be too particular.\n\nWith halting steps I paced the streets, and passed the sign of \"The\nCrossed Harpoons\"--but it looked too expensive and jolly there.\nFurther on, from the bright red windows of the \"Sword-Fish Inn,\"\nthere came such fervent rays, that it seemed to have melted the\npacked snow and ice from before the house, for everywhere else the\ncongealed frost lay ten inches thick in a hard, asphaltic\npavement,--rather weary for me, when I struck my foot against the\nflinty projections, because from hard, remorseless service the soles\nof my boots were in a most miserable plight.  Too expensive and\njolly, again thought I, pausing one moment to watch the broad glare\nin the street, and hear the sounds of the tinkling glasses within.\nBut go on, Ishmael, said I at last; don't you hear? get away from\nbefore the door; your patched boots are stopping the way.  So on I\nwent.  I now by instinct followed the streets that took me waterward,\nfor there, doubtless, were the cheapest, if not the cheeriest inns.\n\nSuch dreary streets! blocks of blackness, not houses, on either\nhand, and here and there a candle, like a candle moving about in a\ntomb.  At this hour of the night, of the last day of the week, that\nquarter of the town proved all but deserted.  But presently I came to\na smoky light proceeding from a low, wide building, the door of which\nstood invitingly open.  It had a careless look, as if it were meant\nfor the uses of the public; so, entering, the first thing I did was\nto stumble over an ash-box in the porch.  Ha! thought I, ha, as the\nflying particles almost choked me, are these ashes from that\ndestroyed city, Gomorrah?  But \"The Crossed Harpoons,\" and \"The\nSword-Fish?\"--this, then must needs be the sign of \"The Trap.\"\nHowever, I picked myself up and hearing a loud voice within, pushed\non and opened a second, interior door.\n\nIt seemed the great Black Parliament sitting in Tophet.  A hundred\nblack faces turned round in their rows to peer; and beyond, a black\nAngel of Doom was beating a book in a pulpit.  It was a negro church;\nand the preacher's text was about the blackness of darkness, and the\nweeping and wailing and teeth-gnashing there.  Ha, Ishmael, muttered\nI, backing out, Wretched entertainment at the sign of 'The Trap!'\n\nMoving on, I at last came to a dim sort of light not far from the\ndocks, and heard a forlorn creaking in the air; and looking up, saw a\nswinging sign over the door with a white painting upon it, faintly\nrepresenting a tall straight jet of misty spray, and these words\nunderneath--\"The Spouter Inn:--Peter Coffin.\"\n\nCoffin?--Spouter?--Rather ominous in that particular connexion,\nthought I.  But it is a common name in Nantucket, they say, and I\nsuppose this Peter here is an emigrant from there.  As the light\nlooked so dim, and the place, for the time, looked quiet enough, and\nthe dilapidated little wooden house itself looked as if it might have\nbeen carted here from the ruins of some burnt district, and as the\nswinging sign had a poverty-stricken sort of creak to it, I thought\nthat here was the very spot for cheap lodgings, and the best of pea\ncoffee.\n\nIt was a queer sort of place--a gable-ended old house, one side\npalsied as it were, and leaning over sadly.  It stood on a sharp\nbleak corner, where that tempestuous wind Euroclydon kept up a worse\nhowling than ever it did about poor Paul's tossed craft.  Euroclydon,\nnevertheless, is a mighty pleasant zephyr to any one in-doors, with\nhis feet on the hob quietly toasting for bed.  \"In judging of that\ntempestuous wind called Euroclydon,\" says an old writer--of whose\nworks I possess the only copy extant--\"it maketh a marvellous\ndifference, whether thou lookest out at it from a glass window where\nthe frost is all on the outside, or whether thou observest it from\nthat sashless window, where the frost is on both sides, and of which\nthe wight Death is the only glazier.\"  True enough, thought I, as\nthis passage occurred to my mind--old black-letter, thou reasonest\nwell.  Yes, these eyes are windows, and this body of mine is the\nhouse.  What a pity they didn't stop up the chinks and the crannies\nthough, and thrust in a little lint here and there.  But it's too\nlate to make any improvements now.  The universe is finished; the\ncopestone is on, and the chips were carted off a million years ago.\nPoor Lazarus there, chattering his teeth against the curbstone for\nhis pillow, and shaking off his tatters with his shiverings, he might\nplug up both ears with rags, and put a corn-cob into his mouth, and\nyet that would not keep out the tempestuous Euroclydon.  Euroclydon!\nsays old Dives, in his red silken wrapper--(he had a redder one\nafterwards) pooh, pooh!  What a fine frosty night; how Orion\nglitters; what northern lights!  Let them talk of their oriental\nsummer climes of everlasting conservatories; give me the privilege of\nmaking my own summer with my own coals.\n\nBut what thinks Lazarus?  Can he warm his blue hands by holding them\nup to the grand northern lights?  Would not Lazarus rather be in\nSumatra than here?  Would he not far rather lay him down lengthwise\nalong the line of the equator; yea, ye gods! go down to the fiery pit\nitself, in order to keep out this frost?\n\nNow, that Lazarus should lie stranded there on the curbstone before\nthe door of Dives, this is more wonderful than that an iceberg should\nbe moored to one of the Moluccas.  Yet Dives himself, he too lives\nlike a Czar in an ice palace made of frozen sighs, and being a\npresident of a temperance society, he only drinks the tepid tears of\norphans.\n\nBut no more of this blubbering now, we are going a-whaling, and there\nis plenty of that yet to come.  Let us scrape the ice from our\nfrosted feet, and see what sort of a place this \"Spouter\" may be.\n\n\n\nCHAPTER 3\n\nThe Spouter-Inn.\n\n\nEntering that gable-ended Spouter-Inn, you found yourself in a wide,\nlow, straggling entry with old-fashioned wainscots, reminding one of\nthe bulwarks of some condemned old craft.  On one side hung a very\nlarge oilpainting so thoroughly besmoked, and every way defaced,\nthat in the unequal crosslights by which you viewed it, it was only\nby diligent study and a series of systematic visits to it, and\ncareful inquiry of the neighbors, that you could any way arrive at an\nunderstanding of its purpose.  Such unaccountable masses of shades\nand shadows, that at first you almost thought some ambitious young\nartist, in the time of the New England hags, had endeavored to\ndelineate chaos bewitched.  But by dint of much and earnest\ncontemplation, and oft repeated ponderings, and especially by\nthrowing open the little window towards the back of the entry, you at\nlast come to the conclusion that such an idea, however wild, might\nnot be altogether unwarranted.\n\nBut what most puzzled and confounded you was a long, limber,\nportentous, black mass of something hovering in the centre of the\npicture over three blue, dim, perpendicular lines floating in a\nnameless yeast.  A boggy, soggy, squitchy picture truly, enough to\ndrive a nervous man distracted.  Yet was there a sort of indefinite,\nhalf-attained, unimaginable sublimity about it that fairly froze you\nto it, till you involuntarily took an oath with yourself to find out\nwhat that marvellous painting meant.  Ever and anon a bright, but,\nalas, deceptive idea would dart you through.--It's the Black Sea in a\nmidnight gale.--It's the unnatural combat of the four primal\nelements.--It's a blasted heath.--It's a Hyperborean winter\nscene.--It's the breaking-up of the icebound stream of Time.  But at\nlast all these fancies yielded to that one portentous something in\nthe picture's midst.  THAT once found out, and all the rest were\nplain.  But stop; does it not bear a faint resemblance to a gigantic\nfish? even the great leviathan himself?\n\nIn fact, the artist's design seemed this: a final theory of my own,\npartly based upon the aggregated opinions of many aged persons with\nwhom I conversed upon the subject.  The picture represents a\nCape-Horner in a great hurricane; the half-foundered ship weltering\nthere with its three dismantled masts alone visible; and an\nexasperated whale, purposing to spring clean over the craft, is in\nthe enormous act of impaling himself upon the three mast-heads.\n\nThe opposite wall of this entry was hung all over with a heathenish\narray of monstrous clubs and spears.  Some were thickly set with\nglittering teeth resembling ivory saws; others were tufted with knots\nof human hair; and one was sickle-shaped, with a vast handle sweeping\nround like the segment made in the new-mown grass by a long-armed\nmower.  You shuddered as you gazed, and wondered what monstrous\ncannibal and savage could ever have gone a death-harvesting with such\na hacking, horrifying implement.  Mixed with these were rusty old\nwhaling lances and harpoons all broken and deformed.  Some were\nstoried weapons.  With this once long lance, now wildly elbowed,\nfifty years ago did Nathan Swain kill fifteen whales between a\nsunrise and a sunset.  And that harpoon--so like a corkscrew now--was\nflung in Javan seas, and run away with by a whale, years afterwards\nslain off the Cape of Blanco.  The original iron entered nigh the\ntail, and, like a restless needle sojourning in the body of a man,\ntravelled full forty feet, and at last was found imbedded in the\nhump.\n\nCrossing this dusky entry, and on through yon low-arched way--cut\nthrough what in old times must have been a great central chimney with\nfireplaces all round--you enter the public room.  A still duskier\nplace is this, with such low ponderous beams above, and such old\nwrinkled planks beneath, that you would almost fancy you trod some\nold craft's cockpits, especially of such a howling night, when this\ncorner-anchored old ark rocked so furiously.  On one side stood a\nlong, low, shelf-like table covered with cracked glass cases, filled\nwith dusty rarities gathered from this wide world's remotest nooks.\nProjecting from the further angle of the room stands a dark-looking\nden--the bar--a rude attempt at a right whale's head.  Be that how it\nmay, there stands the vast arched bone of the whale's jaw, so wide, a\ncoach might almost drive beneath it.  Within are shabby shelves,\nranged round with old decanters, bottles, flasks; and in those jaws\nof swift destruction, like another cursed Jonah (by which name indeed\nthey called him), bustles a little withered old man, who, for their\nmoney, dearly sells the sailors deliriums and death.\n\nAbominable are the tumblers into which he pours his poison.  Though\ntrue cylinders without--within, the villanous green goggling glasses\ndeceitfully tapered downwards to a cheating bottom.  Parallel\nmeridians rudely pecked into the glass, surround these footpads'\ngoblets.  Fill to THIS mark, and your charge is but a penny; to THIS\na penny more; and so on to the full glass--the Cape Horn measure,\nwhich you may gulp down for a shilling.\n\nUpon entering the place I found a number of young seamen gathered\nabout a table, examining by a dim light divers specimens of\nSKRIMSHANDER.  I sought the landlord, and telling him I desired to be\naccommodated with a room, received for answer that his house was\nfull--not a bed unoccupied.  \"But avast,\" he added, tapping his\nforehead, \"you haint no objections to sharing a harpooneer's blanket,\nhave ye?  I s'pose you are goin' a-whalin', so you'd better get used\nto that sort of thing.\"\n\nI told him that I never liked to sleep two in a bed; that if I should\never do so, it would depend upon who the harpooneer might be, and\nthat if he (the landlord) really had no other place for me, and the\nharpooneer was not decidedly objectionable, why rather than wander\nfurther about a strange town on so bitter a night, I would put up\nwith the half of any decent man's blanket.\n\n\"I thought so.  All right; take a seat.  Supper?--you want supper?\nSupper'll be ready directly.\"\n\nI sat down on an old wooden settle, carved all over like a bench on\nthe Battery.  At one end a ruminating tar was still further adorning\nit with his jack-knife, stooping over and diligently working away at\nthe space between his legs.  He was trying his hand at a ship under\nfull sail, but he didn't make much headway, I thought.\n\nAt last some four or five of us were summoned to our meal in an\nadjoining room.  It was cold as Iceland--no fire at all--the landlord\nsaid he couldn't afford it.  Nothing but two dismal tallow candles,\neach in a winding sheet.  We were fain to button up our monkey\njackets, and hold to our lips cups of scalding tea with our half\nfrozen fingers.  But the fare was of the most substantial kind--not\nonly meat and potatoes, but dumplings; good heavens! dumplings for\nsupper!  One young fellow in a green box coat, addressed himself to\nthese dumplings in a most direful manner.\n\n\"My boy,\" said the landlord, \"you'll have the nightmare to a dead\nsartainty.\"\n\n\"Landlord,\" I whispered, \"that aint the harpooneer is it?\"\n\n\"Oh, no,\" said he, looking a sort of diabolically funny, \"the\nharpooneer is a dark complexioned chap.  He never eats dumplings, he\ndon't--he eats nothing but steaks, and he likes 'em rare.\"\n\n\"The devil he does,\" says I.  \"Where is that harpooneer?  Is he\nhere?\"\n\n\"He'll be here afore long,\" was the answer.\n\nI could not help it, but I began to feel suspicious of this \"dark\ncomplexioned\" harpooneer.  At any rate, I made up my mind that if it\nso turned out that we should sleep together, he must undress and get\ninto bed before I did.\n\nSupper over, the company went back to the bar-room, when, knowing not\nwhat else to do with myself, I resolved to spend the rest of the\nevening as a looker on.\n\nPresently a rioting noise was heard without.  Starting up, the\nlandlord cried, \"That's the Grampus's crew.  I seed her reported in\nthe offing this morning; a three years' voyage, and a full ship.\nHurrah, boys; now we'll have the latest news from the Feegees.\"\n\nA tramping of sea boots was heard in the entry; the door was flung\nopen, and in rolled a wild set of mariners enough.  Enveloped in\ntheir shaggy watch coats, and with their heads muffled in woollen\ncomforters, all bedarned and ragged, and their beards stiff with\nicicles, they seemed an eruption of bears from Labrador.  They had\njust landed from their boat, and this was the first house they\nentered.  No wonder, then, that they made a straight wake for the\nwhale's mouth--the bar--when the wrinkled little old Jonah, there\nofficiating, soon poured them out brimmers all round.  One complained\nof a bad cold in his head, upon which Jonah mixed him a pitch-like\npotion of gin and molasses, which he swore was a sovereign cure for\nall colds and catarrhs whatsoever, never mind of how long standing,\nor whether caught off the coast of Labrador, or on the weather side\nof an ice-island.\n\nThe liquor soon mounted into their heads, as it generally does even\nwith the arrantest topers newly landed from sea, and they began\ncapering about most obstreperously.\n\nI observed, however, that one of them held somewhat aloof, and though\nhe seemed desirous not to spoil the hilarity of his shipmates by his\nown sober face, yet upon the whole he refrained from making as much\nnoise as the rest.  This man interested me at once; and since the\nsea-gods had ordained that he should soon become my shipmate (though\nbut a sleeping-partner one, so far as this narrative is concerned),\nI will here venture upon a little description of him.  He stood full\nsix feet in height, with noble shoulders, and a chest like a\ncoffer-dam.  I have seldom seen such brawn in a man.  His face was\ndeeply brown and burnt, making his white teeth dazzling by the\ncontrast; while in the deep shadows of his eyes floated some\nreminiscences that did not seem to give him much joy.  His voice at\nonce announced that he was a Southerner, and from his fine stature, I\nthought he must be one of those tall mountaineers from the\nAlleghanian Ridge in Virginia.  When the revelry of his companions\nhad mounted to its height, this man slipped away unobserved, and I\nsaw no more of him till he became my comrade on the sea.  In a few\nminutes, however, he was missed by his shipmates, and being, it\nseems, for some reason a huge favourite with them, they raised a cry\nof \"Bulkington!  Bulkington! where's Bulkington?\" and darted out of\nthe house in pursuit of him.\n\nIt was now about nine o'clock, and the room seeming almost\nsupernaturally quiet after these orgies, I began to congratulate\nmyself upon a little plan that had occurred to me just previous to\nthe entrance of the seamen.\n\nNo man prefers to sleep two in a bed.  In fact, you would a good deal\nrather not sleep with your own brother.  I don't know how it is, but\npeople like to be private when they are sleeping.  And when it comes\nto sleeping with an unknown stranger, in a strange inn, in a strange\ntown, and that stranger a harpooneer, then your objections\nindefinitely multiply.  Nor was there any earthly reason why I as a\nsailor should sleep two in a bed, more than anybody else; for sailors\nno more sleep two in a bed at sea, than bachelor Kings do ashore.  To\nbe sure they all sleep together in one apartment, but you have your\nown hammock, and cover yourself with your own blanket, and sleep in\nyour own skin.\n\nThe more I pondered over this harpooneer, the more I abominated the\nthought of sleeping with him.  It was fair to presume that being a\nharpooneer, his linen or woollen, as the case might be, would not be\nof the tidiest, certainly none of the finest.  I began to twitch all\nover.  Besides, it was getting late, and my decent harpooneer ought\nto be home and going bedwards.  Suppose now, he should tumble in upon\nme at midnight--how could I tell from what vile hole he had been\ncoming?\n\n\"Landlord!  I've changed my mind about that harpooneer.--I shan't\nsleep with him.  I'll try the bench here.\"\n\n\"Just as you please; I'm sorry I cant spare ye a tablecloth for a\nmattress, and it's a plaguy rough board here\"--feeling of the knots\nand notches.  \"But wait a bit, Skrimshander; I've got a carpenter's\nplane there in the bar--wait, I say, and I'll make ye snug enough.\"\nSo saying he procured the plane; and with his old silk handkerchief\nfirst dusting the bench, vigorously set to planing away at my bed,\nthe while grinning like an ape.  The shavings flew right and left;\ntill at last the plane-iron came bump against an indestructible knot.\nThe landlord was near spraining his wrist, and I told him for\nheaven's sake to quit--the bed was soft enough to suit me, and I did\nnot know how all the planing in the world could make eider down of a\npine plank.  So gathering up the shavings with another grin, and\nthrowing them into the great stove in the middle of the room, he went\nabout his business, and left me in a brown study.\n\nI now took the measure of the bench, and found that it was a foot too\nshort; but that could be mended with a chair.  But it was a foot too\nnarrow, and the other bench in the room was about four inches higher\nthan the planed one--so there was no yoking them.  I then placed the\nfirst bench lengthwise along the only clear space against the wall,\nleaving a little interval between, for my back to settle down in.\nBut I soon found that there came such a draught of cold air over me\nfrom under the sill of the window, that this plan would never do at\nall, especially as another current from the rickety door met the one\nfrom the window, and both together formed a series of small\nwhirlwinds in the immediate vicinity of the spot where I had thought\nto spend the night.\n\nThe devil fetch that harpooneer, thought I, but stop, couldn't I\nsteal a march on him--bolt his door inside, and jump into his bed,\nnot to be wakened by the most violent knockings?  It seemed no bad\nidea; but upon second thoughts I dismissed it.  For who could tell\nbut what the next morning, so soon as I popped out of the room, the\nharpooneer might be standing in the entry, all ready to knock me\ndown!\n\nStill, looking round me again, and seeing no possible chance of\nspending a sufferable night unless in some other person's bed, I\nbegan to think that after all I might be cherishing unwarrantable\nprejudices against this unknown harpooneer.  Thinks I, I'll wait\nawhile; he must be dropping in before long.  I'll have a good look at\nhim then, and perhaps we may become jolly good bedfellows after\nall--there's no telling.\n\nBut though the other boarders kept coming in by ones, twos, and\nthrees, and going to bed, yet no sign of my harpooneer.\n\n\"Landlord! said I, \"what sort of a chap is he--does he always keep\nsuch late hours?\"  It was now hard upon twelve o'clock.\n\nThe landlord chuckled again with his lean chuckle, and seemed to be\nmightily tickled at something beyond my comprehension.  \"No,\" he\nanswered, \"generally he's an early bird--airley to bed and airley to\nrise--yes, he's the bird what catches the worm.  But to-night he\nwent out a peddling, you see, and I don't see what on airth keeps him\nso late, unless, may be, he can't sell his head.\"\n\n\"Can't sell his head?--What sort of a bamboozingly story is this you\nare telling me?\" getting into a towering rage.  \"Do you pretend to\nsay, landlord, that this harpooneer is actually engaged this blessed\nSaturday night, or rather Sunday morning, in peddling his head around\nthis town?\"\n\n\"That's precisely it,\" said the landlord, \"and I told him he couldn't\nsell it here, the market's overstocked.\"\n\n\"With what?\" shouted I.\n\n\"With heads to be sure; ain't there too many heads in the world?\"\n\n\"I tell you what it is, landlord,\" said I quite calmly, \"you'd better\nstop spinning that yarn to me--I'm not green.\"\n\n\"May be not,\" taking out a stick and whittling a toothpick, \"but I\nrayther guess you'll be done BROWN if that ere harpooneer hears you a\nslanderin' his head.\"\n\n\"I'll break it for him,\" said I, now flying into a passion again at\nthis unaccountable farrago of the landlord's.\n\n\"It's broke a'ready,\" said he.\n\n\"Broke,\" said I--\"BROKE, do you mean?\"\n\n\"Sartain, and that's the very reason he can't sell it, I guess.\"\n\n\"Landlord,\" said I, going up to him as cool as Mt. Hecla in a\nsnow-storm--\"landlord, stop whittling.  You and I must understand one\nanother, and that too without delay.  I come to your house and want a\nbed; you tell me you can only give me half a one; that the other half\nbelongs to a certain harpooneer.  And about this harpooneer, whom I\nhave not yet seen, you persist in telling me the most mystifying and\nexasperating stories tending to beget in me an uncomfortable feeling\ntowards the man whom you design for my bedfellow--a sort of\nconnexion, landlord, which is an intimate and confidential one in the\nhighest degree.  I now demand of you to speak out and tell me who and\nwhat this harpooneer is, and whether I shall be in all respects safe\nto spend the night with him.  And in the first place, you will be so\ngood as to unsay that story about selling his head, which if true I\ntake to be good evidence that this harpooneer is stark mad, and I've\nno idea of sleeping with a madman; and you, sir, YOU I mean,\nlandlord, YOU, sir, by trying to induce me to do so knowingly, would\nthereby render yourself liable to a criminal prosecution.\"\n\n\"Wall,\" said the landlord, fetching a long breath, \"that's a purty\nlong sarmon for a chap that rips a little now and then.  But be easy,\nbe easy, this here harpooneer I have been tellin' you of has just\narrived from the south seas, where he bought up a lot of 'balmed New\nZealand heads (great curios, you know), and he's sold all on 'em but\none, and that one he's trying to sell to-night, cause to-morrow's\nSunday, and it would not do to be sellin' human heads about the\nstreets when folks is goin' to churches.  He wanted to, last Sunday,\nbut I stopped him just as he was goin' out of the door with four\nheads strung on a string, for all the airth like a string of inions.\"\n\nThis account cleared up the otherwise unaccountable mystery, and\nshowed that the landlord, after all, had had no idea of fooling\nme--but at the same time what could I think of a harpooneer who\nstayed out of a Saturday night clean into the holy Sabbath, engaged\nin such a cannibal business as selling the heads of dead idolators?\n\n\"Depend upon it, landlord, that harpooneer is a dangerous man.\"\n\n\"He pays reg'lar,\" was the rejoinder.  \"But come, it's getting\ndreadful late, you had better be turning flukes--it's a nice bed;\nSal and me slept in that ere bed the night we were spliced.  There's\nplenty of room for two to kick about in that bed; it's an almighty\nbig bed that.  Why, afore we give it up, Sal used to put our Sam and\nlittle Johnny in the foot of it.  But I got a dreaming and sprawling\nabout one night, and somehow, Sam got pitched on the floor, and came\nnear breaking his arm.  Arter that, Sal said it wouldn't do.  Come\nalong here, I'll give ye a glim in a jiffy;\" and so saying he lighted\na candle and held it towards me, offering to lead the way.  But I\nstood irresolute; when looking at a clock in the corner, he exclaimed\n\"I vum it's Sunday--you won't see that harpooneer to-night; he's come\nto anchor somewhere--come along then; DO come; WON'T ye come?\"\n\nI considered the matter a moment, and then up stairs we went, and I\nwas ushered into a small room, cold as a clam, and furnished, sure\nenough, with a prodigious bed, almost big enough indeed for any four\nharpooneers to sleep abreast.\n\n\"There,\" said the landlord, placing the candle on a crazy old sea\nchest that did double duty as a wash-stand and centre table; \"there,\nmake yourself comfortable now, and good night to ye.\"  I turned\nround from eyeing the bed, but he had disappeared.\n\nFolding back the counterpane, I stooped over the bed.  Though none of\nthe most elegant, it yet stood the scrutiny tolerably well.  I then\nglanced round the room; and besides the bedstead and centre table,\ncould see no other furniture belonging to the place, but a rude\nshelf, the four walls, and a papered fireboard representing a man\nstriking a whale.  Of things not properly belonging to the room,\nthere was a hammock lashed up, and thrown upon the floor in one\ncorner; also a large seaman's bag, containing the harpooneer's\nwardrobe, no doubt in lieu of a land trunk.  Likewise, there was a\nparcel of outlandish bone fish hooks on the shelf over the\nfire-place, and a tall harpoon standing at the head of the bed.\n\nBut what is this on the chest?  I took it up, and held it close to\nthe light, and felt it, and smelt it, and tried every way possible to\narrive at some satisfactory conclusion concerning it.  I can compare\nit to nothing but a large door mat, ornamented at the edges with\nlittle tinkling tags something like the stained porcupine quills\nround an Indian moccasin.  There was a hole or slit in the middle of\nthis mat, as you see the same in South American ponchos.  But could\nit be possible that any sober harpooneer would get into a door mat,\nand parade the streets of any Christian town in that sort of guise?\nI put it on, to try it, and it weighed me down like a hamper, being\nuncommonly shaggy and thick, and I thought a little damp, as though\nthis mysterious harpooneer had been wearing it of a rainy day.  I\nwent up in it to a bit of glass stuck against the wall, and I never\nsaw such a sight in my life.  I tore myself out of it in such a hurry\nthat I gave myself a kink in the neck.\n\nI sat down on the side of the bed, and commenced thinking about this\nhead-peddling harpooneer, and his door mat.  After thinking some time\non the bed-side, I got up and took off my monkey jacket, and then\nstood in the middle of the room thinking.  I then took off my coat,\nand thought a little more in my shirt sleeves.  But beginning to feel\nvery cold now, half undressed as I was, and remembering what the\nlandlord said about the harpooneer's not coming home at all that\nnight, it being so very late, I made no more ado, but jumped out of\nmy pantaloons and boots, and then blowing out the light tumbled into\nbed, and commended myself to the care of heaven.\n\nWhether that mattress was stuffed with corn-cobs or broken crockery,\nthere is no telling, but I rolled about a good deal, and could not\nsleep for a long time.  At last I slid off into a light doze, and had\npretty nearly made a good offing towards the land of Nod, when I\nheard a heavy footfall in the passage, and saw a glimmer of light\ncome into the room from under the door.\n\nLord save me, thinks I, that must be the harpooneer, the infernal\nhead-peddler.  But I lay perfectly still, and resolved not to say a\nword till spoken to.  Holding a light in one hand, and that identical\nNew Zealand head in the other, the stranger entered the room, and\nwithout looking towards the bed, placed his candle a good way off\nfrom me on the floor in one corner, and then began working away at\nthe knotted cords of the large bag I before spoke of as being in the\nroom.  I was all eagerness to see his face, but he kept it averted\nfor some time while employed in unlacing the bag's mouth.  This\naccomplished, however, he turned round--when, good heavens! what a\nsight!  Such a face!  It was of a dark, purplish, yellow colour, here\nand there stuck over with large blackish looking squares.  Yes, it's\njust as I thought, he's a terrible bedfellow; he's been in a fight,\ngot dreadfully cut, and here he is, just from the surgeon.  But at\nthat moment he chanced to turn his face so towards the light, that I\nplainly saw they could not be sticking-plasters at all, those black\nsquares on his cheeks.  They were stains of some sort or other.  At\nfirst I knew not what to make of this; but soon an inkling of the\ntruth occurred to me.  I remembered a story of a white man--a\nwhaleman too--who, falling among the cannibals, had been tattooed by\nthem.  I concluded that this harpooneer, in the course of his distant\nvoyages, must have met with a similar adventure.  And what is it,\nthought I, after all!  It's only his outside; a man can be honest in\nany sort of skin.  But then, what to make of his unearthly\ncomplexion, that part of it, I mean, lying round about, and\ncompletely independent of the squares of tattooing.  To be sure, it\nmight be nothing but a good coat of tropical tanning; but I never\nheard of a hot sun's tanning a white man into a purplish yellow one.\nHowever, I had never been in the South Seas; and perhaps the sun\nthere produced these extraordinary effects upon the skin.  Now, while\nall these ideas were passing through me like lightning, this\nharpooneer never noticed me at all.  But, after some difficulty\nhaving opened his bag, he commenced fumbling in it, and presently\npulled out a sort of tomahawk, and a seal-skin wallet with the hair\non.  Placing these on the old chest in the middle of the room, he\nthen took the New Zealand head--a ghastly thing enough--and crammed\nit down into the bag.  He now took off his hat--a new beaver\nhat--when I came nigh singing out with fresh surprise.  There was no\nhair on his head--none to speak of at least--nothing but a small\nscalp-knot twisted up on his forehead.  His bald purplish head now\nlooked for all the world like a mildewed skull.  Had not the stranger\nstood between me and the door, I would have bolted out of it quicker\nthan ever I bolted a dinner.\n\nEven as it was, I thought something of slipping out of the window,\nbut it was the second floor back.  I am no coward, but what to make\nof this head-peddling purple rascal altogether passed my\ncomprehension.  Ignorance is the parent of fear, and being completely\nnonplussed and confounded about the stranger, I confess I was now as\nmuch afraid of him as if it was the devil himself who had thus broken\ninto my room at the dead of night.  In fact, I was so afraid of him\nthat I was not game enough just then to address him, and demand a\nsatisfactory answer concerning what seemed inexplicable in him.\n\nMeanwhile, he continued the business of undressing, and at last\nshowed his chest and arms.  As I live, these covered parts of him\nwere checkered with the same squares as his face; his back, too, was\nall over the same dark squares; he seemed to have been in a Thirty\nYears' War, and just escaped from it with a sticking-plaster shirt.\nStill more, his very legs were marked, as if a parcel of dark green\nfrogs were running up the trunks of young palms.  It was now quite\nplain that he must be some abominable savage or other shipped aboard\nof a whaleman in the South Seas, and so landed in this Christian\ncountry.  I quaked to think of it.  A peddler of heads too--perhaps\nthe heads of his own brothers.  He might take a fancy to\nmine--heavens! look at that tomahawk!\n\nBut there was no time for shuddering, for now the savage went about\nsomething that completely fascinated my attention, and convinced me\nthat he must indeed be a heathen.  Going to his heavy grego, or\nwrapall, or dreadnaught, which he had previously hung on a chair, he\nfumbled in the pockets, and produced at length a curious little\ndeformed image with a hunch on its back, and exactly the colour of a\nthree days' old Congo baby.  Remembering the embalmed head, at first\nI almost thought that this black manikin was a real baby preserved\nin some similar manner.  But seeing that it was not at all limber,\nand that it glistened a good deal like polished ebony, I concluded\nthat it must be nothing but a wooden idol, which indeed it proved to\nbe.  For now the savage goes up to the empty fire-place, and removing\nthe papered fire-board, sets up this little hunch-backed image, like\na tenpin, between the andirons.  The chimney jambs and all the bricks\ninside were very sooty, so that I thought this fire-place made a very\nappropriate little shrine or chapel for his Congo idol.\n\nI now screwed my eyes hard towards the half hidden image, feeling but\nill at ease meantime--to see what was next to follow.  First he takes\nabout a double handful of shavings out of his grego pocket, and\nplaces them carefully before the idol; then laying a bit of ship\nbiscuit on top and applying the flame from the lamp, he kindled the\nshavings into a sacrificial blaze.  Presently, after many hasty\nsnatches into the fire, and still hastier withdrawals of his fingers\n(whereby he seemed to be scorching them badly), he at last succeeded\nin drawing out the biscuit; then blowing off the heat and ashes a\nlittle, he made a polite offer of it to the little negro.  But the\nlittle devil did not seem to fancy such dry sort of fare at all; he\nnever moved his lips.  All these strange antics were accompanied by\nstill stranger guttural noises from the devotee, who seemed to be\npraying in a sing-song or else singing some pagan psalmody or other,\nduring which his face twitched about in the most unnatural manner.\nAt last extinguishing the fire, he took the idol up very\nunceremoniously, and bagged it again in his grego pocket as\ncarelessly as if he were a sportsman bagging a dead woodcock.\n\nAll these queer proceedings increased my uncomfortableness, and\nseeing him now exhibiting strong symptoms of concluding his business\noperations, and jumping into bed with me, I thought it was high time,\nnow or never, before the light was put out, to break the spell in\nwhich I had so long been bound.\n\nBut the interval I spent in deliberating what to say, was a fatal\none.  Taking up his tomahawk from the table, he examined the head of\nit for an instant, and then holding it to the light, with his mouth\nat the handle, he puffed out great clouds of tobacco smoke.  The next\nmoment the light was extinguished, and this wild cannibal, tomahawk\nbetween his teeth, sprang into bed with me.  I sang out, I could not\nhelp it now; and giving a sudden grunt of astonishment he began\nfeeling me.\n\nStammering out something, I knew not what, I rolled away from him\nagainst the wall, and then conjured him, whoever or whatever he might\nbe, to keep quiet, and let me get up and light the lamp again.  But\nhis guttural responses satisfied me at once that he but ill\ncomprehended my meaning.\n\n\"Who-e debel you?\"--he at last said--\"you no speak-e, dam-me, I\nkill-e.\"  And so saying the lighted tomahawk began flourishing about\nme in the dark.\n\n\"Landlord, for God's sake, Peter Coffin!\" shouted I.  \"Landlord!\nWatch!  Coffin!  Angels! save me!\"\n\n\"Speak-e! tell-ee me who-ee be, or dam-me, I kill-e!\" again growled\nthe cannibal, while his horrid flourishings of the tomahawk scattered\nthe hot tobacco ashes about me till I thought my linen would get on\nfire.  But thank heaven, at that moment the landlord came into the\nroom light in hand, and leaping from the bed I ran up to him.\n\n\"Don't be afraid now,\" said he, grinning again, \"Queequeg here\nwouldn't harm a hair of your head.\"\n\n\"Stop your grinning,\" shouted I, \"and why didn't you tell me that\nthat infernal harpooneer was a cannibal?\"\n\n\"I thought ye know'd it;--didn't I tell ye, he was a peddlin' heads\naround town?--but turn flukes again and go to sleep.  Queequeg, look\nhere--you sabbee me, I sabbee--you this man sleepe you--you sabbee?\"\n\n\"Me sabbee plenty\"--grunted Queequeg, puffing away at his pipe and\nsitting up in bed.\n\n\"You gettee in,\" he added, motioning to me with his tomahawk, and\nthrowing the clothes to one side.  He really did this in not only a\ncivil but a really kind and charitable way.  I stood looking at him a\nmoment.  For all his tattooings he was on the whole a clean, comely\nlooking cannibal.  What's all this fuss I have been making about,\nthought I to myself--the man's a human being just as I am: he has\njust as much reason to fear me, as I have to be afraid of him.\nBetter sleep with a sober cannibal than a drunken Christian.\n\n\"Landlord,\" said I, \"tell him to stash his tomahawk there, or pipe,\nor whatever you call it; tell him to stop smoking, in short, and I\nwill turn in with him.  But I don't fancy having a man smoking in bed\nwith me.  It's dangerous.  Besides, I ain't insured.\"\n\nThis being told to Queequeg, he at once complied, and again politely\nmotioned me to get into bed--rolling over to one side as much as to\nsay--I won't touch a leg of ye.\"\n\n\"Good night, landlord,\" said I, \"you may go.\"\n\nI turned in, and never slept better in my life.\n\n\n\nCHAPTER 4\n\nThe Counterpane.\n\n\nUpon waking next morning about daylight, I found Queequeg's arm\nthrown over me in the most loving and affectionate manner.  You had\nalmost thought I had been his wife.  The counterpane was of\npatchwork, full of odd little parti-coloured squares and triangles;\nand this arm of his tattooed all over with an interminable Cretan\nlabyrinth of a figure, no two parts of which were of one precise\nshade--owing I suppose to his keeping his arm at sea unmethodically\nin sun and shade, his shirt sleeves irregularly rolled up at various\ntimes--this same arm of his, I say, looked for all the world like a\nstrip of that same patchwork quilt.  Indeed, partly lying on it as\nthe arm did when I first awoke, I could hardly tell it from the\nquilt, they so blended their hues together; and it was only by the\nsense of weight and pressure that I could tell that Queequeg was\nhugging me.\n\nMy sensations were strange.  Let me try to explain them.  When I was\na child, I well remember a somewhat similar circumstance that befell\nme; whether it was a reality or a dream, I never could entirely\nsettle.  The circumstance was this.  I had been cutting up some caper\nor other--I think it was trying to crawl up the chimney, as I had\nseen a little sweep do a few days previous; and my stepmother who,\nsomehow or other, was all the time whipping me, or sending me to bed\nsupperless,--my mother dragged me by the legs out of the chimney and\npacked me off to bed, though it was only two o'clock in the afternoon\nof the 21st June, the longest day in the year in our hemisphere.  I\nfelt dreadfully.  But there was no help for it, so up stairs I went\nto my little room in the third floor, undressed myself as slowly as\npossible so as to kill time, and with a bitter sigh got between the\nsheets.\n\nI lay there dismally calculating that sixteen entire hours must\nelapse before I could hope for a resurrection.  Sixteen hours in bed!\nthe small of my back ached to think of it.  And it was so light too;\nthe sun shining in at the window, and a great rattling of coaches in\nthe streets, and the sound of gay voices all over the house.  I felt\nworse and worse--at last I got up, dressed, and softly going down in\nmy stockinged feet, sought out my stepmother, and suddenly threw\nmyself at her feet, beseeching her as a particular favour to give me a\ngood slippering for my misbehaviour; anything indeed but condemning\nme to lie abed such an unendurable length of time.  But she was the\nbest and most conscientious of stepmothers, and back I had to go to\nmy room.  For several hours I lay there broad awake, feeling a great\ndeal worse than I have ever done since, even from the greatest\nsubsequent misfortunes.  At last I must have fallen into a troubled\nnightmare of a doze; and slowly waking from it--half steeped in\ndreams--I opened my eyes, and the before sun-lit room was now wrapped\nin outer darkness.  Instantly I felt a shock running through all my\nframe; nothing was to be seen, and nothing was to be heard; but a\nsupernatural hand seemed placed in mine.  My arm hung over the\ncounterpane, and the nameless, unimaginable, silent form or phantom,\nto which the hand belonged, seemed closely seated by my bed-side.\nFor what seemed ages piled on ages, I lay there, frozen with the most\nawful fears, not daring to drag away my hand; yet ever thinking that\nif I could but stir it one single inch, the horrid spell would be\nbroken.  I knew not how this consciousness at last glided away from\nme; but waking in the morning, I shudderingly remembered it all, and\nfor days and weeks and months afterwards I lost myself in confounding\nattempts to explain the mystery.  Nay, to this very hour, I often\npuzzle myself with it.\n\nNow, take away the awful fear, and my sensations at feeling the\nsupernatural hand in mine were very similar, in their strangeness,\nto those which I experienced on waking up and seeing Queequeg's pagan\narm thrown round me.  But at length all the past night's events\nsoberly recurred, one by one, in fixed reality, and then I lay only\nalive to the comical predicament.  For though I tried to move his\narm--unlock his bridegroom clasp--yet, sleeping as he was, he still\nhugged me tightly, as though naught but death should part us twain.\nI now strove to rouse him--\"Queequeg!\"--but his only answer was a\nsnore.  I then rolled over, my neck feeling as if it were in a\nhorse-collar; and suddenly felt a slight scratch.  Throwing aside the\ncounterpane, there lay the tomahawk sleeping by the savage's side, as\nif it were a hatchet-faced baby.  A pretty pickle, truly, thought I;\nabed here in a strange house in the broad day, with a cannibal and a\ntomahawk!  \"Queequeg!--in the name of goodness, Queequeg, wake!\"  At\nlength, by dint of much wriggling, and loud and incessant\nexpostulations upon the unbecomingness of his hugging a fellow male\nin that matrimonial sort of style, I succeeded in extracting a grunt;\nand presently, he drew back his arm, shook himself all over like a\nNewfoundland dog just from the water, and sat up in bed, stiff as a\npike-staff, looking at me, and rubbing his eyes as if he did not\naltogether remember how I came to be there, though a dim\nconsciousness of knowing something about me seemed slowly dawning\nover him.  Meanwhile, I lay quietly eyeing him, having no serious\nmisgivings now, and bent upon narrowly observing so curious a\ncreature.  When, at last, his mind seemed made up touching the\ncharacter of his bedfellow, and he became, as it were, reconciled to\nthe fact; he jumped out upon the floor, and by certain signs and\nsounds gave me to understand that, if it pleased me, he would dress\nfirst and then leave me to dress afterwards, leaving the whole\napartment to myself.  Thinks I, Queequeg, under the circumstances,\nthis is a very civilized overture; but, the truth is, these savages\nhave an innate sense of delicacy, say what you will; it is marvellous\nhow essentially polite they are.  I pay this particular compliment to\nQueequeg, because he treated me with so much civility and\nconsideration, while I was guilty of great rudeness; staring at him\nfrom the bed, and watching all his toilette motions; for the time my\ncuriosity getting the better of my breeding.  Nevertheless, a man\nlike Queequeg you don't see every day, he and his ways were well\nworth unusual regarding.\n\nHe commenced dressing at top by donning his beaver hat, a very tall\none, by the by, and then--still minus his trowsers--he hunted up his\nboots.  What under the heavens he did it for, I cannot tell, but his\nnext movement was to crush himself--boots in hand, and hat on--under\nthe bed; when, from sundry violent gaspings and strainings, I\ninferred he was hard at work booting himself; though by no law of\npropriety that I ever heard of, is any man required to be private\nwhen putting on his boots.  But Queequeg, do you see, was a creature\nin the transition stage--neither caterpillar nor butterfly.  He was\njust enough civilized to show off his outlandishness in the strangest\npossible manners.  His education was not yet completed.  He was an\nundergraduate.  If he had not been a small degree civilized, he very\nprobably would not have troubled himself with boots at all; but then,\nif he had not been still a savage, he never would have dreamt of\ngetting under the bed to put them on.  At last, he emerged with his\nhat very much dented and crushed down over his eyes, and began\ncreaking and limping about the room, as if, not being much accustomed\nto boots, his pair of damp, wrinkled cowhide ones--probably not made\nto order either--rather pinched and tormented him at the first go off\nof a bitter cold morning.\n\nSeeing, now, that there were no curtains to the window, and that the\nstreet being very narrow, the house opposite commanded a plain view\ninto the room, and observing more and more the indecorous figure that\nQueequeg made, staving about with little else but his hat and boots\non; I begged him as well as I could, to accelerate his toilet\nsomewhat, and particularly to get into his pantaloons as soon as\npossible.  He complied, and then proceeded to wash himself.  At that\ntime in the morning any Christian would have washed his face; but\nQueequeg, to my amazement, contented himself with restricting his\nablutions to his chest, arms, and hands.  He then donned his\nwaistcoat, and taking up a piece of hard soap on the wash-stand\ncentre table, dipped it into water and commenced lathering his face.\nI was watching to see where he kept his razor, when lo and behold, he\ntakes the harpoon from the bed corner, slips out the long wooden\nstock, unsheathes the head, whets it a little on his boot, and\nstriding up to the bit of mirror against the wall, begins a vigorous\nscraping, or rather harpooning of his cheeks.  Thinks I, Queequeg,\nthis is using Rogers's best cutlery with a vengeance.  Afterwards I\nwondered the less at this operation when I came to know of what fine\nsteel the head of a harpoon is made, and how exceedingly sharp the\nlong straight edges are always kept.\n\nThe rest of his toilet was soon achieved, and he proudly marched out\nof the room, wrapped up in his great pilot monkey jacket, and\nsporting his harpoon like a marshal's baton.\n\n\n\nCHAPTER 5\n\nBreakfast.\n\n\nI quickly followed suit, and descending into the bar-room accosted\nthe grinning landlord very pleasantly.  I cherished no malice towards\nhim, though he had been skylarking with me not a little in the matter\nof my bedfellow.\n\nHowever, a good laugh is a mighty good thing, and rather too scarce a\ngood thing; the more's the pity.  So, if any one man, in his own\nproper person, afford stuff for a good joke to anybody, let him not\nbe backward, but let him cheerfully allow himself to spend and be\nspent in that way.  And the man that has anything bountifully\nlaughable about him, be sure there is more in that man than you\nperhaps think for.\n\nThe bar-room was now full of the boarders who had been dropping in\nthe night previous, and whom I had not as yet had a good look at.\nThey were nearly all whalemen; chief mates, and second mates, and\nthird mates, and sea carpenters, and sea coopers, and sea\nblacksmiths, and harpooneers, and ship keepers; a brown and brawny\ncompany, with bosky beards; an unshorn, shaggy set, all wearing\nmonkey jackets for morning gowns.\n\nYou could pretty plainly tell how long each one had been ashore.\nThis young fellow's healthy cheek is like a sun-toasted pear in hue,\nand would seem to smell almost as musky; he cannot have been three\ndays landed from his Indian voyage.  That man next him looks a few\nshades lighter; you might say a touch of satin wood is in him.  In\nthe complexion of a third still lingers a tropic tawn, but slightly\nbleached withal; HE doubtless has tarried whole weeks ashore.  But\nwho could show a cheek like Queequeg? which, barred with various\ntints, seemed like the Andes' western slope, to show forth in one\narray, contrasting climates, zone by zone.\n\n\"Grub, ho!\" now cried the landlord, flinging open a door, and in we\nwent to breakfast.\n\nThey say that men who have seen the world, thereby become quite at\nease in manner, quite self-possessed in company.  Not always, though:\nLedyard, the great New England traveller, and Mungo Park, the Scotch\none; of all men, they possessed the least assurance in the parlor.\nBut perhaps the mere crossing of Siberia in a sledge drawn by dogs as\nLedyard did, or the taking a long solitary walk on an empty stomach,\nin the negro heart of Africa, which was the sum of poor Mungo's\nperformances--this kind of travel, I say, may not be the very best\nmode of attaining a high social polish.  Still, for the most part,\nthat sort of thing is to be had anywhere.\n\nThese reflections just here are occasioned by the circumstance that\nafter we were all seated at the table, and I was preparing to hear\nsome good stories about whaling; to my no small surprise, nearly\nevery man maintained a profound silence.  And not only that, but they\nlooked embarrassed.  Yes, here were a set of sea-dogs, many of whom\nwithout the slightest bashfulness had boarded great whales on the\nhigh seas--entire strangers to them--and duelled them dead without\nwinking; and yet, here they sat at a social breakfast table--all of\nthe same calling, all of kindred tastes--looking round as sheepishly\nat each other as though they had never been out of sight of some\nsheepfold among the Green Mountains.  A curious sight; these bashful\nbears, these timid warrior whalemen!\n\nBut as for Queequeg--why, Queequeg sat there among them--at the head\nof the table, too, it so chanced; as cool as an icicle.  To be sure I\ncannot say much for his breeding.  His greatest admirer could not\nhave cordially justified his bringing his harpoon into breakfast with\nhim, and using it there without ceremony; reaching over the table\nwith it, to the imminent jeopardy of many heads, and grappling the\nbeefsteaks towards him.  But THAT was certainly very coolly done by\nhim, and every one knows that in most people's estimation, to do\nanything coolly is to do it genteelly.\n\nWe will not speak of all Queequeg's peculiarities here; how he\neschewed coffee and hot rolls, and applied his undivided attention to\nbeefsteaks, done rare.  Enough, that when breakfast was over he\nwithdrew like the rest into the public room, lighted his\ntomahawk-pipe, and was sitting there quietly digesting and smoking\nwith his inseparable hat on, when I sallied out for a stroll.\n\n\n\nCHAPTER 6\n\nThe Street.\n\n\nIf I had been astonished at first catching a glimpse of so outlandish\nan individual as Queequeg circulating among the polite society of a\ncivilized town, that astonishment soon departed upon taking my first\ndaylight stroll through the streets of New Bedford.\n\nIn thoroughfares nigh the docks, any considerable seaport will\nfrequently offer to view the queerest looking nondescripts from\nforeign parts.  Even in Broadway and Chestnut streets, Mediterranean\nmariners will sometimes jostle the affrighted ladies.  Regent Street\nis not unknown to Lascars and Malays; and at Bombay, in the Apollo\nGreen, live Yankees have often scared the natives.  But New Bedford\nbeats all Water Street and Wapping.  In these last-mentioned haunts\nyou see only sailors; but in New Bedford, actual cannibals stand\nchatting at street corners; savages outright; many of whom yet carry\non their bones unholy flesh.  It makes a stranger stare.\n\nBut, besides the Feegeeans, Tongatobooarrs, Erromanggoans,\nPannangians, and Brighggians, and, besides the wild specimens of the\nwhaling-craft which unheeded reel about the streets, you will see\nother sights still more curious, certainly more comical.  There\nweekly arrive in this town scores of green Vermonters and New\nHampshire men, all athirst for gain and glory in the fishery.  They\nare mostly young, of stalwart frames; fellows who have felled\nforests, and now seek to drop the axe and snatch the whale-lance.\nMany are as green as the Green Mountains whence they came.  In some\nthings you would think them but a few hours old.  Look there! that\nchap strutting round the corner.  He wears a beaver hat and\nswallow-tailed coat, girdled with a sailor-belt and sheath-knife.\nHere comes another with a sou'-wester and a bombazine cloak.\n\nNo town-bred dandy will compare with a country-bred one--I mean a\ndownright bumpkin dandy--a fellow that, in the dog-days, will mow his\ntwo acres in buckskin gloves for fear of tanning his hands.  Now when\na country dandy like this takes it into his head to make a\ndistinguished reputation, and joins the great whale-fishery, you\nshould see the comical things he does upon reaching the seaport.  In\nbespeaking his sea-outfit, he orders bell-buttons to his waistcoats;\nstraps to his canvas trowsers.  Ah, poor Hay-Seed! how bitterly will\nburst those straps in the first howling gale, when thou art driven,\nstraps, buttons, and all, down the throat of the tempest.\n\nBut think not that this famous town has only harpooneers, cannibals,\nand bumpkins to show her visitors.  Not at all.  Still New Bedford is\na queer place.  Had it not been for us whalemen, that tract of land\nwould this day perhaps have been in as howling condition as the coast\nof Labrador.  As it is, parts of her back country are enough to\nfrighten one, they look so bony.  The town itself is perhaps the\ndearest place to live in, in all New England.  It is a land of oil,\ntrue enough: but not like Canaan; a land, also, of corn and wine.\nThe streets do not run with milk; nor in the spring-time do they pave\nthem with fresh eggs.  Yet, in spite of this, nowhere in all America\nwill you find more patrician-like houses; parks and gardens more\nopulent, than in New Bedford.  Whence came they? how planted upon\nthis once scraggy scoria of a country?\n\nGo and gaze upon the iron emblematical harpoons round yonder lofty\nmansion, and your question will be answered.  Yes; all these brave\nhouses and flowery gardens came from the Atlantic, Pacific, and\nIndian oceans.  One and all, they were harpooned and dragged up\nhither from the bottom of the sea.  Can Herr Alexander perform a feat\nlike that?\n\nIn New Bedford, fathers, they say, give whales for dowers to their\ndaughters, and portion off their nieces with a few porpoises a-piece.\nYou must go to New Bedford to see a brilliant wedding; for, they\nsay, they have reservoirs of oil in every house, and every night\nrecklessly burn their lengths in spermaceti candles.\n\nIn summer time, the town is sweet to see; full of fine maples--long\navenues of green and gold.  And in August, high in air, the beautiful\nand bountiful horse-chestnuts, candelabra-wise, proffer the passer-by\ntheir tapering upright cones of congregated blossoms.  So omnipotent\nis art; which in many a district of New Bedford has superinduced\nbright terraces of flowers upon the barren refuse rocks thrown aside\nat creation's final day.\n\nAnd the women of New Bedford, they bloom like their own red roses.\nBut roses only bloom in summer; whereas the fine carnation of their\ncheeks is perennial as sunlight in the seventh heavens.  Elsewhere\nmatch that bloom of theirs, ye cannot, save in Salem, where they tell\nme the young girls breathe such musk, their sailor sweethearts smell\nthem miles off shore, as though they were drawing nigh the odorous\nMoluccas instead of the Puritanic sands.\n\n\n\nCHAPTER 7\n\nThe Chapel.\n\n\nIn this same New Bedford there stands a Whaleman's Chapel, and few\nare the moody fishermen, shortly bound for the Indian Ocean or\nPacific, who fail to make a Sunday visit to the spot.  I am sure that\nI did not.\n\nReturning from my first morning stroll, I again sallied out upon this\nspecial errand.  The sky had changed from clear, sunny cold, to\ndriving sleet and mist.  Wrapping myself in my shaggy jacket of the\ncloth called bearskin, I fought my way against the stubborn storm.\nEntering, I found a small scattered congregation of sailors, and\nsailors' wives and widows.  A muffled silence reigned, only broken at\ntimes by the shrieks of the storm.  Each silent worshipper seemed\npurposely sitting apart from the other, as if each silent grief were\ninsular and incommunicable.  The chaplain had not yet arrived; and\nthere these silent islands of men and women sat steadfastly eyeing\nseveral marble tablets, with black borders, masoned into the wall on\neither side the pulpit.  Three of them ran something like the\nfollowing, but I do not pretend to quote:--\n\nSACRED\nTO THE MEMORY\nOF\nJOHN TALBOT,\nWho, at the age of eighteen, was lost overboard,\nNear the Isle of Desolation, off Patagonia,\nNovember 1st, 1836.\nTHIS TABLET\nIs erected to his Memory\nBY HIS\nSISTER.\n_____________\n\nSACRED\nTO THE MEMORY\nOF\nROBERT LONG, WILLIS ELLERY,\nNATHAN COLEMAN, WALTER CANNY, SETH MACY,\nAND SAMUEL GLEIG,\nForming one of the boats' crews\nOF\nTHE SHIP ELIZA\nWho were towed out of sight by a Whale,\nOn the Off-shore Ground in the\nPACIFIC,\nDecember 31st, 1839.\nTHIS MARBLE\nIs here placed by their surviving\nSHIPMATES.\n_____________\n\nSACRED\nTO THE MEMORY\nOF\nThe late\nCAPTAIN EZEKIEL HARDY,\nWho in the bows of his boat was killed by a\nSperm Whale on the coast of Japan,\nAUGUST 3d, 1833.\nTHIS TABLET\nIs erected to his Memory\nBY\nHIS WIDOW.\n\nShaking off the sleet from my ice-glazed hat and jacket, I seated\nmyself near the door, and turning sideways was surprised to see\nQueequeg near me.  Affected by the solemnity of the scene, there was\na wondering gaze of incredulous curiosity in his countenance.  This\nsavage was the only person present who seemed to notice my entrance;\nbecause he was the only one who could not read, and, therefore, was\nnot reading those frigid inscriptions on the wall.  Whether any of\nthe relatives of the seamen whose names appeared there were now among\nthe congregation, I knew not; but so many are the unrecorded\naccidents in the fishery, and so plainly did several women present\nwear the countenance if not the trappings of some unceasing grief,\nthat I feel sure that here before me were assembled those, in whose\nunhealing hearts the sight of those bleak tablets sympathetically\ncaused the old wounds to bleed afresh.\n\nOh! ye whose dead lie buried beneath the green grass; who standing\namong flowers can say--here, HERE lies my beloved; ye know not the\ndesolation that broods in bosoms like these.  What bitter blanks in\nthose black-bordered marbles which cover no ashes!  What despair in\nthose immovable inscriptions!  What deadly voids and unbidden\ninfidelities in the lines that seem to gnaw upon all Faith, and\nrefuse resurrections to the beings who have placelessly perished\nwithout a grave.  As well might those tablets stand in the cave of\nElephanta as here.\n\nIn what census of living creatures, the dead of mankind are included;\nwhy it is that a universal proverb says of them, that they tell no\ntales, though containing more secrets than the Goodwin Sands; how it\nis that to his name who yesterday departed for the other world, we\nprefix so significant and infidel a word, and yet do not thus entitle\nhim, if he but embarks for the remotest Indies of this living earth;\nwhy the Life Insurance Companies pay death-forfeitures upon\nimmortals; in what eternal, unstirring paralysis, and deadly,\nhopeless trance, yet lies antique Adam who died sixty round centuries\nago; how it is that we still refuse to be comforted for those who we\nnevertheless maintain are dwelling in unspeakable bliss; why all the\nliving so strive to hush all the dead; wherefore but the rumor of a\nknocking in a tomb will terrify a whole city.  All these things are\nnot without their meanings.\n\nBut Faith, like a jackal, feeds among the tombs, and even from these\ndead doubts she gathers her most vital hope.\n\nIt needs scarcely to be told, with what feelings, on the eve of a\nNantucket voyage, I regarded those marble tablets, and by the murky\nlight of that darkened, doleful day read the fate of the whalemen who\nhad gone before me.  Yes, Ishmael, the same fate may be thine.  But\nsomehow I grew merry again.  Delightful inducements to embark, fine\nchance for promotion, it seems--aye, a stove boat will make me an\nimmortal by brevet.  Yes, there is death in this business of\nwhaling--a speechlessly quick chaotic bundling of a man into\nEternity.  But what then?  Methinks we have hugely mistaken this\nmatter of Life and Death.  Methinks that what they call my shadow\nhere on earth is my true substance.  Methinks that in looking at\nthings spiritual, we are too much like oysters observing the sun\nthrough the water, and thinking that thick water the thinnest of air.\nMethinks my body is but the lees of my better being.  In fact take\nmy body who will, take it I say, it is not me.  And therefore three\ncheers for Nantucket; and come a stove boat and stove body when they\nwill, for stave my soul, Jove himself cannot.\n\n\n\nCHAPTER 8\n\nThe Pulpit.\n\n\nI had not been seated very long ere a man of a certain venerable\nrobustness entered; immediately as the storm-pelted door flew back\nupon admitting him, a quick regardful eyeing of him by all the\ncongregation, sufficiently attested that this fine old man was the\nchaplain.  Yes, it was the famous Father Mapple, so called by the\nwhalemen, among whom he was a very great favourite.  He had been a\nsailor and a harpooneer in his youth, but for many years past had\ndedicated his life to the ministry.  At the time I now write of,\nFather Mapple was in the hardy winter of a healthy old age; that sort\nof old age which seems merging into a second flowering youth, for\namong all the fissures of his wrinkles, there shone certain mild\ngleams of a newly developing bloom--the spring verdure peeping forth\neven beneath February's snow.  No one having previously heard his\nhistory, could for the first time behold Father Mapple without the\nutmost interest, because there were certain engrafted clerical\npeculiarities about him, imputable to that adventurous maritime life\nhe had led.  When he entered I observed that he carried no umbrella,\nand certainly had not come in his carriage, for his tarpaulin hat ran\ndown with melting sleet, and his great pilot cloth jacket seemed\nalmost to drag him to the floor with the weight of the water it had\nabsorbed.  However, hat and coat and overshoes were one by one\nremoved, and hung up in a little space in an adjacent corner; when,\narrayed in a decent suit, he quietly approached the pulpit.\n\nLike most old fashioned pulpits, it was a very lofty one, and since a\nregular stairs to such a height would, by its long angle with the\nfloor, seriously contract the already small area of the chapel, the\narchitect, it seemed, had acted upon the hint of Father Mapple, and\nfinished the pulpit without a stairs, substituting a perpendicular\nside ladder, like those used in mounting a ship from a boat at sea.\nThe wife of a whaling captain had provided the chapel with a handsome\npair of red worsted man-ropes for this ladder, which, being itself\nnicely headed, and stained with a mahogany colour, the whole\ncontrivance, considering what manner of chapel it was, seemed by no\nmeans in bad taste.  Halting for an instant at the foot of the\nladder, and with both hands grasping the ornamental knobs of the\nman-ropes, Father Mapple cast a look upwards, and then with a truly\nsailor-like but still reverential dexterity, hand over hand, mounted\nthe steps as if ascending the main-top of his vessel.\n\nThe perpendicular parts of this side ladder, as is usually the case\nwith swinging ones, were of cloth-covered rope, only the rounds were\nof wood, so that at every step there was a joint.  At my first\nglimpse of the pulpit, it had not escaped me that however convenient\nfor a ship, these joints in the present instance seemed unnecessary.\nFor I was not prepared to see Father Mapple after gaining the height,\nslowly turn round, and stooping over the pulpit, deliberately drag up\nthe ladder step by step, till the whole was deposited within, leaving\nhim impregnable in his little Quebec.\n\nI pondered some time without fully comprehending the reason for this.\nFather Mapple enjoyed such a wide reputation for sincerity and\nsanctity, that I could not suspect him of courting notoriety by any\nmere tricks of the stage.  No, thought I, there must be some sober\nreason for this thing; furthermore, it must symbolize something\nunseen.  Can it be, then, that by that act of physical isolation, he\nsignifies his spiritual withdrawal for the time, from all outward\nworldly ties and connexions?  Yes, for replenished with the meat and\nwine of the word, to the faithful man of God, this pulpit, I see, is\na self-containing stronghold--a lofty Ehrenbreitstein, with a\nperennial well of water within the walls.\n\nBut the side ladder was not the only strange feature of the place,\nborrowed from the chaplain's former sea-farings.  Between the marble\ncenotaphs on either hand of the pulpit, the wall which formed its\nback was adorned with a large painting representing a gallant ship\nbeating against a terrible storm off a lee coast of black rocks and\nsnowy breakers.  But high above the flying scud and dark-rolling\nclouds, there floated a little isle of sunlight, from which beamed\nforth an angel's face; and this bright face shed a distinct spot of\nradiance upon the ship's tossed deck, something like that silver\nplate now inserted into the Victory's plank where Nelson fell.  \"Ah,\nnoble ship,\" the angel seemed to say, \"beat on, beat on, thou noble\nship, and bear a hardy helm; for lo! the sun is breaking through; the\nclouds are rolling off--serenest azure is at hand.\"\n\nNor was the pulpit itself without a trace of the same sea-taste that\nhad achieved the ladder and the picture.  Its panelled front was in\nthe likeness of a ship's bluff bows, and the Holy Bible rested on a\nprojecting piece of scroll work, fashioned after a ship's\nfiddle-headed beak.\n\nWhat could be more full of meaning?--for the pulpit is ever this\nearth's foremost part; all the rest comes in its rear; the pulpit\nleads the world.  From thence it is the storm of God's quick wrath is\nfirst descried, and the bow must bear the earliest brunt.  From\nthence it is the God of breezes fair or foul is first invoked for\nfavourable winds.  Yes, the world's a ship on its passage out, and not\na voyage complete; and the pulpit is its prow.\n\n\n\nCHAPTER 9\n\nThe Sermon.\n\n\nFather Mapple rose, and in a mild voice of unassuming authority\nordered the scattered people to condense.  \"Starboard gangway,\nthere! side away to larboard--larboard gangway to starboard!\nMidships! midships!\"\n\nThere was a low rumbling of heavy sea-boots among the benches, and a\nstill slighter shuffling of women's shoes, and all was quiet again,\nand every eye on the preacher.\n\nHe paused a little; then kneeling in the pulpit's bows, folded his\nlarge brown hands across his chest, uplifted his closed eyes, and\noffered a prayer so deeply devout that he seemed kneeling and praying\nat the bottom of the sea.\n\nThis ended, in prolonged solemn tones, like the continual tolling of\na bell in a ship that is foundering at sea in a fog--in such tones he\ncommenced reading the following hymn; but changing his manner towards\nthe concluding stanzas, burst forth with a pealing exultation and\njoy--\n\n\"The ribs and terrors in the whale,\nArched over me a dismal gloom,\nWhile all God's sun-lit waves rolled by,\nAnd lift me deepening down to doom.\n\n\"I saw the opening maw of hell,\nWith endless pains and sorrows there;\nWhich none but they that feel can tell--\nOh, I was plunging to despair.\n\n\"In black distress, I called my God,\nWhen I could scarce believe him mine,\nHe bowed his ear to my complaints--\nNo more the whale did me confine.\n\n\"With speed he flew to my relief,\nAs on a radiant dolphin borne;\nAwful, yet bright, as lightning shone\nThe face of my Deliverer God.\n\n\"My song for ever shall record\nThat terrible, that joyful hour;\nI give the glory to my God,\nHis all the mercy and the power.\n\n\nNearly all joined in singing this hymn, which swelled high above the\nhowling of the storm.  A brief pause ensued; the preacher slowly\nturned over the leaves of the Bible, and at last, folding his hand\ndown upon the proper page, said: \"Beloved shipmates, clinch the last\nverse of the first chapter of Jonah--'And God had prepared a great\nfish to swallow up Jonah.'\"\n\n\"Shipmates, this book, containing only four chapters--four yarns--is\none of the smallest strands in the mighty cable of the Scriptures.\nYet what depths of the soul does Jonah's deep sealine sound! what a\npregnant lesson to us is this prophet!  What a noble thing is that\ncanticle in the fish's belly!  How billow-like and boisterously\ngrand!  We feel the floods surging over us; we sound with him to the\nkelpy bottom of the waters; sea-weed and all the slime of the sea is\nabout us!  But WHAT is this lesson that the book of Jonah teaches?\nShipmates, it is a two-stranded lesson; a lesson to us all as sinful\nmen, and a lesson to me as a pilot of the living God.  As sinful men,\nit is a lesson to us all, because it is a story of the sin,\nhard-heartedness, suddenly awakened fears, the swift punishment,\nrepentance, prayers, and finally the deliverance and joy of Jonah.\nAs with all sinners among men, the sin of this son of Amittai was in\nhis wilful disobedience of the command of God--never mind now what\nthat command was, or how conveyed--which he found a hard command.\nBut all the things that God would have us do are hard for us to\ndo--remember that--and hence, he oftener commands us than endeavors\nto persuade.  And if we obey God, we must disobey ourselves; and it\nis in this disobeying ourselves, wherein the hardness of obeying God\nconsists.\n\n\"With this sin of disobedience in him, Jonah still further flouts at\nGod, by seeking to flee from Him.  He thinks that a ship made by men\nwill carry him into countries where God does not reign, but only the\nCaptains of this earth.  He skulks about the wharves of Joppa, and\nseeks a ship that's bound for Tarshish.  There lurks, perhaps, a\nhitherto unheeded meaning here.  By all accounts Tarshish could have\nbeen no other city than the modern Cadiz.  That's the opinion of\nlearned men.  And where is Cadiz, shipmates?  Cadiz is in Spain; as\nfar by water, from Joppa, as Jonah could possibly have sailed in\nthose ancient days, when the Atlantic was an almost unknown sea.\nBecause Joppa, the modern Jaffa, shipmates, is on the most easterly\ncoast of the Mediterranean, the Syrian; and Tarshish or Cadiz more\nthan two thousand miles to the westward from that, just outside the\nStraits of Gibraltar.  See ye not then, shipmates, that Jonah sought\nto flee world-wide from God?  Miserable man!  Oh! most contemptible\nand worthy of all scorn; with slouched hat and guilty eye, skulking\nfrom his God; prowling among the shipping like a vile burglar\nhastening to cross the seas.  So disordered, self-condemning is his\nlook, that had there been policemen in those days, Jonah, on the mere\nsuspicion of something wrong, had been arrested ere he touched a\ndeck.  How plainly he's a fugitive! no baggage, not a hat-box,\nvalise, or carpet-bag,--no friends accompany him to the wharf with\ntheir adieux.  At last, after much dodging search, he finds the\nTarshish ship receiving the last items of her cargo; and as he steps\non board to see its Captain in the cabin, all the sailors for the\nmoment desist from hoisting in the goods, to mark the stranger's evil\neye.  Jonah sees this; but in vain he tries to look all ease and\nconfidence; in vain essays his wretched smile.  Strong intuitions of\nthe man assure the mariners he can be no innocent.  In their gamesome\nbut still serious way, one whispers to the other--\"Jack, he's robbed\na widow;\" or, \"Joe, do you mark him; he's a bigamist;\" or, \"Harry\nlad, I guess he's the adulterer that broke jail in old Gomorrah, or\nbelike, one of the missing murderers from Sodom.\"  Another runs to\nread the bill that's stuck against the spile upon the wharf to which\nthe ship is moored, offering five hundred gold coins for the\napprehension of a parricide, and containing a description of his\nperson.  He reads, and looks from Jonah to the bill; while all his\nsympathetic shipmates now crowd round Jonah, prepared to lay their\nhands upon him.  Frighted Jonah trembles, and summoning all his\nboldness to his face, only looks so much the more a coward.  He will\nnot confess himself suspected; but that itself is strong suspicion.\nSo he makes the best of it; and when the sailors find him not to be\nthe man that is advertised, they let him pass, and he descends into\nthe cabin.\n\n\"'Who's there?' cries the Captain at his busy desk, hurriedly making\nout his papers for the Customs--'Who's there?'  Oh! how that harmless\nquestion mangles Jonah!  For the instant he almost turns to flee\nagain.  But he rallies.  'I seek a passage in this ship to Tarshish;\nhow soon sail ye, sir?'  Thus far the busy Captain had not looked up\nto Jonah, though the man now stands before him; but no sooner does he\nhear that hollow voice, than he darts a scrutinizing glance.  'We\nsail with the next coming tide,' at last he slowly answered, still\nintently eyeing him.  'No sooner, sir?'--'Soon enough for any honest\nman that goes a passenger.'  Ha!  Jonah, that's another stab.  But he\nswiftly calls away the Captain from that scent.  'I'll sail with\nye,'--he says,--'the passage money how much is that?--I'll pay now.'\nFor it is particularly written, shipmates, as if it were a thing not\nto be overlooked in this history, 'that he paid the fare thereof' ere\nthe craft did sail.  And taken with the context, this is full of\nmeaning.\n\n\"Now Jonah's Captain, shipmates, was one whose discernment detects\ncrime in any, but whose cupidity exposes it only in the penniless.\nIn this world, shipmates, sin that pays its way can travel freely,\nand without a passport; whereas Virtue, if a pauper, is stopped at\nall frontiers.  So Jonah's Captain prepares to test the length of\nJonah's purse, ere he judge him openly.  He charges him thrice the\nusual sum; and it's assented to.  Then the Captain knows that Jonah\nis a fugitive; but at the same time resolves to help a flight that\npaves its rear with gold.  Yet when Jonah fairly takes out his purse,\nprudent suspicions still molest the Captain.  He rings every coin to\nfind a counterfeit.  Not a forger, any way, he mutters; and Jonah is\nput down for his passage.  'Point out my state-room, Sir,' says Jonah\nnow, 'I'm travel-weary; I need sleep.'  'Thou lookest like it,' says\nthe Captain, 'there's thy room.'  Jonah enters, and would lock the\ndoor, but the lock contains no key.  Hearing him foolishly fumbling\nthere, the Captain laughs lowly to himself, and mutters something\nabout the doors of convicts' cells being never allowed to be locked\nwithin.  All dressed and dusty as he is, Jonah throws himself into\nhis berth, and finds the little state-room ceiling almost resting on\nhis forehead.  The air is close, and Jonah gasps.  Then, in that\ncontracted hole, sunk, too, beneath the ship's water-line, Jonah\nfeels the heralding presentiment of that stifling hour, when the\nwhale shall hold him in the smallest of his bowels' wards.\n\n\"Screwed at its axis against the side, a swinging lamp slightly\noscillates in Jonah's room; and the ship, heeling over towards the\nwharf with the weight of the last bales received, the lamp, flame and\nall, though in slight motion, still maintains a permanent obliquity\nwith reference to the room; though, in truth, infallibly straight\nitself, it but made obvious the false, lying levels among which it\nhung.  The lamp alarms and frightens Jonah; as lying in his berth his\ntormented eyes roll round the place, and this thus far successful\nfugitive finds no refuge for his restless glance.  But that\ncontradiction in the lamp more and more appals him.  The floor, the\nceiling, and the side, are all awry.  'Oh! so my conscience hangs in\nme!' he groans, 'straight upwards, so it burns; but the chambers of\nmy soul are all in crookedness!'\n\n\"Like one who after a night of drunken revelry hies to his bed, still\nreeling, but with conscience yet pricking him, as the plungings of\nthe Roman race-horse but so much the more strike his steel tags into\nhim; as one who in that miserable plight still turns and turns in\ngiddy anguish, praying God for annihilation until the fit be passed;\nand at last amid the whirl of woe he feels, a deep stupor steals over\nhim, as over the man who bleeds to death, for conscience is the\nwound, and there's naught to staunch it; so, after sore wrestlings in\nhis berth, Jonah's prodigy of ponderous misery drags him drowning\ndown to sleep.\n\n\"And now the time of tide has come; the ship casts off her cables;\nand from the deserted wharf the uncheered ship for Tarshish, all\ncareening, glides to sea.  That ship, my friends, was the first of\nrecorded smugglers! the contraband was Jonah.  But the sea rebels; he\nwill not bear the wicked burden.  A dreadful storm comes on, the\nship is like to break.  But now when the boatswain calls all hands to\nlighten her; when boxes, bales, and jars are clattering overboard;\nwhen the wind is shrieking, and the men are yelling, and every plank\nthunders with trampling feet right over Jonah's head; in all this\nraging tumult, Jonah sleeps his hideous sleep.  He sees no black sky\nand raging sea, feels not the reeling timbers, and little hears he or\nheeds he the far rush of the mighty whale, which even now with open\nmouth is cleaving the seas after him.  Aye, shipmates, Jonah was gone\ndown into the sides of the ship--a berth in the cabin as I have taken\nit, and was fast asleep.  But the frightened master comes to him, and\nshrieks in his dead ear, 'What meanest thou, O, sleeper! arise!'\nStartled from his lethargy by that direful cry, Jonah staggers to his\nfeet, and stumbling to the deck, grasps a shroud, to look out upon\nthe sea.  But at that moment he is sprung upon by a panther billow\nleaping over the bulwarks.  Wave after wave thus leaps into the ship,\nand finding no speedy vent runs roaring fore and aft, till the\nmariners come nigh to drowning while yet afloat.  And ever, as the\nwhite moon shows her affrighted face from the steep gullies in the\nblackness overhead, aghast Jonah sees the rearing bowsprit pointing\nhigh upward, but soon beat downward again towards the tormented deep.\n\n\"Terrors upon terrors run shouting through his soul.  In all his\ncringing attitudes, the God-fugitive is now too plainly known.  The\nsailors mark him; more and more certain grow their suspicions of him,\nand at last, fully to test the truth, by referring the whole matter\nto high Heaven, they fall to casting lots, to see for whose\ncause this great tempest was upon them.  The lot is Jonah's; that\ndiscovered, then how furiously they mob him with their questions.\n'What is thine occupation?  Whence comest thou?  Thy country?  What\npeople?  But mark now, my shipmates, the behavior of poor Jonah.  The\neager mariners but ask him who he is, and where from; whereas, they\nnot only receive an answer to those questions, but likewise another\nanswer to a question not put by them, but the unsolicited answer is\nforced from Jonah by the hard hand of God that is upon him.\n\n\"'I am a Hebrew,' he cries--and then--'I fear the Lord the God of\nHeaven who hath made the sea and the dry land!'  Fear him, O Jonah?\nAye, well mightest thou fear the Lord God THEN!  Straightway, he now\ngoes on to make a full confession; whereupon the mariners became more\nand more appalled, but still are pitiful.  For when Jonah, not yet\nsupplicating God for mercy, since he but too well knew the darkness\nof his deserts,--when wretched Jonah cries out to them to take him\nand cast him forth into the sea, for he knew that for HIS sake this\ngreat tempest was upon them; they mercifully turn from him, and seek\nby other means to save the ship.  But all in vain; the indignant gale\nhowls louder; then, with one hand raised invokingly to God, with the\nother they not unreluctantly lay hold of Jonah.\n\n\"And now behold Jonah taken up as an anchor and dropped into the sea;\nwhen instantly an oily calmness floats out from the east, and the sea\nis still, as Jonah carries down the gale with him, leaving smooth\nwater behind.  He goes down in the whirling heart of such a\nmasterless commotion that he scarce heeds the moment when he drops\nseething into the yawning jaws awaiting him; and the whale shoots-to\nall his ivory teeth, like so many white bolts, upon his prison.  Then\nJonah prayed unto the Lord out of the fish's belly.  But observe his\nprayer, and learn a weighty lesson.  For sinful as he is, Jonah does\nnot weep and wail for direct deliverance.  He feels that his dreadful\npunishment is just.  He leaves all his deliverance to God, contenting\nhimself with this, that spite of all his pains and pangs, he will\nstill look towards His holy temple.  And here, shipmates, is true and\nfaithful repentance; not clamorous for pardon, but grateful for\npunishment.  And how pleasing to God was this conduct in Jonah, is\nshown in the eventual deliverance of him from the sea and the whale.\nShipmates, I do not place Jonah before you to be copied for his sin\nbut I do place him before you as a model for repentance.  Sin not;\nbut if you do, take heed to repent of it like Jonah.\"\n\nWhile he was speaking these words, the howling of the shrieking,\nslanting storm without seemed to add new power to the preacher, who,\nwhen describing Jonah's sea-storm, seemed tossed by a storm himself.\nHis deep chest heaved as with a ground-swell; his tossed arms seemed\nthe warring elements at work; and the thunders that rolled away from\noff his swarthy brow, and the light leaping from his eye, made all\nhis simple hearers look on him with a quick fear that was strange to\nthem.\n\nThere now came a lull in his look, as he silently turned over the\nleaves of the Book once more; and, at last, standing motionless, with\nclosed eyes, for the moment, seemed communing with God and himself.\n\nBut again he leaned over towards the people, and bowing his head\nlowly, with an aspect of the deepest yet manliest humility, he spake\nthese words:\n\n\"Shipmates, God has laid but one hand upon you; both his hands press\nupon me.  I have read ye by what murky light may be mine the lesson\nthat Jonah teaches to all sinners; and therefore to ye, and still\nmore to me, for I am a greater sinner than ye.  And now how gladly\nwould I come down from this mast-head and sit on the hatches there\nwhere you sit, and listen as you listen, while some one of you reads\nME that other and more awful lesson which Jonah teaches to ME, as a\npilot of the living God.  How being an anointed pilot-prophet, or\nspeaker of true things, and bidden by the Lord to sound those\nunwelcome truths in the ears of a wicked Nineveh, Jonah, appalled at\nthe hostility he should raise, fled from his mission, and sought to\nescape his duty and his God by taking ship at Joppa.  But God is\neverywhere; Tarshish he never reached.  As we have seen, God came\nupon him in the whale, and swallowed him down to living gulfs of\ndoom, and with swift slantings tore him along 'into the midst of the\nseas,' where the eddying depths sucked him ten thousand fathoms down,\nand 'the weeds were wrapped about his head,' and all the watery world\nof woe bowled over him.  Yet even then beyond the reach of any\nplummet--'out of the belly of hell'--when the whale grounded upon the\nocean's utmost bones, even then, God heard the engulphed, repenting\nprophet when he cried.  Then God spake unto the fish; and from the\nshuddering cold and blackness of the sea, the whale came breeching up\ntowards the warm and pleasant sun, and all the delights of air and\nearth; and 'vomited out Jonah upon the dry land;' when the word of\nthe Lord came a second time; and Jonah, bruised and beaten--his ears,\nlike two sea-shells, still multitudinously murmuring of the\nocean--Jonah did the Almighty's bidding.  And what was that,\nshipmates?  To preach the Truth to the face of Falsehood!  That was\nit!\n\n\"This, shipmates, this is that other lesson; and woe to that pilot of\nthe living God who slights it.  Woe to him whom this world charms\nfrom Gospel duty!  Woe to him who seeks to pour oil upon the waters\nwhen God has brewed them into a gale!  Woe to him who seeks to please\nrather than to appal!  Woe to him whose good name is more to him than\ngoodness!  Woe to him who, in this world, courts not dishonour!  Woe\nto him who would not be true, even though to be false were salvation!\nYea, woe to him who, as the great Pilot Paul has it, while preaching\nto others is himself a castaway!\"\n\nHe dropped and fell away from himself for a moment; then lifting his\nface to them again, showed a deep joy in his eyes, as he cried out\nwith a heavenly enthusiasm,--\"But oh! shipmates! on the starboard\nhand of every woe, there is a sure delight; and higher the top of\nthat delight, than the bottom of the woe is deep.  Is not the\nmain-truck higher than the kelson is low?  Delight is to him--a far,\nfar upward, and inward delight--who against the proud gods and\ncommodores of this earth, ever stands forth his own inexorable self.\nDelight is to him whose strong arms yet support him, when the ship of\nthis base treacherous world has gone down beneath him.  Delight is to\nhim, who gives no quarter in the truth, and kills, burns, and\ndestroys all sin though he pluck it out from under the robes of\nSenators and Judges.  Delight,--top-gallant delight is to him, who\nacknowledges no law or lord, but the Lord his God, and is only a\npatriot to heaven.  Delight is to him, whom all the waves of the\nbillows of the seas of the boisterous mob can never shake from this\nsure Keel of the Ages.  And eternal delight and deliciousness will be\nhis, who coming to lay him down, can say with his final breath--O\nFather!--chiefly known to me by Thy rod--mortal or immortal, here I\ndie.  I have striven to be Thine, more than to be this world's, or\nmine own.  Yet this is nothing: I leave eternity to Thee; for what\nis man that he should live out the lifetime of his God?\"\n\nHe said no more, but slowly waving a benediction, covered his face\nwith his hands, and so remained kneeling, till all the people had\ndeparted, and he was left alone in the place.\n\n\n\nCHAPTER 10\n\nA Bosom Friend.\n\n\nReturning to the Spouter-Inn from the Chapel, I found Queequeg there\nquite alone; he having left the Chapel before the benediction some\ntime.  He was sitting on a bench before the fire, with his feet on\nthe stove hearth, and in one hand was holding close up to his face\nthat little negro idol of his; peering hard into its face, and with a\njack-knife gently whittling away at its nose, meanwhile humming to\nhimself in his heathenish way.\n\nBut being now interrupted, he put up the image; and pretty soon,\ngoing to the table, took up a large book there, and placing it on his\nlap began counting the pages with deliberate regularity; at every\nfiftieth page--as I fancied--stopping a moment, looking vacantly\naround him, and giving utterance to a long-drawn gurgling whistle of\nastonishment.  He would then begin again at the next fifty; seeming\nto commence at number one each time, as though he could not count\nmore than fifty, and it was only by such a large number of fifties\nbeing found together, that his astonishment at the multitude of pages\nwas excited.\n\nWith much interest I sat watching him.  Savage though he was, and\nhideously marred about the face--at least to my taste--his\ncountenance yet had a something in it which was by no means\ndisagreeable.  You cannot hide the soul.  Through all his unearthly\ntattooings, I thought I saw the traces of a simple honest heart; and\nin his large, deep eyes, fiery black and bold, there seemed tokens of\na spirit that would dare a thousand devils.  And besides all this,\nthere was a certain lofty bearing about the Pagan, which even his\nuncouthness could not altogether maim.  He looked like a man who had\nnever cringed and never had had a creditor.  Whether it was, too,\nthat his head being shaved, his forehead was drawn out in freer and\nbrighter relief, and looked more expansive than it otherwise would,\nthis I will not venture to decide; but certain it was his head was\nphrenologically an excellent one.  It may seem ridiculous, but it\nreminded me of General Washington's head, as seen in the popular\nbusts of him.  It had the same long regularly graded retreating slope\nfrom above the brows, which were likewise very projecting, like two\nlong promontories thickly wooded on top.  Queequeg was George\nWashington cannibalistically developed.\n\nWhilst I was thus closely scanning him, half-pretending meanwhile to\nbe looking out at the storm from the casement, he never heeded my\npresence, never troubled himself with so much as a single glance; but\nappeared wholly occupied with counting the pages of the marvellous\nbook.  Considering how sociably we had been sleeping together the\nnight previous, and especially considering the affectionate arm I had\nfound thrown over me upon waking in the morning, I thought this\nindifference of his very strange.  But savages are strange beings; at\ntimes you do not know exactly how to take them.  At first they are\noverawing; their calm self-collectedness of simplicity seems a\nSocratic wisdom.  I had noticed also that Queequeg never consorted at\nall, or but very little, with the other seamen in the inn.  He made\nno advances whatever; appeared to have no desire to enlarge the\ncircle of his acquaintances.  All this struck me as mighty singular;\nyet, upon second thoughts, there was something almost sublime in it.\nHere was a man some twenty thousand miles from home, by the way of\nCape Horn, that is--which was the only way he could get there--thrown\namong people as strange to him as though he were in the planet\nJupiter; and yet he seemed entirely at his ease; preserving the\nutmost serenity; content with his own companionship; always equal to\nhimself.  Surely this was a touch of fine philosophy; though no doubt\nhe had never heard there was such a thing as that.  But, perhaps, to\nbe true philosophers, we mortals should not be conscious of so living\nor so striving.  So soon as I hear that such or such a man gives\nhimself out for a philosopher, I conclude that, like the dyspeptic\nold woman, he must have \"broken his digester.\"\n\nAs I sat there in that now lonely room; the fire burning low, in that\nmild stage when, after its first intensity has warmed the air, it\nthen only glows to be looked at; the evening shades and phantoms\ngathering round the casements, and peering in upon us silent,\nsolitary twain; the storm booming without in solemn swells; I began\nto be sensible of strange feelings.  I felt a melting in me.  No more\nmy splintered heart and maddened hand were turned against the wolfish\nworld.  This soothing savage had redeemed it.  There he sat, his very\nindifference speaking a nature in which there lurked no civilized\nhypocrisies and bland deceits.  Wild he was; a very sight of sights\nto see; yet I began to feel myself mysteriously drawn towards him.\nAnd those same things that would have repelled most others, they were\nthe very magnets that thus drew me.  I'll try a pagan friend, thought\nI, since Christian kindness has proved but hollow courtesy.  I drew\nmy bench near him, and made some friendly signs and hints, doing my\nbest to talk with him meanwhile.  At first he little noticed these\nadvances; but presently, upon my referring to his last night's\nhospitalities, he made out to ask me whether we were again to be\nbedfellows.  I told him yes; whereat I thought he looked pleased,\nperhaps a little complimented.\n\nWe then turned over the book together, and I endeavored to explain to\nhim the purpose of the printing, and the meaning of the few pictures\nthat were in it.  Thus I soon engaged his interest; and from that we\nwent to jabbering the best we could about the various outer sights to\nbe seen in this famous town.  Soon I proposed a social smoke; and,\nproducing his pouch and tomahawk, he quietly offered me a puff.  And\nthen we sat exchanging puffs from that wild pipe of his, and keeping\nit regularly passing between us.\n\nIf there yet lurked any ice of indifference towards me in the Pagan's\nbreast, this pleasant, genial smoke we had, soon thawed it out, and\nleft us cronies.  He seemed to take to me quite as naturally and\nunbiddenly as I to him; and when our smoke was over, he pressed his\nforehead against mine, clasped me round the waist, and said that\nhenceforth we were married; meaning, in his country's phrase, that we\nwere bosom friends; he would gladly die for me, if need should be.\nIn a countryman, this sudden flame of friendship would have seemed\nfar too premature, a thing to be much distrusted; but in this simple\nsavage those old rules would not apply.\n\nAfter supper, and another social chat and smoke, we went to our room\ntogether.  He made me a present of his embalmed head; took out his\nenormous tobacco wallet, and groping under the tobacco, drew out some\nthirty dollars in silver; then spreading them on the table, and\nmechanically dividing them into two equal portions, pushed one of\nthem towards me, and said it was mine.  I was going to remonstrate;\nbut he silenced me by pouring them into my trowsers' pockets.  I let\nthem stay.  He then went about his evening prayers, took out his\nidol, and removed the paper fireboard.  By certain signs and\nsymptoms, I thought he seemed anxious for me to join him; but well\nknowing what was to follow, I deliberated a moment whether, in case\nhe invited me, I would comply or otherwise.\n\nI was a good Christian; born and bred in the bosom of the infallible\nPresbyterian Church.  How then could I unite with this wild idolator\nin worshipping his piece of wood?  But what is worship? thought I.\nDo you suppose now, Ishmael, that the magnanimous God of heaven and\nearth--pagans and all included--can possibly be jealous of an\ninsignificant bit of black wood?  Impossible!  But what is\nworship?--to do the will of God--THAT is worship.  And what is the\nwill of God?--to do to my fellow man what I would have my fellow man\nto do to me--THAT is the will of God.  Now, Queequeg is my fellow\nman.  And what do I wish that this Queequeg would do to me?  Why,\nunite with me in my particular Presbyterian form of worship.\nConsequently, I must then unite with him in his; ergo, I must turn\nidolator.  So I kindled the shavings; helped prop up the innocent\nlittle idol; offered him burnt biscuit with Queequeg; salamed before\nhim twice or thrice; kissed his nose; and that done, we undressed and\nwent to bed, at peace with our own consciences and all the world.\nBut we did not go to sleep without some little chat.\n\nHow it is I know not; but there is no place like a bed for\nconfidential disclosures between friends.  Man and wife, they say,\nthere open the very bottom of their souls to each other; and some old\ncouples often lie and chat over old times till nearly morning.  Thus,\nthen, in our hearts' honeymoon, lay I and Queequeg--a cosy, loving\npair.\n\n\n\nCHAPTER 11\n\nNightgown.\n\n\nWe had lain thus in bed, chatting and napping at short intervals, and\nQueequeg now and then affectionately throwing his brown tattooed legs\nover mine, and then drawing them back; so entirely sociable and free\nand easy were we; when, at last, by reason of our confabulations,\nwhat little nappishness remained in us altogether departed, and we\nfelt like getting up again, though day-break was yet some way down\nthe future.\n\nYes, we became very wakeful; so much so that our recumbent position\nbegan to grow wearisome, and by little and little we found ourselves\nsitting up; the clothes well tucked around us, leaning against the\nhead-board with our four knees drawn up close together, and our two\nnoses bending over them, as if our kneepans were warming-pans.  We\nfelt very nice and snug, the more so since it was so chilly out of\ndoors; indeed out of bed-clothes too, seeing that there was no fire\nin the room.  The more so, I say, because truly to enjoy bodily\nwarmth, some small part of you must be cold, for there is no quality\nin this world that is not what it is merely by contrast.  Nothing\nexists in itself.  If you flatter yourself that you are all over\ncomfortable, and have been so a long time, then you cannot be said to\nbe comfortable any more.  But if, like Queequeg and me in the bed,\nthe tip of your nose or the crown of your head be slightly chilled,\nwhy then, indeed, in the general consciousness you feel most\ndelightfully and unmistakably warm.  For this reason a sleeping\napartment should never be furnished with a fire, which is one of the\nluxurious discomforts of the rich.  For the height of this sort of\ndeliciousness is to have nothing but the blanket between you and\nyour snugness and the cold of the outer air.  Then there you lie like\nthe one warm spark in the heart of an arctic crystal.\n\nWe had been sitting in this crouching manner for some time, when all\nat once I thought I would open my eyes; for when between sheets,\nwhether by day or by night, and whether asleep or awake, I have a way\nof always keeping my eyes shut, in order the more to concentrate the\nsnugness of being in bed.  Because no man can ever feel his own\nidentity aright except his eyes be closed; as if darkness were\nindeed the proper element of our essences, though light be more\ncongenial to our clayey part.  Upon opening my eyes then, and coming\nout of my own pleasant and self-created darkness into the imposed and\ncoarse outer gloom of the unilluminated twelve-o'clock-at-night, I\nexperienced a disagreeable revulsion.  Nor did I at all object to the\nhint from Queequeg that perhaps it were best to strike a light,\nseeing that we were so wide awake; and besides he felt a strong\ndesire to have a few quiet puffs from his Tomahawk.  Be it said, that\nthough I had felt such a strong repugnance to his smoking in the bed\nthe night before, yet see how elastic our stiff prejudices grow when\nlove once comes to bend them.  For now I liked nothing better than\nto have Queequeg smoking by me, even in bed, because he seemed to be\nfull of such serene household joy then.  I no more felt unduly\nconcerned for the landlord's policy of insurance.  I was only alive\nto the condensed confidential comfortableness of sharing a pipe and a\nblanket with a real friend.  With our shaggy jackets drawn about our\nshoulders, we now passed the Tomahawk from one to the other, till\nslowly there grew over us a blue hanging tester of smoke, illuminated\nby the flame of the new-lit lamp.\n\nWhether it was that this undulating tester rolled the savage away to\nfar distant scenes, I know not, but he now spoke of his native\nisland; and, eager to hear his history, I begged him to go on and\ntell it.  He gladly complied.  Though at the time I but ill\ncomprehended not a few of his words, yet subsequent disclosures, when\nI had become more familiar with his broken phraseology, now enable me\nto present the whole story such as it may prove in the mere skeleton\nI give.\n\n\n\nCHAPTER 12\n\nBiographical.\n\n\nQueequeg was a native of Rokovoko, an island far away to the West\nand South.  It is not down in any map; true places never are.\n\nWhen a new-hatched savage running wild about his native woodlands in\na grass clout, followed by the nibbling goats, as if he were a green\nsapling; even then, in Queequeg's ambitious soul, lurked a strong\ndesire to see something more of Christendom than a specimen whaler or\ntwo.  His father was a High Chief, a King; his uncle a High Priest;\nand on the maternal side he boasted aunts who were the wives of\nunconquerable warriors.  There was excellent blood in his\nveins--royal stuff; though sadly vitiated, I fear, by the cannibal\npropensity he nourished in his untutored youth.\n\nA Sag Harbor ship visited his father's bay, and Queequeg sought a\npassage to Christian lands.  But the ship, having her full complement\nof seamen, spurned his suit; and not all the King his father's\ninfluence could prevail.  But Queequeg vowed a vow.  Alone in his\ncanoe, he paddled off to a distant strait, which he knew the ship\nmust pass through when she quitted the island.  On one side was a\ncoral reef; on the other a low tongue of land, covered with mangrove\nthickets that grew out into the water.  Hiding his canoe, still\nafloat, among these thickets, with its prow seaward, he sat down in\nthe stern, paddle low in hand; and when the ship was gliding by, like\na flash he darted out; gained her side; with one backward dash of his\nfoot capsized and sank his canoe; climbed up the chains; and throwing\nhimself at full length upon the deck, grappled a ring-bolt there, and\nswore not to let it go, though hacked in pieces.\n\nIn vain the captain threatened to throw him overboard; suspended a\ncutlass over his naked wrists; Queequeg was the son of a King, and\nQueequeg budged not.  Struck by his desperate dauntlessness, and his\nwild desire to visit Christendom, the captain at last relented, and\ntold him he might make himself at home.  But this fine young\nsavage--this sea Prince of Wales, never saw the Captain's cabin.\nThey put him down among the sailors, and made a whaleman of him.  But\nlike Czar Peter content to toil in the shipyards of foreign cities,\nQueequeg disdained no seeming ignominy, if thereby he might happily\ngain the power of enlightening his untutored countrymen.  For at\nbottom--so he told me--he was actuated by a profound desire to learn\namong the Christians, the arts whereby to make his people still\nhappier than they were; and more than that, still better than they\nwere.  But, alas! the practices of whalemen soon convinced him that\neven Christians could be both miserable and wicked; infinitely more\nso, than all his father's heathens.  Arrived at last in old Sag\nHarbor; and seeing what the sailors did there; and then going on to\nNantucket, and seeing how they spent their wages in that place also,\npoor Queequeg gave it up for lost.  Thought he, it's a wicked world\nin all meridians; I'll die a pagan.\n\nAnd thus an old idolator at heart, he yet lived among these\nChristians, wore their clothes, and tried to talk their gibberish.\nHence the queer ways about him, though now some time from home.\n\nBy hints, I asked him whether he did not propose going back, and\nhaving a coronation; since he might now consider his father dead and\ngone, he being very old and feeble at the last accounts.  He answered\nno, not yet; and added that he was fearful Christianity, or rather\nChristians, had unfitted him for ascending the pure and undefiled\nthrone of thirty pagan Kings before him.  But by and by, he said, he\nwould return,--as soon as he felt himself baptized again.  For the\nnonce, however, he proposed to sail about, and sow his wild oats in\nall four oceans.  They had made a harpooneer of him, and that barbed\niron was in lieu of a sceptre now.\n\nI asked him what might be his immediate purpose, touching his future\nmovements.  He answered, to go to sea again, in his old vocation.\nUpon this, I told him that whaling was my own design, and informed\nhim of my intention to sail out of Nantucket, as being the most\npromising port for an adventurous whaleman to embark from.  He at\nonce resolved to accompany me to that island, ship aboard the same\nvessel, get into the same watch, the same boat, the same mess with\nme, in short to share my every hap; with both my hands in his, boldly\ndip into the Potluck of both worlds.  To all this I joyously\nassented; for besides the affection I now felt for Queequeg, he was\nan experienced harpooneer, and as such, could not fail to be of great\nusefulness to one, who, like me, was wholly ignorant of the mysteries\nof whaling, though well acquainted with the sea, as known to merchant\nseamen.\n\nHis story being ended with his pipe's last dying puff, Queequeg\nembraced me, pressed his forehead against mine, and blowing out the\nlight, we rolled over from each other, this way and that, and very\nsoon were sleeping.\n\n\nCHAPTER 13\n\nWheelbarrow.\n\n\nNext morning, Monday, after disposing of the embalmed head to a\nbarber, for a block, I settled my own and comrade's bill; using,\nhowever, my comrade's money.  The grinning landlord, as well as the\nboarders, seemed amazingly tickled at the sudden friendship which had\nsprung up between me and Queequeg--especially as Peter Coffin's cock\nand bull stories about him had previously so much alarmed me\nconcerning the very person whom I now companied with.\n\nWe borrowed a wheelbarrow, and embarking our things, including my own\npoor carpet-bag, and Queequeg's canvas sack and hammock, away we went\ndown to \"the Moss,\" the little Nantucket packet schooner moored at\nthe wharf.  As we were going along the people stared; not at Queequeg\nso much--for they were used to seeing cannibals like him in their\nstreets,--but at seeing him and me upon such confidential terms.  But\nwe heeded them not, going along wheeling the barrow by turns, and\nQueequeg now and then stopping to adjust the sheath on his harpoon\nbarbs.  I asked him why he carried such a troublesome thing with him\nashore, and whether all whaling ships did not find their own\nharpoons.  To this, in substance, he replied, that though what I\nhinted was true enough, yet he had a particular affection for his own\nharpoon, because it was of assured stuff, well tried in many a mortal\ncombat, and deeply intimate with the hearts of whales.  In short,\nlike many inland reapers and mowers, who go into the farmers' meadows\narmed with their own scythes--though in no wise obliged to furnish\nthem--even so, Queequeg, for his own private reasons, preferred his\nown harpoon.\n\nShifting the barrow from my hand to his, he told me a funny story\nabout the first wheelbarrow he had ever seen.  It was in Sag Harbor.\nThe owners of his ship, it seems, had lent him one, in which to carry\nhis heavy chest to his boarding house.  Not to seem ignorant about\nthe thing--though in truth he was entirely so, concerning the precise\nway in which to manage the barrow--Queequeg puts his chest upon it;\nlashes it fast; and then shoulders the barrow and marches up the\nwharf.  \"Why,\" said I, \"Queequeg, you might have known better than\nthat, one would think.  Didn't the people laugh?\"\n\nUpon this, he told me another story.  The people of his island of\nRokovoko, it seems, at their wedding feasts express the fragrant\nwater of young cocoanuts into a large stained calabash like a\npunchbowl; and this punchbowl always forms the great central ornament\non the braided mat where the feast is held.  Now a certain grand\nmerchant ship once touched at Rokovoko, and its commander--from all\naccounts, a very stately punctilious gentleman, at least for a sea\ncaptain--this commander was invited to the wedding feast of\nQueequeg's sister, a pretty young princess just turned of ten.  Well;\nwhen all the wedding guests were assembled at the bride's bamboo\ncottage, this Captain marches in, and being assigned the post of\nhonour, placed himself over against the punchbowl, and between the\nHigh Priest and his majesty the King, Queequeg's father.  Grace being\nsaid,--for those people have their grace as well as we--though\nQueequeg told me that unlike us, who at such times look downwards to\nour platters, they, on the contrary, copying the ducks, glance\nupwards to the great Giver of all feasts--Grace, I say, being said,\nthe High Priest opens the banquet by the immemorial ceremony of the\nisland; that is, dipping his consecrated and consecrating fingers\ninto the bowl before the blessed beverage circulates.  Seeing himself\nplaced next the Priest, and noting the ceremony, and thinking\nhimself--being Captain of a ship--as having plain precedence over a\nmere island King, especially in the King's own house--the Captain\ncoolly proceeds to wash his hands in the punchbowl;--taking it I\nsuppose for a huge finger-glass.  \"Now,\" said Queequeg, \"what you\ntink now?--Didn't our people laugh?\"\n\nAt last, passage paid, and luggage safe, we stood on board the\nschooner.  Hoisting sail, it glided down the Acushnet river.  On one\nside, New Bedford rose in terraces of streets, their ice-covered\ntrees all glittering in the clear, cold air.  Huge hills and\nmountains of casks on casks were piled upon her wharves, and side by\nside the world-wandering whale ships lay silent and safely moored at\nlast; while from others came a sound of carpenters and coopers, with\nblended noises of fires and forges to melt the pitch, all betokening\nthat new cruises were on the start; that one most perilous and long\nvoyage ended, only begins a second; and a second ended, only begins a\nthird, and so on, for ever and for aye.  Such is the endlessness,\nyea, the intolerableness of all earthly effort.\n\nGaining the more open water, the bracing breeze waxed fresh; the\nlittle Moss tossed the quick foam from her bows, as a young colt his\nsnortings.  How I snuffed that Tartar air!--how I spurned that\nturnpike earth!--that common highway all over dented with the marks\nof slavish heels and hoofs; and turned me to admire the magnanimity\nof the sea which will permit no records.\n\nAt the same foam-fountain, Queequeg seemed to drink and reel with me.\nHis dusky nostrils swelled apart; he showed his filed and pointed\nteeth.  On, on we flew; and our offing gained, the Moss did homage to\nthe blast; ducked and dived her bows as a slave before the Sultan.\nSideways leaning, we sideways darted; every ropeyarn tingling like a\nwire; the two tall masts buckling like Indian canes in land\ntornadoes.  So full of this reeling scene were we, as we stood by the\nplunging bowsprit, that for some time we did not notice the jeering\nglances of the passengers, a lubber-like assembly, who marvelled that\ntwo fellow beings should be so companionable; as though a white man\nwere anything more dignified than a whitewashed negro.  But there\nwere some boobies and bumpkins there, who, by their intense\ngreenness, must have come from the heart and centre of all verdure.\nQueequeg caught one of these young saplings mimicking him behind his\nback.  I thought the bumpkin's hour of doom was come.  Dropping his\nharpoon, the brawny savage caught him in his arms, and by an almost\nmiraculous dexterity and strength, sent him high up bodily into the\nair; then slightly tapping his stern in mid-somerset, the fellow\nlanded with bursting lungs upon his feet, while Queequeg, turning his\nback upon him, lighted his tomahawk pipe and passed it to me for a\npuff.\n\n\"Capting!  Capting! yelled the bumpkin, running towards that officer;\n\"Capting, Capting, here's the devil.\"\n\n\"Hallo, YOU sir,\" cried the Captain, a gaunt rib of the sea, stalking\nup to Queequeg, \"what in thunder do you mean by that?  Don't you know\nyou might have killed that chap?\"\n\n\"What him say?\" said Queequeg, as he mildly turned to me.\n\n\"He say,\" said I, \"that you came near kill-e that man there,\"\npointing to the still shivering greenhorn.\n\n\"Kill-e,\" cried Queequeg, twisting his tattooed face into an\nunearthly expression of disdain, \"ah! him bevy small-e fish-e;\nQueequeg no kill-e so small-e fish-e; Queequeg kill-e big whale!\"\n\n\"Look you,\" roared the Captain, \"I'll kill-e YOU, you cannibal, if\nyou try any more of your tricks aboard here; so mind your eye.\"\n\nBut it so happened just then, that it was high time for the Captain\nto mind his own eye.  The prodigious strain upon the main-sail had\nparted the weather-sheet, and the tremendous boom was now flying from\nside to side, completely sweeping the entire after part of the deck.\nThe poor fellow whom Queequeg had handled so roughly, was swept\noverboard; all hands were in a panic; and to attempt snatching at the\nboom to stay it, seemed madness.  It flew from right to left, and\nback again, almost in one ticking of a watch, and every instant\nseemed on the point of snapping into splinters.  Nothing was done,\nand nothing seemed capable of being done; those on deck rushed\ntowards the bows, and stood eyeing the boom as if it were the lower\njaw of an exasperated whale.  In the midst of this consternation,\nQueequeg dropped deftly to his knees, and crawling under the path of\nthe boom, whipped hold of a rope, secured one end to the bulwarks,\nand then flinging the other like a lasso, caught it round the boom as\nit swept over his head, and at the next jerk, the spar was that way\ntrapped, and all was safe.  The schooner was run into the wind, and\nwhile the hands were clearing away the stern boat, Queequeg, stripped\nto the waist, darted from the side with a long living arc of a leap.\nFor three minutes or more he was seen swimming like a dog, throwing\nhis long arms straight out before him, and by turns revealing his\nbrawny shoulders through the freezing foam.  I looked at the grand\nand glorious fellow, but saw no one to be saved.  The greenhorn had\ngone down.  Shooting himself perpendicularly from the water,\nQueequeg, now took an instant's glance around him, and seeming to see\njust how matters were, dived down and disappeared.  A few minutes\nmore, and he rose again, one arm still striking out, and with the\nother dragging a lifeless form.  The boat soon picked them up.  The\npoor bumpkin was restored.  All hands voted Queequeg a noble trump;\nthe captain begged his pardon.  From that hour I clove to Queequeg\nlike a barnacle; yea, till poor Queequeg took his last long dive.\n\nWas there ever such unconsciousness?  He did not seem to think that\nhe at all deserved a medal from the Humane and Magnanimous Societies.\nHe only asked for water--fresh water--something to wipe the brine\noff; that done, he put on dry clothes, lighted his pipe, and leaning\nagainst the bulwarks, and mildly eyeing those around him, seemed to\nbe saying to himself--\"It's a mutual, joint-stock world, in all\nmeridians.  We cannibals must help these Christians.\"\n\n\n\nCHAPTER 14\n\nNantucket.\n\n\nNothing more happened on the passage worthy the mentioning; so, after\na fine run, we safely arrived in Nantucket.\n\nNantucket!  Take out your map and look at it.  See what a real corner\nof the world it occupies; how it stands there, away off shore, more\nlonely than the Eddystone lighthouse.  Look at it--a mere hillock,\nand elbow of sand; all beach, without a background.  There is more\nsand there than you would use in twenty years as a substitute for\nblotting paper.  Some gamesome wights will tell you that they have to\nplant weeds there, they don't grow naturally; that they import Canada\nthistles; that they have to send beyond seas for a spile to stop a\nleak in an oil cask; that pieces of wood in Nantucket are carried\nabout like bits of the true cross in Rome; that people there plant\ntoadstools before their houses, to get under the shade in summer\ntime; that one blade of grass makes an oasis, three blades in a day's\nwalk a prairie; that they wear quicksand shoes, something like\nLaplander snow-shoes; that they are so shut up, belted about, every\nway inclosed, surrounded, and made an utter island of by the ocean,\nthat to their very chairs and tables small clams will sometimes be\nfound adhering, as to the backs of sea turtles.  But these\nextravaganzas only show that Nantucket is no Illinois.\n\nLook now at the wondrous traditional story of how this island was\nsettled by the red-men.  Thus goes the legend.  In olden times an\neagle swooped down upon the New England coast, and carried off an\ninfant Indian in his talons.  With loud lament the parents saw their\nchild borne out of sight over the wide waters.  They resolved to\nfollow in the same direction.  Setting out in their canoes, after a\nperilous passage they discovered the island, and there they found an\nempty ivory casket,--the poor little Indian's skeleton.\n\nWhat wonder, then, that these Nantucketers, born on a beach, should\ntake to the sea for a livelihood!  They first caught crabs and\nquohogs in the sand; grown bolder, they waded out with nets for\nmackerel; more experienced, they pushed off in boats and captured\ncod; and at last, launching a navy of great ships on the sea,\nexplored this watery world; put an incessant belt of\ncircumnavigations round it; peeped in at Behring's Straits; and in\nall seasons and all oceans declared everlasting war with the\nmightiest animated mass that has survived the flood; most monstrous\nand most mountainous!  That Himmalehan, salt-sea Mastodon, clothed\nwith such portentousness of unconscious power, that his very panics\nare more to be dreaded than his most fearless and malicious assaults!\n\nAnd thus have these naked Nantucketers, these sea hermits, issuing\nfrom their ant-hill in the sea, overrun and conquered the watery\nworld like so many Alexanders; parcelling out among them the\nAtlantic, Pacific, and Indian oceans, as the three pirate powers did\nPoland.  Let America add Mexico to Texas, and pile Cuba upon Canada;\nlet the English overswarm all India, and hang out their blazing\nbanner from the sun; two thirds of this terraqueous globe are the\nNantucketer's.  For the sea is his; he owns it, as Emperors own\nempires; other seamen having but a right of way through it.  Merchant\nships are but extension bridges; armed ones but floating forts; even\npirates and privateers, though following the sea as highwaymen the\nroad, they but plunder other ships, other fragments of the land like\nthemselves, without seeking to draw their living from the bottomless\ndeep itself.  The Nantucketer, he alone resides and riots on the sea;\nhe alone, in Bible language, goes down to it in ships; to and fro\nploughing it as his own special plantation.  THERE is his home; THERE\nlies his business, which a Noah's flood would not interrupt, though\nit overwhelmed all the millions in China.  He lives on the sea, as\nprairie cocks in the prairie; he hides among the waves, he climbs\nthem as chamois hunters climb the Alps.  For years he knows not the\nland; so that when he comes to it at last, it smells like another\nworld, more strangely than the moon would to an Earthsman.  With the\nlandless gull, that at sunset folds her wings and is rocked to sleep\nbetween billows; so at nightfall, the Nantucketer, out of sight of\nland, furls his sails, and lays him to his rest, while under his very\npillow rush herds of walruses and whales.\n\n\n\nCHAPTER 15\n\nChowder.\n\n\nIt was quite late in the evening when the little Moss came snugly to\nanchor, and Queequeg and I went ashore; so we could attend to no\nbusiness that day, at least none but a supper and a bed.  The\nlandlord of the Spouter-Inn had recommended us to his cousin Hosea\nHussey of the Try Pots, whom he asserted to be the proprietor of one\nof the best kept hotels in all Nantucket, and moreover he had assured\nus that Cousin Hosea, as he called him, was famous for his chowders.\nIn short, he plainly hinted that we could not possibly do better than\ntry pot-luck at the Try Pots.  But the directions he had given us\nabout keeping a yellow warehouse on our starboard hand till we opened\na white church to the larboard, and then keeping that on the larboard\nhand till we made a corner three points to the starboard, and that\ndone, then ask the first man we met where the place was: these\ncrooked directions of his very much puzzled us at first, especially\nas, at the outset, Queequeg insisted that the yellow warehouse--our\nfirst point of departure--must be left on the larboard hand, whereas\nI had understood Peter Coffin to say it was on the starboard.\nHowever, by dint of beating about a little in the dark, and now and\nthen knocking up a peaceable inhabitant to inquire the way, we at\nlast came to something which there was no mistaking.\n\nTwo enormous wooden pots painted black, and suspended by asses' ears,\nswung from the cross-trees of an old top-mast, planted in front of an\nold doorway.  The horns of the cross-trees were sawed off on the\nother side, so that this old top-mast looked not a little like a\ngallows.  Perhaps I was over sensitive to such impressions at the\ntime, but I could not help staring at this gallows with a vague\nmisgiving.  A sort of crick was in my neck as I gazed up to the two\nremaining horns; yes, TWO of them, one for Queequeg, and one for me.\nIt's ominous, thinks I.  A Coffin my Innkeeper upon landing in my\nfirst whaling port; tombstones staring at me in the whalemen's\nchapel; and here a gallows! and a pair of prodigious black pots too!\nAre these last throwing out oblique hints touching Tophet?\n\nI was called from these reflections by the sight of a freckled woman\nwith yellow hair and a yellow gown, standing in the porch of the inn,\nunder a dull red lamp swinging there, that looked much like an\ninjured eye, and carrying on a brisk scolding with a man in a purple\nwoollen shirt.\n\n\"Get along with ye,\" said she to the man, \"or I'll be combing ye!\"\n\n\"Come on, Queequeg,\" said I, \"all right.  There's Mrs. Hussey.\"\n\nAnd so it turned out; Mr. Hosea Hussey being from home, but leaving\nMrs. Hussey entirely competent to attend to all his affairs.  Upon\nmaking known our desires for a supper and a bed, Mrs. Hussey,\npostponing further scolding for the present, ushered us into a little\nroom, and seating us at a table spread with the relics of a recently\nconcluded repast, turned round to us and said--\"Clam or Cod?\"\n\n\"What's that about Cods, ma'am?\" said I, with much politeness.\n\n\"Clam or Cod?\" she repeated.\n\n\"A clam for supper? a cold clam; is THAT what you mean, Mrs. Hussey?\"\nsays I, \"but that's a rather cold and clammy reception in the winter\ntime, ain't it, Mrs. Hussey?\"\n\nBut being in a great hurry to resume scolding the man in the purple\nShirt, who was waiting for it in the entry, and seeming to hear\nnothing but the word \"clam,\" Mrs. Hussey hurried towards an open door\nleading to the kitchen, and bawling out \"clam for two,\" disappeared.\n\n\"Queequeg,\" said I, \"do you think that we can make out a supper for\nus both on one clam?\"\n\nHowever, a warm savory steam from the kitchen served to belie the\napparently cheerless prospect before us.  But when that smoking\nchowder came in, the mystery was delightfully explained.  Oh, sweet\nfriends! hearken to me.  It was made of small juicy clams, scarcely\nbigger than hazel nuts, mixed with pounded ship biscuit, and salted\npork cut up into little flakes; the whole enriched with butter, and\nplentifully seasoned with pepper and salt.  Our appetites being\nsharpened by the frosty voyage, and in particular, Queequeg seeing\nhis favourite fishing food before him, and the chowder being\nsurpassingly excellent, we despatched it with great expedition: when\nleaning back a moment and bethinking me of Mrs. Hussey's clam and cod\nannouncement, I thought I would try a little experiment.  Stepping to\nthe kitchen door, I uttered the word \"cod\" with great emphasis, and\nresumed my seat.  In a few moments the savoury steam came forth\nagain, but with a different flavor, and in good time a fine\ncod-chowder was placed before us.\n\nWe resumed business; and while plying our spoons in the bowl, thinks\nI to myself, I wonder now if this here has any effect on the head?\nWhat's that stultifying saying about chowder-headed people?  \"But\nlook, Queequeg, ain't that a live eel in your bowl?  Where's your\nharpoon?\"\n\nFishiest of all fishy places was the Try Pots, which well deserved\nits name; for the pots there were always boiling chowders.  Chowder\nfor breakfast, and chowder for dinner, and chowder for supper, till\nyou began to look for fish-bones coming through your clothes.  The\narea before the house was paved with clam-shells.  Mrs. Hussey wore a\npolished necklace of codfish vertebra; and Hosea Hussey had his\naccount books bound in superior old shark-skin.  There was a fishy\nflavor to the milk, too, which I could not at all account for, till\none morning happening to take a stroll along the beach among some\nfishermen's boats, I saw Hosea's brindled cow feeding on fish\nremnants, and marching along the sand with each foot in a cod's\ndecapitated head, looking very slip-shod, I assure ye.\n\nSupper concluded, we received a lamp, and directions from Mrs. Hussey\nconcerning the nearest way to bed; but, as Queequeg was about to\nprecede me up the stairs, the lady reached forth her arm, and\ndemanded his harpoon; she allowed no harpoon in her chambers.  \"Why\nnot? said I; \"every true whaleman sleeps with his harpoon--but why\nnot?\"  \"Because it's dangerous,\" says she.  \"Ever since young Stiggs\ncoming from that unfort'nt v'y'ge of his, when he was gone four years\nand a half, with only three barrels of ILE, was found dead in my\nfirst floor back, with his harpoon in his side; ever since then I\nallow no boarders to take sich dangerous weepons in their rooms at\nnight.  So, Mr. Queequeg\" (for she had learned his name), \"I will\njust take this here iron, and keep it for you till morning.  But the\nchowder; clam or cod to-morrow for breakfast, men?\"\n\n\"Both,\" says I; \"and let's have a couple of smoked herring by way of\nvariety.\"\n\n\n\nCHAPTER 16\n\nThe Ship.\n\n\nIn bed we concocted our plans for the morrow.  But to my surprise and\nno small concern, Queequeg now gave me to understand, that he had\nbeen diligently consulting Yojo--the name of his black little\ngod--and Yojo had told him two or three times over, and strongly\ninsisted upon it everyway, that instead of our going together among\nthe whaling-fleet in harbor, and in concert selecting our craft;\ninstead of this, I say, Yojo earnestly enjoined that the selection of\nthe ship should rest wholly with me, inasmuch as Yojo purposed\nbefriending us; and, in order to do so, had already pitched upon a\nvessel, which, if left to myself, I, Ishmael, should infallibly light\nupon, for all the world as though it had turned out by chance; and in\nthat vessel I must immediately ship myself, for the present\nirrespective of Queequeg.\n\nI have forgotten to mention that, in many things, Queequeg placed\ngreat confidence in the excellence of Yojo's judgment and surprising\nforecast of things; and cherished Yojo with considerable esteem, as a\nrather good sort of god, who perhaps meant well enough upon the\nwhole, but in all cases did not succeed in his benevolent designs.\n\nNow, this plan of Queequeg's, or rather Yojo's, touching the\nselection of our craft; I did not like that plan at all.  I had not a\nlittle relied upon Queequeg's sagacity to point out the whaler best\nfitted to carry us and our fortunes securely.  But as all my\nremonstrances produced no effect upon Queequeg, I was obliged to\nacquiesce; and accordingly prepared to set about this business with a\ndetermined rushing sort of energy and vigor, that should quickly\nsettle that trifling little affair.  Next morning early, leaving\nQueequeg shut up with Yojo in our little bedroom--for it seemed that\nit was some sort of Lent or Ramadan, or day of fasting, humiliation,\nand prayer with Queequeg and Yojo that day; HOW it was I never could\nfind out, for, though I applied myself to it several times, I never\ncould master his liturgies and XXXIX Articles--leaving Queequeg,\nthen, fasting on his tomahawk pipe, and Yojo warming himself at his\nsacrificial fire of shavings, I sallied out among the shipping.\nAfter much prolonged sauntering and many random inquiries, I learnt\nthat there were three ships up for three-years' voyages--The\nDevil-dam, the Tit-bit, and the Pequod.  DEVIL-DAM, I do not know\nthe origin of; TIT-BIT is obvious; PEQUOD, you will no doubt\nremember, was the name of a celebrated tribe of Massachusetts\nIndians; now extinct as the ancient Medes.  I peered and pryed about\nthe Devil-dam; from her, hopped over to the Tit-bit; and finally,\ngoing on board the Pequod, looked around her for a moment, and then\ndecided that this was the very ship for us.\n\nYou may have seen many a quaint craft in your day, for aught I\nknow;--square-toed luggers; mountainous Japanese junks; butter-box\ngalliots, and what not; but take my word for it, you never saw such a\nrare old craft as this same rare old Pequod.  She was a ship of the\nold school, rather small if anything; with an old-fashioned\nclaw-footed look about her.  Long seasoned and weather-stained in the\ntyphoons and calms of all four oceans, her old hull's complexion was\ndarkened like a French grenadier's, who has alike fought in Egypt and\nSiberia.  Her venerable bows looked bearded.  Her masts--cut\nsomewhere on the coast of Japan, where her original ones were lost\noverboard in a gale--her masts stood stiffly up like the spines of\nthe three old kings of Cologne.  Her ancient decks were worn and\nwrinkled, like the pilgrim-worshipped flag-stone in Canterbury\nCathedral where Becket bled.  But to all these her old antiquities,\nwere added new and marvellous features, pertaining to the wild\nbusiness that for more than half a century she had followed.  Old\nCaptain Peleg, many years her chief-mate, before he commanded another\nvessel of his own, and now a retired seaman, and one of the principal\nowners of the Pequod,--this old Peleg, during the term of his\nchief-mateship, had built upon her original grotesqueness, and inlaid\nit, all over, with a quaintness both of material and device,\nunmatched by anything except it be Thorkill-Hake's carved buckler or\nbedstead.  She was apparelled like any barbaric Ethiopian emperor,\nhis neck heavy with pendants of polished ivory.  She was a thing of\ntrophies.  A cannibal of a craft, tricking herself forth in the\nchased bones of her enemies.  All round, her unpanelled, open\nbulwarks were garnished like one continuous jaw, with the long sharp\nteeth of the sperm whale, inserted there for pins, to fasten her old\nhempen thews and tendons to.  Those thews ran not through base blocks\nof land wood, but deftly travelled over sheaves of sea-ivory.\nScorning a turnstile wheel at her reverend helm, she sported there a\ntiller; and that tiller was in one mass, curiously carved from the\nlong narrow lower jaw of her hereditary foe.  The helmsman who\nsteered by that tiller in a tempest, felt like the Tartar, when he\nholds back his fiery steed by clutching its jaw.  A noble craft, but\nsomehow a most melancholy!  All noble things are touched with that.\n\nNow when I looked about the quarter-deck, for some one having\nauthority, in order to propose myself as a candidate for the voyage,\nat first I saw nobody; but I could not well overlook a strange sort\nof tent, or rather wigwam, pitched a little behind the main-mast.  It\nseemed only a temporary erection used in port.  It was of a conical\nshape, some ten feet high; consisting of the long, huge slabs of\nlimber black bone taken from the middle and highest part of the jaws\nof the right-whale.  Planted with their broad ends on the deck, a\ncircle of these slabs laced together, mutually sloped towards each\nother, and at the apex united in a tufted point, where the loose\nhairy fibres waved to and fro like the top-knot on some old\nPottowottamie Sachem's head.  A triangular opening faced towards the\nbows of the ship, so that the insider commanded a complete view\nforward.\n\nAnd half concealed in this queer tenement, I at length found one who\nby his aspect seemed to have authority; and who, it being noon, and\nthe ship's work suspended, was now enjoying respite from the burden\nof command.  He was seated on an old-fashioned oaken chair, wriggling\nall over with curious carving; and the bottom of which was formed of\na stout interlacing of the same elastic stuff of which the wigwam was\nconstructed.\n\nThere was nothing so very particular, perhaps, about the appearance\nof the elderly man I saw; he was brown and brawny, like most old\nseamen, and heavily rolled up in blue pilot-cloth, cut in the Quaker\nstyle; only there was a fine and almost microscopic net-work of the\nminutest wrinkles interlacing round his eyes, which must have arisen\nfrom his continual sailings in many hard gales, and always looking to\nwindward;--for this causes the muscles about the eyes to become\npursed together.  Such eye-wrinkles are very effectual in a scowl.\n\n\"Is this the Captain of the Pequod?\" said I, advancing to the door of\nthe tent.\n\n\"Supposing it be the captain of the Pequod, what dost thou want of\nhim?\" he demanded.\n\n\"I was thinking of shipping.\"\n\n\"Thou wast, wast thou?  I see thou art no Nantucketer--ever been in\na stove boat?\"\n\n\"No, Sir, I never have.\"\n\n\"Dost know nothing at all about whaling, I dare say--eh?\n\n\"Nothing, Sir; but I have no doubt I shall soon learn.  I've been\nseveral voyages in the merchant service, and I think that--\"\n\n\"Merchant service be damned.  Talk not that lingo to me.  Dost see\nthat leg?--I'll take that leg away from thy stern, if ever thou\ntalkest of the marchant service to me again.  Marchant service\nindeed!  I suppose now ye feel considerable proud of having served in\nthose marchant ships.  But flukes! man, what makes thee want to go a\nwhaling, eh?--it looks a little suspicious, don't it, eh?--Hast not\nbeen a pirate, hast thou?--Didst not rob thy last Captain, didst\nthou?--Dost not think of murdering the officers when thou gettest to\nsea?\"\n\nI protested my innocence of these things.  I saw that under the mask\nof these half humorous innuendoes, this old seaman, as an insulated\nQuakerish Nantucketer, was full of his insular prejudices, and rather\ndistrustful of all aliens, unless they hailed from Cape Cod or the\nVineyard.\n\n\"But what takes thee a-whaling?  I want to know that before I think\nof shipping ye.\"\n\n\"Well, sir, I want to see what whaling is.  I want to see the world.\"\n\n\"Want to see what whaling is, eh?  Have ye clapped eye on Captain\nAhab?\"\n\n\"Who is Captain Ahab, sir?\"\n\n\"Aye, aye, I thought so.  Captain Ahab is the Captain of this ship.\"\n\n\"I am mistaken then.  I thought I was speaking to the Captain\nhimself.\"\n\n\"Thou art speaking to Captain Peleg--that's who ye are speaking to,\nyoung man.  It belongs to me and Captain Bildad to see the Pequod\nfitted out for the voyage, and supplied with all her needs, including\ncrew.  We are part owners and agents.  But as I was going to say, if\nthou wantest to know what whaling is, as thou tellest ye do, I can\nput ye in a way of finding it out before ye bind yourself to it, past\nbacking out.  Clap eye on Captain Ahab, young man, and thou wilt find\nthat he has only one leg.\"\n\n\"What do you mean, sir?  Was the other one lost by a whale?\"\n\n\"Lost by a whale!  Young man, come nearer to me: it was devoured,\nchewed up, crunched by the monstrousest parmacetty that ever chipped\na boat!--ah, ah!\"\n\nI was a little alarmed by his energy, perhaps also a little touched\nat the hearty grief in his concluding exclamation, but said as calmly\nas I could, \"What you say is no doubt true enough, sir; but how could\nI know there was any peculiar ferocity in that particular whale,\nthough indeed I might have inferred as much from the simple fact of\nthe accident.\"\n\n\"Look ye now, young man, thy lungs are a sort of soft, d'ye see; thou\ndost not talk shark a bit.  SURE, ye've been to sea before now; sure\nof that?\"\n\n\"Sir,\" said I, \"I thought I told you that I had been four voyages in\nthe merchant--\"\n\n\"Hard down out of that!  Mind what I said about the marchant\nservice--don't aggravate me--I won't have it.  But let us understand\neach other.  I have given thee a hint about what whaling is; do ye\nyet feel inclined for it?\"\n\n\"I do, sir.\"\n\n\"Very good.  Now, art thou the man to pitch a harpoon down a live\nwhale's throat, and then jump after it?  Answer, quick!\"\n\n\"I am, sir, if it should be positively indispensable to do so; not to\nbe got rid of, that is; which I don't take to be the fact.\"\n\n\"Good again.  Now then, thou not only wantest to go a-whaling, to\nfind out by experience what whaling is, but ye also want to go in\norder to see the world?  Was not that what ye said?  I thought so.\nWell then, just step forward there, and take a peep over the\nweather-bow, and then back to me and tell me what ye see there.\"\n\nFor a moment I stood a little puzzled by this curious request, not\nknowing exactly how to take it, whether humorously or in earnest.\nBut concentrating all his crow's feet into one scowl, Captain Peleg\nstarted me on the errand.\n\nGoing forward and glancing over the weather bow, I perceived that the\nship swinging to her anchor with the flood-tide, was now obliquely\npointing towards the open ocean.  The prospect was unlimited, but\nexceedingly monotonous and forbidding; not the slightest variety that\nI could see.\n\n\"Well, what's the report?\" said Peleg when I came back; \"what did ye\nsee?\"\n\n\"Not much,\" I replied--\"nothing but water; considerable horizon\nthough, and there's a squall coming up, I think.\"\n\n\"Well, what does thou think then of seeing the world?  Do ye wish to\ngo round Cape Horn to see any more of it, eh?  Can't ye see the world\nwhere you stand?\"\n\nI was a little staggered, but go a-whaling I must, and I would; and\nthe Pequod was as good a ship as any--I thought the best--and all\nthis I now repeated to Peleg.  Seeing me so determined, he expressed\nhis willingness to ship me.\n\n\"And thou mayest as well sign the papers right off,\" he added--\"come\nalong with ye.\"  And so saying, he led the way below deck into the\ncabin.\n\nSeated on the transom was what seemed to me a most uncommon and\nsurprising figure.  It turned out to be Captain Bildad, who along\nwith Captain Peleg was one of the largest owners of the vessel; the\nother shares, as is sometimes the case in these ports, being held by\na crowd of old annuitants; widows, fatherless children, and chancery\nwards; each owning about the value of a timber head, or a foot of\nplank, or a nail or two in the ship.  People in Nantucket invest\ntheir money in whaling vessels, the same way that you do yours in\napproved state stocks bringing in good interest.\n\nNow, Bildad, like Peleg, and indeed many other Nantucketers, was a\nQuaker, the island having been originally settled by that sect; and\nto this day its inhabitants in general retain in an uncommon measure\nthe peculiarities of the Quaker, only variously and anomalously\nmodified by things altogether alien and heterogeneous.  For some of\nthese same Quakers are the most sanguinary of all sailors and\nwhale-hunters.  They are fighting Quakers; they are Quakers with a\nvengeance.\n\nSo that there are instances among them of men, who, named with\nScripture names--a singularly common fashion on the island--and in\nchildhood naturally imbibing the stately dramatic thee and thou of\nthe Quaker idiom; still, from the audacious, daring, and boundless\nadventure of their subsequent lives, strangely blend with these\nunoutgrown peculiarities, a thousand bold dashes of character, not\nunworthy a Scandinavian sea-king, or a poetical Pagan Roman.  And\nwhen these things unite in a man of greatly superior natural force,\nwith a globular brain and a ponderous heart; who has also by the\nstillness and seclusion of many long night-watches in the remotest\nwaters, and beneath constellations never seen here at the north, been\nled to think untraditionally and independently; receiving all\nnature's sweet or savage impressions fresh from her own virgin\nvoluntary and confiding breast, and thereby chiefly, but with some\nhelp from accidental advantages, to learn a bold and nervous lofty\nlanguage--that man makes one in a whole nation's census--a mighty\npageant creature, formed for noble tragedies.  Nor will it at all\ndetract from him, dramatically regarded, if either by birth or other\ncircumstances, he have what seems a half wilful overruling morbidness\nat the bottom of his nature.  For all men tragically great are made\nso through a certain morbidness.  Be sure of this, O young ambition,\nall mortal greatness is but disease.  But, as yet we have not to do\nwith such an one, but with quite another; and still a man, who, if\nindeed peculiar, it only results again from another phase of the\nQuaker, modified by individual circumstances.\n\nLike Captain Peleg, Captain Bildad was a well-to-do, retired\nwhaleman.  But unlike Captain Peleg--who cared not a rush for what\nare called serious things, and indeed deemed those self-same serious\nthings the veriest of all trifles--Captain Bildad had not only been\noriginally educated according to the strictest sect of Nantucket\nQuakerism, but all his subsequent ocean life, and the sight of many\nunclad, lovely island creatures, round the Horn--all that had not\nmoved this native born Quaker one single jot, had not so much as\naltered one angle of his vest.  Still, for all this immutableness,\nwas there some lack of common consistency about worthy Captain\nPeleg.  Though refusing, from conscientious scruples, to bear arms\nagainst land invaders, yet himself had illimitably invaded the\nAtlantic and Pacific; and though a sworn foe to human bloodshed, yet\nhad he in his straight-bodied coat, spilled tuns upon tuns of\nleviathan gore.  How now in the contemplative evening of his days,\nthe pious Bildad reconciled these things in the reminiscence, I do\nnot know; but it did not seem to concern him much, and very probably\nhe had long since come to the sage and sensible conclusion that a\nman's religion is one thing, and this practical world quite another.\nThis world pays dividends.  Rising from a little cabin-boy in short\nclothes of the drabbest drab, to a harpooneer in a broad shad-bellied\nwaistcoat; from that becoming boat-header, chief-mate, and captain,\nand finally a ship owner; Bildad, as I hinted before, had concluded\nhis adventurous career by wholly retiring from active life at the\ngoodly age of sixty, and dedicating his remaining days to the quiet\nreceiving of his well-earned income.\n\nNow, Bildad, I am sorry to say, had the reputation of being an\nincorrigible old hunks, and in his sea-going days, a bitter, hard\ntask-master.  They told me in Nantucket, though it certainly seems a\ncurious story, that when he sailed the old Categut whaleman, his\ncrew, upon arriving home, were mostly all carried ashore to the\nhospital, sore exhausted and worn out.  For a pious man, especially\nfor a Quaker, he was certainly rather hard-hearted, to say the\nleast.  He never used to swear, though, at his men, they said; but\nsomehow he got an inordinate quantity of cruel, unmitigated hard work\nout of them.  When Bildad was a chief-mate, to have his drab-coloured\neye intently looking at you, made you feel completely nervous, till\nyou could clutch something--a hammer or a marling-spike, and go to\nwork like mad, at something or other, never mind what.  Indolence and\nidleness perished before him.  His own person was the exact\nembodiment of his utilitarian character.  On his long, gaunt body, he\ncarried no spare flesh, no superfluous beard, his chin having a soft,\neconomical nap to it, like the worn nap of his broad-brimmed hat.\n\nSuch, then, was the person that I saw seated on the transom when I\nfollowed Captain Peleg down into the cabin.  The space between the\ndecks was small; and there, bolt-upright, sat old Bildad, who always\nsat so, and never leaned, and this to save his coat tails.  His\nbroad-brim was placed beside him; his legs were stiffly crossed; his\ndrab vesture was buttoned up to his chin; and spectacles on nose, he\nseemed absorbed in reading from a ponderous volume.\n\n\"Bildad,\" cried Captain Peleg, \"at it again, Bildad, eh?  Ye have\nbeen studying those Scriptures, now, for the last thirty years, to my\ncertain knowledge.  How far ye got, Bildad?\"\n\nAs if long habituated to such profane talk from his old shipmate,\nBildad, without noticing his present irreverence, quietly looked up,\nand seeing me, glanced again inquiringly towards Peleg.\n\n\"He says he's our man, Bildad,\" said Peleg, \"he wants to ship.\"\n\n\"Dost thee?\" said Bildad, in a hollow tone, and turning round to me.\n\n\"I dost,\" said I unconsciously, he was so intense a Quaker.\n\n\"What do ye think of him, Bildad?\" said Peleg.\n\n\"He'll do,\" said Bildad, eyeing me, and then went on spelling away at\nhis book in a mumbling tone quite audible.\n\nI thought him the queerest old Quaker I ever saw, especially as\nPeleg, his friend and old shipmate, seemed such a blusterer.  But I\nsaid nothing, only looking round me sharply.  Peleg now threw open a\nchest, and drawing forth the ship's articles, placed pen and ink\nbefore him, and seated himself at a little table.  I began to think\nit was high time to settle with myself at what terms I would be\nwilling to engage for the voyage.  I was already aware that in the\nwhaling business they paid no wages; but all hands, including the\ncaptain, received certain shares of the profits called lays, and that\nthese lays were proportioned to the degree of importance pertaining\nto the respective duties of the ship's company.  I was also aware\nthat being a green hand at whaling, my own lay would not be very\nlarge; but considering that I was used to the sea, could steer a\nship, splice a rope, and all that, I made no doubt that from all I\nhad heard I should be offered at least the 275th lay--that is, the\n275th part of the clear net proceeds of the voyage, whatever that\nmight eventually amount to.  And though the 275th lay was what they\ncall a rather LONG LAY, yet it was better than nothing; and if we had\na lucky voyage, might pretty nearly pay for the clothing I would wear\nout on it, not to speak of my three years' beef and board, for which\nI would not have to pay one stiver.\n\nIt might be thought that this was a poor way to accumulate a princely\nfortune--and so it was, a very poor way indeed.  But I am one of\nthose that never take on about princely fortunes, and am quite\ncontent if the world is ready to board and lodge me, while I am\nputting up at this grim sign of the Thunder Cloud.  Upon the whole, I\nthought that the 275th lay would be about the fair thing, but would not\nhave been surprised had I been offered the 200th, considering I was\nof a broad-shouldered make.\n\nBut one thing, nevertheless, that made me a little distrustful about\nreceiving a generous share of the profits was this: Ashore, I had\nheard something of both Captain Peleg and his unaccountable old crony\nBildad; how that they being the principal proprietors of the Pequod,\ntherefore the other and more inconsiderable and scattered owners,\nleft nearly the whole management of the ship's affairs to these two.\nAnd I did not know but what the stingy old Bildad might have a mighty\ndeal to say about shipping hands, especially as I now found him on\nboard the Pequod, quite at home there in the cabin, and reading his\nBible as if at his own fireside.  Now while Peleg was vainly trying\nto mend a pen with his jack-knife, old Bildad, to my no small\nsurprise, considering that he was such an interested party in these\nproceedings; Bildad never heeded us, but went on mumbling to himself\nout of his book, \"LAY not up for yourselves treasures upon earth,\nwhere moth--\"\n\n\"Well, Captain Bildad,\" interrupted Peleg, \"what d'ye say, what lay\nshall we give this young man?\"\n\n\"Thou knowest best,\" was the sepulchral reply, \"the seven hundred and\nseventy-seventh wouldn't be too much, would it?--'where moth and rust\ndo corrupt, but LAY--'\"\n\nLAY, indeed, thought I, and such a lay! the seven hundred and\nseventy-seventh!  Well, old Bildad, you are determined that I, for\none, shall not LAY up many LAYS here below, where moth and rust do\ncorrupt.  It was an exceedingly LONG LAY that, indeed; and though\nfrom the magnitude of the figure it might at first deceive a\nlandsman, yet the slightest consideration will show that though seven\nhundred and seventy-seven is a pretty large number, yet, when you\ncome to make a TEENTH of it, you will then see, I say, that the seven\nhundred and seventy-seventh part of a farthing is a good deal less\nthan seven hundred and seventy-seven gold doubloons; and so I thought\nat the time.\n\n\"Why, blast your eyes, Bildad,\" cried Peleg, \"thou dost not want to\nswindle this young man! he must have more than that.\"\n\n\"Seven hundred and seventy-seventh,\" again said Bildad, without\nlifting his eyes; and then went on mumbling--\"for where your treasure\nis, there will your heart be also.\"\n\n\"I am going to put him down for the three hundredth,\" said Peleg, \"do\nye hear that, Bildad!  The three hundredth lay, I say.\"\n\nBildad laid down his book, and turning solemnly towards him said,\n\"Captain Peleg, thou hast a generous heart; but thou must consider\nthe duty thou owest to the other owners of this ship--widows and\norphans, many of them--and that if we too abundantly reward the\nlabors of this young man, we may be taking the bread from those\nwidows and those orphans.  The seven hundred and seventy-seventh lay,\nCaptain Peleg.\"\n\n\"Thou Bildad!\" roared Peleg, starting up and clattering about the\ncabin.  \"Blast ye, Captain Bildad, if I had followed thy advice in\nthese matters, I would afore now had a conscience to lug about that\nwould be heavy enough to founder the largest ship that ever sailed\nround Cape Horn.\"\n\n\"Captain Peleg,\" said Bildad steadily, \"thy conscience may be drawing\nten inches of water, or ten fathoms, I can't tell; but as thou art\nstill an impenitent man, Captain Peleg, I greatly fear lest thy\nconscience be but a leaky one; and will in the end sink thee\nfoundering down to the fiery pit, Captain Peleg.\"\n\n\"Fiery pit! fiery pit! ye insult me, man; past all natural bearing,\nye insult me.  It's an all-fired outrage to tell any human creature\nthat he's bound to hell.  Flukes and flames!  Bildad, say that again\nto me, and start my soul-bolts, but I'll--I'll--yes, I'll swallow a\nlive goat with all his hair and horns on.  Out of the cabin, ye\ncanting, drab-coloured son of a wooden gun--a straight wake with ye!\"\n\nAs he thundered out this he made a rush at Bildad, but with a\nmarvellous oblique, sliding celerity, Bildad for that time eluded\nhim.\n\nAlarmed at this terrible outburst between the two principal and\nresponsible owners of the ship, and feeling half a mind to give up\nall idea of sailing in a vessel so questionably owned and temporarily\ncommanded, I stepped aside from the door to give egress to Bildad,\nwho, I made no doubt, was all eagerness to vanish from before the\nawakened wrath of Peleg.  But to my astonishment, he sat down again\non the transom very quietly, and seemed to have not the slightest\nintention of withdrawing.  He seemed quite used to impenitent Peleg\nand his ways.  As for Peleg, after letting off his rage as he had,\nthere seemed no more left in him, and he, too, sat down like a lamb,\nthough he twitched a little as if still nervously agitated.  \"Whew!\"\nhe whistled at last--\"the squall's gone off to leeward, I think.\nBildad, thou used to be good at sharpening a lance, mend that pen,\nwill ye.  My jack-knife here needs the grindstone.  That's he; thank\nye, Bildad.  Now then, my young man, Ishmael's thy name, didn't ye\nsay?  Well then, down ye go here, Ishmael, for the three hundredth\nlay.\"\n\n\"Captain Peleg,\" said I, \"I have a friend with me who wants to ship\ntoo--shall I bring him down to-morrow?\"\n\n\"To be sure,\" said Peleg.  \"Fetch him along, and we'll look at him.\"\n\n\"What lay does he want?\" groaned Bildad, glancing up from the book\nin which he had again been burying himself.\n\n\"Oh! never thee mind about that, Bildad,\" said Peleg.  \"Has he ever\nwhaled it any?\" turning to me.\n\n\"Killed more whales than I can count, Captain Peleg.\"\n\n\"Well, bring him along then.\"\n\nAnd, after signing the papers, off I went; nothing doubting but that\nI had done a good morning's work, and that the Pequod was the\nidentical ship that Yojo had provided to carry Queequeg and me round\nthe Cape.\n\nBut I had not proceeded far, when I began to bethink me that the\nCaptain with whom I was to sail yet remained unseen by me; though,\nindeed, in many cases, a whale-ship will be completely fitted out,\nand receive all her crew on board, ere the captain makes himself\nvisible by arriving to take command; for sometimes these voyages are\nso prolonged, and the shore intervals at home so exceedingly brief,\nthat if the captain have a family, or any absorbing concernment of\nthat sort, he does not trouble himself much about his ship in port,\nbut leaves her to the owners till all is ready for sea.  However, it\nis always as well to have a look at him before irrevocably committing\nyourself into his hands.  Turning back I accosted Captain Peleg,\ninquiring where Captain Ahab was to be found.\n\n\"And what dost thou want of Captain Ahab?  It's all right enough;\nthou art shipped.\"\n\n\"Yes, but I should like to see him.\"\n\n\"But I don't think thou wilt be able to at present.  I don't know\nexactly what's the matter with him; but he keeps close inside the\nhouse; a sort of sick, and yet he don't look so.  In fact, he ain't\nsick; but no, he isn't well either.  Any how, young man, he won't\nalways see me, so I don't suppose he will thee.  He's a queer man,\nCaptain Ahab--so some think--but a good one.  Oh, thou'lt like him\nwell enough; no fear, no fear.  He's a grand, ungodly, god-like man,\nCaptain Ahab; doesn't speak much; but, when he does speak, then you\nmay well listen.  Mark ye, be forewarned; Ahab's above the common;\nAhab's been in colleges, as well as 'mong the cannibals; been used to\ndeeper wonders than the waves; fixed his fiery lance in mightier,\nstranger foes than whales.  His lance! aye, the keenest and the surest\nthat out of all our isle!  Oh! he ain't Captain Bildad; no, and he\nain't Captain Peleg; HE'S AHAB, boy; and Ahab of old, thou knowest,\nwas a crowned king!\"\n\n\"And a very vile one.  When that wicked king was slain, the dogs, did\nthey not lick his blood?\"\n\n\"Come hither to me--hither, hither,\" said Peleg, with a significance\nin his eye that almost startled me.  \"Look ye, lad; never say that on\nboard the Pequod.  Never say it anywhere.  Captain Ahab did not name\nhimself.  'Twas a foolish, ignorant whim of his crazy, widowed\nmother, who died when he was only a twelvemonth old.  And yet the old\nsquaw Tistig, at Gayhead, said that the name would somehow prove\nprophetic.  And, perhaps, other fools like her may tell thee the\nsame.  I wish to warn thee.  It's a lie.  I know Captain Ahab well;\nI've sailed with him as mate years ago; I know what he is--a good\nman--not a pious, good man, like Bildad, but a swearing good\nman--something like me--only there's a good deal more of him.  Aye,\naye, I know that he was never very jolly; and I know that on the\npassage home, he was a little out of his mind for a spell; but it was\nthe sharp shooting pains in his bleeding stump that brought that\nabout, as any one might see.  I know, too, that ever since he lost\nhis leg last voyage by that accursed whale, he's been a kind of\nmoody--desperate moody, and savage sometimes; but that will all pass\noff.  And once for all, let me tell thee and assure thee, young man,\nit's better to sail with a moody good captain than a laughing bad\none.  So good-bye to thee--and wrong not Captain Ahab, because he\nhappens to have a wicked name.  Besides, my boy, he has a wife--not\nthree voyages wedded--a sweet, resigned girl.  Think of that; by that\nsweet girl that old man has a child: hold ye then there can be any\nutter, hopeless harm in Ahab?  No, no, my lad; stricken, blasted, if\nhe be, Ahab has his humanities!\"\n\nAs I walked away, I was full of thoughtfulness; what had been\nincidentally revealed to me of Captain Ahab, filled me with a certain\nwild vagueness of painfulness concerning him.  And somehow, at the\ntime, I felt a sympathy and a sorrow for him, but for I don't know\nwhat, unless it was the cruel loss of his leg.  And yet I also felt a\nstrange awe of him; but that sort of awe, which I cannot at all\ndescribe, was not exactly awe; I do not know what it was.  But I felt\nit; and it did not disincline me towards him; though I felt\nimpatience at what seemed like mystery in him, so imperfectly as he\nwas known to me then.  However, my thoughts were at length carried in\nother directions, so that for the present dark Ahab slipped my mind.\n\n\n\nCHAPTER 17\n\nThe Ramadan.\n\n\nAs Queequeg's Ramadan, or Fasting and Humiliation, was to continue\nall day, I did not choose to disturb him till towards night-fall; for\nI cherish the greatest respect towards everybody's religious\nobligations, never mind how comical, and could not find it in my\nheart to undervalue even a congregation of ants worshipping a\ntoad-stool; or those other creatures in certain parts of our earth,\nwho with a degree of footmanism quite unprecedented in other planets,\nbow down before the torso of a deceased landed proprietor merely on\naccount of the inordinate possessions yet owned and rented in his\nname.\n\nI say, we good Presbyterian Christians should be charitable in these\nthings, and not fancy ourselves so vastly superior to other mortals,\npagans and what not, because of their half-crazy conceits on these\nsubjects.  There was Queequeg, now, certainly entertaining the most\nabsurd notions about Yojo and his Ramadan;--but what of that?\nQueequeg thought he knew what he was about, I suppose; he seemed to\nbe content; and there let him rest.  All our arguing with him would\nnot avail; let him be, I say: and Heaven have mercy on us\nall--Presbyterians and Pagans alike--for we are all somehow\ndreadfully cracked about the head, and sadly need mending.\n\nTowards evening, when I felt assured that all his performances and\nrituals must be over, I went up to his room and knocked at the door;\nbut no answer.  I tried to open it, but it was fastened inside.\n\"Queequeg,\" said I softly through the key-hole:--all silent.  \"I say,\nQueequeg! why don't you speak?  It's I--Ishmael.\"  But all remained\nstill as before.  I began to grow alarmed.  I had allowed him such\nabundant time; I thought he might have had an apoplectic fit.  I\nlooked through the key-hole; but the door opening into an odd corner\nof the room, the key-hole prospect was but a crooked and sinister\none.  I could only see part of the foot-board of the bed and a line\nof the wall, but nothing more.  I was surprised to behold resting\nagainst the wall the wooden shaft of Queequeg's harpoon, which the\nlandlady the evening previous had taken from him, before our mounting\nto the chamber.  That's strange, thought I; but at any rate, since\nthe harpoon stands yonder, and he seldom or never goes abroad without\nit, therefore he must be inside here, and no possible mistake.\n\n\"Queequeg!--Queequeg!\"--all still.  Something must have happened.\nApoplexy!  I tried to burst open the door; but it stubbornly\nresisted.  Running down stairs, I quickly stated my suspicions to the\nfirst person I met--the chamber-maid.  \"La! la!\" she cried, \"I\nthought something must be the matter.  I went to make the bed after\nbreakfast, and the door was locked; and not a mouse to be heard; and\nit's been just so silent ever since.  But I thought, may be, you had\nboth gone off and locked your baggage in for safe keeping.  La! la,\nma'am!--Mistress! murder!  Mrs. Hussey! apoplexy!\"--and with these\ncries, she ran towards the kitchen, I following.\n\nMrs. Hussey soon appeared, with a mustard-pot in one hand and a\nvinegar-cruet in the other, having just broken away from the\noccupation of attending to the castors, and scolding her little black\nboy meantime.\n\n\"Wood-house!\" cried I, \"which way to it?  Run for God's sake, and\nfetch something to pry open the door--the axe!--the axe! he's had a\nstroke; depend upon it!\"--and so saying I was unmethodically rushing\nup stairs again empty-handed, when Mrs. Hussey interposed the\nmustard-pot and vinegar-cruet, and the entire castor of her\ncountenance.\n\n\"What's the matter with you, young man?\"\n\n\"Get the axe!  For God's sake, run for the doctor, some one, while I\npry it open!\"\n\n\"Look here,\" said the landlady, quickly putting down the\nvinegar-cruet, so as to have one hand free; \"look here; are you\ntalking about prying open any of my doors?\"--and with that she seized\nmy arm.  \"What's the matter with you?  What's the matter with you,\nshipmate?\"\n\nIn as calm, but rapid a manner as possible, I gave her to understand\nthe whole case.  Unconsciously clapping the vinegar-cruet to one side\nof her nose, she ruminated for an instant; then exclaimed--\"No!  I\nhaven't seen it since I put it there.\"  Running to a little closet\nunder the landing of the stairs, she glanced in, and returning, told\nme that Queequeg's harpoon was missing.  \"He's killed himself,\" she\ncried.  \"It's unfort'nate Stiggs done over again there goes another\ncounterpane--God pity his poor mother!--it will be the ruin of my\nhouse.  Has the poor lad a sister?  Where's that girl?--there, Betty,\ngo to Snarles the Painter, and tell him to paint me a sign, with--\"no\nsuicides permitted here, and no smoking in the parlor;\"--might as\nwell kill both birds at once.  Kill?  The Lord be merciful to his\nghost!  What's that noise there?  You, young man, avast there!\"\n\nAnd running up after me, she caught me as I was again trying to force\nopen the door.\n\n\"I don't allow it; I won't have my premises spoiled.  Go for the\nlocksmith, there's one about a mile from here.  But avast!\" putting\nher hand in her side-pocket, \"here's a key that'll fit, I guess;\nlet's see.\"  And with that, she turned it in the lock; but, alas!\nQueequeg's supplemental bolt remained unwithdrawn within.\n\n\"Have to burst it open,\" said I, and was running down the entry a\nlittle, for a good start, when the landlady caught at me, again\nvowing I should not break down her premises; but I tore from her, and\nwith a sudden bodily rush dashed myself full against the mark.\n\nWith a prodigious noise the door flew open, and the knob slamming\nagainst the wall, sent the plaster to the ceiling; and there, good\nheavens! there sat Queequeg, altogether cool and self-collected;\nright in the middle of the room; squatting on his hams, and holding\nYojo on top of his head.  He looked neither one way nor the other\nway, but sat like a carved image with scarce a sign of active life.\n\n\"Queequeg,\" said I, going up to him, \"Queequeg, what's the matter\nwith you?\"\n\n\"He hain't been a sittin' so all day, has he?\" said the landlady.\n\nBut all we said, not a word could we drag out of him; I almost felt\nlike pushing him over, so as to change his position, for it was\nalmost intolerable, it seemed so painfully and unnaturally\nconstrained; especially, as in all probability he had been sitting so\nfor upwards of eight or ten hours, going too without his regular\nmeals.\n\n\"Mrs. Hussey,\" said I, \"he's ALIVE at all events; so leave us, if you\nplease, and I will see to this strange affair myself.\"\n\nClosing the door upon the landlady, I endeavored to prevail upon\nQueequeg to take a chair; but in vain.  There he sat; and all he\ncould do--for all my polite arts and blandishments--he would not move\na peg, nor say a single word, nor even look at me, nor notice my\npresence in the slightest way.\n\nI wonder, thought I, if this can possibly be a part of his Ramadan;\ndo they fast on their hams that way in his native island.  It must be\nso; yes, it's part of his creed, I suppose; well, then, let him\nrest; he'll get up sooner or later, no doubt.  It can't last for\never, thank God, and his Ramadan only comes once a year; and I don't\nbelieve it's very punctual then.\n\nI went down to supper.  After sitting a long time listening to the\nlong stories of some sailors who had just come from a plum-pudding\nvoyage, as they called it (that is, a short whaling-voyage in a\nschooner or brig, confined to the north of the line, in the Atlantic\nOcean only); after listening to these plum-puddingers till nearly\neleven o'clock, I went up stairs to go to bed, feeling quite sure by\nthis time Queequeg must certainly have brought his Ramadan to a\ntermination.  But no; there he was just where I had left him; he had\nnot stirred an inch.  I began to grow vexed with him; it seemed so\ndownright senseless and insane to be sitting there all day and half\nthe night on his hams in a cold room, holding a piece of wood on his\nhead.\n\n\"For heaven's sake, Queequeg, get up and shake yourself; get up and\nhave some supper.  You'll starve; you'll kill yourself, Queequeg.\"\nBut not a word did he reply.\n\nDespairing of him, therefore, I determined to go to bed and to sleep;\nand no doubt, before a great while, he would follow me.  But previous\nto turning in, I took my heavy bearskin jacket, and threw it over\nhim, as it promised to be a very cold night; and he had nothing but\nhis ordinary round jacket on.  For some time, do all I would, I could\nnot get into the faintest doze.  I had blown out the candle; and the\nmere thought of Queequeg--not four feet off--sitting there in that\nuneasy position, stark alone in the cold and dark; this made me\nreally wretched.  Think of it; sleeping all night in the same room\nwith a wide awake pagan on his hams in this dreary, unaccountable\nRamadan!\n\nBut somehow I dropped off at last, and knew nothing more till break\nof day; when, looking over the bedside, there squatted Queequeg, as\nif he had been screwed down to the floor.  But as soon as the first\nglimpse of sun entered the window, up he got, with stiff and grating\njoints, but with a cheerful look; limped towards me where I lay;\npressed his forehead again against mine; and said his Ramadan was\nover.\n\nNow, as I before hinted, I have no objection to any person's\nreligion, be it what it may, so long as that person does not kill or\ninsult any other person, because that other person don't believe it\nalso.  But when a man's religion becomes really frantic; when it is a\npositive torment to him; and, in fine, makes this earth of ours an\nuncomfortable inn to lodge in; then I think it high time to take that\nindividual aside and argue the point with him.\n\nAnd just so I now did with Queequeg.  \"Queequeg,\" said I, \"get into\nbed now, and lie and listen to me.\"  I then went on, beginning with\nthe rise and progress of the primitive religions, and coming down to\nthe various religions of the present time, during which time I\nlabored to show Queequeg that all these Lents, Ramadans, and\nprolonged ham-squattings in cold, cheerless rooms were stark\nnonsense; bad for the health; useless for the soul; opposed, in\nshort, to the obvious laws of Hygiene and common sense.  I told him,\ntoo, that he being in other things such an extremely sensible and\nsagacious savage, it pained me, very badly pained me, to see him now\nso deplorably foolish about this ridiculous Ramadan of his.  Besides,\nargued I, fasting makes the body cave in; hence the spirit caves in;\nand all thoughts born of a fast must necessarily be half-starved.\nThis is the reason why most dyspeptic religionists cherish such\nmelancholy notions about their hereafters.  In one word, Queequeg,\nsaid I, rather digressively; hell is an idea first born on an\nundigested apple-dumpling; and since then perpetuated through the\nhereditary dyspepsias nurtured by Ramadans.\n\nI then asked Queequeg whether he himself was ever troubled with\ndyspepsia; expressing the idea very plainly, so that he could take it\nin.  He said no; only upon one memorable occasion.  It was after a\ngreat feast given by his father the king, on the gaining of a great\nbattle wherein fifty of the enemy had been killed by about two\no'clock in the afternoon, and all cooked and eaten that very evening.\n\n\"No more, Queequeg,\" said I, shuddering; \"that will do;\" for I knew\nthe inferences without his further hinting them.  I had seen a sailor\nwho had visited that very island, and he told me that it was the\ncustom, when a great battle had been gained there, to barbecue all\nthe slain in the yard or garden of the victor; and then, one by one,\nthey were placed in great wooden trenchers, and garnished round like\na pilau, with breadfruit and cocoanuts; and with some parsley in\ntheir mouths, were sent round with the victor's compliments to all\nhis friends, just as though these presents were so many Christmas\nturkeys.\n\nAfter all, I do not think that my remarks about religion made much\nimpression upon Queequeg.  Because, in the first place, he somehow\nseemed dull of hearing on that important subject, unless considered\nfrom his own point of view; and, in the second place, he did not more\nthan one third understand me, couch my ideas simply as I would; and,\nfinally, he no doubt thought he knew a good deal more about the true\nreligion than I did.  He looked at me with a sort of condescending\nconcern and compassion, as though he thought it a great pity that\nsuch a sensible young man should be so hopelessly lost to evangelical\npagan piety.\n\nAt last we rose and dressed; and Queequeg, taking a prodigiously\nhearty breakfast of chowders of all sorts, so that the landlady\nshould not make much profit by reason of his Ramadan, we sallied out\nto board the Pequod, sauntering along, and picking our teeth with\nhalibut bones.\n\n\n\nCHAPTER 18\n\nHis Mark.\n\n\nAs we were walking down the end of the wharf towards the ship,\nQueequeg carrying his harpoon, Captain Peleg in his gruff voice\nloudly hailed us from his wigwam, saying he had not suspected my\nfriend was a cannibal, and furthermore announcing that he let no\ncannibals on board that craft, unless they previously produced their\npapers.\n\n\"What do you mean by that, Captain Peleg?\" said I, now jumping on the\nbulwarks, and leaving my comrade standing on the wharf.\n\n\"I mean,\" he replied, \"he must show his papers.\"\n\n\"Yes,\" said Captain Bildad in his hollow voice, sticking his head\nfrom behind Peleg's, out of the wigwam.  \"He must show that he's\nconverted.  Son of darkness,\" he added, turning to Queequeg, \"art\nthou at present in communion with any Christian church?\"\n\n\"Why,\" said I, \"he's a member of the first Congregational Church.\"\nHere be it said, that many tattooed savages sailing in Nantucket\nships at last come to be converted into the churches.\n\n\"First Congregational Church,\" cried Bildad, \"what! that worships in\nDeacon Deuteronomy Coleman's meeting-house?\" and so saying, taking\nout his spectacles, he rubbed them with his great yellow bandana\nhandkerchief, and putting them on very carefully, came out of the\nwigwam, and leaning stiffly over the bulwarks, took a good long look\nat Queequeg.\n\n\"How long hath he been a member?\" he then said, turning to me; \"not\nvery long, I rather guess, young man.\"\n\n\"No,\" said Peleg, \"and he hasn't been baptized right either, or it\nwould have washed some of that devil's blue off his face.\"\n\n\"Do tell, now,\" cried Bildad, \"is this Philistine a regular member of\nDeacon Deuteronomy's meeting?  I never saw him going there, and I\npass it every Lord's day.\"\n\n\"I don't know anything about Deacon Deuteronomy or his meeting,\" said\nI; \"all I know is, that Queequeg here is a born member of the First\nCongregational Church.  He is a deacon himself, Queequeg is.\"\n\n\"Young man,\" said Bildad sternly, \"thou art skylarking with\nme--explain thyself, thou young Hittite.  What church dost thee mean?\nanswer me.\"\n\nFinding myself thus hard pushed, I replied.  \"I mean, sir, the same\nancient Catholic Church to which you and I, and Captain Peleg there,\nand Queequeg here, and all of us, and every mother's son and soul of\nus belong; the great and everlasting First Congregation of this whole\nworshipping world; we all belong to that; only some of us cherish\nsome queer crotchets no ways touching the grand belief; in THAT we\nall join hands.\"\n\n\"Splice, thou mean'st SPLICE hands,\" cried Peleg, drawing nearer.\n\"Young man, you'd better ship for a missionary, instead of a\nfore-mast hand; I never heard a better sermon.  Deacon\nDeuteronomy--why Father Mapple himself couldn't beat it, and he's\nreckoned something.  Come aboard, come aboard; never mind about the\npapers.  I say, tell Quohog there--what's that you call him? tell\nQuohog to step along.  By the great anchor, what a harpoon he's got\nthere! looks like good stuff that; and he handles it about right.  I\nsay, Quohog, or whatever your name is, did you ever stand in the head\nof a whale-boat? did you ever strike a fish?\"\n\nWithout saying a word, Queequeg, in his wild sort of way, jumped upon\nthe bulwarks, from thence into the bows of one of the whale-boats\nhanging to the side; and then bracing his left knee, and poising his\nharpoon, cried out in some such way as this:--\n\n\"Cap'ain, you see him small drop tar on water dere?  You see him?\nwell, spose him one whale eye, well, den!\" and taking sharp aim at\nit, he darted the iron right over old Bildad's broad brim, clean\nacross the ship's decks, and struck the glistening tar spot out of\nsight.\n\n\"Now,\" said Queequeg, quietly hauling in the line, \"spos-ee him\nwhale-e eye; why, dad whale dead.\"\n\n\"Quick, Bildad,\" said Peleg, his partner, who, aghast at the close\nvicinity of the flying harpoon, had retreated towards the cabin\ngangway.  \"Quick, I say, you Bildad, and get the ship's papers.  We\nmust have Hedgehog there, I mean Quohog, in one of our boats.  Look\nye, Quohog, we'll give ye the ninetieth lay, and that's more than\never was given a harpooneer yet out of Nantucket.\"\n\nSo down we went into the cabin, and to my great joy Queequeg was soon\nenrolled among the same ship's company to which I myself belonged.\n\nWhen all preliminaries were over and Peleg had got everything ready\nfor signing, he turned to me and said, \"I guess, Quohog there don't\nknow how to write, does he?  I say, Quohog, blast ye! dost thou sign\nthy name or make thy mark?\n\nBut at this question, Queequeg, who had twice or thrice before taken\npart in similar ceremonies, looked no ways abashed; but taking the\noffered pen, copied upon the paper, in the proper place, an exact\ncounterpart of a queer round figure which was tattooed upon his arm;\nso that through Captain Peleg's obstinate mistake touching his\nappellative, it stood something like this:--\n\nQuohog.\nhis X mark.\n\nMeanwhile Captain Bildad sat earnestly and steadfastly eyeing\nQueequeg, and at last rising solemnly and fumbling in the huge\npockets of his broad-skirted drab coat, took out a bundle of tracts,\nand selecting one entitled \"The Latter Day Coming; or No Time to\nLose,\" placed it in Queequeg's hands, and then grasping them and the\nbook with both his, looked earnestly into his eyes, and said, \"Son of\ndarkness, I must do my duty by thee; I am part owner of this ship,\nand feel concerned for the souls of all its crew; if thou still\nclingest to thy Pagan ways, which I sadly fear, I beseech thee,\nremain not for aye a Belial bondsman.  Spurn the idol Bell, and the\nhideous dragon; turn from the wrath to come; mind thine eye, I say;\noh! goodness gracious! steer clear of the fiery pit!\"\n\nSomething of the salt sea yet lingered in old Bildad's language,\nheterogeneously mixed with Scriptural and domestic phrases.\n\n\"Avast there, avast there, Bildad, avast now spoiling our\nharpooneer,\" Peleg.  \"Pious harpooneers never make good voyagers--it\ntakes the shark out of 'em; no harpooneer is worth a straw who aint\npretty sharkish.  There was young Nat Swaine, once the bravest\nboat-header out of all Nantucket and the Vineyard; he joined the\nmeeting, and never came to good.  He got so frightened about his\nplaguy soul, that he shrinked and sheered away from whales, for fear\nof after-claps, in case he got stove and went to Davy Jones.\"\n\n\"Peleg!  Peleg!\" said Bildad, lifting his eyes and hands, \"thou\nthyself, as I myself, hast seen many a perilous time; thou knowest,\nPeleg, what it is to have the fear of death; how, then, can'st thou\nprate in this ungodly guise.  Thou beliest thine own heart, Peleg.\nTell me, when this same Pequod here had her three masts overboard in\nthat typhoon on Japan, that same voyage when thou went mate with\nCaptain Ahab, did'st thou not think of Death and the Judgment then?\"\n\n\"Hear him, hear him now,\" cried Peleg, marching across the cabin, and\nthrusting his hands far down into his pockets,--\"hear him, all of ye.\nThink of that!  When every moment we thought the ship would sink!\nDeath and the Judgment then?  What?  With all three masts making such\nan everlasting thundering against the side; and every sea breaking\nover us, fore and aft.  Think of Death and the Judgment then?  No!\nno time to think about Death then.  Life was what Captain Ahab and I\nwas thinking of; and how to save all hands--how to rig\njury-masts--how to get into the nearest port; that was what I was\nthinking of.\"\n\nBildad said no more, but buttoning up his coat, stalked on deck,\nwhere we followed him.  There he stood, very quietly overlooking some\nsailmakers who were mending a top-sail in the waist.  Now and then he\nstooped to pick up a patch, or save an end of tarred twine, which\notherwise might have been wasted.\n\n\n\nCHAPTER 19\n\nThe Prophet.\n\n\n\"Shipmates, have ye shipped in that ship?\"\n\nQueequeg and I had just left the Pequod, and were sauntering away from\nthe water, for the moment each occupied with his own thoughts, when\nthe above words were put to us by a stranger, who, pausing before us,\nlevelled his massive forefinger at the vessel in question.  He was\nbut shabbily apparelled in faded jacket and patched trowsers; a rag\nof a black handkerchief investing his neck.  A confluent small-pox\nhad in all directions flowed over his face, and left it like the\ncomplicated ribbed bed of a torrent, when the rushing waters have\nbeen dried up.\n\n\"Have ye shipped in her?\" he repeated.\n\n\"You mean the ship Pequod, I suppose,\" said I, trying to gain a\nlittle more time for an uninterrupted look at him.\n\n\"Aye, the Pequod--that ship there,\" he said, drawing back his whole\narm, and then rapidly shoving it straight out from him, with the\nfixed bayonet of his pointed finger darted full at the object.\n\n\"Yes,\" said I, \"we have just signed the articles.\"\n\n\"Anything down there about your souls?\"\n\n\"About what?\"\n\n\"Oh, perhaps you hav'n't got any,\" he said quickly.  \"No matter\nthough, I know many chaps that hav'n't got any,--good luck to 'em;\nand they are all the better off for it.  A soul's a sort of a fifth\nwheel to a wagon.\"\n\n\"What are you jabbering about, shipmate?\" said I.\n\n\"HE'S got enough, though, to make up for all deficiencies of that\nsort in other chaps,\" abruptly said the stranger, placing a nervous\nemphasis upon the word HE.\n\n\"Queequeg,\" said I, \"let's go; this fellow has broken loose from\nsomewhere; he's talking about something and somebody we don't know.\"\n\n\"Stop!\" cried the stranger.  \"Ye said true--ye hav'n't seen Old\nThunder yet, have ye?\"\n\n\"Who's Old Thunder?\" said I, again riveted with the insane\nearnestness of his manner.\n\n\"Captain Ahab.\"\n\n\"What! the captain of our ship, the Pequod?\"\n\n\"Aye, among some of us old sailor chaps, he goes by that name.  Ye\nhav'n't seen him yet, have ye?\"\n\n\"No, we hav'n't.  He's sick they say, but is getting better, and will\nbe all right again before long.\"\n\n\"All right again before long!\" laughed the stranger, with a solemnly\nderisive sort of laugh.  \"Look ye; when Captain Ahab is all right,\nthen this left arm of mine will be all right; not before.\"\n\n\"What do you know about him?\"\n\n\"What did they TELL you about him?  Say that!\"\n\n\"They didn't tell much of anything about him; only I've heard that\nhe's a good whale-hunter, and a good captain to his crew.\"\n\n\"That's true, that's true--yes, both true enough.  But you must jump\nwhen he gives an order.  Step and growl; growl and go--that's the\nword with Captain Ahab.  But nothing about that thing that happened\nto him off Cape Horn, long ago, when he lay like dead for three days\nand nights; nothing about that deadly skrimmage with the Spaniard\nafore the altar in Santa?--heard nothing about that, eh?  Nothing\nabout the silver calabash he spat into?  And nothing about his losing\nhis leg last voyage, according to the prophecy.  Didn't ye hear a\nword about them matters and something more, eh?  No, I don't think ye\ndid; how could ye?  Who knows it?  Not all Nantucket, I guess.  But\nhows'ever, mayhap, ye've heard tell about the leg, and how he lost\nit; aye, ye have heard of that, I dare say.  Oh yes, THAT every one\nknows a'most--I mean they know he's only one leg; and that a\nparmacetti took the other off.\"\n\n\"My friend,\" said I, \"what all this gibberish of yours is about, I\ndon't know, and I don't much care; for it seems to me that you must\nbe a little damaged in the head.  But if you are speaking of Captain\nAhab, of that ship there, the Pequod, then let me tell you, that I\nknow all about the loss of his leg.\"\n\n\"ALL about it, eh--sure you do?--all?\"\n\n\"Pretty sure.\"\n\nWith finger pointed and eye levelled at the Pequod, the beggar-like\nstranger stood a moment, as if in a troubled reverie; then starting a\nlittle, turned and said:--\"Ye've shipped, have ye?  Names down on the\npapers?  Well, well, what's signed, is signed; and what's to be, will\nbe; and then again, perhaps it won't be, after all.  Anyhow, it's\nall fixed and arranged a'ready; and some sailors or other must go\nwith him, I suppose; as well these as any other men, God pity 'em!\nMorning to ye, shipmates, morning; the ineffable heavens bless ye;\nI'm sorry I stopped ye.\"\n\n\"Look here, friend,\" said I, \"if you have anything important to tell\nus, out with it; but if you are only trying to bamboozle us, you are\nmistaken in your game; that's all I have to say.\"\n\n\"And it's said very well, and I like to hear a chap talk up that way;\nyou are just the man for him--the likes of ye.  Morning to ye,\nshipmates, morning!  Oh! when ye get there, tell 'em I've concluded\nnot to make one of 'em.\"\n\n\"Ah, my dear fellow, you can't fool us that way--you can't fool us.\nIt is the easiest thing in the world for a man to look as if he had a\ngreat secret in him.\"\n\n\"Morning to ye, shipmates, morning.\"\n\n\"Morning it is,\" said I.  \"Come along, Queequeg, let's leave this\ncrazy man.  But stop, tell me your name, will you?\"\n\n\"Elijah.\"\n\nElijah! thought I, and we walked away, both commenting, after each\nother's fashion, upon this ragged old sailor; and agreed that he was\nnothing but a humbug, trying to be a bugbear.  But we had not gone\nperhaps above a hundred yards, when chancing to turn a corner, and\nlooking back as I did so, who should be seen but Elijah following us,\nthough at a distance.  Somehow, the sight of him struck me so, that I\nsaid nothing to Queequeg of his being behind, but passed on with my\ncomrade, anxious to see whether the stranger would turn the same\ncorner that we did.  He did; and then it seemed to me that he was\ndogging us, but with what intent I could not for the life of me\nimagine.  This circumstance, coupled with his ambiguous,\nhalf-hinting, half-revealing, shrouded sort of talk, now begat in me\nall kinds of vague wonderments and half-apprehensions, and all\nconnected with the Pequod; and Captain Ahab; and the leg he had lost;\nand the Cape Horn fit; and the silver calabash; and what Captain\nPeleg had said of him, when I left the ship the day previous; and the\nprediction of the squaw Tistig; and the voyage we had bound ourselves\nto sail; and a hundred other shadowy things.\n\nI was resolved to satisfy myself whether this ragged Elijah was\nreally dogging us or not, and with that intent crossed the way with\nQueequeg, and on that side of it retraced our steps.  But Elijah\npassed on, without seeming to notice us.  This relieved me; and once\nmore, and finally as it seemed to me, I pronounced him in my heart, a\nhumbug.\n\n\n\nCHAPTER 20\n\nAll Astir.\n\n\nA day or two passed, and there was great activity aboard the Pequod.\nNot only were the old sails being mended, but new sails were coming\non board, and bolts of canvas, and coils of rigging; in short,\neverything betokened that the ship's preparations were hurrying to a\nclose.  Captain Peleg seldom or never went ashore, but sat in his\nwigwam keeping a sharp look-out upon the hands: Bildad did all the\npurchasing and providing at the stores; and the men employed in the\nhold and on the rigging were working till long after night-fall.\n\nOn the day following Queequeg's signing the articles, word was given\nat all the inns where the ship's company were stopping, that their\nchests must be on board before night, for there was no telling how\nsoon the vessel might be sailing.  So Queequeg and I got down our\ntraps, resolving, however, to sleep ashore till the last.  But it\nseems they always give very long notice in these cases, and the ship\ndid not sail for several days.  But no wonder; there was a good deal\nto be done, and there is no telling how many things to be thought of,\nbefore the Pequod was fully equipped.\n\nEvery one knows what a multitude of things--beds, sauce-pans, knives\nand forks, shovels and tongs, napkins, nut-crackers, and what not,\nare indispensable to the business of housekeeping.  Just so with\nwhaling, which necessitates a three-years' housekeeping upon the wide\nocean, far from all grocers, costermongers, doctors, bakers, and\nbankers.  And though this also holds true of merchant vessels, yet\nnot by any means to the same extent as with whalemen.  For besides\nthe great length of the whaling voyage, the numerous articles\npeculiar to the prosecution of the fishery, and the impossibility of\nreplacing them at the remote harbors usually frequented, it must be\nremembered, that of all ships, whaling vessels are the most exposed\nto accidents of all kinds, and especially to the destruction and loss\nof the very things upon which the success of the voyage most depends.\nHence, the spare boats, spare spars, and spare lines and harpoons,\nand spare everythings, almost, but a spare Captain and duplicate\nship.\n\nAt the period of our arrival at the Island, the heaviest storage of\nthe Pequod had been almost completed; comprising her beef, bread,\nwater, fuel, and iron hoops and staves.  But, as before hinted, for\nsome time there was a continual fetching and carrying on board of\ndivers odds and ends of things, both large and small.\n\nChief among those who did this fetching and carrying was Captain\nBildad's sister, a lean old lady of a most determined and\nindefatigable spirit, but withal very kindhearted, who seemed\nresolved that, if SHE could help it, nothing should be found wanting\nin the Pequod, after once fairly getting to sea.  At one time she\nwould come on board with a jar of pickles for the steward's pantry;\nanother time with a bunch of quills for the chief mate's desk, where\nhe kept his log; a third time with a roll of flannel for the small of\nsome one's rheumatic back.  Never did any woman better deserve her\nname, which was Charity--Aunt Charity, as everybody called her.  And\nlike a sister of charity did this charitable Aunt Charity bustle\nabout hither and thither, ready to turn her hand and heart to\nanything that promised to yield safety, comfort, and consolation to\nall on board a ship in which her beloved brother Bildad was\nconcerned, and in which she herself owned a score or two of\nwell-saved dollars.\n\nBut it was startling to see this excellent hearted Quakeress coming\non board, as she did the last day, with a long oil-ladle in one hand,\nand a still longer whaling lance in the other.  Nor was Bildad himself\nnor Captain Peleg at all backward.  As for Bildad, he carried about\nwith him a long list of the articles needed, and at every fresh\narrival, down went his mark opposite that article upon the paper.\nEvery once in a while Peleg came hobbling out of his whalebone den,\nroaring at the men down the hatchways, roaring up to the riggers at\nthe mast-head, and then concluded by roaring back into his wigwam.\n\nDuring these days of preparation, Queequeg and I often visited the\ncraft, and as often I asked about Captain Ahab, and how he was, and\nwhen he was going to come on board his ship.  To these questions they\nwould answer, that he was getting better and better, and was expected\naboard every day; meantime, the two captains, Peleg and Bildad, could\nattend to everything necessary to fit the vessel for the voyage.  If\nI had been downright honest with myself, I would have seen very\nplainly in my heart that I did but half fancy being committed this\nway to so long a voyage, without once laying my eyes on the man who\nwas to be the absolute dictator of it, so soon as the ship sailed out\nupon the open sea.  But when a man suspects any wrong, it sometimes\nhappens that if he be already involved in the matter, he insensibly\nstrives to cover up his suspicions even from himself.  And much this\nway it was with me.  I said nothing, and tried to think nothing.\n\nAt last it was given out that some time next day the ship would\ncertainly sail.  So next morning, Queequeg and I took a very early\nstart.\n\n\n\nCHAPTER 21\n\nGoing Aboard.\n\n\nIt was nearly six o'clock, but only grey imperfect misty dawn, when\nwe drew nigh the wharf.\n\n\"There are some sailors running ahead there, if I see right,\" said I\nto Queequeg, \"it can't be shadows; she's off by sunrise, I guess;\ncome on!\"\n\n\"Avast!\" cried a voice, whose owner at the same time coming close\nbehind us, laid a hand upon both our shoulders, and then insinuating\nhimself between us, stood stooping forward a little, in the uncertain\ntwilight, strangely peering from Queequeg to me.  It was Elijah.\n\n\"Going aboard?\"\n\n\"Hands off, will you,\" said I.\n\n\"Lookee here,\" said Queequeg, shaking himself, \"go 'way!\"\n\n\"Ain't going aboard, then?\"\n\n\"Yes, we are,\" said I, \"but what business is that of yours?  Do you\nknow, Mr. Elijah, that I consider you a little impertinent?\"\n\n\"No, no, no; I wasn't aware of that,\" said Elijah, slowly and\nwonderingly looking from me to Queequeg, with the most unaccountable\nglances.\n\n\"Elijah,\" said I, \"you will oblige my friend and me by withdrawing.\nWe are going to the Indian and Pacific Oceans, and would prefer not\nto be detained.\"\n\n\"Ye be, be ye?  Coming back afore breakfast?\"\n\n\"He's cracked, Queequeg,\" said I, \"come on.\"\n\n\"Holloa!\" cried stationary Elijah, hailing us when we had removed a\nfew paces.\n\n\"Never mind him,\" said I, \"Queequeg, come on.\"\n\nBut he stole up to us again, and suddenly clapping his hand on my\nshoulder, said--\"Did ye see anything looking like men going towards\nthat ship a while ago?\"\n\nStruck by this plain matter-of-fact question, I answered, saying,\n\"Yes, I thought I did see four or five men; but it was too dim to be\nsure.\"\n\n\"Very dim, very dim,\" said Elijah.  \"Morning to ye.\"\n\nOnce more we quitted him; but once more he came softly after us; and\ntouching my shoulder again, said, \"See if you can find 'em now, will\nye?\n\n\"Find who?\"\n\n\"Morning to ye! morning to ye!\" he rejoined, again moving off.  \"Oh!\nI was going to warn ye against--but never mind, never mind--it's all\none, all in the family too;--sharp frost this morning, ain't it?\nGood-bye to ye.  Shan't see ye again very soon, I guess; unless it's\nbefore the Grand Jury.\"  And with these cracked words he finally\ndeparted, leaving me, for the moment, in no small wonderment at his\nfrantic impudence.\n\nAt last, stepping on board the Pequod, we found everything in\nprofound quiet, not a soul moving.  The cabin entrance was locked\nwithin; the hatches were all on, and lumbered with coils of rigging.\nGoing forward to the forecastle, we found the slide of the scuttle\nopen.  Seeing a light, we went down, and found only an old rigger\nthere, wrapped in a tattered pea-jacket.  He was thrown at whole\nlength upon two chests, his face downwards and inclosed in his folded\narms.  The profoundest slumber slept upon him.\n\n\"Those sailors we saw, Queequeg, where can they have gone to?\" said\nI, looking dubiously at the sleeper.  But it seemed that, when on the\nwharf, Queequeg had not at all noticed what I now alluded to; hence I\nwould have thought myself to have been optically deceived in that\nmatter, were it not for Elijah's otherwise inexplicable question.\nBut I beat the thing down; and again marking the sleeper, jocularly\nhinted to Queequeg that perhaps we had best sit up with the body;\ntelling him to establish himself accordingly.  He put his hand upon\nthe sleeper's rear, as though feeling if it was soft enough; and\nthen, without more ado, sat quietly down there.\n\n\"Gracious!  Queequeg, don't sit there,\" said I.\n\n\"Oh! perry dood seat,\" said Queequeg, \"my country way; won't hurt\nhim face.\"\n\n\"Face!\" said I, \"call that his face? very benevolent countenance\nthen; but how hard he breathes, he's heaving himself; get off,\nQueequeg, you are heavy, it's grinding the face of the poor.  Get\noff, Queequeg!  Look, he'll twitch you off soon.  I wonder he don't\nwake.\"\n\nQueequeg removed himself to just beyond the head of the sleeper, and\nlighted his tomahawk pipe.  I sat at the feet.  We kept the pipe\npassing over the sleeper, from one to the other.  Meanwhile, upon\nquestioning him in his broken fashion, Queequeg gave me to understand\nthat, in his land, owing to the absence of settees and sofas of all\nsorts, the king, chiefs, and great people generally, were in the\ncustom of fattening some of the lower orders for ottomans; and to\nfurnish a house comfortably in that respect, you had only to buy up\neight or ten lazy fellows, and lay them round in the piers and\nalcoves.  Besides, it was very convenient on an excursion; much\nbetter than those garden-chairs which are convertible into\nwalking-sticks; upon occasion, a chief calling his attendant, and\ndesiring him to make a settee of himself under a spreading tree,\nperhaps in some damp marshy place.\n\nWhile narrating these things, every time Queequeg received the\ntomahawk from me, he flourished the hatchet-side of it over the\nsleeper's head.\n\n\"What's that for, Queequeg?\"\n\n\"Perry easy, kill-e; oh! perry easy!\n\nHe was going on with some wild reminiscences about his tomahawk-pipe,\nwhich, it seemed, had in its two uses both brained his foes and\nsoothed his soul, when we were directly attracted to the sleeping\nrigger.  The strong vapour now completely filling the contracted hole,\nit began to tell upon him.  He breathed with a sort of muffledness;\nthen seemed troubled in the nose; then revolved over once or twice;\nthen sat up and rubbed his eyes.\n\n\"Holloa!\" he breathed at last, \"who be ye smokers?\"\n\n\"Shipped men,\" answered I, \"when does she sail?\"\n\n\"Aye, aye, ye are going in her, be ye?  She sails to-day.  The\nCaptain came aboard last night.\"\n\n\"What Captain?--Ahab?\"\n\n\"Who but him indeed?\"\n\nI was going to ask him some further questions concerning Ahab, when\nwe heard a noise on deck.\n\n\"Holloa!  Starbuck's astir,\" said the rigger.  \"He's a lively chief\nmate, that; good man, and a pious; but all alive now, I must turn\nto.\"  And so saying he went on deck, and we followed.\n\nIt was now clear sunrise.  Soon the crew came on board in twos and\nthrees; the riggers bestirred themselves; the mates were actively\nengaged; and several of the shore people were busy in bringing\nvarious last things on board.  Meanwhile Captain Ahab remained\ninvisibly enshrined within his cabin.\n\n\n\nCHAPTER 22\n\nMerry Christmas.\n\n\nAt length, towards noon, upon the final dismissal of the ship's\nriggers, and after the Pequod had been hauled out from the wharf, and\nafter the ever-thoughtful Charity had come off in a whale-boat, with\nher last gift--a night-cap for Stubb, the second mate, her\nbrother-in-law, and a spare Bible for the steward--after all this,\nthe two Captains, Peleg and Bildad, issued from the cabin, and\nturning to the chief mate, Peleg said:\n\n\"Now, Mr. Starbuck, are you sure everything is right?  Captain Ahab\nis all ready--just spoke to him--nothing more to be got from shore,\neh?  Well, call all hands, then.  Muster 'em aft here--blast 'em!\"\n\n\"No need of profane words, however great the hurry, Peleg,\" said\nBildad, \"but away with thee, friend Starbuck, and do our bidding.\"\n\nHow now!  Here upon the very point of starting for the voyage,\nCaptain Peleg and Captain Bildad were going it with a high hand on\nthe quarter-deck, just as if they were to be joint-commanders at sea,\nas well as to all appearances in port.  And, as for Captain Ahab, no\nsign of him was yet to be seen; only, they said he was in the cabin.\nBut then, the idea was, that his presence was by no means necessary\nin getting the ship under weigh, and steering her well out to sea.\nIndeed, as that was not at all his proper business, but the pilot's;\nand as he was not yet completely recovered--so they said--therefore,\nCaptain Ahab stayed below.  And all this seemed natural enough;\nespecially as in the merchant service many captains never show\nthemselves on deck for a considerable time after heaving up the\nanchor, but remain over the cabin table, having a farewell\nmerry-making with their shore friends, before they quit the ship for\ngood with the pilot.\n\nBut there was not much chance to think over the matter, for Captain\nPeleg was now all alive.  He seemed to do most of the talking and\ncommanding, and not Bildad.\n\n\"Aft here, ye sons of bachelors,\" he cried, as the sailors lingered\nat the main-mast.  \"Mr. Starbuck, drive'em aft.\"\n\n\"Strike the tent there!\"--was the next order.  As I hinted before,\nthis whalebone marquee was never pitched except in port; and on board\nthe Pequod, for thirty years, the order to strike the tent was well\nknown to be the next thing to heaving up the anchor.\n\n\"Man the capstan!  Blood and thunder!--jump!\"--was the next command,\nand the crew sprang for the handspikes.\n\nNow in getting under weigh, the station generally occupied by the\npilot is the forward part of the ship.  And here Bildad, who, with\nPeleg, be it known, in addition to his other officers, was one of the\nlicensed pilots of the port--he being suspected to have got himself\nmade a pilot in order to save the Nantucket pilot-fee to all the\nships he was concerned in, for he never piloted any other\ncraft--Bildad, I say, might now be seen actively engaged in looking\nover the bows for the approaching anchor, and at intervals singing\nwhat seemed a dismal stave of psalmody, to cheer the hands at the\nwindlass, who roared forth some sort of a chorus about the girls in\nBooble Alley, with hearty good will.  Nevertheless, not three days\nprevious, Bildad had told them that no profane songs would be allowed\non board the Pequod, particularly in getting under weigh; and\nCharity, his sister, had placed a small choice copy of Watts in each\nseaman's berth.\n\nMeantime, overseeing the other part of the ship, Captain Peleg ripped\nand swore astern in the most frightful manner.  I almost thought he\nwould sink the ship before the anchor could be got up; involuntarily\nI paused on my handspike, and told Queequeg to do the same, thinking\nof the perils we both ran, in starting on the voyage with such a\ndevil for a pilot.  I was comforting myself, however, with the\nthought that in pious Bildad might be found some salvation, spite of\nhis seven hundred and seventy-seventh lay; when I felt a sudden sharp\npoke in my rear, and turning round, was horrified at the apparition\nof Captain Peleg in the act of withdrawing his leg from my immediate\nvicinity.  That was my first kick.\n\n\"Is that the way they heave in the marchant service?\" he roared.\n\"Spring, thou sheep-head; spring, and break thy backbone!  Why don't\nye spring, I say, all of ye--spring!  Quohog! spring, thou chap with\nthe red whiskers; spring there, Scotch-cap; spring, thou green\npants.  Spring, I say, all of ye, and spring your eyes out!\"  And so\nsaying, he moved along the windlass, here and there using his leg\nvery freely, while imperturbable Bildad kept leading off with his\npsalmody.  Thinks I, Captain Peleg must have been drinking something\nto-day.\n\nAt last the anchor was up, the sails were set, and off we glided.  It\nwas a short, cold Christmas; and as the short northern day merged\ninto night, we found ourselves almost broad upon the wintry ocean,\nwhose freezing spray cased us in ice, as in polished armor.  The long\nrows of teeth on the bulwarks glistened in the moonlight; and like\nthe white ivory tusks of some huge elephant, vast curving icicles\ndepended from the bows.\n\nLank Bildad, as pilot, headed the first watch, and ever and anon, as\nthe old craft deep dived into the green seas, and sent the shivering\nfrost all over her, and the winds howled, and the cordage rang, his\nsteady notes were heard,--\n\n\"Sweet fields beyond the swelling flood,\nStand dressed in living green.\nSo to the Jews old Canaan stood,\nWhile Jordan rolled between.\"\n\n\nNever did those sweet words sound more sweetly to me than then.  They\nwere full of hope and fruition.  Spite of this frigid winter night in\nthe boisterous Atlantic, spite of my wet feet and wetter jacket,\nthere was yet, it then seemed to me, many a pleasant haven in store;\nand meads and glades so eternally vernal, that the grass shot up by\nthe spring, untrodden, unwilted, remains at midsummer.\n\nAt last we gained such an offing, that the two pilots were needed no\nlonger.  The stout sail-boat that had accompanied us began ranging\nalongside.\n\nIt was curious and not unpleasing, how Peleg and Bildad were affected\nat this juncture, especially Captain Bildad.  For loath to depart,\nyet; very loath to leave, for good, a ship bound on so long and\nperilous a voyage--beyond both stormy Capes; a ship in which some\nthousands of his hard earned dollars were invested; a ship, in which\nan old shipmate sailed as captain; a man almost as old as he, once\nmore starting to encounter all the terrors of the pitiless jaw; loath\nto say good-bye to a thing so every way brimful of every interest to\nhim,--poor old Bildad lingered long; paced the deck with anxious\nstrides; ran down into the cabin to speak another farewell word\nthere; again came on deck, and looked to windward; looked towards the\nwide and endless waters, only bounded by the far-off unseen Eastern\nContinents; looked towards the land; looked aloft; looked right and\nleft; looked everywhere and nowhere; and at last, mechanically\ncoiling a rope upon its pin, convulsively grasped stout Peleg by the\nhand, and holding up a lantern, for a moment stood gazing heroically\nin his face, as much as to say, \"Nevertheless, friend Peleg, I can\nstand it; yes, I can.\"\n\nAs for Peleg himself, he took it more like a philosopher; but for all\nhis philosophy, there was a tear twinkling in his eye, when the\nlantern came too near.  And he, too, did not a little run from cabin\nto deck--now a word below, and now a word with Starbuck, the chief\nmate.\n\nBut, at last, he turned to his comrade, with a final sort of look\nabout him,--\"Captain Bildad--come, old shipmate, we must go.  Back\nthe main-yard there!  Boat ahoy!  Stand by to come close alongside,\nnow!  Careful, careful!--come, Bildad, boy--say your last.  Luck to\nye, Starbuck--luck to ye, Mr. Stubb--luck to ye, Mr. Flask--good-bye\nand good luck to ye all--and this day three years I'll have a hot\nsupper smoking for ye in old Nantucket.  Hurrah and away!\"\n\n\"God bless ye, and have ye in His holy keeping, men,\" murmured old\nBildad, almost incoherently.  \"I hope ye'll have fine weather now, so\nthat Captain Ahab may soon be moving among ye--a pleasant sun is all\nhe needs, and ye'll have plenty of them in the tropic voyage ye go.\nBe careful in the hunt, ye mates.  Don't stave the boats needlessly,\nye harpooneers; good white cedar plank is raised full three per cent.\nwithin the year.  Don't forget your prayers, either.  Mr. Starbuck,\nmind that cooper don't waste the spare staves.  Oh! the sail-needles\nare in the green locker!  Don't whale it too much a' Lord's days,\nmen; but don't miss a fair chance either, that's rejecting Heaven's\ngood gifts.  Have an eye to the molasses tierce, Mr. Stubb; it was a\nlittle leaky, I thought.  If ye touch at the islands, Mr. Flask,\nbeware of fornication.  Good-bye, good-bye!  Don't keep that cheese\ntoo long down in the hold, Mr. Starbuck; it'll spoil.  Be careful\nwith the butter--twenty cents the pound it was, and mind ye, if--\"\n\n\"Come, come, Captain Bildad; stop palavering,--away!\" and with that,\nPeleg hurried him over the side, and both dropt into the boat.\n\nShip and boat diverged; the cold, damp night breeze blew between; a\nscreaming gull flew overhead; the two hulls wildly rolled; we gave\nthree heavy-hearted cheers, and blindly plunged like fate into the\nlone Atlantic.\n\n\n\nCHAPTER 23\n\nThe Lee Shore.\n\n\nSome chapters back, one Bulkington was spoken of, a tall, newlanded\nmariner, encountered in New Bedford at the inn.\n\nWhen on that shivering winter's night, the Pequod thrust her\nvindictive bows into the cold malicious waves, who should I see\nstanding at her helm but Bulkington!  I looked with sympathetic awe\nand fearfulness upon the man, who in mid-winter just landed from a\nfour years' dangerous voyage, could so unrestingly push off again for\nstill another tempestuous term.  The land seemed scorching to his\nfeet.  Wonderfullest things are ever the unmentionable; deep memories\nyield no epitaphs; this six-inch chapter is the stoneless grave of\nBulkington.  Let me only say that it fared with him as with the\nstorm-tossed ship, that miserably drives along the leeward land.  The\nport would fain give succor; the port is pitiful; in the port is\nsafety, comfort, hearthstone, supper, warm blankets, friends, all\nthat's kind to our mortalities.  But in that gale, the port, the\nland, is that ship's direst jeopardy; she must fly all hospitality;\none touch of land, though it but graze the keel, would make her\nshudder through and through.  With all her might she crowds all sail\noff shore; in so doing, fights 'gainst the very winds that fain would\nblow her homeward; seeks all the lashed sea's landlessness again; for\nrefuge's sake forlornly rushing into peril; her only friend her\nbitterest foe!\n\nKnow ye now, Bulkington?  Glimpses do ye seem to see of that mortally\nintolerable truth; that all deep, earnest thinking is but the\nintrepid effort of the soul to keep the open independence of her sea;\nwhile the wildest winds of heaven and earth conspire to cast her on\nthe treacherous, slavish shore?\n\nBut as in landlessness alone resides highest truth, shoreless,\nindefinite as God--so, better is it to perish in that howling\ninfinite, than be ingloriously dashed upon the lee, even if that were\nsafety!  For worm-like, then, oh! who would craven crawl to land!\nTerrors of the terrible! is all this agony so vain?  Take heart, take\nheart, O Bulkington!  Bear thee grimly, demigod!  Up from the spray\nof thy ocean-perishing--straight up, leaps thy apotheosis!\n\n\n\nCHAPTER 24\n\nThe Advocate.\n\n\nAs Queequeg and I are now fairly embarked in this business of\nwhaling; and as this business of whaling has somehow come to be\nregarded among landsmen as a rather unpoetical and disreputable\npursuit; therefore, I am all anxiety to convince ye, ye landsmen, of\nthe injustice hereby done to us hunters of whales.\n\nIn the first place, it may be deemed almost superfluous to establish\nthe fact, that among people at large, the business of whaling is not\naccounted on a level with what are called the liberal professions.\nIf a stranger were introduced into any miscellaneous metropolitan\nsociety, it would but slightly advance the general opinion of his\nmerits, were he presented to the company as a harpooneer, say; and if\nin emulation of the naval officers he should append the initials\nS.W.F. (Sperm Whale Fishery) to his visiting card, such a procedure\nwould be deemed pre-eminently presuming and ridiculous.\n\nDoubtless one leading reason why the world declines honouring us\nwhalemen, is this: they think that, at best, our vocation amounts to\na butchering sort of business; and that when actively engaged\ntherein, we are surrounded by all manner of defilements.  Butchers we\nare, that is true.  But butchers, also, and butchers of the bloodiest\nbadge have been all Martial Commanders whom the world invariably\ndelights to honour.  And as for the matter of the alleged\nuncleanliness of our business, ye shall soon be initiated into\ncertain facts hitherto pretty generally unknown, and which, upon the\nwhole, will triumphantly plant the sperm whale-ship at least among\nthe cleanliest things of this tidy earth.  But even granting the\ncharge in question to be true; what disordered slippery decks of a\nwhale-ship are comparable to the unspeakable carrion of those\nbattle-fields from which so many soldiers return to drink in all\nladies' plaudits?  And if the idea of peril so much enhances the\npopular conceit of the soldier's profession; let me assure ye that\nmany a veteran who has freely marched up to a battery, would quickly\nrecoil at the apparition of the sperm whale's vast tail, fanning into\neddies the air over his head.  For what are the comprehensible\nterrors of man compared with the interlinked terrors and wonders of\nGod!\n\nBut, though the world scouts at us whale hunters, yet does it\nunwittingly pay us the profoundest homage; yea, an all-abounding\nadoration! for almost all the tapers, lamps, and candles that burn\nround the globe, burn, as before so many shrines, to our glory!\n\nBut look at this matter in other lights; weigh it in all sorts of\nscales; see what we whalemen are, and have been.\n\nWhy did the Dutch in De Witt's time have admirals of their whaling\nfleets?  Why did Louis XVI. of France, at his own personal expense,\nfit out whaling ships from Dunkirk, and politely invite to that town\nsome score or two of families from our own island of Nantucket?  Why\ndid Britain between the years 1750 and 1788 pay to her whalemen in\nbounties upwards of L1,000,000?  And lastly, how comes it that we\nwhalemen of America now outnumber all the rest of the banded whalemen\nin the world; sail a navy of upwards of seven hundred vessels; manned\nby eighteen thousand men; yearly consuming 4,000,000 of dollars; the\nships worth, at the time of sailing, $20,000,000! and every year\nimporting into our harbors a well reaped harvest of $7,000,000.  How\ncomes all this, if there be not something puissant in whaling?\n\nBut this is not the half; look again.\n\nI freely assert, that the cosmopolite philosopher cannot, for his\nlife, point out one single peaceful influence, which within the last\nsixty years has operated more potentially upon the whole broad world,\ntaken in one aggregate, than the high and mighty business of whaling.\nOne way and another, it has begotten events so remarkable in\nthemselves, and so continuously momentous in their sequential issues,\nthat whaling may well be regarded as that Egyptian mother, who bore\noffspring themselves pregnant from her womb.  It would be a hopeless,\nendless task to catalogue all these things.  Let a handful suffice.\nFor many years past the whale-ship has been the pioneer in ferreting\nout the remotest and least known parts of the earth.  She has\nexplored seas and archipelagoes which had no chart, where no Cook or\nVancouver had ever sailed.  If American and European men-of-war\nnow peacefully ride in once savage harbors, let them fire salutes to\nthe honour and glory of the whale-ship, which originally showed them\nthe way, and first interpreted between them and the savages.  They\nmay celebrate as they will the heroes of Exploring Expeditions, your\nCooks, your Krusensterns; but I say that scores of anonymous\nCaptains have sailed out of Nantucket, that were as great, and\ngreater than your Cook and your Krusenstern.  For in their\nsuccourless empty-handedness, they, in the heathenish sharked waters,\nand by the beaches of unrecorded, javelin islands, battled with\nvirgin wonders and terrors that Cook with all his marines and\nmuskets would not willingly have dared.  All that is made such a\nflourish of in the old South Sea Voyages, those things were but the\nlife-time commonplaces of our heroic Nantucketers.  Often,\nadventures which Vancouver dedicates three chapters to, these men\naccounted unworthy of being set down in the ship's common log.  Ah,\nthe world!  Oh, the world!\n\nUntil the whale fishery rounded Cape Horn, no commerce but colonial,\nscarcely any intercourse but colonial, was carried on between Europe\nand the long line of the opulent Spanish provinces on the Pacific\ncoast.  It was the whaleman who first broke through the jealous\npolicy of the Spanish crown, touching those colonies; and, if space\npermitted, it might be distinctly shown how from those whalemen at\nlast eventuated the liberation of Peru, Chili, and Bolivia from the\nyoke of Old Spain, and the establishment of the eternal democracy in\nthose parts.\n\nThat great America on the other side of the sphere, Australia, was\ngiven to the enlightened world by the whaleman.  After its first\nblunder-born discovery by a Dutchman, all other ships long shunned\nthose shores as pestiferously barbarous; but the whale-ship touched\nthere.  The whale-ship is the true mother of that now mighty colony.\nMoreover, in the infancy of the first Australian settlement, the\nemigrants were several times saved from starvation by the benevolent\nbiscuit of the whale-ship luckily dropping an anchor in their waters.\nThe uncounted isles of all Polynesia confess the same truth, and do\ncommercial homage to the whale-ship, that cleared the way for the\nmissionary and the merchant, and in many cases carried the primitive\nmissionaries to their first destinations.  If that double-bolted\nland, Japan, is ever to become hospitable, it is the whale-ship alone\nto whom the credit will be due; for already she is on the threshold.\n\nBut if, in the face of all this, you still declare that whaling has\nno aesthetically noble associations connected with it, then am I\nready to shiver fifty lances with you there, and unhorse you with a\nsplit helmet every time.\n\nThe whale has no famous author, and whaling no famous chronicler, you\nwill say.\n\nTHE WHALE NO FAMOUS AUTHOR, AND WHALING NO FAMOUS CHRONICLER?  Who\nwrote the first account of our Leviathan?  Who but mighty Job!  And\nwho composed the first narrative of a whaling-voyage?  Who, but no\nless a prince than Alfred the Great, who, with his own royal pen,\ntook down the words from Other, the Norwegian whale-hunter of those\ntimes!  And who pronounced our glowing eulogy in Parliament?  Who,\nbut Edmund Burke!\n\nTrue enough, but then whalemen themselves are poor devils; they have\nno good blood in their veins.\n\nNO GOOD BLOOD IN THEIR VEINS?  They have something better than royal\nblood there.  The grandmother of Benjamin Franklin was Mary Morrel;\nafterwards, by marriage, Mary Folger, one of the old settlers of\nNantucket, and the ancestress to a long line of Folgers and\nharpooneers--all kith and kin to noble Benjamin--this day darting the\nbarbed iron from one side of the world to the other.\n\nGood again; but then all confess that somehow whaling is not\nrespectable.\n\nWHALING NOT RESPECTABLE?  Whaling is imperial!  By old English\nstatutory law, the whale is declared \"a royal fish.\"*\n\nOh, that's only nominal!  The whale himself has never figured in any\ngrand imposing way.\n\nTHE WHALE NEVER FIGURED IN ANY GRAND IMPOSING WAY?  In one of the\nmighty triumphs given to a Roman general upon his entering the\nworld's capital, the bones of a whale, brought all the way from the\nSyrian coast, were the most conspicuous object in the cymballed\nprocession.*\n\n\n*See subsequent chapters for something more on this head.\n\n\nGrant it, since you cite it; but, say what you will, there is no real\ndignity in whaling.\n\nNO DIGNITY IN WHALING?  The dignity of our calling the very heavens\nattest.  Cetus is a constellation in the South!  No more!  Drive\ndown your hat in presence of the Czar, and take it off to Queequeg!\nNo more!  I know a man that, in his lifetime, has taken three hundred\nand fifty whales.  I account that man more honourable than that great\ncaptain of antiquity who boasted of taking as many walled towns.\n\nAnd, as for me, if, by any possibility, there be any as yet\nundiscovered prime thing in me; if I shall ever deserve any real\nrepute in that small but high hushed world which I might not be\nunreasonably ambitious of; if hereafter I shall do anything that, upon\nthe whole, a man might rather have done than to have left undone; if,\nat my death, my executors, or more properly my creditors, find any\nprecious MSS. in my desk, then here I prospectively ascribe all the\nhonour and the glory to whaling; for a whale-ship was my Yale College\nand my Harvard.\n\n\n\nCHAPTER 25\n\nPostscript.\n\n\nIn behalf of the dignity of whaling, I would fain advance naught but\nsubstantiated facts.  But after embattling his facts, an advocate who\nshould wholly suppress a not unreasonable surmise, which might tell\neloquently upon his cause--such an advocate, would he not be\nblameworthy?\n\nIt is well known that at the coronation of kings and queens, even\nmodern ones, a certain curious process of seasoning them for their\nfunctions is gone through.  There is a saltcellar of state, so\ncalled, and there may be a castor of state.  How they use the salt,\nprecisely--who knows?  Certain I am, however, that a king's head is\nsolemnly oiled at his coronation, even as a head of salad.  Can it\nbe, though, that they anoint it with a view of making its interior\nrun well, as they anoint machinery?  Much might be ruminated here,\nconcerning the essential dignity of this regal process, because in\ncommon life we esteem but meanly and contemptibly a fellow who\nanoints his hair, and palpably smells of that anointing.  In truth, a\nmature man who uses hair-oil, unless medicinally, that man has\nprobably got a quoggy spot in him somewhere.  As a general rule, he\ncan't amount to much in his totality.\n\nBut the only thing to be considered here, is this--what kind of oil\nis used at coronations?  Certainly it cannot be olive oil, nor\nmacassar oil, nor castor oil, nor bear's oil, nor train oil, nor\ncod-liver oil.  What then can it possibly be, but sperm oil in\nits unmanufactured, unpolluted state, the sweetest of all oils?\n\nThink of that, ye loyal Britons! we whalemen supply your kings and\nqueens with coronation stuff!\n\n\n\nCHAPTER 26\n\nKnights and Squires.\n\n\nThe chief mate of the Pequod was Starbuck, a native of Nantucket, and\na Quaker by descent.  He was a long, earnest man, and though born on\nan icy coast, seemed well adapted to endure hot latitudes, his flesh\nbeing hard as twice-baked biscuit.  Transported to the Indies, his\nlive blood would not spoil like bottled ale.  He must have been born\nin some time of general drought and famine, or upon one of those fast\ndays for which his state is famous.  Only some thirty arid summers\nhad he seen; those summers had dried up all his physical\nsuperfluousness.  But this, his thinness, so to speak, seemed no more\nthe token of wasting anxieties and cares, than it seemed the\nindication of any bodily blight.  It was merely the condensation of\nthe man.  He was by no means ill-looking; quite the contrary.  His\npure tight skin was an excellent fit; and closely wrapped up in it,\nand embalmed with inner health and strength, like a revivified\nEgyptian, this Starbuck seemed prepared to endure for long ages to\ncome, and to endure always, as now; for be it Polar snow or torrid\nsun, like a patent chronometer, his interior vitality was warranted\nto do well in all climates.  Looking into his eyes, you seemed to\nsee there the yet lingering images of those thousand-fold perils he\nhad calmly confronted through life.  A staid, steadfast man, whose\nlife for the most part was a telling pantomime of action, and not a\ntame chapter of sounds.  Yet, for all his hardy sobriety and\nfortitude, there were certain qualities in him which at times\naffected, and in some cases seemed well nigh to overbalance all the\nrest.  Uncommonly conscientious for a seaman, and endued with a deep\nnatural reverence, the wild watery loneliness of his life did\ntherefore strongly incline him to superstition; but to that sort of\nsuperstition, which in some organizations seems rather to spring,\nsomehow, from intelligence than from ignorance.  Outward portents and\ninward presentiments were his.  And if at times these things bent the\nwelded iron of his soul, much more did his far-away domestic memories\nof his young Cape wife and child, tend to bend him still more from\nthe original ruggedness of his nature, and open him still further to\nthose latent influences which, in some honest-hearted men, restrain\nthe gush of dare-devil daring, so often evinced by others in the more\nperilous vicissitudes of the fishery.  \"I will have no man in my\nboat,\" said Starbuck, \"who is not afraid of a whale.\"  By this, he\nseemed to mean, not only that the most reliable and useful courage\nwas that which arises from the fair estimation of the encountered\nperil, but that an utterly fearless man is a far more dangerous\ncomrade than a coward.\n\n\"Aye, aye,\" said Stubb, the second mate, \"Starbuck, there, is as\ncareful a man as you'll find anywhere in this fishery.\"  But we shall\nere long see what that word \"careful\" precisely means when used by a\nman like Stubb, or almost any other whale hunter.\n\nStarbuck was no crusader after perils; in him courage was not a\nsentiment; but a thing simply useful to him, and always at hand upon\nall mortally practical occasions.  Besides, he thought, perhaps, that\nin this business of whaling, courage was one of the great staple\noutfits of the ship, like her beef and her bread, and not to be\nfoolishly wasted.  Wherefore he had no fancy for lowering for whales\nafter sun-down; nor for persisting in fighting a fish that too much\npersisted in fighting him.  For, thought Starbuck, I am here in this\ncritical ocean to kill whales for my living, and not to be killed by\nthem for theirs; and that hundreds of men had been so killed Starbuck\nwell knew.  What doom was his own father's?  Where, in the bottomless\ndeeps, could he find the torn limbs of his brother?\n\nWith memories like these in him, and, moreover, given to a certain\nsuperstitiousness, as has been said; the courage of this Starbuck\nwhich could, nevertheless, still flourish, must indeed have been\nextreme.  But it was not in reasonable nature that a man so\norganized, and with such terrible experiences and remembrances as he\nhad; it was not in nature that these things should fail in latently\nengendering an element in him, which, under suitable circumstances,\nwould break out from its confinement, and burn all his courage up.\nAnd brave as he might be, it was that sort of bravery chiefly,\nvisible in some intrepid men, which, while generally abiding firm in\nthe conflict with seas, or winds, or whales, or any of the ordinary\nirrational horrors of the world, yet cannot withstand those more\nterrific, because more spiritual terrors, which sometimes menace you\nfrom the concentrating brow of an enraged and mighty man.\n\nBut were the coming narrative to reveal in any instance, the complete\nabasement of poor Starbuck's fortitude, scarce might I have the heart\nto write it; for it is a thing most sorrowful, nay shocking, to\nexpose the fall of valour in the soul.  Men may seem detestable as\njoint stock-companies and nations; knaves, fools, and murderers there\nmay be; men may have mean and meagre faces; but man, in the ideal,\nis so noble and so sparkling, such a grand and glowing creature, that\nover any ignominious blemish in him all his fellows should run to\nthrow their costliest robes.  That immaculate manliness we feel\nwithin ourselves, so far within us, that it remains intact though all\nthe outer character seem gone; bleeds with keenest anguish at the\nundraped spectacle of a valor-ruined man.  Nor can piety itself, at\nsuch a shameful sight, completely stifle her upbraidings against the\npermitting stars.  But this august dignity I treat of, is not the\ndignity of kings and robes, but that abounding dignity which has no\nrobed investiture.  Thou shalt see it shining in the arm that wields\na pick or drives a spike; that democratic dignity which, on all\nhands, radiates without end from God; Himself!  The great God\nabsolute!  The centre and circumference of all democracy!  His\nomnipresence, our divine equality!\n\nIf, then, to meanest mariners, and renegades and castaways, I shall\nhereafter ascribe high qualities, though dark; weave round them\ntragic graces; if even the most mournful, perchance the most abased,\namong them all, shall at times lift himself to the exalted mounts; if\nI shall touch that workman's arm with some ethereal light; if I shall\nspread a rainbow over his disastrous set of sun; then against all\nmortal critics bear me out in it, thou Just Spirit of Equality,\nwhich hast spread one royal mantle of humanity over all my kind!\nBear me out in it, thou great democratic God! who didst not refuse to\nthe swart convict, Bunyan, the pale, poetic pearl; Thou who didst\nclothe with doubly hammered leaves of finest gold, the stumped and\npaupered arm of old Cervantes; Thou who didst pick up Andrew Jackson\nfrom the pebbles; who didst hurl him upon a war-horse; who didst\nthunder him higher than a throne!  Thou who, in all Thy mighty,\nearthly marchings, ever cullest Thy selectest champions from the\nkingly commons; bear me out in it, O God!\n\n\n\nCHAPTER 27\n\nKnights and Squires.\n\n\nStubb was the second mate.  He was a native of Cape Cod; and hence,\naccording to local usage, was called a Cape-Cod-man.  A\nhappy-go-lucky; neither craven nor valiant; taking perils as they\ncame with an indifferent air; and while engaged in the most imminent\ncrisis of the chase, toiling away, calm and collected as a journeyman\njoiner engaged for the year.  Good-humored, easy, and careless, he\npresided over his whale-boat as if the most deadly encounter were but\na dinner, and his crew all invited guests.  He was as particular\nabout the comfortable arrangement of his part of the boat, as an\nold stage-driver is about the snugness of his box.  When close to the\nwhale, in the very death-lock of the fight, he handled his unpitying\nlance coolly and off-handedly, as a whistling tinker his hammer.  He\nwould hum over his old rigadig tunes while flank and flank with the\nmost exasperated monster.  Long usage had, for this Stubb, converted\nthe jaws of death into an easy chair.  What he thought of death\nitself, there is no telling.  Whether he ever thought of it at all,\nmight be a question; but, if he ever did chance to cast his mind that\nway after a comfortable dinner, no doubt, like a good sailor, he took\nit to be a sort of call of the watch to tumble aloft, and bestir\nthemselves there, about something which he would find out when he\nobeyed the order, and not sooner.\n\nWhat, perhaps, with other things, made Stubb such an easy-going,\nunfearing man, so cheerily trudging off with the burden of life in a\nworld full of grave pedlars, all bowed to the ground with their\npacks; what helped to bring about that almost impious good-humor of\nhis; that thing must have been his pipe.  For, like his nose, his\nshort, black little pipe was one of the regular features of his face.\nYou would almost as soon have expected him to turn out of his bunk\nwithout his nose as without his pipe.  He kept a whole row of pipes\nthere ready loaded, stuck in a rack, within easy reach of his hand;\nand, whenever he turned in, he smoked them all out in succession,\nlighting one from the other to the end of the chapter; then loading\nthem again to be in readiness anew.  For, when Stubb dressed, instead\nof first putting his legs into his trowsers, he put his pipe into his\nmouth.\n\nI say this continual smoking must have been one cause, at least, of\nhis peculiar disposition; for every one knows that this earthly air,\nwhether ashore or afloat, is terribly infected with the nameless\nmiseries of the numberless mortals who have died exhaling it; and as\nin time of the cholera, some people go about with a camphorated\nhandkerchief to their mouths; so, likewise, against all mortal\ntribulations, Stubb's tobacco smoke might have operated as a sort of\ndisinfecting agent.\n\nThe third mate was Flask, a native of Tisbury, in Martha's Vineyard.\nA short, stout, ruddy young fellow, very pugnacious concerning\nwhales, who somehow seemed to think that the great leviathans had\npersonally and hereditarily affronted him; and therefore it was a\nsort of point of honour with him, to destroy them whenever\nencountered.  So utterly lost was he to all sense of reverence for\nthe many marvels of their majestic bulk and mystic ways; and so dead\nto anything like an apprehension of any possible danger from\nencountering them; that in his poor opinion, the wondrous whale was\nbut a species of magnified mouse, or at least water-rat, requiring\nonly a little circumvention and some small application of time and\ntrouble in order to kill and boil.  This ignorant, unconscious\nfearlessness of his made him a little waggish in the matter of\nwhales; he followed these fish for the fun of it; and a three years'\nvoyage round Cape Horn was only a jolly joke that lasted that length\nof time.  As a carpenter's nails are divided into wrought nails and\ncut nails; so mankind may be similarly divided.  Little Flask was one\nof the wrought ones; made to clinch tight and last long.  They called\nhim King-Post on board of the Pequod; because, in form, he could be\nwell likened to the short, square timber known by that name in Arctic\nwhalers; and which by the means of many radiating side timbers\ninserted into it, serves to brace the ship against the icy\nconcussions of those battering seas.\n\nNow these three mates--Starbuck, Stubb, and Flask, were momentous\nmen.  They it was who by universal prescription commanded three of the\nPequod's boats as headsmen.  In that grand order of battle in which\nCaptain Ahab would probably marshal his forces to descend on the\nwhales, these three headsmen were as captains of companies.  Or,\nbeing armed with their long keen whaling spears, they were as a\npicked trio of lancers; even as the harpooneers were flingers of\njavelins.\n\nAnd since in this famous fishery, each mate or headsman, like a\nGothic Knight of old, is always accompanied by his boat-steerer or\nharpooneer, who in certain conjunctures provides him with a fresh\nlance, when the former one has been badly twisted, or elbowed in the\nassault; and moreover, as there generally subsists between the two, a\nclose intimacy and friendliness; it is therefore but meet, that in\nthis place we set down who the Pequod's harpooneers were, and to what\nheadsman each of them belonged.\n\nFirst of all was Queequeg, whom Starbuck, the chief mate, had\nselected for his squire.  But Queequeg is already known.\n\nNext was Tashtego, an unmixed Indian from Gay Head, the most westerly\npromontory of Martha's Vineyard, where there still exists the last\nremnant of a village of red men, which has long supplied the\nneighboring island of Nantucket with many of her most daring\nharpooneers.  In the fishery, they usually go by the generic name of\nGay-Headers.  Tashtego's long, lean, sable hair, his high cheek\nbones, and black rounding eyes--for an Indian, Oriental in their\nlargeness, but Antarctic in their glittering expression--all this\nsufficiently proclaimed him an inheritor of the unvitiated blood of\nthose proud warrior hunters, who, in quest of the great New England\nmoose, had scoured, bow in hand, the aboriginal forests of the main.\nBut no longer snuffing in the trail of the wild beasts of the\nwoodland, Tashtego now hunted in the wake of the great whales of the\nsea; the unerring harpoon of the son fitly replacing the infallible\narrow of the sires.  To look at the tawny brawn of his lithe snaky\nlimbs, you would almost have credited the superstitions of some of\nthe earlier Puritans, and half-believed this wild Indian to be a son\nof the Prince of the Powers of the Air.  Tashtego was Stubb the\nsecond mate's squire.\n\nThird among the harpooneers was Daggoo, a gigantic, coal-black\nnegro-savage, with a lion-like tread--an Ahasuerus to behold.\nSuspended from his ears were two golden hoops, so large that the\nsailors called them ring-bolts, and would talk of securing the\ntop-sail halyards to them.  In his youth Daggoo had voluntarily\nshipped on board of a whaler, lying in a lonely bay on his native\ncoast.  And never having been anywhere in the world but in Africa,\nNantucket, and the pagan harbors most frequented by whalemen; and\nhaving now led for many years the bold life of the fishery in the\nships of owners uncommonly heedful of what manner of men they\nshipped; Daggoo retained all his barbaric virtues, and erect as a\ngiraffe, moved about the decks in all the pomp of six feet five in\nhis socks.  There was a corporeal humility in looking up at him; and\na white man standing before him seemed a white flag come to beg truce\nof a fortress.  Curious to tell, this imperial negro, Ahasuerus\nDaggoo, was the Squire of little Flask, who looked like a chess-man\nbeside him.  As for the residue of the Pequod's company, be it said,\nthat at the present day not one in two of the many thousand men\nbefore the mast employed in the American whale fishery, are Americans\nborn, though pretty nearly all the officers are.  Herein it is the\nsame with the American whale fishery as with the American army and\nmilitary and merchant navies, and the engineering forces employed in\nthe construction of the American Canals and Railroads.  The same, I\nsay, because in all these cases the native American liberally\nprovides the brains, the rest of the world as generously supplying\nthe muscles.  No small number of these whaling seamen belong to the\nAzores, where the outward bound Nantucket whalers frequently touch to\naugment their crews from the hardy peasants of those rocky shores.\nIn like manner, the Greenland whalers sailing out of Hull or London,\nput in at the Shetland Islands, to receive the full complement of\ntheir crew.  Upon the passage homewards, they drop them there again.\nHow it is, there is no telling, but Islanders seem to make the best\nwhalemen.  They were nearly all Islanders in the Pequod, ISOLATOES\ntoo, I call such, not acknowledging the common continent of men, but\neach ISOLATO living on a separate continent of his own.  Yet now,\nfederated along one keel, what a set these Isolatoes were!  An\nAnacharsis Clootz deputation from all the isles of the sea, and all\nthe ends of the earth, accompanying Old Ahab in the Pequod to lay the\nworld's grievances before that bar from which not very many of them\never come back.  Black Little Pip--he never did--oh, no! he went\nbefore.  Poor Alabama boy!  On the grim Pequod's forecastle, ye shall\nere long see him, beating his tambourine; prelusive of the eternal\ntime, when sent for, to the great quarter-deck on high, he was bid\nstrike in with angels, and beat his tambourine in glory; called a\ncoward here, hailed a hero there!\n\n\n\nCHAPTER 28\n\nAhab.\n\n\nFor several days after leaving Nantucket, nothing above hatches was\nseen of Captain Ahab.  The mates regularly relieved each other at the\nwatches, and for aught that could be seen to the contrary, they\nseemed to be the only commanders of the ship; only they sometimes\nissued from the cabin with orders so sudden and peremptory, that\nafter all it was plain they but commanded vicariously.  Yes, their\nsupreme lord and dictator was there, though hitherto unseen by any\neyes not permitted to penetrate into the now sacred retreat of the\ncabin.\n\nEvery time I ascended to the deck from my watches below, I instantly\ngazed aft to mark if any strange face were visible; for my first\nvague disquietude touching the unknown captain, now in the seclusion\nof the sea, became almost a perturbation.  This was strangely\nheightened at times by the ragged Elijah's diabolical incoherences\nuninvitedly recurring to me, with a subtle energy I could not have\nbefore conceived of.  But poorly could I withstand them, much as in\nother moods I was almost ready to smile at the solemn whimsicalities\nof that outlandish prophet of the wharves.  But whatever it was of\napprehensiveness or uneasiness--to call it so--which I felt, yet\nwhenever I came to look about me in the ship, it seemed against all\nwarrantry to cherish such emotions.  For though the harpooneers, with\nthe great body of the crew, were a far more barbaric, heathenish, and\nmotley set than any of the tame merchant-ship companies which my\nprevious experiences had made me acquainted with, still I ascribed\nthis--and rightly ascribed it--to the fierce uniqueness of the very\nnature of that wild Scandinavian vocation in which I had so\nabandonedly embarked.  But it was especially the aspect of the three\nchief officers of the ship, the mates, which was most forcibly\ncalculated to allay these colourless misgivings, and induce confidence\nand cheerfulness in every presentment of the voyage.  Three better,\nmore likely sea-officers and men, each in his own different way,\ncould not readily be found, and they were every one of them\nAmericans; a Nantucketer, a Vineyarder, a Cape man.  Now, it being\nChristmas when the ship shot from out her harbor, for a space we had\nbiting Polar weather, though all the time running away from it to the\nsouthward; and by every degree and minute of latitude which we\nsailed, gradually leaving that merciless winter, and all its\nintolerable weather behind us.  It was one of those less lowering,\nbut still grey and gloomy enough mornings of the transition, when\nwith a fair wind the ship was rushing through the water with a\nvindictive sort of leaping and melancholy rapidity, that as I mounted\nto the deck at the call of the forenoon watch, so soon as I levelled\nmy glance towards the taffrail, foreboding shivers ran over me.\nReality outran apprehension; Captain Ahab stood upon his\nquarter-deck.\n\nThere seemed no sign of common bodily illness about him, nor of the\nrecovery from any.  He looked like a man cut away from the stake,\nwhen the fire has overrunningly wasted all the limbs without\nconsuming them, or taking away one particle from their compacted aged\nrobustness.  His whole high, broad form, seemed made of solid bronze,\nand shaped in an unalterable mould, like Cellini's cast Perseus.\nThreading its way out from among his grey hairs, and continuing right\ndown one side of his tawny scorched face and neck, till it\ndisappeared in his clothing, you saw a slender rod-like mark, lividly\nwhitish.  It resembled that perpendicular seam sometimes made in the\nstraight, lofty trunk of a great tree, when the upper lightning\ntearingly darts down it, and without wrenching a single twig, peels\nand grooves out the bark from top to bottom, ere running off into the\nsoil, leaving the tree still greenly alive, but branded.  Whether\nthat mark was born with him, or whether it was the scar left by some\ndesperate wound, no one could certainly say.  By some tacit consent,\nthroughout the voyage little or no allusion was made to it,\nespecially by the mates.  But once Tashtego's senior, an old Gay-Head\nIndian among the crew, superstitiously asserted that not till he was\nfull forty years old did Ahab become that way branded, and then it\ncame upon him, not in the fury of any mortal fray, but in an\nelemental strife at sea.  Yet, this wild hint seemed inferentially\nnegatived, by what a grey Manxman insinuated, an old sepulchral man,\nwho, having never before sailed out of Nantucket, had never ere this\nlaid eye upon wild Ahab.  Nevertheless, the old sea-traditions, the\nimmemorial credulities, popularly invested this old Manxman with\npreternatural powers of discernment.  So that no white sailor\nseriously contradicted him when he said that if ever Captain Ahab\nshould be tranquilly laid out--which might hardly come to pass, so he\nmuttered--then, whoever should do that last office for the dead,\nwould find a birth-mark on him from crown to sole.\n\nSo powerfully did the whole grim aspect of Ahab affect me, and the\nlivid brand which streaked it, that for the first few moments I\nhardly noted that not a little of this overbearing grimness was owing\nto the barbaric white leg upon which he partly stood.  It had\npreviously come to me that this ivory leg had at sea been fashioned\nfrom the polished bone of the sperm whale's jaw.  \"Aye, he was\ndismasted off Japan,\" said the old Gay-Head Indian once; \"but like\nhis dismasted craft, he shipped another mast without coming home for\nit.  He has a quiver of 'em.\"\n\nI was struck with the singular posture he maintained.  Upon each side\nof the Pequod's quarter deck, and pretty close to the mizzen shrouds,\nthere was an auger hole, bored about half an inch or so, into the\nplank.  His bone leg steadied in that hole; one arm elevated, and\nholding by a shroud; Captain Ahab stood erect, looking straight out\nbeyond the ship's ever-pitching prow.  There was an infinity of\nfirmest fortitude, a determinate, unsurrenderable wilfulness, in the\nfixed and fearless, forward dedication of that glance.  Not a word he\nspoke; nor did his officers say aught to him; though by all their\nminutest gestures and expressions, they plainly showed the uneasy, if\nnot painful, consciousness of being under a troubled master-eye.  And\nnot only that, but moody stricken Ahab stood before them with a\ncrucifixion in his face; in all the nameless regal overbearing\ndignity of some mighty woe.\n\nEre long, from his first visit in the air, he withdrew into his\ncabin.  But after that morning, he was every day visible to the crew;\neither standing in his pivot-hole, or seated upon an ivory stool he\nhad; or heavily walking the deck.  As the sky grew less gloomy;\nindeed, began to grow a little genial, he became still less and less\na recluse; as if, when the ship had sailed from home, nothing but the\ndead wintry bleakness of the sea had then kept him so secluded.  And,\nby and by, it came to pass, that he was almost continually in the\nair; but, as yet, for all that he said, or perceptibly did, on the at\nlast sunny deck, he seemed as unnecessary there as another mast.  But\nthe Pequod was only making a passage now; not regularly cruising;\nnearly all whaling preparatives needing supervision the mates were\nfully competent to, so that there was little or nothing, out of\nhimself, to employ or excite Ahab, now; and thus chase away, for that\none interval, the clouds that layer upon layer were piled upon his\nbrow, as ever all clouds choose the loftiest peaks to pile themselves\nupon.\n\nNevertheless, ere long, the warm, warbling persuasiveness of the\npleasant, holiday weather we came to, seemed gradually to charm him\nfrom his mood.  For, as when the red-cheeked, dancing girls, April\nand May, trip home to the wintry, misanthropic woods; even the\nbarest, ruggedest, most thunder-cloven old oak will at least send\nforth some few green sprouts, to welcome such glad-hearted visitants;\nso Ahab did, in the end, a little respond to the playful allurings of\nthat girlish air.  More than once did he put forth the faint blossom\nof a look, which, in any other man, would have soon flowered out in a\nsmile.\n\n\n\nCHAPTER 29\n\nEnter Ahab; to Him, Stubb.\n\n\nSome days elapsed, and ice and icebergs all astern, the Pequod now\nwent rolling through the bright Quito spring, which, at sea, almost\nperpetually reigns on the threshold of the eternal August of the\nTropic.  The warmly cool, clear, ringing, perfumed, overflowing,\nredundant days, were as crystal goblets of Persian sherbet, heaped\nup--flaked up, with rose-water snow.  The starred and stately nights\nseemed haughty dames in jewelled velvets, nursing at home in lonely\npride, the memory of their absent conquering Earls, the golden\nhelmeted suns!  For sleeping man, 'twas hard to choose between such\nwinsome days and such seducing nights.  But all the witcheries of\nthat unwaning weather did not merely lend new spells and potencies to\nthe outward world.  Inward they turned upon the soul, especially when\nthe still mild hours of eve came on; then, memory shot her crystals\nas the clear ice most forms of noiseless twilights.  And all these\nsubtle agencies, more and more they wrought on Ahab's texture.\n\nOld age is always wakeful; as if, the longer linked with life, the\nless man has to do with aught that looks like death.  Among\nsea-commanders, the old greybeards will oftenest leave their berths\nto visit the night-cloaked deck.  It was so with Ahab; only that now,\nof late, he seemed so much to live in the open air, that truly\nspeaking, his visits were more to the cabin, than from the cabin to\nthe planks.  \"It feels like going down into one's tomb,\"--he would\nmutter to himself--\"for an old captain like me to be descending this\nnarrow scuttle, to go to my grave-dug berth.\"\n\nSo, almost every twenty-four hours, when the watches of the night\nwere set, and the band on deck sentinelled the slumbers of the band\nbelow; and when if a rope was to be hauled upon the forecastle, the\nsailors flung it not rudely down, as by day, but with some\ncautiousness dropt it to its place for fear of disturbing their\nslumbering shipmates; when this sort of steady quietude would begin\nto prevail, habitually, the silent steersman would watch the\ncabin-scuttle; and ere long the old man would emerge, gripping at the\niron banister, to help his crippled way.  Some considering touch of\nhumanity was in him; for at times like these, he usually abstained\nfrom patrolling the quarter-deck; because to his wearied mates,\nseeking repose within six inches of his ivory heel, such would have\nbeen the reverberating crack and din of that bony step, that their\ndreams would have been on the crunching teeth of sharks.  But once,\nthe mood was on him too deep for common regardings; and as with\nheavy, lumber-like pace he was measuring the ship from taffrail to\nmainmast, Stubb, the old second mate, came up from below, with a\ncertain unassured, deprecating humorousness, hinted that if Captain\nAhab was pleased to walk the planks, then, no one could say nay; but\nthere might be some way of muffling the noise; hinting something\nindistinctly and hesitatingly about a globe of tow, and the insertion\ninto it, of the ivory heel.  Ah!  Stubb, thou didst not know Ahab\nthen.\n\n\"Am I a cannon-ball, Stubb,\" said Ahab, \"that thou wouldst wad me\nthat fashion?  But go thy ways; I had forgot.  Below to thy nightly\ngrave; where such as ye sleep between shrouds, to use ye to the\nfilling one at last.--Down, dog, and kennel!\"\n\nStarting at the unforseen concluding exclamation of the so suddenly\nscornful old man, Stubb was speechless a moment; then said excitedly,\n\"I am not used to be spoken to that way, sir; I do but less than half\nlike it, sir.\"\n\n\"Avast! gritted Ahab between his set teeth, and violently moving\naway, as if to avoid some passionate temptation.\n\n\"No, sir; not yet,\" said Stubb, emboldened, \"I will not tamely be\ncalled a dog, sir.\"\n\n\"Then be called ten times a donkey, and a mule, and an ass, and\nbegone, or I'll clear the world of thee!\"\n\nAs he said this, Ahab advanced upon him with such overbearing terrors\nin his aspect, that Stubb involuntarily retreated.\n\n\"I was never served so before without giving a hard blow for it,\"\nmuttered Stubb, as he found himself descending the cabin-scuttle.\n\"It's very queer.  Stop, Stubb; somehow, now, I don't well know\nwhether to go back and strike him, or--what's that?--down here on my\nknees and pray for him?  Yes, that was the thought coming up in me;\nbut it would be the first time I ever DID pray.  It's queer; very\nqueer; and he's queer too; aye, take him fore and aft, he's about the\nqueerest old man Stubb ever sailed with.  How he flashed at me!--his\neyes like powder-pans! is he mad?  Anyway there's something on his\nmind, as sure as there must be something on a deck when it cracks.\nHe aint in his bed now, either, more than three hours out of the\ntwenty-four; and he don't sleep then.  Didn't that Dough-Boy, the\nsteward, tell me that of a morning he always finds the old man's\nhammock clothes all rumpled and tumbled, and the sheets down at the\nfoot, and the coverlid almost tied into knots, and the pillow a sort\nof frightful hot, as though a baked brick had been on it?  A hot old\nman!  I guess he's got what some folks ashore call a conscience; it's\na kind of Tic-Dolly-row they say--worse nor a toothache.  Well, well;\nI don't know what it is, but the Lord keep me from catching it.  He's\nfull of riddles; I wonder what he goes into the after hold for, every\nnight, as Dough-Boy tells me he suspects; what's that for, I should\nlike to know?  Who's made appointments with him in the hold?  Ain't\nthat queer, now?  But there's no telling, it's the old game--Here\ngoes for a snooze.  Damn me, it's worth a fellow's while to be born\ninto the world, if only to fall right asleep.  And now that I think\nof it, that's about the first thing babies do, and that's a sort of\nqueer, too.  Damn me, but all things are queer, come to think of 'em.\nBut that's against my principles.  Think not, is my eleventh\ncommandment; and sleep when you can, is my twelfth--So here goes\nagain.  But how's that? didn't he call me a dog? blazes! he called me\nten times a donkey, and piled a lot of jackasses on top of THAT!  He\nmight as well have kicked me, and done with it.  Maybe he DID kick\nme, and I didn't observe it, I was so taken all aback with his brow,\nsomehow.  It flashed like a bleached bone.  What the devil's the\nmatter with me?  I don't stand right on my legs.  Coming afoul of\nthat old man has a sort of turned me wrong side out.  By the Lord, I\nmust have been dreaming, though--How? how? how?--but the only way's\nto stash it; so here goes to hammock again; and in the morning, I'll\nsee how this plaguey juggling thinks over by daylight.\"\n\n\n\nCHAPTER 30\n\nThe Pipe.\n\n\nWhen Stubb had departed, Ahab stood for a while leaning over the\nbulwarks; and then, as had been usual with him of late, calling a\nsailor of the watch, he sent him below for his ivory stool, and also\nhis pipe.  Lighting the pipe at the binnacle lamp and planting the\nstool on the weather side of the deck, he sat and smoked.\n\nIn old Norse times, the thrones of the sea-loving Danish kings were\nfabricated, saith tradition, of the tusks of the narwhale.  How could\none look at Ahab then, seated on that tripod of bones, without\nbethinking him of the royalty it symbolized?  For a Khan of the\nplank, and a king of the sea, and a great lord of Leviathans was\nAhab.\n\nSome moments passed, during which the thick vapour came from his mouth\nin quick and constant puffs, which blew back again into his face.\n\"How now,\" he soliloquized at last, withdrawing the tube, \"this\nsmoking no longer soothes.  Oh, my pipe! hard must it go with me if\nthy charm be gone!  Here have I been unconsciously toiling, not\npleasuring--aye, and ignorantly smoking to windward all the while; to\nwindward, and with such nervous whiffs, as if, like the dying whale,\nmy final jets were the strongest and fullest of trouble.  What\nbusiness have I with this pipe?  This thing that is meant for\nsereneness, to send up mild white vapours among mild white hairs, not\namong torn iron-grey locks like mine.  I'll smoke no more--\"\n\nHe tossed the still lighted pipe into the sea.  The fire hissed in\nthe waves; the same instant the ship shot by the bubble the sinking\npipe made.  With slouched hat, Ahab lurchingly paced the planks.\n\n\n\nCHAPTER 31\n\nQueen Mab.\n\n\nNext morning Stubb accosted Flask.\n\n\"Such a queer dream, King-Post, I never had.  You know the old man's\nivory leg, well I dreamed he kicked me with it; and when I tried to\nkick back, upon my soul, my little man, I kicked my leg right off!\nAnd then, presto!  Ahab seemed a pyramid, and I, like a blazing fool,\nkept kicking at it.  But what was still more curious, Flask--you know\nhow curious all dreams are--through all this rage that I was in, I\nsomehow seemed to be thinking to myself, that after all, it was not\nmuch of an insult, that kick from Ahab.  'Why,' thinks I, 'what's the\nrow?  It's not a real leg, only a false leg.'  And there's a mighty\ndifference between a living thump and a dead thump.  That's what\nmakes a blow from the hand, Flask, fifty times more savage to bear\nthan a blow from a cane.  The living member--that makes the living\ninsult, my little man.  And thinks I to myself all the while, mind,\nwhile I was stubbing my silly toes against that cursed pyramid--so\nconfoundedly contradictory was it all, all the while, I say, I was\nthinking to myself, 'what's his leg now, but a cane--a whalebone\ncane.  Yes,' thinks I, 'it was only a playful cudgelling--in fact,\nonly a whaleboning that he gave me--not a base kick.  Besides,'\nthinks I, 'look at it once; why, the end of it--the foot part--what a\nsmall sort of end it is; whereas, if a broad footed farmer kicked me,\nTHERE'S a devilish broad insult.  But this insult is whittled down to\na point only.'  But now comes the greatest joke of the dream, Flask.\nWhile I was battering away at the pyramid, a sort of badger-haired\nold merman, with a hump on his back, takes me by the shoulders, and\nslews me round.  'What are you 'bout?' says he.  Slid! man, but I was\nfrightened.  Such a phiz!  But, somehow, next moment I was over the\nfright.  'What am I about?' says I at last.  'And what business is\nthat of yours, I should like to know, Mr. Humpback?  Do YOU want a\nkick?'  By the lord, Flask, I had no sooner said that, than he turned\nround his stern to me, bent over, and dragging up a lot of seaweed he\nhad for a clout--what do you think, I saw?--why thunder alive, man,\nhis stern was stuck full of marlinspikes, with the points out.  Says\nI, on second thoughts, 'I guess I won't kick you, old fellow.'  'Wise\nStubb,' said he, 'wise Stubb;' and kept muttering it all the time, a\nsort of eating of his own gums like a chimney hag.  Seeing he wasn't\ngoing to stop saying over his 'wise Stubb, wise Stubb,' I thought I\nmight as well fall to kicking the pyramid again.  But I had only just\nlifted my foot for it, when he roared out, 'Stop that kicking!'\n'Halloa,' says I, 'what's the matter now, old fellow?'  'Look ye\nhere,' says he; 'let's argue the insult.  Captain Ahab kicked ye,\ndidn't he?'  'Yes, he did,' says I--'right HERE it was.'  'Very\ngood,' says he--'he used his ivory leg, didn't he?'  'Yes, he did,'\nsays I.  'Well then,' says he, 'wise Stubb, what have you to complain\nof?  Didn't he kick with right good will? it wasn't a common pitch\npine leg he kicked with, was it?  No, you were kicked by a great man,\nand with a beautiful ivory leg, Stubb.  It's an honour; I consider it\nan honour.  Listen, wise Stubb.  In old England the greatest lords\nthink it great glory to be slapped by a queen, and made\ngarter-knights of; but, be YOUR boast, Stubb, that ye were kicked by\nold Ahab, and made a wise man of.  Remember what I say; BE kicked by\nhim; account his kicks honours; and on no account kick back; for you\ncan't help yourself, wise Stubb.  Don't you see that pyramid?'  With\nthat, he all of a sudden seemed somehow, in some queer fashion, to\nswim off into the air.  I snored; rolled over; and there I was in my\nhammock!  Now, what do you think of that dream, Flask?\"\n\n\"I don't know; it seems a sort of foolish to me, tho.'\"\n\n\"May be; may be.  But it's made a wise man of me, Flask.  D'ye see\nAhab standing there, sideways looking over the stern?  Well, the best\nthing you can do, Flask, is to let the old man alone; never speak to\nhim, whatever he says.  Halloa!  What's that he shouts?  Hark!\"\n\n\"Mast-head, there!  Look sharp, all of ye!  There are whales\nhereabouts!\n\nIf ye see a white one, split your lungs for him!\n\n\"What do you think of that now, Flask? ain't there a small drop of\nsomething queer about that, eh?  A white whale--did ye mark that,\nman?  Look ye--there's something special in the wind.  Stand by for\nit, Flask.  Ahab has that that's bloody on his mind.  But, mum; he\ncomes this way.\"\n\n\n\nCHAPTER 32\n\nCetology.\n\n\nAlready we are boldly launched upon the deep; but soon we shall be\nlost in its unshored, harbourless immensities.  Ere that come to pass;\nere the Pequod's weedy hull rolls side by side with the barnacled\nhulls of the leviathan; at the outset it is but well to attend to a\nmatter almost indispensable to a thorough appreciative understanding\nof the more special leviathanic revelations and allusions of all\nsorts which are to follow.\n\nIt is some systematized exhibition of the whale in his broad genera,\nthat I would now fain put before you.  Yet is it no easy task.  The\nclassification of the constituents of a chaos, nothing less is here\nessayed.  Listen to what the best and latest authorities have laid\ndown.\n\n\"No branch of Zoology is so much involved as that which is entitled\nCetology,\" says Captain Scoresby, A.D. 1820.\n\n\"It is not my intention, were it in my power, to enter into the\ninquiry as to the true method of dividing the cetacea into groups and\nfamilies....  Utter confusion exists among the historians of this\nanimal\" (sperm whale), says Surgeon Beale, A.D. 1839.\n\n\"Unfitness to pursue our research in the unfathomable waters.\"\n\"Impenetrable veil covering our knowledge of the cetacea.\"  \"A field\nstrewn with thorns.\"  \"All these incomplete indications but serve to\ntorture us naturalists.\"\n\nThus speak of the whale, the great Cuvier, and John Hunter, and\nLesson, those lights of zoology and anatomy.  Nevertheless, though of\nreal knowledge there be little, yet of books there are a plenty; and\nso in some small degree, with cetology, or the science of whales.\nMany are the men, small and great, old and new, landsmen and seamen,\nwho have at large or in little, written of the whale.  Run over a\nfew:--The Authors of the Bible; Aristotle; Pliny; Aldrovandi; Sir\nThomas Browne; Gesner; Ray; Linnaeus; Rondeletius; Willoughby; Green;\nArtedi; Sibbald; Brisson; Marten; Lacepede; Bonneterre; Desmarest;\nBaron Cuvier; Frederick Cuvier; John Hunter; Owen; Scoresby; Beale;\nBennett; J.  Ross Browne; the Author of Miriam Coffin; Olmstead; and\nthe Rev.  T.  Cheever.  But to what ultimate generalizing purpose all\nthese have written, the above cited extracts will show.\n\nOf the names in this list of whale authors, only those following Owen\never saw living whales; and but one of them was a real professional\nharpooneer and whaleman.  I mean Captain Scoresby.  On the separate\nsubject of the Greenland or right-whale, he is the best existing\nauthority.  But Scoresby knew nothing and says nothing of the great\nsperm whale, compared with which the Greenland whale is almost\nunworthy mentioning.  And here be it said, that the Greenland whale\nis an usurper upon the throne of the seas.  He is not even by any\nmeans the largest of the whales.  Yet, owing to the long priority of\nhis claims, and the profound ignorance which, till some seventy years\nback, invested the then fabulous or utterly unknown sperm-whale, and\nwhich ignorance to this present day still reigns in all but some few\nscientific retreats and whale-ports; this usurpation has been every\nway complete.  Reference to nearly all the leviathanic allusions in\nthe great poets of past days, will satisfy you that the Greenland\nwhale, without one rival, was to them the monarch of the seas.  But\nthe time has at last come for a new proclamation.  This is Charing\nCross; hear ye! good people all,--the Greenland whale is\ndeposed,--the great sperm whale now reigneth!\n\nThere are only two books in being which at all pretend to put the\nliving sperm whale before you, and at the same time, in the remotest\ndegree succeed in the attempt.  Those books are Beale's and\nBennett's; both in their time surgeons to English South-Sea\nwhale-ships, and both exact and reliable men.  The original matter\ntouching the sperm whale to be found in their volumes is necessarily\nsmall; but so far as it goes, it is of excellent quality, though\nmostly confined to scientific description.  As yet, however, the\nsperm whale, scientific or poetic, lives not complete in any\nliterature.  Far above all other hunted whales, his is an unwritten\nlife.\n\nNow the various species of whales need some sort of popular\ncomprehensive classification, if only an easy outline one for the\npresent, hereafter to be filled in all its departments by subsequent\nlaborers.  As no better man advances to take this matter in hand, I\nhereupon offer my own poor endeavors.  I promise nothing complete;\nbecause any human thing supposed to be complete, must for that very\nreason infallibly be faulty.  I shall not pretend to a minute\nanatomical description of the various species, or--in this place at\nleast--to much of any description.  My object here is simply to\nproject the draught of a systematization of cetology.  I am the\narchitect, not the builder.\n\nBut it is a ponderous task; no ordinary letter-sorter in the\nPost-Office is equal to it.  To grope down into the bottom of the sea\nafter them; to have one's hands among the unspeakable foundations,\nribs, and very pelvis of the world; this is a fearful thing.  What am\nI that I should essay to hook the nose of this leviathan!  The awful\ntauntings in Job might well appal me.  \"Will he the (leviathan) make\na covenant with thee?  Behold the hope of him is vain!  But I have\nswam through libraries and sailed through oceans; I have had to do\nwith whales with these visible hands; I am in earnest; and I will\ntry.  There are some preliminaries to settle.\n\nFirst: The uncertain, unsettled condition of this science of Cetology\nis in the very vestibule attested by the fact, that in some quarters\nit still remains a moot point whether a whale be a fish.  In his\nSystem of Nature, A.D. 1776, Linnaeus declares, \"I hereby separate\nthe whales from the fish.\"  But of my own knowledge, I know that down\nto the year 1850, sharks and shad, alewives and herring, against\nLinnaeus's express edict, were still found dividing the possession of\nthe same seas with the Leviathan.\n\nThe grounds upon which Linnaeus would fain have banished the whales\nfrom the waters, he states as follows: \"On account of their warm\nbilocular heart, their lungs, their movable eyelids, their hollow\nears, penem intrantem feminam mammis lactantem,\" and finally, \"ex\nlege naturae jure meritoque.\"  I submitted all this to my friends\nSimeon Macey and Charley Coffin, of Nantucket, both messmates of mine\nin a certain voyage, and they united in the opinion that the reasons\nset forth were altogether insufficient.  Charley profanely hinted\nthey were humbug.\n\nBe it known that, waiving all argument, I take the good old fashioned\nground that the whale is a fish, and call upon holy Jonah to back me.\nThis fundamental thing settled, the next point is, in what internal\nrespect does the whale differ from other fish.  Above, Linnaeus has\ngiven you those items.  But in brief, they are these: lungs and warm\nblood; whereas, all other fish are lungless and cold blooded.\n\nNext: how shall we define the whale, by his obvious externals, so as\nconspicuously to label him for all time to come?  To be short, then,\na whale is A SPOUTING FISH WITH A HORIZONTAL TAIL.  There you have\nhim.  However contracted, that definition is the result of expanded\nmeditation.  A walrus spouts much like a whale, but the walrus is not\na fish, because he is amphibious.  But the last term of the\ndefinition is still more cogent, as coupled with the first.  Almost\nany one must have noticed that all the fish familiar to landsmen have\nnot a flat, but a vertical, or up-and-down tail.  Whereas, among\nspouting fish the tail, though it may be similarly shaped, invariably\nassumes a horizontal position.\n\nBy the above definition of what a whale is, I do by no means exclude\nfrom the leviathanic brotherhood any sea creature hitherto identified\nwith the whale by the best informed Nantucketers; nor, on the other\nhand, link with it any fish hitherto authoritatively regarded as\nalien.*  Hence, all the smaller, spouting, and horizontal tailed fish\nmust be included in this ground-plan of Cetology.  Now, then, come\nthe grand divisions of the entire whale host.\n\n\n*I am aware that down to the present time, the fish styled Lamatins\nand Dugongs (Pig-fish and Sow-fish of the Coffins of Nantucket) are\nincluded by many naturalists among the whales.  But as these pig-fish\nare a noisy, contemptible set, mostly lurking in the mouths of\nrivers, and feeding on wet hay, and especially as they do not spout,\nI deny their credentials as whales; and have presented them with\ntheir passports to quit the Kingdom of Cetology.\n\n\nFirst: According to magnitude I divide the whales into three primary\nBOOKS (subdivisible into CHAPTERS), and these shall comprehend them\nall, both small and large.\n\nI. THE FOLIO WHALE; II. the OCTAVO WHALE; III. the DUODECIMO WHALE.\n\nAs the type of the FOLIO I present the SPERM WHALE; of the OCTAVO,\nthe GRAMPUS; of the DUODECIMO, the PORPOISE.\n\nFOLIOS.  Among these I here include the following chapters:--I. The\nSPERM WHALE; II. the RIGHT WHALE; III. the FIN-BACK WHALE; IV. the\nHUMP-BACKED WHALE; V. the RAZOR-BACK WHALE; VI. the SULPHUR-BOTTOM\nWHALE.\n\nBOOK I. (FOLIO), CHAPTER I. (SPERM WHALE).--This whale, among the\nEnglish of old vaguely known as the Trumpa whale, and the Physeter\nwhale, and the Anvil Headed whale, is the present Cachalot of the\nFrench, and the Pottsfich of the Germans, and the Macrocephalus of\nthe Long Words.  He is, without doubt, the largest inhabitant of the\nglobe; the most formidable of all whales to encounter; the most\nmajestic in aspect; and lastly, by far the most valuable in commerce;\nhe being the only creature from which that valuable substance,\nspermaceti, is obtained.  All his peculiarities will, in many other\nplaces, be enlarged upon.  It is chiefly with his name that I now\nhave to do.  Philologically considered, it is absurd.  Some centuries\nago, when the Sperm whale was almost wholly unknown in his own\nproper individuality, and when his oil was only accidentally obtained\nfrom the stranded fish; in those days spermaceti, it would seem, was\npopularly supposed to be derived from a creature identical with the\none then known in England as the Greenland or Right Whale.  It was\nthe idea also, that this same spermaceti was that quickening humor of\nthe Greenland Whale which the first syllable of the word literally\nexpresses.  In those times, also, spermaceti was exceedingly scarce,\nnot being used for light, but only as an ointment and medicament.  It\nwas only to be had from the druggists as you nowadays buy an ounce of\nrhubarb.  When, as I opine, in the course of time, the true nature of\nspermaceti became known, its original name was still retained by the\ndealers; no doubt to enhance its value by a notion so strangely\nsignificant of its scarcity.  And so the appellation must at last\nhave come to be bestowed upon the whale from which this spermaceti\nwas really derived.\n\nBOOK I. (FOLIO), CHAPTER II. (RIGHT WHALE).--In one respect this is\nthe most venerable of the leviathans, being the one first regularly\nhunted by man.  It yields the article commonly known as whalebone or\nbaleen; and the oil specially known as \"whale oil,\" an inferior\narticle in commerce.  Among the fishermen, he is indiscriminately\ndesignated by all the following titles: The Whale; the Greenland\nWhale; the Black Whale; the Great Whale; the True Whale; the Right\nWhale.  There is a deal of obscurity concerning the identity of the\nspecies thus multitudinously baptised.  What then is the whale, which\nI include in the second species of my Folios?  It is the Great\nMysticetus of the English naturalists; the Greenland Whale of the\nEnglish whalemen; the Baliene Ordinaire of the French whalemen; the\nGrowlands Walfish of the Swedes.  It is the whale which for more than\ntwo centuries past has been hunted by the Dutch and English in the\nArctic seas; it is the whale which the American fishermen have long\npursued in the Indian ocean, on the Brazil Banks, on the Nor' West\nCoast, and various other parts of the world, designated by them Right\nWhale Cruising Grounds.\n\nSome pretend to see a difference between the Greenland whale of the\nEnglish and the right whale of the Americans.  But they precisely\nagree in all their grand features; nor has there yet been presented a\nsingle determinate fact upon which to ground a radical distinction.\nIt is by endless subdivisions based upon the most inconclusive\ndifferences, that some departments of natural history become so\nrepellingly intricate.  The right whale will be elsewhere treated of\nat some length, with reference to elucidating the sperm whale.\n\nBOOK I. (FOLIO), CHAPTER III. (FIN-BACK).--Under this head I reckon a\nmonster which, by the various names of Fin-Back, Tall-Spout, and\nLong-John, has been seen almost in every sea and is commonly the\nwhale whose distant jet is so often descried by passengers crossing\nthe Atlantic, in the New York packet-tracks.  In the length he\nattains, and in his baleen, the Fin-back resembles the right whale,\nbut is of a less portly girth, and a lighter colour, approaching to\nolive.  His great lips present a cable-like aspect, formed by the\nintertwisting, slanting folds of large wrinkles.  His grand\ndistinguishing feature, the fin, from which he derives his name, is\noften a conspicuous object.  This fin is some three or four feet\nlong, growing vertically from the hinder part of the back, of an\nangular shape, and with a very sharp pointed end.  Even if not the\nslightest other part of the creature be visible, this isolated fin\nwill, at times, be seen plainly projecting from the surface.  When\nthe sea is moderately calm, and slightly marked with spherical\nripples, and this gnomon-like fin stands up and casts shadows upon\nthe wrinkled surface, it may well be supposed that the watery circle\nsurrounding it somewhat resembles a dial, with its style and wavy\nhour-lines graved on it.  On that Ahaz-dial the shadow often goes\nback.  The Fin-Back is not gregarious.  He seems a whale-hater, as\nsome men are man-haters.  Very shy; always going solitary;\nunexpectedly rising to the surface in the remotest and most sullen\nwaters; his straight and single lofty jet rising like a tall\nmisanthropic spear upon a barren plain; gifted with such wondrous\npower and velocity in swimming, as to defy all present pursuit from\nman; this leviathan seems the banished and unconquerable Cain of his\nrace, bearing for his mark that style upon his back.  From having the\nbaleen in his mouth, the Fin-Back is sometimes included with the\nright whale, among a theoretic species denominated WHALEBONE WHALES,\nthat is, whales with baleen.  Of these so called Whalebone whales,\nthere would seem to be several varieties, most of which, however, are\nlittle known.  Broad-nosed whales and beaked whales; pike-headed\nwhales; bunched whales; under-jawed whales and rostrated whales, are\nthe fishermen's names for a few sorts.\n\nIn connection with this appellative of \"Whalebone whales,\" it is of\ngreat importance to mention, that however such a nomenclature may be\nconvenient in facilitating allusions to some kind of whales, yet it\nis in vain to attempt a clear classification of the Leviathan,\nfounded upon either his baleen, or hump, or fin, or teeth;\nnotwithstanding that those marked parts or features very obviously\nseem better adapted to afford the basis for a regular system of\nCetology than any other detached bodily distinctions, which the\nwhale, in his kinds, presents.  How then?  The baleen, hump,\nback-fin, and teeth; these are things whose peculiarities are\nindiscriminately dispersed among all sorts of whales, without any\nregard to what may be the nature of their structure in other and\nmore essential particulars.  Thus, the sperm whale and the humpbacked\nwhale, each has a hump; but there the similitude ceases.  Then, this\nsame humpbacked whale and the Greenland whale, each of these has\nbaleen; but there again the similitude ceases.  And it is just the\nsame with the other parts above mentioned.  In various sorts of\nwhales, they form such irregular combinations; or, in the case of any\none of them detached, such an irregular isolation; as utterly to defy\nall general methodization formed upon such a basis.  On this rock\nevery one of the whale-naturalists has split.\n\nBut it may possibly be conceived that, in the internal parts of the\nwhale, in his anatomy--there, at least, we shall be able to hit the\nright classification.  Nay; what thing, for example, is there in the\nGreenland whale's anatomy more striking than his baleen?  Yet we have\nseen that by his baleen it is impossible correctly to classify the\nGreenland whale.  And if you descend into the bowels of the various\nleviathans, why there you will not find distinctions a fiftieth part\nas available to the systematizer as those external ones already\nenumerated.  What then remains? nothing but to take hold of the\nwhales bodily, in their entire liberal volume, and boldly sort them\nthat way.  And this is the Bibliographical system here adopted; and\nit is the only one that can possibly succeed, for it alone is\npracticable.  To proceed.\n\nBOOK I. (FOLIO) CHAPTER IV. (HUMP-BACK).--This whale is often seen on\nthe northern American coast.  He has been frequently captured there,\nand towed into harbor.  He has a great pack on him like a peddler; or\nyou might call him the Elephant and Castle whale.  At any rate, the\npopular name for him does not sufficiently distinguish him, since the\nsperm whale also has a hump though a smaller one.  His oil is not\nvery valuable.  He has baleen.  He is the most gamesome and\nlight-hearted of all the whales, making more gay foam and white water\ngenerally than any other of them.\n\nBOOK I. (FOLIO), CHAPTER V. (RAZOR-BACK).--Of this whale little is\nknown but his name.  I have seen him at a distance off Cape Horn.  Of\na retiring nature, he eludes both hunters and philosophers.  Though\nno coward, he has never yet shown any part of him but his back, which\nrises in a long sharp ridge.  Let him go.  I know little more of him,\nnor does anybody else.\n\nBOOK I. (FOLIO), CHAPTER VI. (SULPHUR-BOTTOM).--Another retiring\ngentleman, with a brimstone belly, doubtless got by scraping along\nthe Tartarian tiles in some of his profounder divings.  He is seldom\nseen; at least I have never seen him except in the remoter southern\nseas, and then always at too great a distance to study his\ncountenance.  He is never chased; he would run away with rope-walks\nof line.  Prodigies are told of him.  Adieu, Sulphur Bottom!  I can\nsay nothing more that is true of ye, nor can the oldest Nantucketer.\n\nThus ends BOOK I. (FOLIO), and now begins BOOK II. (OCTAVO).\n\nOCTAVOES.*--These embrace the whales of middling magnitude, among\nwhich present may be numbered:--I., the GRAMPUS; II., the BLACK FISH;\nIII., the NARWHALE; IV., the THRASHER; V., the KILLER.\n\n\n*Why this book of whales is not denominated the Quarto is very plain.\nBecause, while the whales of this order, though smaller than those\nof the former order, nevertheless retain a proportionate likeness to\nthem in figure, yet the bookbinder's Quarto volume in its dimensioned\nform does not preserve the shape of the Folio volume, but the Octavo\nvolume does.\n\n\nBOOK II. (OCTAVO), CHAPTER I. (GRAMPUS).--Though this fish, whose\nloud sonorous breathing, or rather blowing, has furnished a proverb\nto landsmen, is so well known a denizen of the deep, yet is he not\npopularly classed among whales.  But possessing all the grand\ndistinctive features of the leviathan, most naturalists have\nrecognised him for one.  He is of moderate octavo size, varying from\nfifteen to twenty-five feet in length, and of corresponding\ndimensions round the waist.  He swims in herds; he is never regularly\nhunted, though his oil is considerable in quantity, and pretty good\nfor light.  By some fishermen his approach is regarded as premonitory\nof the advance of the great sperm whale.\n\nBOOK II. (OCTAVO), CHAPTER II. (BLACK FISH).--I give the popular\nfishermen's names for all these fish, for generally they are the\nbest.  Where any name happens to be vague or inexpressive, I shall\nsay so, and suggest another.  I do so now, touching the Black Fish,\nso-called, because blackness is the rule among almost all whales.\nSo, call him the Hyena Whale, if you please.  His voracity is well\nknown, and from the circumstance that the inner angles of his lips\nare curved upwards, he carries an everlasting Mephistophelean grin on\nhis face.  This whale averages some sixteen or eighteen feet in\nlength.  He is found in almost all latitudes.  He has a peculiar way\nof showing his dorsal hooked fin in swimming, which looks something\nlike a Roman nose.  When not more profitably employed, the sperm\nwhale hunters sometimes capture the Hyena whale, to keep up the\nsupply of cheap oil for domestic employment--as some frugal\nhousekeepers, in the absence of company, and quite alone by\nthemselves, burn unsavory tallow instead of odorous wax.  Though\ntheir blubber is very thin, some of these whales will yield you\nupwards of thirty gallons of oil.\n\nBOOK II. (OCTAVO), CHAPTER III. (NARWHALE), that is, NOSTRIL\nWHALE.--Another instance of a curiously named whale, so named I\nsuppose from his peculiar horn being originally mistaken for a peaked\nnose.  The creature is some sixteen feet in length, while its horn\naverages five feet, though some exceed ten, and even attain to\nfifteen feet.  Strictly speaking, this horn is but a lengthened tusk,\ngrowing out from the jaw in a line a little depressed from the\nhorizontal.  But it is only found on the sinister side, which has an\nill effect, giving its owner something analogous to the aspect of a\nclumsy left-handed man.  What precise purpose this ivory horn or\nlance answers, it would be hard to say.  It does not seem to be used\nlike the blade of the sword-fish and bill-fish; though some sailors\ntell me that the Narwhale employs it for a rake in turning over the\nbottom of the sea for food.  Charley Coffin said it was used for an\nice-piercer; for the Narwhale, rising to the surface of the Polar\nSea, and finding it sheeted with ice, thrusts his horn up, and so\nbreaks through.  But you cannot prove either of these surmises to be\ncorrect.  My own opinion is, that however this one-sided horn may\nreally be used by the Narwhale--however that may be--it would\ncertainly be very convenient to him for a folder in reading\npamphlets.  The Narwhale I have heard called the Tusked whale, the\nHorned whale, and the Unicorn whale.  He is certainly a curious\nexample of the Unicornism to be found in almost every kingdom of\nanimated nature.  From certain cloistered old authors I have gathered\nthat this same sea-unicorn's horn was in ancient days regarded as the\ngreat antidote against poison, and as such, preparations of it\nbrought immense prices.  It was also distilled to a volatile salts\nfor fainting ladies, the same way that the horns of the male deer are\nmanufactured into hartshorn.  Originally it was in itself accounted\nan object of great curiosity.  Black Letter tells me that Sir Martin\nFrobisher on his return from that voyage, when Queen Bess did\ngallantly wave her jewelled hand to him from a window of Greenwich\nPalace, as his bold ship sailed down the Thames; \"when Sir Martin\nreturned from that voyage,\" saith Black Letter, \"on bended knees he\npresented to her highness a prodigious long horn of the Narwhale,\nwhich for a long period after hung in the castle at Windsor.\"  An\nIrish author avers that the Earl of Leicester, on bended knees, did\nlikewise present to her highness another horn, pertaining to a land\nbeast of the unicorn nature.\n\nThe Narwhale has a very picturesque, leopard-like look, being of a\nmilk-white ground colour, dotted with round and oblong spots of black.\nHis oil is very superior, clear and fine; but there is little of it,\nand he is seldom hunted.  He is mostly found in the circumpolar seas.\n\nBOOK II. (OCTAVO), CHAPTER IV. (KILLER).--Of this whale little is\nprecisely known to the Nantucketer, and nothing at all to the\nprofessed naturalist.  From what I have seen of him at a distance,\nI should say that he was about the bigness of a grampus.  He is very\nsavage--a sort of Feegee fish.  He sometimes takes the great Folio\nwhales by the lip, and hangs there like a leech, till the mighty\nbrute is worried to death.  The Killer is never hunted.  I never\nheard what sort of oil he has.  Exception might be taken to the name\nbestowed upon this whale, on the ground of its indistinctness.  For\nwe are all killers, on land and on sea; Bonapartes and Sharks\nincluded.\n\nBOOK II. (OCTAVO), CHAPTER V. (THRASHER).--This gentleman is famous\nfor his tail, which he uses for a ferule in thrashing his foes.  He\nmounts the Folio whale's back, and as he swims, he works his passage\nby flogging him; as some schoolmasters get along in the world by a\nsimilar process.  Still less is known of the Thrasher than of the\nKiller.  Both are outlaws, even in the lawless seas.\n\nThus ends BOOK II. (OCTAVO), and begins BOOK III. (DUODECIMO).\n\nDUODECIMOES.--These include the smaller whales.  I. The Huzza\nPorpoise.  II. The Algerine Porpoise.  III. The Mealy-mouthed\nPorpoise.\n\nTo those who have not chanced specially to study the subject, it may\npossibly seem strange, that fishes not commonly exceeding four or\nfive feet should be marshalled among WHALES--a word, which, in the\npopular sense, always conveys an idea of hugeness.  But the creatures\nset down above as Duodecimoes are infallibly whales, by the terms of\nmy definition of what a whale is--i.e. a spouting fish, with a\nhorizontal tail.\n\nBOOK III. (DUODECIMO), CHAPTER 1. (HUZZA PORPOISE).--This is the\ncommon porpoise found almost all over the globe.  The name is of my\nown bestowal; for there are more than one sort of porpoises, and\nsomething must be done to distinguish them.  I call him thus, because\nhe always swims in hilarious shoals, which upon the broad sea keep\ntossing themselves to heaven like caps in a Fourth-of-July crowd.\nTheir appearance is generally hailed with delight by the mariner.\nFull of fine spirits, they invariably come from the breezy billows to\nwindward.  They are the lads that always live before the wind.  They\nare accounted a lucky omen.  If you yourself can withstand three\ncheers at beholding these vivacious fish, then heaven help ye; the\nspirit of godly gamesomeness is not in ye.  A well-fed, plump Huzza\nPorpoise will yield you one good gallon of good oil.  But the fine\nand delicate fluid extracted from his jaws is exceedingly valuable.\nIt is in request among jewellers and watchmakers.  Sailors put it on\ntheir hones.  Porpoise meat is good eating, you know.  It may never\nhave occurred to you that a porpoise spouts.  Indeed, his spout is so\nsmall that it is not very readily discernible.  But the next time you\nhave a chance, watch him; and you will then see the great Sperm whale\nhimself in miniature.\n\nBOOK III. (DUODECIMO), CHAPTER II. (ALGERINE PORPOISE).--A pirate.\nVery savage.  He is only found, I think, in the Pacific.  He is\nsomewhat larger than the Huzza Porpoise, but much of the same general\nmake.  Provoke him, and he will buckle to a shark.  I have lowered\nfor him many times, but never yet saw him captured.\n\nBOOK III. (DUODECIMO), CHAPTER III. (MEALY-MOUTHED PORPOISE).--The\nlargest kind of Porpoise; and only found in the Pacific, so far as it\nis known.  The only English name, by which he has hitherto been\ndesignated, is that of the fishers--Right-Whale Porpoise, from the\ncircumstance that he is chiefly found in the vicinity of that Folio.\nIn shape, he differs in some degree from the Huzza Porpoise, being of\na less rotund and jolly girth; indeed, he is of quite a neat and\ngentleman-like figure.  He has no fins on his back (most other\nporpoises have), he has a lovely tail, and sentimental Indian eyes of\na hazel hue.  But his mealy-mouth spoils all.  Though his entire\nback down to his side fins is of a deep sable, yet a boundary line,\ndistinct as the mark in a ship's hull, called the \"bright waist,\"\nthat line streaks him from stem to stern, with two separate colours,\nblack above and white below.  The white comprises part of his head,\nand the whole of his mouth, which makes him look as if he had just\nescaped from a felonious visit to a meal-bag.  A most mean and mealy\naspect!  His oil is much like that of the common porpoise.\n\n\nBeyond the DUODECIMO, this system does not proceed, inasmuch as the\nPorpoise is the smallest of the whales.  Above, you have all the\nLeviathans of note.  But there are a rabble of uncertain, fugitive,\nhalf-fabulous whales, which, as an American whaleman, I know by\nreputation, but not personally.  I shall enumerate them by their\nfore-castle appellations; for possibly such a list may be valuable to\nfuture investigators, who may complete what I have here but begun.\nIf any of the following whales, shall hereafter be caught and marked,\nthen he can readily be incorporated into this System, according to\nhis Folio, Octavo, or Duodecimo magnitude:--The Bottle-Nose Whale;\nthe Junk Whale; the Pudding-Headed Whale; the Cape Whale; the Leading\nWhale; the Cannon Whale; the Scragg Whale; the Coppered Whale; the\nElephant Whale; the Iceberg Whale; the Quog Whale; the Blue Whale; etc.\nFrom Icelandic, Dutch, and old English authorities, there might\nbe quoted other lists of uncertain whales, blessed with all manner of\nuncouth names.  But I omit them as altogether obsolete; and can\nhardly help suspecting them for mere sounds, full of Leviathanism,\nbut signifying nothing.\n\nFinally: It was stated at the outset, that this system would not be\nhere, and at once, perfected.  You cannot but plainly see that I have\nkept my word.  But I now leave my cetological System standing thus\nunfinished, even as the great Cathedral of Cologne was left, with the\ncrane still standing upon the top of the uncompleted tower.  For\nsmall erections may be finished by their first architects; grand\nones, true ones, ever leave the copestone to posterity.  God keep me\nfrom ever completing anything.  This whole book is but a\ndraught--nay, but the draught of a draught.  Oh, Time, Strength,\nCash, and Patience!\n\n\n\nCHAPTER 33\n\nThe Specksynder.\n\n\nConcerning the officers of the whale-craft, this seems as good a\nplace as any to set down a little domestic peculiarity on ship-board,\narising from the existence of the harpooneer class of officers, a\nclass unknown of course in any other marine than the whale-fleet.\n\nThe large importance attached to the harpooneer's vocation is evinced\nby the fact, that originally in the old Dutch Fishery, two centuries\nand more ago, the command of a whale ship was not wholly lodged in\nthe person now called the captain, but was divided between him and an\nofficer called the Specksynder.  Literally this word means\nFat-Cutter; usage, however, in time made it equivalent to Chief\nHarpooneer.  In those days, the captain's authority was restricted to\nthe navigation and general management of the vessel; while over the\nwhale-hunting department and all its concerns, the Specksynder or\nChief Harpooneer reigned supreme.  In the British Greenland Fishery,\nunder the corrupted title of Specksioneer, this old Dutch official is\nstill retained, but his former dignity is sadly abridged.  At present\nhe ranks simply as senior Harpooneer; and as such, is but one of the\ncaptain's more inferior subalterns.  Nevertheless, as upon the good\nconduct of the harpooneers the success of a whaling voyage largely\ndepends, and since in the American Fishery he is not only an\nimportant officer in the boat, but under certain circumstances (night\nwatches on a whaling ground) the command of the ship's deck is also\nhis; therefore the grand political maxim of the sea demands, that he\nshould nominally live apart from the men before the mast, and be in\nsome way distinguished as their professional superior; though always,\nby them, familiarly regarded as their social equal.\n\nNow, the grand distinction drawn between officer and man at sea, is\nthis--the first lives aft, the last forward.  Hence, in whale-ships\nand merchantmen alike, the mates have their quarters with the\ncaptain; and so, too, in most of the American whalers the harpooneers\nare lodged in the after part of the ship.  That is to say, they take\ntheir meals in the captain's cabin, and sleep in a place indirectly\ncommunicating with it.\n\nThough the long period of a Southern whaling voyage (by far the\nlongest of all voyages now or ever made by man), the peculiar perils\nof it, and the community of interest prevailing among a company, all\nof whom, high or low, depend for their profits, not upon fixed wages,\nbut upon their common luck, together with their common vigilance,\nintrepidity, and hard work; though all these things do in some cases\ntend to beget a less rigorous discipline than in merchantmen\ngenerally; yet, never mind how much like an old Mesopotamian family\nthese whalemen may, in some primitive instances, live together; for\nall that, the punctilious externals, at least, of the quarter-deck\nare seldom materially relaxed, and in no instance done away.  Indeed,\nmany are the Nantucket ships in which you will see the skipper\nparading his quarter-deck with an elated grandeur not surpassed in\nany military navy; nay, extorting almost as much outward homage as if\nhe wore the imperial purple, and not the shabbiest of pilot-cloth.\n\nAnd though of all men the moody captain of the Pequod was the least\ngiven to that sort of shallowest assumption; and though the only\nhomage he ever exacted, was implicit, instantaneous obedience; though\nhe required no man to remove the shoes from his feet ere stepping\nupon the quarter-deck; and though there were times when, owing to\npeculiar circumstances connected with events hereafter to be\ndetailed, he addressed them in unusual terms, whether of\ncondescension or IN TERROREM, or otherwise; yet even Captain Ahab was\nby no means unobservant of the paramount forms and usages of the sea.\n\nNor, perhaps, will it fail to be eventually perceived, that behind\nthose forms and usages, as it were, he sometimes masked himself;\nincidentally making use of them for other and more private ends than\nthey were legitimately intended to subserve.  That certain sultanism\nof his brain, which had otherwise in a good degree remained\nunmanifested; through those forms that same sultanism became\nincarnate in an irresistible dictatorship.  For be a man's\nintellectual superiority what it will, it can never assume the\npractical, available supremacy over other men, without the aid of\nsome sort of external arts and entrenchments, always, in themselves,\nmore or less paltry and base.  This it is, that for ever keeps God's\ntrue princes of the Empire from the world's hustings; and leaves the\nhighest honours that this air can give, to those men who become famous\nmore through their infinite inferiority to the choice hidden handful\nof the Divine Inert, than through their undoubted superiority over\nthe dead level of the mass.  Such large virtue lurks in these small\nthings when extreme political superstitions invest them, that in some\nroyal instances even to idiot imbecility they have imparted potency.\nBut when, as in the case of Nicholas the Czar, the ringed crown of\ngeographical empire encircles an imperial brain; then, the plebeian\nherds crouch abased before the tremendous centralization.  Nor, will\nthe tragic dramatist who would depict mortal indomitableness in its\nfullest sweep and direct swing, ever forget a hint, incidentally so\nimportant in his art, as the one now alluded to.\n\nBut Ahab, my Captain, still moves before me in all his Nantucket\ngrimness and shagginess; and in this episode touching Emperors and\nKings, I must not conceal that I have only to do with a poor old\nwhale-hunter like him; and, therefore, all outward majestical\ntrappings and housings are denied me.  Oh, Ahab! what shall be grand\nin thee, it must needs be plucked at from the skies, and dived for in\nthe deep, and featured in the unbodied air!\n\n\n\nCHAPTER 34\n\nThe Cabin-Table.\n\n\nIt is noon; and Dough-Boy, the steward, thrusting his pale\nloaf-of-bread face from the cabin-scuttle, announces dinner to his\nlord and master; who, sitting in the lee quarter-boat, has just been\ntaking an observation of the sun; and is now mutely reckoning the\nlatitude on the smooth, medallion-shaped tablet, reserved for that\ndaily purpose on the upper part of his ivory leg.  From his complete\ninattention to the tidings, you would think that moody Ahab had not\nheard his menial.  But presently, catching hold of the mizen shrouds,\nhe swings himself to the deck, and in an even, unexhilarated voice,\nsaying, \"Dinner, Mr. Starbuck,\" disappears into the cabin.\n\nWhen the last echo of his sultan's step has died away, and Starbuck,\nthe first Emir, has every reason to suppose that he is seated, then\nStarbuck rouses from his quietude, takes a few turns along the\nplanks, and, after a grave peep into the binnacle, says, with some\ntouch of pleasantness, \"Dinner, Mr. Stubb,\" and descends the scuttle.\nThe second Emir lounges about the rigging awhile, and then slightly\nshaking the main brace, to see whether it will be all right with\nthat important rope, he likewise takes up the old burden, and with a\nrapid \"Dinner, Mr. Flask,\" follows after his predecessors.\n\nBut the third Emir, now seeing himself all alone on the quarter-deck,\nseems to feel relieved from some curious restraint; for, tipping all\nsorts of knowing winks in all sorts of directions, and kicking off\nhis shoes, he strikes into a sharp but noiseless squall of a hornpipe\nright over the Grand Turk's head; and then, by a dexterous sleight,\npitching his cap up into the mizentop for a shelf, he goes down\nrollicking so far at least as he remains visible from the deck,\nreversing all other processions, by bringing up the rear with music.\nBut ere stepping into the cabin doorway below, he pauses, ships a new\nface altogether, and, then, independent, hilarious little Flask\nenters King Ahab's presence, in the character of Abjectus, or the\nSlave.\n\nIt is not the least among the strange things bred by the intense\nartificialness of sea-usages, that while in the open air of the deck\nsome officers will, upon provocation, bear themselves boldly and\ndefyingly enough towards their commander; yet, ten to one, let those\nvery officers the next moment go down to their customary dinner in\nthat same commander's cabin, and straightway their inoffensive, not\nto say deprecatory and humble air towards him, as he sits at the head\nof the table; this is marvellous, sometimes most comical.  Wherefore\nthis difference?  A problem?  Perhaps not.  To have been Belshazzar,\nKing of Babylon; and to have been Belshazzar, not haughtily but\ncourteously, therein certainly must have been some touch of mundane\ngrandeur.  But he who in the rightly regal and intelligent spirit\npresides over his own private dinner-table of invited guests, that\nman's unchallenged power and dominion of individual influence for the\ntime; that man's royalty of state transcends Belshazzar's, for\nBelshazzar was not the greatest.  Who has but once dined his friends,\nhas tasted what it is to be Caesar.  It is a witchery of social\nczarship which there is no withstanding.  Now, if to this\nconsideration you superadd the official supremacy of a ship-master,\nthen, by inference, you will derive the cause of that peculiarity of\nsea-life just mentioned.\n\nOver his ivory-inlaid table, Ahab presided like a mute, maned\nsea-lion on the white coral beach, surrounded by his warlike but\nstill deferential cubs.  In his own proper turn, each officer waited\nto be served.  They were as little children before Ahab; and yet, in\nAhab, there seemed not to lurk the smallest social arrogance.  With\none mind, their intent eyes all fastened upon the old man's knife, as\nhe carved the chief dish before him.  I do not suppose that for the\nworld they would have profaned that moment with the slightest\nobservation, even upon so neutral a topic as the weather.  No!  And\nwhen reaching out his knife and fork, between which the slice of beef\nwas locked, Ahab thereby motioned Starbuck's plate towards him, the\nmate received his meat as though receiving alms; and cut it tenderly;\nand a little started if, perchance, the knife grazed against the\nplate; and chewed it noiselessly; and swallowed it, not without\ncircumspection.  For, like the Coronation banquet at Frankfort, where\nthe German Emperor profoundly dines with the seven Imperial\nElectors, so these cabin meals were somehow solemn meals, eaten in\nawful silence; and yet at table old Ahab forbade not conversation;\nonly he himself was dumb.  What a relief it was to choking Stubb,\nwhen a rat made a sudden racket in the hold below.  And poor little\nFlask, he was the youngest son, and little boy of this weary family\nparty.  His were the shinbones of the saline beef; his would have\nbeen the drumsticks.  For Flask to have presumed to help himself,\nthis must have seemed to him tantamount to larceny in the first\ndegree.  Had he helped himself at that table, doubtless, never more\nwould he have been able to hold his head up in this honest world;\nnevertheless, strange to say, Ahab never forbade him.  And had Flask\nhelped himself, the chances were Ahab had never so much as noticed\nit.  Least of all, did Flask presume to help himself to butter.\nWhether he thought the owners of the ship denied it to him, on\naccount of its clotting his clear, sunny complexion; or whether he\ndeemed that, on so long a voyage in such marketless waters, butter\nwas at a premium, and therefore was not for him, a subaltern; however\nit was, Flask, alas! was a butterless man!\n\nAnother thing.  Flask was the last person down at the dinner, and\nFlask is the first man up.  Consider!  For hereby Flask's dinner was\nbadly jammed in point of time.  Starbuck and Stubb both had the start\nof him; and yet they also have the privilege of lounging in the rear.\nIf Stubb even, who is but a peg higher than Flask, happens to have\nbut a small appetite, and soon shows symptoms of concluding his\nrepast, then Flask must bestir himself, he will not get more than\nthree mouthfuls that day; for it is against holy usage for Stubb to\nprecede Flask to the deck.  Therefore it was that Flask once admitted\nin private, that ever since he had arisen to the dignity of an\nofficer, from that moment he had never known what it was to be\notherwise than hungry, more or less.  For what he ate did not so much\nrelieve his hunger, as keep it immortal in him.  Peace and\nsatisfaction, thought Flask, have for ever departed from my stomach.\nI am an officer; but, how I wish I could fish a bit of old-fashioned\nbeef in the forecastle, as I used to when I was before the mast.\nThere's the fruits of promotion now; there's the vanity of glory:\nthere's the insanity of life!  Besides, if it were so that any mere\nsailor of the Pequod had a grudge against Flask in Flask's official\ncapacity, all that sailor had to do, in order to obtain ample\nvengeance, was to go aft at dinner-time, and get a peep at Flask\nthrough the cabin sky-light, sitting silly and dumfoundered before\nawful Ahab.\n\nNow, Ahab and his three mates formed what may be called the first\ntable in the Pequod's cabin.  After their departure, taking place in\ninverted order to their arrival, the canvas cloth was cleared, or\nrather was restored to some hurried order by the pallid steward.  And\nthen the three harpooneers were bidden to the feast, they being its\nresiduary legatees.  They made a sort of temporary servants' hall of\nthe high and mighty cabin.\n\nIn strange contrast to the hardly tolerable constraint and nameless\ninvisible domineerings of the captain's table, was the entire\ncare-free license and ease, the almost frantic democracy of those\ninferior fellows the harpooneers.  While their masters, the mates,\nseemed afraid of the sound of the hinges of their own jaws, the\nharpooneers chewed their food with such a relish that there was a\nreport to it.  They dined like lords; they filled their bellies like\nIndian ships all day loading with spices.  Such portentous appetites\nhad Queequeg and Tashtego, that to fill out the vacancies made by the\nprevious repast, often the pale Dough-Boy was fain to bring on a\ngreat baron of salt-junk, seemingly quarried out of the solid ox.\nAnd if he were not lively about it, if he did not go with a nimble\nhop-skip-and-jump, then Tashtego had an ungentlemanly way of\naccelerating him by darting a fork at his back, harpoon-wise.  And\nonce Daggoo, seized with a sudden humor, assisted Dough-Boy's memory\nby snatching him up bodily, and thrusting his head into a great empty\nwooden trencher, while Tashtego, knife in hand, began laying out the\ncircle preliminary to scalping him.  He was naturally a very nervous,\nshuddering sort of little fellow, this bread-faced steward; the\nprogeny of a bankrupt baker and a hospital nurse.  And what with the\nstanding spectacle of the black terrific Ahab, and the periodical\ntumultuous visitations of these three savages, Dough-Boy's whole life\nwas one continual lip-quiver.  Commonly, after seeing the harpooneers\nfurnished with all things they demanded, he would escape from their\nclutches into his little pantry adjoining, and fearfully peep out at\nthem through the blinds of its door, till all was over.\n\nIt was a sight to see Queequeg seated over against Tashtego, opposing\nhis filed teeth to the Indian's: crosswise to them, Daggoo seated on\nthe floor, for a bench would have brought his hearse-plumed head to\nthe low carlines; at every motion of his colossal limbs, making the\nlow cabin framework to shake, as when an African elephant goes\npassenger in a ship.  But for all this, the great negro was\nwonderfully abstemious, not to say dainty.  It seemed hardly possible\nthat by such comparatively small mouthfuls he could keep up the\nvitality diffused through so broad, baronial, and superb a person.\nBut, doubtless, this noble savage fed strong and drank deep of the\nabounding element of air; and through his dilated nostrils snuffed in\nthe sublime life of the worlds.  Not by beef or by bread, are giants\nmade or nourished.  But Queequeg, he had a mortal, barbaric smack of\nthe lip in eating--an ugly sound enough--so much so, that the\ntrembling Dough-Boy almost looked to see whether any marks of teeth\nlurked in his own lean arms.  And when he would hear Tashtego singing\nout for him to produce himself, that his bones might be picked, the\nsimple-witted steward all but shattered the crockery hanging round\nhim in the pantry, by his sudden fits of the palsy.  Nor did the\nwhetstone which the harpooneers carried in their pockets, for their\nlances and other weapons; and with which whetstones, at dinner, they\nwould ostentatiously sharpen their knives; that grating sound did not\nat all tend to tranquillize poor Dough-Boy.  How could he forget that\nin his Island days, Queequeg, for one, must certainly have been\nguilty of some murderous, convivial indiscretions.  Alas!  Dough-Boy!\nhard fares the white waiter who waits upon cannibals.  Not a napkin\nshould he carry on his arm, but a buckler.  In good time, though, to\nhis great delight, the three salt-sea warriors would rise and depart;\nto his credulous, fable-mongering ears, all their martial bones\njingling in them at every step, like Moorish scimetars in scabbards.\n\nBut, though these barbarians dined in the cabin, and nominally lived\nthere; still, being anything but sedentary in their habits, they were\nscarcely ever in it except at mealtimes, and just before\nsleeping-time, when they passed through it to their own peculiar\nquarters.\n\nIn this one matter, Ahab seemed no exception to most American whale\ncaptains, who, as a set, rather incline to the opinion that by rights\nthe ship's cabin belongs to them; and that it is by courtesy alone\nthat anybody else is, at any time, permitted there.  So that, in real\ntruth, the mates and harpooneers of the Pequod might more properly be\nsaid to have lived out of the cabin than in it.  For when they did\nenter it, it was something as a street-door enters a house; turning\ninwards for a moment, only to be turned out the next; and, as a\npermanent thing, residing in the open air.  Nor did they lose much\nhereby; in the cabin was no companionship; socially, Ahab was\ninaccessible.  Though nominally included in the census of\nChristendom, he was still an alien to it.  He lived in the world, as\nthe last of the Grisly Bears lived in settled Missouri.  And as when\nSpring and Summer had departed, that wild Logan of the woods, burying\nhimself in the hollow of a tree, lived out the winter there, sucking\nhis own paws; so, in his inclement, howling old age, Ahab's soul,\nshut up in the caved trunk of his body, there fed upon the sullen\npaws of its gloom!\n\n\n\nCHAPTER 35\n\nThe Mast-Head.\n\n\nIt was during the more pleasant weather, that in due rotation with\nthe other seamen my first mast-head came round.\n\nIn most American whalemen the mast-heads are manned almost\nsimultaneously with the vessel's leaving her port; even though she\nmay have fifteen thousand miles, and more, to sail ere reaching her\nproper cruising ground.  And if, after a three, four, or five years'\nvoyage she is drawing nigh home with anything empty in her--say, an\nempty vial even--then, her mast-heads are kept manned to the last;\nand not till her skysail-poles sail in among the spires of the port,\ndoes she altogether relinquish the hope of capturing one whale more.\n\nNow, as the business of standing mast-heads, ashore or afloat, is a\nvery ancient and interesting one, let us in some measure expatiate\nhere.  I take it, that the earliest standers of mast-heads were the\nold Egyptians; because, in all my researches, I find none prior to\nthem.  For though their progenitors, the builders of Babel, must\ndoubtless, by their tower, have intended to rear the loftiest\nmast-head in all Asia, or Africa either; yet (ere the final truck was\nput to it) as that great stone mast of theirs may be said to have\ngone by the board, in the dread gale of God's wrath; therefore, we\ncannot give these Babel builders priority over the Egyptians.  And\nthat the Egyptians were a nation of mast-head standers, is an\nassertion based upon the general belief among archaeologists, that\nthe first pyramids were founded for astronomical purposes: a theory\nsingularly supported by the peculiar stair-like formation of all four\nsides of those edifices; whereby, with prodigious long upliftings of\ntheir legs, those old astronomers were wont to mount to the apex, and\nsing out for new stars; even as the look-outs of a modern ship sing\nout for a sail, or a whale just bearing in sight.  In Saint Stylites,\nthe famous Christian hermit of old times, who built him a lofty stone\npillar in the desert and spent the whole latter portion of his life\non its summit, hoisting his food from the ground with a tackle; in\nhim we have a remarkable instance of a dauntless\nstander-of-mast-heads; who was not to be driven from his place by\nfogs or frosts, rain, hail, or sleet; but valiantly facing everything\nout to the last, literally died at his post.  Of modern\nstanders-of-mast-heads we have but a lifeless set; mere stone, iron,\nand bronze men; who, though well capable of facing out a stiff gale,\nare still entirely incompetent to the business of singing out upon\ndiscovering any strange sight.  There is Napoleon; who, upon the top\nof the column of Vendome, stands with arms folded, some one hundred\nand fifty feet in the air; careless, now, who rules the decks below;\nwhether Louis Philippe, Louis Blanc, or Louis the Devil.  Great\nWashington, too, stands high aloft on his towering main-mast in\nBaltimore, and like one of Hercules' pillars, his column marks that\npoint of human grandeur beyond which few mortals will go.  Admiral\nNelson, also, on a capstan of gun-metal, stands his mast-head in\nTrafalgar Square; and ever when most obscured by that London smoke,\ntoken is yet given that a hidden hero is there; for where there is\nsmoke, must be fire.  But neither great Washington, nor Napoleon, nor\nNelson, will answer a single hail from below, however madly invoked\nto befriend by their counsels the distracted decks upon which they\ngaze; however it may be surmised, that their spirits penetrate\nthrough the thick haze of the future, and descry what shoals and what\nrocks must be shunned.\n\nIt may seem unwarrantable to couple in any respect the mast-head\nstanders of the land with those of the sea; but that in truth it is\nnot so, is plainly evinced by an item for which Obed Macy, the sole\nhistorian of Nantucket, stands accountable.  The worthy Obed tells\nus, that in the early times of the whale fishery, ere ships were\nregularly launched in pursuit of the game, the people of that island\nerected lofty spars along the sea-coast, to which the look-outs\nascended by means of nailed cleats, something as fowls go upstairs in\na hen-house.  A few years ago this same plan was adopted by the Bay\nwhalemen of New Zealand, who, upon descrying the game, gave notice to\nthe ready-manned boats nigh the beach.  But this custom has now\nbecome obsolete; turn we then to the one proper mast-head, that of a\nwhale-ship at sea.  The three mast-heads are kept manned from\nsun-rise to sun-set; the seamen taking their regular turns (as at the\nhelm), and relieving each other every two hours.  In the serene\nweather of the tropics it is exceedingly pleasant the mast-head; nay,\nto a dreamy meditative man it is delightful.  There you stand, a\nhundred feet above the silent decks, striding along the deep, as if\nthe masts were gigantic stilts, while beneath you and between your\nlegs, as it were, swim the hugest monsters of the sea, even as ships\nonce sailed between the boots of the famous Colossus at old Rhodes.\nThere you stand, lost in the infinite series of the sea, with nothing\nruffled but the waves.  The tranced ship indolently rolls; the drowsy\ntrade winds blow; everything resolves you into languor.  For the most\npart, in this tropic whaling life, a sublime uneventfulness invests\nyou; you hear no news; read no gazettes; extras with startling\naccounts of commonplaces never delude you into unnecessary\nexcitements; you hear of no domestic afflictions; bankrupt\nsecurities; fall of stocks; are never troubled with the thought of\nwhat you shall have for dinner--for all your meals for three years\nand more are snugly stowed in casks, and your bill of fare is\nimmutable.\n\nIn one of those southern whalesmen, on a long three or four years'\nvoyage, as often happens, the sum of the various hours you spend at\nthe mast-head would amount to several entire months.  And it is much\nto be deplored that the place to which you devote so considerable a\nportion of the whole term of your natural life, should be so sadly\ndestitute of anything approaching to a cosy inhabitiveness, or\nadapted to breed a comfortable localness of feeling, such as pertains\nto a bed, a hammock, a hearse, a sentry box, a pulpit, a coach, or\nany other of those small and snug contrivances in which men\ntemporarily isolate themselves.  Your most usual point of perch is\nthe head of the t' gallant-mast, where you stand upon two thin\nparallel sticks (almost peculiar to whalemen) called the t' gallant\ncross-trees.  Here, tossed about by the sea, the beginner feels about\nas cosy as he would standing on a bull's horns.  To be sure, in cold\nweather you may carry your house aloft with you, in the shape of a\nwatch-coat; but properly speaking the thickest watch-coat is no more\nof a house than the unclad body; for as the soul is glued inside of\nits fleshy tabernacle, and cannot freely move about in it, nor even\nmove out of it, without running great risk of perishing (like an\nignorant pilgrim crossing the snowy Alps in winter); so a watch-coat\nis not so much of a house as it is a mere envelope, or additional\nskin encasing you.  You cannot put a shelf or chest of drawers in\nyour body, and no more can you make a convenient closet of your\nwatch-coat.\n\nConcerning all this, it is much to be deplored that the mast-heads of\na southern whale ship are unprovided with those enviable little tents\nor pulpits, called CROW'S-NESTS, in which the look-outs of a\nGreenland whaler are protected from the inclement weather of the\nfrozen seas.  In the fireside narrative of Captain Sleet, entitled\n\"A Voyage among the Icebergs, in quest of the Greenland Whale, and\nincidentally for the re-discovery of the Lost Icelandic Colonies of\nOld Greenland;\" in this admirable volume, all standers of mast-heads\nare furnished with a charmingly circumstantial account of the then\nrecently invented CROW'S-NEST of the Glacier, which was the name of\nCaptain Sleet's good craft.  He called it the SLEET'S CROW'S-NEST, in\nhonour of himself; he being the original inventor and patentee, and\nfree from all ridiculous false delicacy, and holding that if we call\nour own children after our own names (we fathers being the original\ninventors and patentees), so likewise should we denominate after\nourselves any other apparatus we may beget.  In shape, the Sleet's\ncrow's-nest is something like a large tierce or pipe; it is open\nabove, however, where it is furnished with a movable side-screen to\nkeep to windward of your head in a hard gale.  Being fixed on the\nsummit of the mast, you ascend into it through a little trap-hatch in\nthe bottom.  On the after side, or side next the stern of the ship,\nis a comfortable seat, with a locker underneath for umbrellas,\ncomforters, and coats.  In front is a leather rack, in which to keep\nyour speaking trumpet, pipe, telescope, and other nautical\nconveniences.  When Captain Sleet in person stood his mast-head in\nthis crow's-nest of his, he tells us that he always had a rifle with\nhim (also fixed in the rack), together with a powder flask and shot,\nfor the purpose of popping off the stray narwhales, or vagrant sea\nunicorns infesting those waters; for you cannot successfully shoot at\nthem from the deck owing to the resistance of the water, but to shoot\ndown upon them is a very different thing.  Now, it was plainly a\nlabor of love for Captain Sleet to describe, as he does, all the\nlittle detailed conveniences of his crow's-nest; but though he so\nenlarges upon many of these, and though he treats us to a very\nscientific account of his experiments in this crow's-nest, with a\nsmall compass he kept there for the purpose of counteracting the\nerrors resulting from what is called the \"local attraction\" of all\nbinnacle magnets; an error ascribable to the horizontal vicinity of\nthe iron in the ship's planks, and in the Glacier's case, perhaps, to\nthere having been so many broken-down blacksmiths among her crew; I\nsay, that though the Captain is very discreet and scientific here,\nyet, for all his learned \"binnacle deviations,\" \"azimuth compass\nobservations,\" and \"approximate errors,\" he knows very well, Captain\nSleet, that he was not so much immersed in those profound magnetic\nmeditations, as to fail being attracted occasionally towards that\nwell replenished little case-bottle, so nicely tucked in on one side\nof his crow's nest, within easy reach of his hand.  Though, upon the\nwhole, I greatly admire and even love the brave, the honest, and\nlearned Captain; yet I take it very ill of him that he should so\nutterly ignore that case-bottle, seeing what a faithful friend and\ncomforter it must have been, while with mittened fingers and hooded\nhead he was studying the mathematics aloft there in that bird's nest\nwithin three or four perches of the pole.\n\nBut if we Southern whale-fishers are not so snugly housed aloft as\nCaptain Sleet and his Greenlandmen were; yet that disadvantage is\ngreatly counter-balanced by the widely contrasting serenity of those\nseductive seas in which we South fishers mostly float.  For one, I\nused to lounge up the rigging very leisurely, resting in the top to\nhave a chat with Queequeg, or any one else off duty whom I might find\nthere; then ascending a little way further, and throwing a lazy leg\nover the top-sail yard, take a preliminary view of the watery\npastures, and so at last mount to my ultimate destination.\n\nLet me make a clean breast of it here, and frankly admit that I kept\nbut sorry guard.  With the problem of the universe revolving in me,\nhow could I--being left completely to myself at such a\nthought-engendering altitude--how could I but lightly hold my\nobligations to observe all whale-ships' standing orders, \"Keep your\nweather eye open, and sing out every time.\"\n\nAnd let me in this place movingly admonish you, ye ship-owners of\nNantucket!  Beware of enlisting in your vigilant fisheries any lad\nwith lean brow and hollow eye; given to unseasonable meditativeness;\nand who offers to ship with the Phaedon instead of Bowditch in his\nhead.  Beware of such an one, I say; your whales must be seen before\nthey can be killed; and this sunken-eyed young Platonist will tow you\nten wakes round the world, and never make you one pint of sperm the\nricher.  Nor are these monitions at all unneeded.  For nowadays, the\nwhale-fishery furnishes an asylum for many romantic, melancholy, and\nabsent-minded young men, disgusted with the carking cares of earth,\nand seeking sentiment in tar and blubber.  Childe Harold not\nunfrequently perches himself upon the mast-head of some luckless\ndisappointed whale-ship, and in moody phrase ejaculates:--\n\n\"Roll on, thou deep and dark blue ocean, roll!  Ten thousand\nblubber-hunters sweep over thee in vain.\"\n\nVery often do the captains of such ships take those absent-minded\nyoung philosophers to task, upbraiding them with not feeling\nsufficient \"interest\" in the voyage; half-hinting that they are so\nhopelessly lost to all honourable ambition, as that in their secret\nsouls they would rather not see whales than otherwise.  But all in\nvain; those young Platonists have a notion that their vision is\nimperfect; they are short-sighted; what use, then, to strain the\nvisual nerve?  They have left their opera-glasses at home.\n\n\"Why, thou monkey,\" said a harpooneer to one of these lads, \"we've\nbeen cruising now hard upon three years, and thou hast not raised a\nwhale yet.  Whales are scarce as hen's teeth whenever thou art up\nhere.\"  Perhaps they were; or perhaps there might have been shoals of\nthem in the far horizon; but lulled into such an opium-like\nlistlessness of vacant, unconscious reverie is this absent-minded\nyouth by the blending cadence of waves with thoughts, that at last he\nloses his identity; takes the mystic ocean at his feet for the\nvisible image of that deep, blue, bottomless soul, pervading mankind\nand nature; and every strange, half-seen, gliding, beautiful thing\nthat eludes him; every dimly-discovered, uprising fin of some\nundiscernible form, seems to him the embodiment of those elusive\nthoughts that only people the soul by continually flitting through\nit.  In this enchanted mood, thy spirit ebbs away to whence it came;\nbecomes diffused through time and space; like Crammer's sprinkled\nPantheistic ashes, forming at last a part of every shore the round\nglobe over.\n\nThere is no life in thee, now, except that rocking life imparted by a\ngently rolling ship; by her, borrowed from the sea; by the sea, from\nthe inscrutable tides of God.  But while this sleep, this dream is on\nye, move your foot or hand an inch; slip your hold at all; and your\nidentity comes back in horror.  Over Descartian vortices you hover.\nAnd perhaps, at mid-day, in the fairest weather, with one\nhalf-throttled shriek you drop through that transparent air into the\nsummer sea, no more to rise for ever.  Heed it well, ye Pantheists!\n\n\n\nCHAPTER 36\n\nThe Quarter-Deck.\n\n\n(ENTER AHAB: THEN, ALL)\n\n\nIt was not a great while after the affair of the pipe, that one\nmorning shortly after breakfast, Ahab, as was his wont, ascended the\ncabin-gangway to the deck.  There most sea-captains usually walk at\nthat hour, as country gentlemen, after the same meal, take a few\nturns in the garden.\n\nSoon his steady, ivory stride was heard, as to and fro he paced his\nold rounds, upon planks so familiar to his tread, that they were all\nover dented, like geological stones, with the peculiar mark of his\nwalk.  Did you fixedly gaze, too, upon that ribbed and dented brow;\nthere also, you would see still stranger foot-prints--the foot-prints\nof his one unsleeping, ever-pacing thought.\n\nBut on the occasion in question, those dents looked deeper, even as\nhis nervous step that morning left a deeper mark.  And, so full of\nhis thought was Ahab, that at every uniform turn that he made, now at\nthe main-mast and now at the binnacle, you could almost see that\nthought turn in him as he turned, and pace in him as he paced; so\ncompletely possessing him, indeed, that it all but seemed the inward\nmould of every outer movement.\n\n\"D'ye mark him, Flask?\" whispered Stubb; \"the chick that's in him\npecks the shell.  'Twill soon be out.\"\n\nThe hours wore on;--Ahab now shut up within his cabin; anon, pacing\nthe deck, with the same intense bigotry of purpose in his aspect.\n\nIt drew near the close of day.  Suddenly he came to a halt by the\nbulwarks, and inserting his bone leg into the auger-hole there, and\nwith one hand grasping a shroud, he ordered Starbuck to send\neverybody aft.\n\n\"Sir!\" said the mate, astonished at an order seldom or never given on\nship-board except in some extraordinary case.\n\n\"Send everybody aft,\" repeated Ahab.  \"Mast-heads, there! come down!\"\n\nWhen the entire ship's company were assembled, and with curious and\nnot wholly unapprehensive faces, were eyeing him, for he looked not\nunlike the weather horizon when a storm is coming up, Ahab, after\nrapidly glancing over the bulwarks, and then darting his eyes among\nthe crew, started from his standpoint; and as though not a soul were\nnigh him resumed his heavy turns upon the deck.  With bent head and\nhalf-slouched hat he continued to pace, unmindful of the wondering\nwhispering among the men; till Stubb cautiously whispered to Flask,\nthat Ahab must have summoned them there for the purpose of witnessing\na pedestrian feat.  But this did not last long.  Vehemently pausing,\nhe cried:--\n\n\"What do ye do when ye see a whale, men?\"\n\n\"Sing out for him!\" was the impulsive rejoinder from a score of\nclubbed voices.\n\n\"Good!\" cried Ahab, with a wild approval in his tones; observing the\nhearty animation into which his unexpected question had so\nmagnetically thrown them.\n\n\"And what do ye next, men?\"\n\n\"Lower away, and after him!\"\n\n\"And what tune is it ye pull to, men?\"\n\n\"A dead whale or a stove boat!\"\n\nMore and more strangely and fiercely glad and approving, grew the\ncountenance of the old man at every shout; while the mariners began\nto gaze curiously at each other, as if marvelling how it was that\nthey themselves became so excited at such seemingly purposeless\nquestions.\n\nBut, they were all eagerness again, as Ahab, now half-revolving in\nhis pivot-hole, with one hand reaching high up a shroud, and tightly,\nalmost convulsively grasping it, addressed them thus:--\n\n\"All ye mast-headers have before now heard me give orders about a\nwhite whale.  Look ye! d'ye see this Spanish ounce of gold?\"--holding\nup a broad bright coin to the sun--\"it is a sixteen dollar piece,\nmen.  D'ye see it?  Mr. Starbuck, hand me yon top-maul.\"\n\nWhile the mate was getting the hammer, Ahab, without speaking, was\nslowly rubbing the gold piece against the skirts of his jacket, as if\nto heighten its lustre, and without using any words was meanwhile\nlowly humming to himself, producing a sound so strangely muffled and\ninarticulate that it seemed the mechanical humming of the wheels of\nhis vitality in him.\n\nReceiving the top-maul from Starbuck, he advanced towards the\nmain-mast with the hammer uplifted in one hand, exhibiting the gold\nwith the other, and with a high raised voice exclaiming: \"Whosoever\nof ye raises me a white-headed whale with a wrinkled brow and a\ncrooked jaw; whosoever of ye raises me that white-headed whale, with\nthree holes punctured in his starboard fluke--look ye, whosoever of\nye raises me that same white whale, he shall have this gold ounce, my\nboys!\"\n\n\"Huzza! huzza!\" cried the seamen, as with swinging tarpaulins they\nhailed the act of nailing the gold to the mast.\n\n\"It's a white whale, I say,\" resumed Ahab, as he threw down the\ntopmaul: \"a white whale.  Skin your eyes for him, men; look sharp for\nwhite water; if ye see but a bubble, sing out.\"\n\nAll this while Tashtego, Daggoo, and Queequeg had looked on with even\nmore intense interest and surprise than the rest, and at the mention\nof the wrinkled brow and crooked jaw they had started as if each was\nseparately touched by some specific recollection.\n\n\"Captain Ahab,\" said Tashtego, \"that white whale must be the same\nthat some call Moby Dick.\"\n\n\"Moby Dick?\" shouted Ahab.  \"Do ye know the white whale then, Tash?\"\n\n\"Does he fan-tail a little curious, sir, before he goes down?\" said\nthe Gay-Header deliberately.\n\n\"And has he a curious spout, too,\" said Daggoo, \"very bushy, even for\na parmacetty, and mighty quick, Captain Ahab?\"\n\n\"And he have one, two, three--oh! good many iron in him hide, too,\nCaptain,\" cried Queequeg disjointedly, \"all twiske-tee be-twisk, like\nhim--him--\" faltering hard for a word, and screwing his hand round\nand round as though uncorking a bottle--\"like him--him--\"\n\n\"Corkscrew!\" cried Ahab, \"aye, Queequeg, the harpoons lie all twisted\nand wrenched in him; aye, Daggoo, his spout is a big one, like a\nwhole shock of wheat, and white as a pile of our Nantucket wool after\nthe great annual sheep-shearing; aye, Tashtego, and he fan-tails like\na split jib in a squall.  Death and devils! men, it is Moby Dick ye\nhave seen--Moby Dick--Moby Dick!\"\n\n\"Captain Ahab,\" said Starbuck, who, with Stubb and Flask, had thus\nfar been eyeing his superior with increasing surprise, but at last\nseemed struck with a thought which somewhat explained all the wonder.\n\"Captain Ahab, I have heard of Moby Dick--but it was not Moby Dick\nthat took off thy leg?\"\n\n\"Who told thee that?\" cried Ahab; then pausing, \"Aye, Starbuck; aye,\nmy hearties all round; it was Moby Dick that dismasted me; Moby Dick\nthat brought me to this dead stump I stand on now.  Aye, aye,\" he\nshouted with a terrific, loud, animal sob, like that of a\nheart-stricken moose; \"Aye, aye! it was that accursed white whale\nthat razeed me; made a poor pegging lubber of me for ever and a day!\"\nThen tossing both arms, with measureless imprecations he shouted\nout: \"Aye, aye! and I'll chase him round Good Hope, and round the\nHorn, and round the Norway Maelstrom, and round perdition's flames\nbefore I give him up.  And this is what ye have shipped for, men! to\nchase that white whale on both sides of land, and over all sides of\nearth, till he spouts black blood and rolls fin out.  What say ye,\nmen, will ye splice hands on it, now?  I think ye do look brave.\"\n\n\"Aye, aye!\" shouted the harpooneers and seamen, running closer to the\nexcited old man: \"A sharp eye for the white whale; a sharp lance for\nMoby Dick!\"\n\n\"God bless ye,\" he seemed to half sob and half shout.  \"God bless ye,\nmen.  Steward! go draw the great measure of grog.  But what's this\nlong face about, Mr. Starbuck; wilt thou not chase the white whale?\nart not game for Moby Dick?\"\n\n\"I am game for his crooked jaw, and for the jaws of Death too,\nCaptain Ahab, if it fairly comes in the way of the business we\nfollow; but I came here to hunt whales, not my commander's vengeance.\nHow many barrels will thy vengeance yield thee even if thou gettest\nit, Captain Ahab? it will not fetch thee much in our Nantucket\nmarket.\"\n\n\"Nantucket market!  Hoot!  But come closer, Starbuck; thou requirest\na little lower layer.  If money's to be the measurer, man, and the\naccountants have computed their great counting-house the globe, by\ngirdling it with guineas, one to every three parts of an inch; then,\nlet me tell thee, that my vengeance will fetch a great premium HERE!\"\n\n\"He smites his chest,\" whispered Stubb, \"what's that for? methinks it\nrings most vast, but hollow.\"\n\n\"Vengeance on a dumb brute!\" cried Starbuck, \"that simply smote thee\nfrom blindest instinct!  Madness!  To be enraged with a dumb thing,\nCaptain Ahab, seems blasphemous.\"\n\n\"Hark ye yet again--the little lower layer.  All visible objects,\nman, are but as pasteboard masks.  But in each event--in the living\nact, the undoubted deed--there, some unknown but still reasoning\nthing puts forth the mouldings of its features from behind the\nunreasoning mask.  If man will strike, strike through the mask!  How\ncan the prisoner reach outside except by thrusting through the wall?\nTo me, the white whale is that wall, shoved near to me.  Sometimes I\nthink there's naught beyond.  But 'tis enough.  He tasks me; he heaps\nme; I see in him outrageous strength, with an inscrutable malice\nsinewing it.  That inscrutable thing is chiefly what I hate; and be\nthe white whale agent, or be the white whale principal, I will wreak\nthat hate upon him.  Talk not to me of blasphemy, man; I'd strike the\nsun if it insulted me.  For could the sun do that, then could I do\nthe other; since there is ever a sort of fair play herein, jealousy\npresiding over all creations.  But not my master, man, is even that\nfair play.  Who's over me?  Truth hath no confines.  Take off thine\neye! more intolerable than fiends' glarings is a doltish stare!  So,\nso; thou reddenest and palest; my heat has melted thee to anger-glow.\nBut look ye, Starbuck, what is said in heat, that thing unsays\nitself.  There are men from whom warm words are small indignity.  I\nmeant not to incense thee.  Let it go.  Look! see yonder Turkish\ncheeks of spotted tawn--living, breathing pictures painted by the\nsun.  The Pagan leopards--the unrecking and unworshipping things,\nthat live; and seek, and give no reasons for the torrid life they\nfeel!  The crew, man, the crew!  Are they not one and all with Ahab,\nin this matter of the whale?  See Stubb! he laughs!  See yonder\nChilian! he snorts to think of it.  Stand up amid the general\nhurricane, thy one tost sapling cannot, Starbuck!  And what is it?\nReckon it.  'Tis but to help strike a fin; no wondrous feat for\nStarbuck.  What is it more?  From this one poor hunt, then, the best\nlance out of all Nantucket, surely he will not hang back, when every\nforemast-hand has clutched a whetstone?  Ah! constrainings seize\nthee; I see! the billow lifts thee!  Speak, but speak!--Aye, aye! thy\nsilence, then, THAT voices thee.  (ASIDE) Something shot from my\ndilated nostrils, he has inhaled it in his lungs.  Starbuck now is\nmine; cannot oppose me now, without rebellion.\"\n\n\"God keep me!--keep us all!\" murmured Starbuck, lowly.\n\nBut in his joy at the enchanted, tacit acquiescence of the mate, Ahab\ndid not hear his foreboding invocation; nor yet the low laugh from\nthe hold; nor yet the presaging vibrations of the winds in the\ncordage; nor yet the hollow flap of the sails against the masts, as\nfor a moment their hearts sank in.  For again Starbuck's downcast\neyes lighted up with the stubbornness of life; the subterranean laugh\ndied away; the winds blew on; the sails filled out; the ship heaved\nand rolled as before.  Ah, ye admonitions and warnings! why stay ye\nnot when ye come?  But rather are ye predictions than warnings, ye\nshadows!  Yet not so much predictions from without, as verifications\nof the foregoing things within.  For with little external to\nconstrain us, the innermost necessities in our being, these still\ndrive us on.\n\n\"The measure! the measure!\" cried Ahab.\n\nReceiving the brimming pewter, and turning to the harpooneers, he\nordered them to produce their weapons.  Then ranging them before him\nnear the capstan, with their harpoons in their hands, while his three\nmates stood at his side with their lances, and the rest of the ship's\ncompany formed a circle round the group; he stood for an instant\nsearchingly eyeing every man of his crew.  But those wild eyes met\nhis, as the bloodshot eyes of the prairie wolves meet the eye of\ntheir leader, ere he rushes on at their head in the trail of the\nbison; but, alas! only to fall into the hidden snare of the Indian.\n\n\"Drink and pass!\" he cried, handing the heavy charged flagon to the\nnearest seaman.  \"The crew alone now drink.  Round with it, round!\nShort draughts--long swallows, men; 'tis hot as Satan's hoof.  So,\nso; it goes round excellently.  It spiralizes in ye; forks out at the\nserpent-snapping eye.  Well done; almost drained.  That way it went,\nthis way it comes.  Hand it me--here's a hollow!  Men, ye seem the\nyears; so brimming life is gulped and gone.  Steward, refill!\n\n\"Attend now, my braves.  I have mustered ye all round this capstan;\nand ye mates, flank me with your lances; and ye harpooneers, stand\nthere with your irons; and ye, stout mariners, ring me in, that I may\nin some sort revive a noble custom of my fisherman fathers before\nme.  O men, you will yet see that--Ha! boy, come back? bad pennies\ncome not sooner.  Hand it me.  Why, now, this pewter had run brimming\nagain, were't not thou St. Vitus' imp--away, thou ague!\n\n\"Advance, ye mates!  Cross your lances full before me.  Well done!\nLet me touch the axis.\"  So saying, with extended arm, he grasped the\nthree level, radiating lances at their crossed centre; while so\ndoing, suddenly and nervously twitched them; meanwhile, glancing\nintently from Starbuck to Stubb; from Stubb to Flask.  It seemed as\nthough, by some nameless, interior volition, he would fain have\nshocked into them the same fiery emotion accumulated within the\nLeyden jar of his own magnetic life.  The three mates quailed before\nhis strong, sustained, and mystic aspect.  Stubb and Flask looked\nsideways from him; the honest eye of Starbuck fell downright.\n\n\"In vain!\" cried Ahab; \"but, maybe, 'tis well.  For did ye three but\nonce take the full-forced shock, then mine own electric thing, THAT\nhad perhaps expired from out me.  Perchance, too, it would have\ndropped ye dead.  Perchance ye need it not.  Down lances!  And now,\nye mates, I do appoint ye three cupbearers to my three pagan kinsmen\nthere--yon three most honourable gentlemen and noblemen, my valiant\nharpooneers.  Disdain the task?  What, when the great Pope washes the\nfeet of beggars, using his tiara for ewer?  Oh, my sweet cardinals!\nyour own condescension, THAT shall bend ye to it.  I do not order ye;\nye will it.  Cut your seizings and draw the poles, ye harpooneers!\"\n\nSilently obeying the order, the three harpooneers now stood with the\ndetached iron part of their harpoons, some three feet long, held,\nbarbs up, before him.\n\n\"Stab me not with that keen steel!  Cant them; cant them over! know\nye not the goblet end?  Turn up the socket!  So, so; now, ye\ncup-bearers, advance.  The irons! take them; hold them while I fill!\"\nForthwith, slowly going from one officer to the other, he brimmed\nthe harpoon sockets with the fiery waters from the pewter.\n\n\"Now, three to three, ye stand.  Commend the murderous chalices!\nBestow them, ye who are now made parties to this indissoluble league.\nHa!  Starbuck! but the deed is done!  Yon ratifying sun now waits to\nsit upon it.  Drink, ye harpooneers! drink and swear, ye men that man\nthe deathful whaleboat's bow--Death to Moby Dick!  God hunt us all,\nif we do not hunt Moby Dick to his death!\"  The long, barbed steel\ngoblets were lifted; and to cries and maledictions against the white\nwhale, the spirits were simultaneously quaffed down with a hiss.\nStarbuck paled, and turned, and shivered.  Once more, and finally,\nthe replenished pewter went the rounds among the frantic crew; when,\nwaving his free hand to them, they all dispersed; and Ahab retired\nwithin his cabin.\n\n\n\nCHAPTER 37\n\nSunset.\n\n\nTHE CABIN; BY THE STERN WINDOWS; AHAB SITTING ALONE, AND GAZING OUT.\n\n\nI leave a white and turbid wake; pale waters, paler cheeks, where'er\nI sail.  The envious billows sidelong swell to whelm my track; let\nthem; but first I pass.\n\nYonder, by ever-brimming goblet's rim, the warm waves blush like\nwine.  The gold brow plumbs the blue.  The diver sun--slow dived from\nnoon--goes down; my soul mounts up! she wearies with her endless\nhill.  Is, then, the crown too heavy that I wear? this Iron Crown of\nLombardy.  Yet is it bright with many a gem; I the wearer, see not\nits far flashings; but darkly feel that I wear that, that dazzlingly\nconfounds.  'Tis iron--that I know--not gold.  'Tis split, too--that\nI feel; the jagged edge galls me so, my brain seems to beat against\nthe solid metal; aye, steel skull, mine; the sort that needs no\nhelmet in the most brain-battering fight!\n\nDry heat upon my brow?  Oh! time was, when as the sunrise nobly\nspurred me, so the sunset soothed.  No more.  This lovely light, it\nlights not me; all loveliness is anguish to me, since I can ne'er\nenjoy.  Gifted with the high perception, I lack the low, enjoying\npower; damned, most subtly and most malignantly! damned in the midst\nof Paradise!  Good night--good night! (WAVING HIS HAND, HE MOVES FROM\nTHE WINDOW.)\n\n'Twas not so hard a task.  I thought to find one stubborn, at the\nleast; but my one cogged circle fits into all their various wheels,\nand they revolve.  Or, if you will, like so many ant-hills of powder,\nthey all stand before me; and I their match.  Oh, hard! that to fire\nothers, the match itself must needs be wasting!  What I've dared,\nI've willed; and what I've willed, I'll do!  They think me\nmad--Starbuck does; but I'm demoniac, I am madness maddened!  That\nwild madness that's only calm to comprehend itself!  The prophecy was\nthat I should be dismembered; and--Aye!  I lost this leg.  I now\nprophesy that I will dismember my dismemberer.  Now, then, be the\nprophet and the fulfiller one.  That's more than ye, ye great gods,\never were.  I laugh and hoot at ye, ye cricket-players, ye pugilists,\nye deaf Burkes and blinded Bendigoes!  I will not say as schoolboys\ndo to bullies--Take some one of your own size; don't pommel ME!  No,\nye've knocked me down, and I am up again; but YE have run and hidden.\nCome forth from behind your cotton bags!  I have no long gun to\nreach ye.  Come, Ahab's compliments to ye; come and see if ye can\nswerve me.  Swerve me? ye cannot swerve me, else ye swerve\nyourselves! man has ye there.  Swerve me?  The path to my fixed\npurpose is laid with iron rails, whereon my soul is grooved to run.\nOver unsounded gorges, through the rifled hearts of mountains, under\ntorrents' beds, unerringly I rush!  Naught's an obstacle, naught's an\nangle to the iron way!\n\n\n\nCHAPTER 38\n\nDusk.\n\n\nBY THE MAINMAST; STARBUCK LEANING AGAINST IT.\n\n\nMy soul is more than matched; she's overmanned; and by a madman!\nInsufferable sting, that sanity should ground arms on such a field!\nBut he drilled deep down, and blasted all my reason out of me!  I\nthink I see his impious end; but feel that I must help him to it.\nWill I, nill I, the ineffable thing has tied me to him; tows me with\na cable I have no knife to cut.  Horrible old man!  Who's over him,\nhe cries;--aye, he would be a democrat to all above; look, how he\nlords it over all below!  Oh!  I plainly see my miserable office,--to\nobey, rebelling; and worse yet, to hate with touch of pity!  For in\nhis eyes I read some lurid woe would shrivel me up, had I it.  Yet is\nthere hope.  Time and tide flow wide.  The hated whale has the round\nwatery world to swim in, as the small gold-fish has its glassy globe.\nHis heaven-insulting purpose, God may wedge aside.  I would up\nheart, were it not like lead.  But my whole clock's run down; my\nheart the all-controlling weight, I have no key to lift again.\n\n\n[A BURST OF REVELRY FROM THE FORECASTLE.]\n\n\nOh, God! to sail with such a heathen crew that have small touch of\nhuman mothers in them!  Whelped somewhere by the sharkish sea.  The\nwhite whale is their demigorgon.  Hark! the infernal orgies! that\nrevelry is forward! mark the unfaltering silence aft!  Methinks it\npictures life.  Foremost through the sparkling sea shoots on the gay,\nembattled, bantering bow, but only to drag dark Ahab after it, where\nhe broods within his sternward cabin, builded over the dead water of\nthe wake, and further on, hunted by its wolfish gurglings.  The long\nhowl thrills me through!  Peace! ye revellers, and set the watch!\nOh, life!  'tis in an hour like this, with soul beat down and held to\nknowledge,--as wild, untutored things are forced to feed--Oh, life!\n'tis now that I do feel the latent horror in thee! but 'tis not me!\nthat horror's out of me! and with the soft feeling of the human in\nme, yet will I try to fight ye, ye grim, phantom futures!  Stand by\nme, hold me, bind me, O ye blessed influences!\n\n\n\nCHAPTER 39\n\nFirst Night Watch.\n\nFore-Top.\n\n(STUBB SOLUS, AND MENDING A BRACE.)\n\n\nHa! ha! ha! ha! hem! clear my throat!--I've been thinking over it\never since, and that ha, ha's the final consequence.  Why so?\nBecause a laugh's the wisest, easiest answer to all that's queer; and\ncome what will, one comfort's always left--that unfailing comfort is,\nit's all predestinated.  I heard not all his talk with Starbuck; but\nto my poor eye Starbuck then looked something as I the other evening\nfelt.  Be sure the old Mogul has fixed him, too.  I twigged it, knew\nit; had had the gift, might readily have prophesied it--for when I\nclapped my eye upon his skull I saw it.  Well, Stubb, WISE\nStubb--that's my title--well, Stubb, what of it, Stubb?  Here's a\ncarcase.  I know not all that may be coming, but be it what it will,\nI'll go to it laughing.  Such a waggish leering as lurks in all your\nhorribles!  I feel funny.  Fa, la! lirra, skirra!  What's my juicy\nlittle pear at home doing now?  Crying its eyes out?--Giving a party\nto the last arrived harpooneers, I dare say, gay as a frigate's\npennant, and so am I--fa, la! lirra, skirra!  Oh--\n\nWe'll drink to-night with hearts as light,\nTo love, as gay and fleeting\nAs bubbles that swim, on the beaker's brim,\nAnd break on the lips while meeting.\n\n\nA brave stave that--who calls?  Mr. Starbuck?  Aye, aye, sir--(ASIDE)\nhe's my superior, he has his too, if I'm not mistaken.--Aye, aye,\nsir, just through with this job--coming.\n\n\n\nCHAPTER 40\n\nMidnight, Forecastle.\n\nHARPOONEERS AND SAILORS.\n\n(FORESAIL RISES AND DISCOVERS THE WATCH STANDING, LOUNGING, LEANING,\nAND LYING IN VARIOUS ATTITUDES, ALL SINGING IN CHORUS.)\n\nFarewell and adieu to you, Spanish ladies!\nFarewell and adieu to you, ladies of Spain!\nOur captain's commanded.--\n\n1ST NANTUCKET SAILOR.\nOh, boys, don't be sentimental; it's bad for the digestion!  Take a\ntonic, follow me!\n(SINGS, AND ALL FOLLOW)\n\nOur captain stood upon the deck,\nA spy-glass in his hand,\nA viewing of those gallant whales\nThat blew at every strand.\nOh, your tubs in your boats, my boys,\nAnd by your braces stand,\nAnd we'll have one of those fine whales,\nHand, boys, over hand!\nSo, be cheery, my lads! may your hearts never fail!\nWhile the bold harpooner is striking the whale!\n\nMATE'S VOICE FROM THE QUARTER-DECK.\nEight bells there, forward!\n\n2ND NANTUCKET SAILOR.\nAvast the chorus!  Eight bells there! d'ye hear, bell-boy?  Strike\nthe bell eight, thou Pip! thou blackling! and let me call the watch.\nI've the sort of mouth for that--the hogshead mouth.  So, so,\n(THRUSTS HIS HEAD DOWN THE SCUTTLE,) Star-bo-l-e-e-n-s, a-h-o-y!\nEight bells there below!  Tumble up!\n\nDUTCH SAILOR.\nGrand snoozing to-night, maty; fat night for that.  I mark this in\nour old Mogul's wine; it's quite as deadening to some as filliping to\nothers.  We sing; they sleep--aye, lie down there, like ground-tier\nbutts.  At 'em again!  There, take this copper-pump, and hail 'em\nthrough it.  Tell 'em to avast dreaming of their lasses.  Tell 'em\nit's the resurrection; they must kiss their last, and come to\njudgment.  That's the way--THAT'S it; thy throat ain't spoiled with\neating Amsterdam butter.\n\nFRENCH SAILOR.\nHist, boys! let's have a jig or two before we ride to anchor in\nBlanket Bay.  What say ye?  There comes the other watch.  Stand by\nall legs!  Pip! little Pip! hurrah with your tambourine!\n\nPIP.\n(SULKY AND SLEEPY)\nDon't know where it is.\n\nFRENCH SAILOR.\nBeat thy belly, then, and wag thy ears.  Jig it, men, I say; merry's\nthe word; hurrah!  Damn me, won't you dance?  Form, now, Indian-file,\nand gallop into the double-shuffle?  Throw yourselves!  Legs! legs!\n\nICELAND SAILOR.\nI don't like your floor, maty; it's too springy to my taste.  I'm\nused to ice-floors.  I'm sorry to throw cold water on the subject;\nbut excuse me.\n\nMALTESE SAILOR.\nMe too; where's your girls?  Who but a fool would take his left hand\nby his right, and say to himself, how d'ye do?  Partners!  I must\nhave partners!\n\nSICILIAN SAILOR.\nAye; girls and a green!--then I'll hop with ye; yea, turn\ngrasshopper!\n\nLONG-ISLAND SAILOR.\nWell, well, ye sulkies, there's plenty more of us.  Hoe corn when you\nmay, say I.  All legs go to harvest soon.  Ah! here comes the music;\nnow for it!\n\nAZORE SAILOR.\n(ASCENDING, AND PITCHING THE TAMBOURINE UP THE SCUTTLE.)\nHere you are, Pip; and there's the windlass-bitts; up you mount!\nNow, boys!\n(THE HALF OF THEM DANCE TO THE TAMBOURINE; SOME GO BELOW; SOME SLEEP\nOR LIE AMONG THE COILS OF RIGGING.  OATHS A-PLENTY.)\n\nAZORE SAILOR.\n(DANCING)\nGo it, Pip!  Bang it, bell-boy!  Rig it, dig it, stig it, quig it,\nbell-boy!  Make fire-flies; break the jinglers!\n\nPIP.\nJinglers, you say?--there goes another, dropped off; I pound it so.\n\nCHINA SAILOR.\nRattle thy teeth, then, and pound away; make a pagoda of thyself.\n\n\nFRENCH SAILOR.\nMerry-mad!  Hold up thy hoop, Pip, till I jump through it!  Split\njibs! tear yourselves!\n\nTASHTEGO.\n(QUIETLY SMOKING)\nThat's a white man; he calls that fun: humph!  I save my sweat.\n\nOLD MANX SAILOR.\nI wonder whether those jolly lads bethink them of what they are\ndancing over.  I'll dance over your grave, I will--that's the\nbitterest threat of your night-women, that beat head-winds round\ncorners.  O Christ! to think of the green navies and the\ngreen-skulled crews!  Well, well; belike the whole world's a ball, as\nyou scholars have it; and so 'tis right to make one ballroom of it.\nDance on, lads, you're young; I was once.\n\n3D NANTUCKET SAILOR.\nSpell oh!--whew! this is worse than pulling after whales in a\ncalm--give us a whiff, Tash.\n\n(THEY CEASE DANCING, AND GATHER IN CLUSTERS.  MEANTIME THE SKY\nDARKENS--THE WIND RISES.)\n\nLASCAR SAILOR.\nBy Brahma! boys, it'll be douse sail soon.  The sky-born, high-tide\nGanges turned to wind!  Thou showest thy black brow, Seeva!\n\nMALTESE SAILOR.\n(RECLINING AND SHAKING HIS CAP.)\nIt's the waves--the snow's caps turn to jig it now.  They'll shake\ntheir tassels soon.  Now would all the waves were women, then I'd go\ndrown, and chassee with them evermore!  There's naught so sweet on\nearth--heaven may not match it!--as those swift glances of warm, wild\nbosoms in the dance, when the over-arboring arms hide such ripe,\nbursting grapes.\n\nSICILIAN SAILOR.\n(RECLINING.)\nTell me not of it!  Hark ye, lad--fleet interlacings of the\nlimbs--lithe swayings--coyings--flutterings! lip! heart! hip! all\ngraze: unceasing touch and go! not taste, observe ye, else come\nsatiety.  Eh, Pagan? (NUDGING.)\n\nTAHITAN SAILOR.\n(RECLINING ON A MAT.)\nHail, holy nakedness of our dancing girls!--the Heeva-Heeva!  Ah! low\nveiled, high palmed Tahiti!  I still rest me on thy mat, but the soft\nsoil has slid!  I saw thee woven in the wood, my mat! green the first\nday I brought ye thence; now worn and wilted quite.  Ah me!--not thou\nnor I can bear the change!  How then, if so be transplanted to yon\nsky?  Hear I the roaring streams from Pirohitee's peak of spears,\nwhen they leap down the crags and drown the villages?--The blast! the\nblast!  Up, spine, and meet it! (LEAPS TO HIS FEET.)\n\nPORTUGUESE SAILOR.\nHow the sea rolls swashing 'gainst the side!  Stand by for reefing,\nhearties! the winds are just crossing swords, pell-mell they'll go\nlunging presently.\n\nDANISH SAILOR.\nCrack, crack, old ship! so long as thou crackest, thou holdest!  Well\ndone!  The mate there holds ye to it stiffly.  He's no more afraid\nthan the isle fort at Cattegat, put there to fight the Baltic with\nstorm-lashed guns, on which the sea-salt cakes!\n\n4TH NANTUCKET SAILOR.\nHe has his orders, mind ye that.  I heard old Ahab tell him he must\nalways kill a squall, something as they burst a waterspout with a\npistol--fire your ship right into it!\n\nENGLISH SAILOR.\nBlood! but that old man's a grand old cove!  We are the lads to hunt\nhim up his whale!\n\nALL.\nAye! aye!\n\nOLD MANX SAILOR.\nHow the three pines shake!  Pines are the hardest sort of tree to\nlive when shifted to any other soil, and here there's none but the\ncrew's cursed clay.  Steady, helmsman! steady.  This is the sort of\nweather when brave hearts snap ashore, and keeled hulls split at sea.\nOur captain has his birthmark; look yonder, boys, there's another in\nthe sky--lurid-like, ye see, all else pitch black.\n\nDAGGOO.\nWhat of that?  Who's afraid of black's afraid of me!  I'm quarried\nout of it!\n\nSPANISH SAILOR.\n(ASIDE.) He wants to bully, ah!--the old grudge makes me touchy\n(ADVANCING.) Aye, harpooneer, thy race is the undeniable dark side of\nmankind--devilish dark at that.  No offence.\n\nDAGGOO (GRIMLY).\nNone.\n\nST. JAGO'S SAILOR.\nThat Spaniard's mad or drunk.  But that can't be, or else in his one\ncase our old Mogul's fire-waters are somewhat long in working.\n\n5TH NANTUCKET SAILOR.\nWhat's that I saw--lightning?  Yes.\n\nSPANISH SAILOR.\nNo; Daggoo showing his teeth.\n\nDAGGOO (SPRINGING).\nSwallow thine, mannikin!  White skin, white liver!\n\nSPANISH SAILOR (MEETING HIM).\nKnife thee heartily! big frame, small spirit!\n\nALL.\nA row! a row! a row!\n\nTASHTEGO (WITH A WHIFF).\nA row a'low, and a row aloft--Gods and men--both brawlers!  Humph!\n\nBELFAST SAILOR.\nA row! arrah a row!  The Virgin be blessed, a row!  Plunge in with\nye!\n\nENGLISH SAILOR.\nFair play!  Snatch the Spaniard's knife!  A ring, a ring!\n\nOLD MANX SAILOR.\nReady formed.  There! the ringed horizon.  In that ring Cain struck\nAbel.  Sweet work, right work!  No?  Why then, God, mad'st thou the\nring?\n\nMATE'S VOICE FROM THE QUARTER-DECK.\nHands by the halyards! in top-gallant sails!  Stand by to reef\ntopsails!\n\nALL.\nThe squall! the squall! jump, my jollies! (THEY SCATTER.)\n\n\nPIP (SHRINKING UNDER THE WINDLASS).\nJollies?  Lord help such jollies!  Crish, crash! there goes the\njib-stay!  Blang-whang!  God!  Duck lower, Pip, here comes the royal\nyard!  It's worse than being in the whirled woods, the last day of\nthe year!  Who'd go climbing after chestnuts now?  But there they\ngo, all cursing, and here I don't.  Fine prospects to 'em; they're on\nthe road to heaven.  Hold on hard!  Jimmini, what a squall!  But\nthose chaps there are worse yet--they are your white squalls, they.\nWhite squalls? white whale, shirr! shirr!  Here have I heard all\ntheir chat just now, and the white whale--shirr! shirr!--but spoken\nof once! and only this evening--it makes me jingle all over like my\ntambourine--that anaconda of an old man swore 'em in to hunt him!\nOh, thou big white God aloft there somewhere in yon darkness, have\nmercy on this small black boy down here; preserve him from all men\nthat have no bowels to feel fear!\n\n\n\nCHAPTER 41\n\nMoby Dick.\n\n\nI, Ishmael, was one of that crew; my shouts had gone up with the\nrest; my oath had been welded with theirs; and stronger I shouted,\nand more did I hammer and clinch my oath, because of the dread in my\nsoul.  A wild, mystical, sympathetical feeling was in me; Ahab's\nquenchless feud seemed mine.  With greedy ears I learned the history\nof that murderous monster against whom I and all the others had taken\nour oaths of violence and revenge.\n\nFor some time past, though at intervals only, the unaccompanied,\nsecluded White Whale had haunted those uncivilized seas mostly\nfrequented by the Sperm Whale fishermen.  But not all of them knew of\nhis existence; only a few of them, comparatively, had knowingly seen\nhim; while the number who as yet had actually and knowingly given\nbattle to him, was small indeed.  For, owing to the large number of\nwhale-cruisers; the disorderly way they were sprinkled over the\nentire watery circumference, many of them adventurously pushing their\nquest along solitary latitudes, so as seldom or never for a whole\ntwelvemonth or more on a stretch, to encounter a single news-telling\nsail of any sort; the inordinate length of each separate voyage; the\nirregularity of the times of sailing from home; all these, with other\ncircumstances, direct and indirect, long obstructed the spread\nthrough the whole world-wide whaling-fleet of the special\nindividualizing tidings concerning Moby Dick.  It was hardly to be\ndoubted, that several vessels reported to have encountered, at such\nor such a time, or on such or such a meridian, a Sperm Whale of\nuncommon magnitude and malignity, which whale, after doing great\nmischief to his assailants, had completely escaped them; to some\nminds it was not an unfair presumption, I say, that the whale in\nquestion must have been no other than Moby Dick.  Yet as of late the\nSperm Whale fishery had been marked by various and not unfrequent\ninstances of great ferocity, cunning, and malice in the monster\nattacked; therefore it was, that those who by accident ignorantly\ngave battle to Moby Dick; such hunters, perhaps, for the most part,\nwere content to ascribe the peculiar terror he bred, more, as it\nwere, to the perils of the Sperm Whale fishery at large, than to the\nindividual cause.  In that way, mostly, the disastrous encounter\nbetween Ahab and the whale had hitherto been popularly regarded.\n\nAnd as for those who, previously hearing of the White Whale, by\nchance caught sight of him; in the beginning of the thing they had\nevery one of them, almost, as boldly and fearlessly lowered for him,\nas for any other whale of that species.  But at length, such\ncalamities did ensue in these assaults--not restricted to sprained\nwrists and ankles, broken limbs, or devouring amputations--but fatal\nto the last degree of fatality; those repeated disastrous repulses,\nall accumulating and piling their terrors upon Moby Dick; those\nthings had gone far to shake the fortitude of many brave hunters, to\nwhom the story of the White Whale had eventually come.\n\nNor did wild rumors of all sorts fail to exaggerate, and still the\nmore horrify the true histories of these deadly encounters.  For not\nonly do fabulous rumors naturally grow out of the very body of all\nsurprising terrible events,--as the smitten tree gives birth to its\nfungi; but, in maritime life, far more than in that of terra firma,\nwild rumors abound, wherever there is any adequate reality for them\nto cling to.  And as the sea surpasses the land in this matter, so\nthe whale fishery surpasses every other sort of maritime life, in the\nwonderfulness and fearfulness of the rumors which sometimes circulate\nthere.  For not only are whalemen as a body unexempt from that\nignorance and superstitiousness hereditary to all sailors; but of all\nsailors, they are by all odds the most directly brought into contact\nwith whatever is appallingly astonishing in the sea; face to face\nthey not only eye its greatest marvels, but, hand to jaw, give battle\nto them.  Alone, in such remotest waters, that though you sailed a\nthousand miles, and passed a thousand shores, you would not come to\nany chiseled hearth-stone, or aught hospitable beneath that part of\nthe sun; in such latitudes and longitudes, pursuing too such a\ncalling as he does, the whaleman is wrapped by influences all tending\nto make his fancy pregnant with many a mighty birth.\n\nNo wonder, then, that ever gathering volume from the mere transit\nover the widest watery spaces, the outblown rumors of the White Whale\ndid in the end incorporate with themselves all manner of morbid\nhints, and half-formed foetal suggestions of supernatural agencies,\nwhich eventually invested Moby Dick with new terrors unborrowed from\nanything that visibly appears.  So that in many cases such a panic\ndid he finally strike, that few who by those rumors, at least, had\nheard of the White Whale, few of those hunters were willing to\nencounter the perils of his jaw.\n\nBut there were still other and more vital practical influences at\nwork.  Not even at the present day has the original prestige of the\nSperm Whale, as fearfully distinguished from all other species of the\nleviathan, died out of the minds of the whalemen as a body.  There\nare those this day among them, who, though intelligent and courageous\nenough in offering battle to the Greenland or Right whale, would\nperhaps--either from professional inexperience, or incompetency, or\ntimidity, decline a contest with the Sperm Whale; at any rate, there\nare plenty of whalemen, especially among those whaling nations not\nsailing under the American flag, who have never hostilely encountered\nthe Sperm Whale, but whose sole knowledge of the leviathan is\nrestricted to the ignoble monster primitively pursued in the North;\nseated on their hatches, these men will hearken with a childish\nfireside interest and awe, to the wild, strange tales of Southern\nwhaling.  Nor is the pre-eminent tremendousness of the great Sperm\nWhale anywhere more feelingly comprehended, than on board of those\nprows which stem him.\n\nAnd as if the now tested reality of his might had in former legendary\ntimes thrown its shadow before it; we find some book\nnaturalists--Olassen and Povelson--declaring the Sperm Whale not only\nto be a consternation to every other creature in the sea, but also to\nbe so incredibly ferocious as continually to be athirst for human\nblood.  Nor even down to so late a time as Cuvier's, were these or\nalmost similar impressions effaced.  For in his Natural History, the\nBaron himself affirms that at sight of the Sperm Whale, all fish\n(sharks included) are \"struck with the most lively terrors,\" and\n\"often in the precipitancy of their flight dash themselves against\nthe rocks with such violence as to cause instantaneous death.\"  And\nhowever the general experiences in the fishery may amend such reports\nas these; yet in their full terribleness, even to the bloodthirsty\nitem of Povelson, the superstitious belief in them is, in some\nvicissitudes of their vocation, revived in the minds of the hunters.\n\nSo that overawed by the rumors and portents concerning him, not a few\nof the fishermen recalled, in reference to Moby Dick, the earlier\ndays of the Sperm Whale fishery, when it was oftentimes hard to\ninduce long practised Right whalemen to embark in the perils of this\nnew and daring warfare; such men protesting that although other\nleviathans might be hopefully pursued, yet to chase and point lance\nat such an apparition as the Sperm Whale was not for mortal man.\nThat to attempt it, would be inevitably to be torn into a quick\neternity.  On this head, there are some remarkable documents that may\nbe consulted.\n\nNevertheless, some there were, who even in the face of these things\nwere ready to give chase to Moby Dick; and a still greater number\nwho, chancing only to hear of him distantly and vaguely, without the\nspecific details of any certain calamity, and without superstitious\naccompaniments, were sufficiently hardy not to flee from the battle\nif offered.\n\nOne of the wild suggestions referred to, as at last coming to be\nlinked with the White Whale in the minds of the superstitiously\ninclined, was the unearthly conceit that Moby Dick was ubiquitous;\nthat he had actually been encountered in opposite latitudes at one\nand the same instant of time.\n\nNor, credulous as such minds must have been, was this conceit\naltogether without some faint show of superstitious probability.  For\nas the secrets of the currents in the seas have never yet been\ndivulged, even to the most erudite research; so the hidden ways of\nthe Sperm Whale when beneath the surface remain, in great part,\nunaccountable to his pursuers; and from time to time have originated\nthe most curious and contradictory speculations regarding them,\nespecially concerning the mystic modes whereby, after sounding to a\ngreat depth, he transports himself with such vast swiftness to the\nmost widely distant points.\n\nIt is a thing well known to both American and English whale-ships,\nand as well a thing placed upon authoritative record years ago by\nScoresby, that some whales have been captured far north in the\nPacific, in whose bodies have been found the barbs of harpoons darted\nin the Greenland seas.  Nor is it to be gainsaid, that in some of\nthese instances it has been declared that the interval of time\nbetween the two assaults could not have exceeded very many days.\nHence, by inference, it has been believed by some whalemen, that the\nNor' West Passage, so long a problem to man, was never a problem to\nthe whale.  So that here, in the real living experience of living\nmen, the prodigies related in old times of the inland Strello\nmountain in Portugal (near whose top there was said to be a lake in\nwhich the wrecks of ships floated up to the surface); and that still\nmore wonderful story of the Arethusa fountain near Syracuse (whose\nwaters were believed to have come from the Holy Land by an\nunderground passage); these fabulous narrations are almost fully\nequalled by the realities of the whalemen.\n\nForced into familiarity, then, with such prodigies as these; and\nknowing that after repeated, intrepid assaults, the White Whale had\nescaped alive; it cannot be much matter of surprise that some\nwhalemen should go still further in their superstitions; declaring\nMoby Dick not only ubiquitous, but immortal (for immortality is but\nubiquity in time); that though groves of spears should be planted in\nhis flanks, he would still swim away unharmed; or if indeed he should\never be made to spout thick blood, such a sight would be but a\nghastly deception; for again in unensanguined billows hundreds of\nleagues away, his unsullied jet would once more be seen.\n\nBut even stripped of these supernatural surmisings, there was enough\nin the earthly make and incontestable character of the monster to\nstrike the imagination with unwonted power.  For, it was not so much\nhis uncommon bulk that so much distinguished him from other sperm\nwhales, but, as was elsewhere thrown out--a peculiar snow-white\nwrinkled forehead, and a high, pyramidical white hump.  These were\nhis prominent features; the tokens whereby, even in the limitless,\nuncharted seas, he revealed his identity, at a long distance, to\nthose who knew him.\n\nThe rest of his body was so streaked, and spotted, and marbled with\nthe same shrouded hue, that, in the end, he had gained his\ndistinctive appellation of the White Whale; a name, indeed, literally\njustified by his vivid aspect, when seen gliding at high noon through\na dark blue sea, leaving a milky-way wake of creamy foam, all\nspangled with golden gleamings.\n\nNor was it his unwonted magnitude, nor his remarkable hue, nor yet\nhis deformed lower jaw, that so much invested the whale with natural\nterror, as that unexampled, intelligent malignity which, according to\nspecific accounts, he had over and over again evinced in his\nassaults.  More than all, his treacherous retreats struck more of\ndismay than perhaps aught else.  For, when swimming before his\nexulting pursuers, with every apparent symptom of alarm, he had\nseveral times been known to turn round suddenly, and, bearing down\nupon them, either stave their boats to splinters, or drive them back\nin consternation to their ship.\n\nAlready several fatalities had attended his chase.  But though\nsimilar disasters, however little bruited ashore, were by no means\nunusual in the fishery; yet, in most instances, such seemed the White\nWhale's infernal aforethought of ferocity, that every dismembering or\ndeath that he caused, was not wholly regarded as having been\ninflicted by an unintelligent agent.\n\nJudge, then, to what pitches of inflamed, distracted fury the minds\nof his more desperate hunters were impelled, when amid the chips of\nchewed boats, and the sinking limbs of torn comrades, they swam out\nof the white curds of the whale's direful wrath into the serene,\nexasperating sunlight, that smiled on, as if at a birth or a bridal.\n\nHis three boats stove around him, and oars and men both whirling in\nthe eddies; one captain, seizing the line-knife from his broken prow,\nhad dashed at the whale, as an Arkansas duellist at his foe, blindly\nseeking with a six inch blade to reach the fathom-deep life of the\nwhale.  That captain was Ahab.  And then it was, that suddenly\nsweeping his sickle-shaped lower jaw beneath him, Moby Dick had\nreaped away Ahab's leg, as a mower a blade of grass in the field.  No\nturbaned Turk, no hired Venetian or Malay, could have smote him with\nmore seeming malice.  Small reason was there to doubt, then, that\never since that almost fatal encounter, Ahab had cherished a wild\nvindictiveness against the whale, all the more fell for that in his\nfrantic morbidness he at last came to identify with him, not only all\nhis bodily woes, but all his intellectual and spiritual\nexasperations.  The White Whale swam before him as the monomaniac\nincarnation of all those malicious agencies which some deep men feel\neating in them, till they are left living on with half a heart and\nhalf a lung.  That intangible malignity which has been from the\nbeginning; to whose dominion even the modern Christians ascribe\none-half of the worlds; which the ancient Ophites of the east\nreverenced in their statue devil;--Ahab did not fall down and worship\nit like them; but deliriously transferring its idea to the abhorred\nwhite whale, he pitted himself, all mutilated, against it.  All that\nmost maddens and torments; all that stirs up the lees of things; all\ntruth with malice in it; all that cracks the sinews and cakes the\nbrain; all the subtle demonisms of life and thought; all evil, to\ncrazy Ahab, were visibly personified, and made practically assailable\nin Moby Dick.  He piled upon the whale's white hump the sum of all\nthe general rage and hate felt by his whole race from Adam down; and\nthen, as if his chest had been a mortar, he burst his hot heart's\nshell upon it.\n\nIt is not probable that this monomania in him took its instant rise\nat the precise time of his bodily dismemberment.  Then, in darting at\nthe monster, knife in hand, he had but given loose to a sudden,\npassionate, corporal animosity; and when he received the stroke that\ntore him, he probably but felt the agonizing bodily laceration, but\nnothing more.  Yet, when by this collision forced to turn towards\nhome, and for long months of days and weeks, Ahab and anguish lay\nstretched together in one hammock, rounding in mid winter that\ndreary, howling Patagonian Cape; then it was, that his torn body and\ngashed soul bled into one another; and so interfusing, made him mad.\nThat it was only then, on the homeward voyage, after the encounter,\nthat the final monomania seized him, seems all but certain from the\nfact that, at intervals during the passage, he was a raving lunatic;\nand, though unlimbed of a leg, yet such vital strength yet lurked in\nhis Egyptian chest, and was moreover intensified by his delirium,\nthat his mates were forced to lace him fast, even there, as he\nsailed, raving in his hammock.  In a strait-jacket, he swung to the\nmad rockings of the gales.  And, when running into more sufferable\nlatitudes, the ship, with mild stun'sails spread, floated across the\ntranquil tropics, and, to all appearances, the old man's delirium\nseemed left behind him with the Cape Horn swells, and he came forth\nfrom his dark den into the blessed light and air; even then, when he\nbore that firm, collected front, however pale, and issued his calm\norders once again; and his mates thanked God the direful madness was\nnow gone; even then, Ahab, in his hidden self, raved on.  Human\nmadness is oftentimes a cunning and most feline thing.  When you\nthink it fled, it may have but become transfigured into some still\nsubtler form.  Ahab's full lunacy subsided not, but deepeningly\ncontracted; like the unabated Hudson, when that noble Northman flows\nnarrowly, but unfathomably through the Highland gorge.  But, as in\nhis narrow-flowing monomania, not one jot of Ahab's broad madness had\nbeen left behind; so in that broad madness, not one jot of his great\nnatural intellect had perished.  That before living agent, now became\nthe living instrument.  If such a furious trope may stand, his\nspecial lunacy stormed his general sanity, and carried it, and turned\nall its concentred cannon upon its own mad mark; so that far from\nhaving lost his strength, Ahab, to that one end, did now possess a\nthousand fold more potency than ever he had sanely brought to bear\nupon any one reasonable object.\n\nThis is much; yet Ahab's larger, darker, deeper part remains\nunhinted.  But vain to popularize profundities, and all truth is\nprofound.  Winding far down from within the very heart of this spiked\nHotel de Cluny where we here stand--however grand and wonderful, now\nquit it;--and take your way, ye nobler, sadder souls, to those vast\nRoman halls of Thermes; where far beneath the fantastic towers of\nman's upper earth, his root of grandeur, his whole awful essence sits\nin bearded state; an antique buried beneath antiquities, and throned\non torsoes!  So with a broken throne, the great gods mock that\ncaptive king; so like a Caryatid, he patient sits, upholding on his\nfrozen brow the piled entablatures of ages.  Wind ye down there, ye\nprouder, sadder souls! question that proud, sad king!  A family\nlikeness! aye, he did beget ye, ye young exiled royalties; and from\nyour grim sire only will the old State-secret come.\n\nNow, in his heart, Ahab had some glimpse of this, namely: all my\nmeans are sane, my motive and my object mad.  Yet without power to\nkill, or change, or shun the fact; he likewise knew that to mankind\nhe did long dissemble; in some sort, did still.  But that thing of\nhis dissembling was only subject to his perceptibility, not to his\nwill determinate.  Nevertheless, so well did he succeed in that\ndissembling, that when with ivory leg he stepped ashore at last, no\nNantucketer thought him otherwise than but naturally grieved, and\nthat to the quick, with the terrible casualty which had overtaken\nhim.\n\nThe report of his undeniable delirium at sea was likewise popularly\nascribed to a kindred cause.  And so too, all the added moodiness\nwhich always afterwards, to the very day of sailing in the Pequod on\nthe present voyage, sat brooding on his brow.  Nor is it so very\nunlikely, that far from distrusting his fitness for another whaling\nvoyage, on account of such dark symptoms, the calculating people of\nthat prudent isle were inclined to harbor the conceit, that for those\nvery reasons he was all the better qualified and set on edge, for a\npursuit so full of rage and wildness as the bloody hunt of whales.\nGnawed within and scorched without, with the infixed, unrelenting\nfangs of some incurable idea; such an one, could he be found, would\nseem the very man to dart his iron and lift his lance against the\nmost appalling of all brutes.  Or, if for any reason thought to be\ncorporeally incapacitated for that, yet such an one would seem\nsuperlatively competent to cheer and howl on his underlings to the\nattack.  But be all this as it may, certain it is, that with the mad\nsecret of his unabated rage bolted up and keyed in him, Ahab had\npurposely sailed upon the present voyage with the one only and\nall-engrossing object of hunting the White Whale.  Had any one of his\nold acquaintances on shore but half dreamed of what was lurking in\nhim then, how soon would their aghast and righteous souls have\nwrenched the ship from such a fiendish man!  They were bent on\nprofitable cruises, the profit to be counted down in dollars from the\nmint.  He was intent on an audacious, immitigable, and supernatural\nrevenge.\n\nHere, then, was this grey-headed, ungodly old man, chasing with\ncurses a Job's whale round the world, at the head of a crew, too,\nchiefly made up of mongrel renegades, and castaways, and\ncannibals--morally enfeebled also, by the incompetence of mere\nunaided virtue or right-mindedness in Starbuck, the invunerable\njollity of indifference and recklessness in Stubb, and the pervading\nmediocrity in Flask.  Such a crew, so officered, seemed specially\npicked and packed by some infernal fatality to help him to his\nmonomaniac revenge.  How it was that they so aboundingly responded to\nthe old man's ire--by what evil magic their souls were possessed,\nthat at times his hate seemed almost theirs; the White Whale as much\ntheir insufferable foe as his; how all this came to be--what the\nWhite Whale was to them, or how to their unconscious understandings,\nalso, in some dim, unsuspected way, he might have seemed the gliding\ngreat demon of the seas of life,--all this to explain, would be to\ndive deeper than Ishmael can go.  The subterranean miner that works\nin us all, how can one tell whither leads his shaft by the ever\nshifting, muffled sound of his pick?  Who does not feel the\nirresistible arm drag?  What skiff in tow of a seventy-four can stand\nstill?  For one, I gave myself up to the abandonment of the time and\nthe place; but while yet all a-rush to encounter the whale, could see\nnaught in that brute but the deadliest ill.\n\n\n\nCHAPTER 42\n\nThe Whiteness of The Whale.\n\n\nWhat the white whale was to Ahab, has been hinted; what, at times, he\nwas to me, as yet remains unsaid.\n\nAside from those more obvious considerations touching Moby Dick,\nwhich could not but occasionally awaken in any man's soul some alarm,\nthere was another thought, or rather vague, nameless horror\nconcerning him, which at times by its intensity completely\noverpowered all the rest; and yet so mystical and well nigh ineffable\nwas it, that I almost despair of putting it in a comprehensible form.\nIt was the whiteness of the whale that above all things appalled me.\nBut how can I hope to explain myself here; and yet, in some dim,\nrandom way, explain myself I must, else all these chapters might be\nnaught.\n\nThough in many natural objects, whiteness refiningly enhances beauty,\nas if imparting some special virtue of its own, as in marbles,\njaponicas, and pearls; and though various nations have in some way\nrecognised a certain royal preeminence in this hue; even the\nbarbaric, grand old kings of Pegu placing the title \"Lord of the\nWhite Elephants\" above all their other magniloquent ascriptions of\ndominion; and the modern kings of Siam unfurling the same snow-white\nquadruped in the royal standard; and the Hanoverian flag bearing the\none figure of a snow-white charger; and the great Austrian Empire,\nCaesarian, heir to overlording Rome, having for the imperial colour\nthe same imperial hue; and though this pre-eminence in it applies to\nthe human race itself, giving the white man ideal mastership over\nevery dusky tribe; and though, besides, all this, whiteness has been\neven made significant of gladness, for among the Romans a white stone\nmarked a joyful day; and though in other mortal sympathies and\nsymbolizings, this same hue is made the emblem of many touching,\nnoble things--the innocence of brides, the benignity of age; though\namong the Red Men of America the giving of the white belt of wampum\nwas the deepest pledge of honour; though in many climes, whiteness\ntypifies the majesty of Justice in the ermine of the Judge, and\ncontributes to the daily state of kings and queens drawn by\nmilk-white steeds; though even in the higher mysteries of the most\naugust religions it has been made the symbol of the divine\nspotlessness and power; by the Persian fire worshippers, the white\nforked flame being held the holiest on the altar; and in the Greek\nmythologies, Great Jove himself being made incarnate in a snow-white\nbull; and though to the noble Iroquois, the midwinter sacrifice of\nthe sacred White Dog was by far the holiest festival of their\ntheology, that spotless, faithful creature being held the purest\nenvoy they could send to the Great Spirit with the annual tidings of\ntheir own fidelity; and though directly from the Latin word for\nwhite, all Christian priests derive the name of one part of their\nsacred vesture, the alb or tunic, worn beneath the cassock; and\nthough among the holy pomps of the Romish faith, white is specially\nemployed in the celebration of the Passion of our Lord; though in the\nVision of St. John, white robes are given to the redeemed, and the\nfour-and-twenty elders stand clothed in white before the great-white\nthrone, and the Holy One that sitteth there white like wool; yet for\nall these accumulated associations, with whatever is sweet, and\nhonourable, and sublime, there yet lurks an elusive something in the\ninnermost idea of this hue, which strikes more of panic to the soul\nthan that redness which affrights in blood.\n\nThis elusive quality it is, which causes the thought of whiteness,\nwhen divorced from more kindly associations, and coupled with any\nobject terrible in itself, to heighten that terror to the furthest\nbounds.  Witness the white bear of the poles, and the white shark of\nthe tropics; what but their smooth, flaky whiteness makes them the\ntranscendent horrors they are?  That ghastly whiteness it is which\nimparts such an abhorrent mildness, even more loathsome than\nterrific, to the dumb gloating of their aspect.  So that not the\nfierce-fanged tiger in his heraldic coat can so stagger courage as\nthe white-shrouded bear or shark.*\n\n\n*With reference to the Polar bear, it may possibly be urged by him\nwho would fain go still deeper into this matter, that it is not the\nwhiteness, separately regarded, which heightens the intolerable\nhideousness of that brute; for, analysed, that heightened\nhideousness, it might be said, only rises from the circumstance, that\nthe irresponsible ferociousness of the creature stands invested in\nthe fleece of celestial innocence and love; and hence, by bringing\ntogether two such opposite emotions in our minds, the Polar bear\nfrightens us with so unnatural a contrast.  But even assuming all\nthis to be true; yet, were it not for the whiteness, you would not\nhave that intensified terror.\n\nAs for the white shark, the white gliding ghostliness of repose in\nthat creature, when beheld in his ordinary moods, strangely tallies\nwith the same quality in the Polar quadruped.  This peculiarity is\nmost vividly hit by the French in the name they bestow upon that\nfish.  The Romish mass for the dead begins with \"Requiem eternam\"\n(eternal rest), whence REQUIEM denominating the mass itself, and any\nother funeral music.  Now, in allusion to the white, silent stillness\nof death in this shark, and the mild deadliness of his habits, the\nFrench call him REQUIN.\n\n\nBethink thee of the albatross, whence come those clouds of spiritual\nwonderment and pale dread, in which that white phantom sails in all\nimaginations?  Not Coleridge first threw that spell; but God's great,\nunflattering laureate, Nature.*\n\n\n*I remember the first albatross I ever saw.  It was during a\nprolonged gale, in waters hard upon the Antarctic seas.  From my\nforenoon watch below, I ascended to the overclouded deck; and there,\ndashed upon the main hatches, I saw a regal, feathery thing of\nunspotted whiteness, and with a hooked, Roman bill sublime.  At\nintervals, it arched forth its vast archangel wings, as if to embrace\nsome holy ark.  Wondrous flutterings and throbbings shook it.  Though\nbodily unharmed, it uttered cries, as some king's ghost in\nsupernatural distress.  Through its inexpressible, strange eyes,\nmethought I peeped to secrets which took hold of God.  As Abraham\nbefore the angels, I bowed myself; the white thing was so white, its\nwings so wide, and in those for ever exiled waters, I had lost the\nmiserable warping memories of traditions and of towns.  Long I gazed\nat that prodigy of plumage.  I cannot tell, can only hint, the things\nthat darted through me then.  But at last I awoke; and turning, asked\na sailor what bird was this.  A goney, he replied.  Goney! never had\nheard that name before; is it conceivable that this glorious thing is\nutterly unknown to men ashore! never!  But some time after, I learned\nthat goney was some seaman's name for albatross.  So that by no\npossibility could Coleridge's wild Rhyme have had aught to do with\nthose mystical impressions which were mine, when I saw that bird upon\nour deck.  For neither had I then read the Rhyme, nor knew the bird\nto be an albatross.  Yet, in saying this, I do but indirectly burnish\na little brighter the noble merit of the poem and the poet.\n\nI assert, then, that in the wondrous bodily whiteness of the bird\nchiefly lurks the secret of the spell; a truth the more evinced in\nthis, that by a solecism of terms there are birds called grey\nalbatrosses; and these I have frequently seen, but never with such\nemotions as when I beheld the Antarctic fowl.\n\nBut how had the mystic thing been caught?  Whisper it not, and I will\ntell; with a treacherous hook and line, as the fowl floated on the\nsea.  At last the Captain made a postman of it; tying a lettered,\nleathern tally round its neck, with the ship's time and place; and\nthen letting it escape.  But I doubt not, that leathern tally, meant\nfor man, was taken off in Heaven, when the white fowl flew to join\nthe wing-folding, the invoking, and adoring cherubim!\n\n\nMost famous in our Western annals and Indian traditions is that of\nthe White Steed of the Prairies; a magnificent milk-white charger,\nlarge-eyed, small-headed, bluff-chested, and with the dignity of a\nthousand monarchs in his lofty, overscorning carriage.  He was the\nelected Xerxes of vast herds of wild horses, whose pastures in those\ndays were only fenced by the Rocky Mountains and the Alleghanies.  At\ntheir flaming head he westward trooped it like that chosen star which\nevery evening leads on the hosts of light.  The flashing cascade of\nhis mane, the curving comet of his tail, invested him with housings\nmore resplendent than gold and silver-beaters could have furnished\nhim.  A most imperial and archangelical apparition of that unfallen,\nwestern world, which to the eyes of the old trappers and hunters\nrevived the glories of those primeval times when Adam walked majestic\nas a god, bluff-browed and fearless as this mighty steed.  Whether\nmarching amid his aides and marshals in the van of countless cohorts\nthat endlessly streamed it over the plains, like an Ohio; or whether\nwith his circumambient subjects browsing all around at the horizon,\nthe White Steed gallopingly reviewed them with warm nostrils\nreddening through his cool milkiness; in whatever aspect he presented\nhimself, always to the bravest Indians he was the object of trembling\nreverence and awe.  Nor can it be questioned from what stands on\nlegendary record of this noble horse, that it was his spiritual\nwhiteness chiefly, which so clothed him with divineness; and that\nthis divineness had that in it which, though commanding worship, at\nthe same time enforced a certain nameless terror.\n\nBut there are other instances where this whiteness loses all that\naccessory and strange glory which invests it in the White Steed and\nAlbatross.\n\nWhat is it that in the Albino man so peculiarly repels and often\nshocks the eye, as that sometimes he is loathed by his own kith and\nkin!  It is that whiteness which invests him, a thing expressed by\nthe name he bears.  The Albino is as well made as other men--has no\nsubstantive deformity--and yet this mere aspect of all-pervading\nwhiteness makes him more strangely hideous than the ugliest abortion.\nWhy should this be so?\n\nNor, in quite other aspects, does Nature in her least palpable but\nnot the less malicious agencies, fail to enlist among her forces this\ncrowning attribute of the terrible.  From its snowy aspect, the\ngauntleted ghost of the Southern Seas has been denominated the White\nSquall.  Nor, in some historic instances, has the art of human malice\nomitted so potent an auxiliary.  How wildly it heightens the effect\nof that passage in Froissart, when, masked in the snowy symbol of\ntheir faction, the desperate White Hoods of Ghent murder their\nbailiff in the market-place!\n\nNor, in some things, does the common, hereditary experience of all\nmankind fail to bear witness to the supernaturalism of this hue.  It\ncannot well be doubted, that the one visible quality in the aspect of\nthe dead which most appals the gazer, is the marble pallor lingering\nthere; as if indeed that pallor were as much like the badge of\nconsternation in the other world, as of mortal trepidation here.  And\nfrom that pallor of the dead, we borrow the expressive hue of the\nshroud in which we wrap them.  Nor even in our superstitions do we\nfail to throw the same snowy mantle round our phantoms; all ghosts\nrising in a milk-white fog--Yea, while these terrors seize us, let us\nadd, that even the king of terrors, when personified by the\nevangelist, rides on his pallid horse.\n\nTherefore, in his other moods, symbolize whatever grand or gracious\nthing he will by whiteness, no man can deny that in its profoundest\nidealized significance it calls up a peculiar apparition to the soul.\n\nBut though without dissent this point be fixed, how is mortal man to\naccount for it?  To analyse it, would seem impossible.  Can we,\nthen, by the citation of some of those instances wherein this thing\nof whiteness--though for the time either wholly or in great part\nstripped of all direct associations calculated to impart to it aught\nfearful, but nevertheless, is found to exert over us the same\nsorcery, however modified;--can we thus hope to light upon some\nchance clue to conduct us to the hidden cause we seek?\n\nLet us try.  But in a matter like this, subtlety appeals to subtlety,\nand without imagination no man can follow another into these halls.\nAnd though, doubtless, some at least of the imaginative impressions\nabout to be presented may have been shared by most men, yet few\nperhaps were entirely conscious of them at the time, and therefore\nmay not be able to recall them now.\n\nWhy to the man of untutored ideality, who happens to be but loosely\nacquainted with the peculiar character of the day, does the bare\nmention of Whitsuntide marshal in the fancy such long, dreary,\nspeechless processions of slow-pacing pilgrims, down-cast and hooded\nwith new-fallen snow?  Or, to the unread, unsophisticated Protestant\nof the Middle American States, why does the passing mention of a\nWhite Friar or a White Nun, evoke such an eyeless statue in the soul?\n\nOr what is there apart from the traditions of dungeoned warriors and\nkings (which will not wholly account for it) that makes the White\nTower of London tell so much more strongly on the imagination of an\nuntravelled American, than those other storied structures, its\nneighbors--the Byward Tower, or even the Bloody?  And those sublimer\ntowers, the White Mountains of New Hampshire, whence, in peculiar\nmoods, comes that gigantic ghostliness over the soul at the bare\nmention of that name, while the thought of Virginia's Blue Ridge is\nfull of a soft, dewy, distant dreaminess?  Or why, irrespective of\nall latitudes and longitudes, does the name of the White Sea exert\nsuch a spectralness over the fancy, while that of the Yellow Sea\nlulls us with mortal thoughts of long lacquered mild afternoons on\nthe waves, followed by the gaudiest and yet sleepiest of sunsets?\nOr, to choose a wholly unsubstantial instance, purely addressed to\nthe fancy, why, in reading the old fairy tales of Central Europe,\ndoes \"the tall pale man\" of the Hartz forests, whose changeless\npallor unrustlingly glides through the green of the groves--why is\nthis phantom more terrible than all the whooping imps of the\nBlocksburg?\n\nNor is it, altogether, the remembrance of her cathedral-toppling\nearthquakes; nor the stampedoes of her frantic seas; nor the\ntearlessness of arid skies that never rain; nor the sight of her\nwide field of leaning spires, wrenched cope-stones, and crosses all\nadroop (like canted yards of anchored fleets); and her suburban\navenues of house-walls lying over upon each other, as a tossed pack\nof cards;--it is not these things alone which make tearless Lima, the\nstrangest, saddest city thou can'st see.  For Lima has taken the\nwhite veil; and there is a higher horror in this whiteness of her\nwoe.  Old as Pizarro, this whiteness keeps her ruins for ever new;\nadmits not the cheerful greenness of complete decay; spreads over her\nbroken ramparts the rigid pallor of an apoplexy that fixes its own\ndistortions.\n\nI know that, to the common apprehension, this phenomenon of whiteness\nis not confessed to be the prime agent in exaggerating the terror of\nobjects otherwise terrible; nor to the unimaginative mind is there\naught of terror in those appearances whose awfulness to another mind\nalmost solely consists in this one phenomenon, especially when\nexhibited under any form at all approaching to muteness or\nuniversality.  What I mean by these two statements may perhaps be\nrespectively elucidated by the following examples.\n\nFirst: The mariner, when drawing nigh the coasts of foreign lands, if\nby night he hear the roar of breakers, starts to vigilance, and feels\njust enough of trepidation to sharpen all his faculties; but under\nprecisely similar circumstances, let him be called from his hammock\nto view his ship sailing through a midnight sea of milky\nwhiteness--as if from encircling headlands shoals of combed white\nbears were swimming round him, then he feels a silent, superstitious\ndread; the shrouded phantom of the whitened waters is horrible to him\nas a real ghost; in vain the lead assures him he is still off\nsoundings; heart and helm they both go down; he never rests till blue\nwater is under him again.  Yet where is the mariner who will tell\nthee, \"Sir, it was not so much the fear of striking hidden rocks, as\nthe fear of that hideous whiteness that so stirred me?\"\n\nSecond: To the native Indian of Peru, the continual sight of the\nsnowhowdahed Andes conveys naught of dread, except, perhaps, in the\nmere fancying of the eternal frosted desolateness reigning at such\nvast altitudes, and the natural conceit of what a fearfulness it\nwould be to lose oneself in such inhuman solitudes.  Much the same is\nit with the backwoodsman of the West, who with comparative\nindifference views an unbounded prairie sheeted with driven snow, no\nshadow of tree or twig to break the fixed trance of whiteness.  Not\nso the sailor, beholding the scenery of the Antarctic seas; where at\ntimes, by some infernal trick of legerdemain in the powers of frost\nand air, he, shivering and half shipwrecked, instead of rainbows\nspeaking hope and solace to his misery, views what seems a boundless\nchurchyard grinning upon him with its lean ice monuments and\nsplintered crosses.\n\nBut thou sayest, methinks that white-lead chapter about whiteness is\nbut a white flag hung out from a craven soul; thou surrenderest to a\nhypo, Ishmael.\n\nTell me, why this strong young colt, foaled in some peaceful valley\nof Vermont, far removed from all beasts of prey--why is it that upon\nthe sunniest day, if you but shake a fresh buffalo robe behind him,\nso that he cannot even see it, but only smells its wild animal\nmuskiness--why will he start, snort, and with bursting eyes paw the\nground in phrensies of affright?  There is no remembrance in him of\nany gorings of wild creatures in his green northern home, so that the\nstrange muskiness he smells cannot recall to him anything associated\nwith the experience of former perils; for what knows he, this New\nEngland colt, of the black bisons of distant Oregon?\n\nNo; but here thou beholdest even in a dumb brute, the instinct of the\nknowledge of the demonism in the world.  Though thousands of miles\nfrom Oregon, still when he smells that savage musk, the rending,\ngoring bison herds are as present as to the deserted wild foal of the\nprairies, which this instant they may be trampling into dust.\n\nThus, then, the muffled rollings of a milky sea; the bleak rustlings\nof the festooned frosts of mountains; the desolate shiftings of the\nwindrowed snows of prairies; all these, to Ishmael, are as the\nshaking of that buffalo robe to the frightened colt!\n\nThough neither knows where lie the nameless things of which the\nmystic sign gives forth such hints; yet with me, as with the colt,\nsomewhere those things must exist.  Though in many of its aspects\nthis visible world seems formed in love, the invisible spheres were\nformed in fright.\n\nBut not yet have we solved the incantation of this whiteness, and\nlearned why it appeals with such power to the soul; and more strange\nand far more portentous--why, as we have seen, it is at once the most\nmeaning symbol of spiritual things, nay, the very veil of the\nChristian's Deity; and yet should be as it is, the intensifying agent\nin things the most appalling to mankind.\n\nIs it that by its indefiniteness it shadows forth the heartless voids\nand immensities of the universe, and thus stabs us from behind with\nthe thought of annihilation, when beholding the white depths of the\nmilky way?  Or is it, that as in essence whiteness is not so much a\ncolour as the visible absence of colour; and at the same time the\nconcrete of all colours; is it for these reasons that there is such a\ndumb blankness, full of meaning, in a wide landscape of snows--a\ncolourless, all-colour of atheism from which we shrink?  And when we\nconsider that other theory of the natural philosophers, that all\nother earthly hues--every stately or lovely emblazoning--the sweet\ntinges of sunset skies and woods; yea, and the gilded velvets of\nbutterflies, and the butterfly cheeks of young girls; all these are\nbut subtile deceits, not actually inherent in substances, but only\nlaid on from without; so that all deified Nature absolutely paints\nlike the harlot, whose allurements cover nothing but the\ncharnel-house within; and when we proceed further, and consider that\nthe mystical cosmetic which produces every one of her hues, the great\nprinciple of light, for ever remains white or colourless in itself,\nand if operating without medium upon matter, would touch all objects,\neven tulips and roses, with its own blank tinge--pondering all this,\nthe palsied universe lies before us a leper; and like wilful\ntravellers in Lapland, who refuse to wear coloured and colouring\nglasses upon their eyes, so the wretched infidel gazes himself blind\nat the monumental white shroud that wraps all the prospect around\nhim.  And of all these things the Albino whale was the symbol.\nWonder ye then at the fiery hunt?\n\n\n\nCHAPTER 43\n\nHark!\n\n\n\"HIST!  Did you hear that noise, Cabaco?\n\nIt was the middle-watch; a fair moonlight; the seamen were standing\nin a cordon, extending from one of the fresh-water butts in the\nwaist, to the scuttle-butt near the taffrail.  In this manner, they\npassed the buckets to fill the scuttle-butt.  Standing, for the most\npart, on the hallowed precincts of the quarter-deck, they were\ncareful not to speak or rustle their feet.  From hand to hand, the\nbuckets went in the deepest silence, only broken by the occasional\nflap of a sail, and the steady hum of the unceasingly advancing keel.\n\nIt was in the midst of this repose, that Archy, one of the cordon,\nwhose post was near the after-hatches, whispered to his neighbor, a\nCholo, the words above.\n\n\"Hist! did you hear that noise, Cabaco?\"\n\n\"Take the bucket, will ye, Archy? what noise d'ye mean?\"\n\n\"There it is again--under the hatches--don't you hear it--a cough--it\nsounded like a cough.\"\n\n\"Cough be damned!  Pass along that return bucket.\"\n\n\"There again--there it is!--it sounds like two or three sleepers\nturning over, now!\"\n\n\"Caramba! have done, shipmate, will ye?  It's the three soaked\nbiscuits ye eat for supper turning over inside of ye--nothing else.\nLook to the bucket!\"\n\n\"Say what ye will, shipmate; I've sharp ears.\"\n\n\"Aye, you are the chap, ain't ye, that heard the hum of the old\nQuakeress's knitting-needles fifty miles at sea from Nantucket;\nyou're the chap.\"\n\n\"Grin away; we'll see what turns up.  Hark ye, Cabaco, there is\nsomebody down in the after-hold that has not yet been seen on deck;\nand I suspect our old Mogul knows something of it too.  I heard Stubb\ntell Flask, one morning watch, that there was something of that sort\nin the wind.\"\n\n\"Tish! the bucket!\"\n\n\n\nCHAPTER 44\n\nThe Chart.\n\n\nHad you followed Captain Ahab down into his cabin after the squall\nthat took place on the night succeeding that wild ratification of his\npurpose with his crew, you would have seen him go to a locker in the\ntransom, and bringing out a large wrinkled roll of yellowish sea\ncharts, spread them before him on his screwed-down table.  Then\nseating himself before it, you would have seen him intently study the\nvarious lines and shadings which there met his eye; and with slow but\nsteady pencil trace additional courses over spaces that before were\nblank.  At intervals, he would refer to piles of old log-books beside\nhim, wherein were set down the seasons and places in which, on\nvarious former voyages of various ships, sperm whales had been\ncaptured or seen.\n\nWhile thus employed, the heavy pewter lamp suspended in chains over\nhis head, continually rocked with the motion of the ship, and for\never threw shifting gleams and shadows of lines upon his wrinkled\nbrow, till it almost seemed that while he himself was marking out\nlines and courses on the wrinkled charts, some invisible pencil was\nalso tracing lines and courses upon the deeply marked chart of his\nforehead.\n\nBut it was not this night in particular that, in the solitude of his\ncabin, Ahab thus pondered over his charts.  Almost every night they\nwere brought out; almost every night some pencil marks were effaced,\nand others were substituted.  For with the charts of all four oceans\nbefore him, Ahab was threading a maze of currents and eddies, with a\nview to the more certain accomplishment of that monomaniac thought of\nhis soul.\n\nNow, to any one not fully acquainted with the ways of the leviathans,\nit might seem an absurdly hopeless task thus to seek out one solitary\ncreature in the unhooped oceans of this planet.  But not so did it\nseem to Ahab, who knew the sets of all tides and currents; and\nthereby calculating the driftings of the sperm whale's food; and,\nalso, calling to mind the regular, ascertained seasons for hunting\nhim in particular latitudes; could arrive at reasonable surmises,\nalmost approaching to certainties, concerning the timeliest day to be\nupon this or that ground in search of his prey.\n\nSo assured, indeed, is the fact concerning the periodicalness of the\nsperm whale's resorting to given waters, that many hunters believe\nthat, could he be closely observed and studied throughout the world;\nwere the logs for one voyage of the entire whale fleet carefully\ncollated, then the migrations of the sperm whale would be found to\ncorrespond in invariability to those of the herring-shoals or the\nflights of swallows.  On this hint, attempts have been made to\nconstruct elaborate migratory charts of the sperm whale.*\n\n\n*Since the above was written, the statement is happily borne out by\nan official circular, issued by Lieutenant Maury, of the National\nObservatory, Washington, April 16th, 1851.  By that circular, it\nappears that precisely such a chart is in course of completion; and\nportions of it are presented in the circular.  \"This chart divides\nthe ocean into districts of five degrees of latitude by five degrees\nof longitude; perpendicularly through each of which districts are\ntwelve columns for the twelve months; and horizontally through each\nof which districts are three lines; one to show the number of days\nthat have been spent in each month in every district, and the two\nothers to show the number of days in which whales, sperm or right,\nhave been seen.\"\n\n\nBesides, when making a passage from one feeding-ground to another,\nthe sperm whales, guided by some infallible instinct--say, rather,\nsecret intelligence from the Deity--mostly swim in VEINS, as they are\ncalled; continuing their way along a given ocean-line with such\nundeviating exactitude, that no ship ever sailed her course, by any\nchart, with one tithe of such marvellous precision.  Though, in these\ncases, the direction taken by any one whale be straight as a\nsurveyor's parallel, and though the line of advance be strictly\nconfined to its own unavoidable, straight wake, yet the arbitrary\nVEIN in which at these times he is said to swim, generally embraces\nsome few miles in width (more or less, as the vein is presumed to\nexpand or contract); but never exceeds the visual sweep from the\nwhale-ship's mast-heads, when circumspectly gliding along this magic\nzone.  The sum is, that at particular seasons within that breadth and\nalong that path, migrating whales may with great confidence be looked\nfor.\n\nAnd hence not only at substantiated times, upon well known separate\nfeeding-grounds, could Ahab hope to encounter his prey; but in\ncrossing the widest expanses of water between those grounds he could,\nby his art, so place and time himself on his way, as even then not to\nbe wholly without prospect of a meeting.\n\nThere was a circumstance which at first sight seemed to entangle his\ndelirious but still methodical scheme.  But not so in the reality,\nperhaps.  Though the gregarious sperm whales have their regular\nseasons for particular grounds, yet in general you cannot conclude\nthat the herds which haunted such and such a latitude or longitude\nthis year, say, will turn out to be identically the same with those\nthat were found there the preceding season; though there are peculiar\nand unquestionable instances where the contrary of this has proved\ntrue.  In general, the same remark, only within a less wide limit,\napplies to the solitaries and hermits among the matured, aged sperm\nwhales.  So that though Moby Dick had in a former year been seen, for\nexample, on what is called the Seychelle ground in the Indian ocean,\nor Volcano Bay on the Japanese Coast; yet it did not follow, that\nwere the Pequod to visit either of those spots at any subsequent\ncorresponding season, she would infallibly encounter him there.  So,\ntoo, with some other feeding grounds, where he had at times revealed\nhimself.  But all these seemed only his casual stopping-places and\nocean-inns, so to speak, not his places of prolonged abode.  And\nwhere Ahab's chances of accomplishing his object have hitherto been\nspoken of, allusion has only been made to whatever way-side,\nantecedent, extra prospects were his, ere a particular set time or\nplace were attained, when all possibilities would become\nprobabilities, and, as Ahab fondly thought, every possibility the\nnext thing to a certainty.  That particular set time and place were\nconjoined in the one technical phrase--the Season-on-the-Line.  For\nthere and then, for several consecutive years, Moby Dick had been\nperiodically descried, lingering in those waters for awhile, as the\nsun, in its annual round, loiters for a predicted interval in any one\nsign of the Zodiac.  There it was, too, that most of the deadly\nencounters with the white whale had taken place; there the waves were\nstoried with his deeds; there also was that tragic spot where the\nmonomaniac old man had found the awful motive to his vengeance.  But\nin the cautious comprehensiveness and unloitering vigilance with\nwhich Ahab threw his brooding soul into this unfaltering hunt, he\nwould not permit himself to rest all his hopes upon the one crowning\nfact above mentioned, however flattering it might be to those hopes;\nnor in the sleeplessness of his vow could he so tranquillize his\nunquiet heart as to postpone all intervening quest.\n\nNow, the Pequod had sailed from Nantucket at the very beginning of\nthe Season-on-the-Line.  No possible endeavor then could enable her\ncommander to make the great passage southwards, double Cape Horn, and\nthen running down sixty degrees of latitude arrive in the equatorial\nPacific in time to cruise there.  Therefore, he must wait for the\nnext ensuing season.  Yet the premature hour of the Pequod's sailing\nhad, perhaps, been correctly selected by Ahab, with a view to this\nvery complexion of things.  Because, an interval of three hundred and\nsixty-five days and nights was before him; an interval which, instead\nof impatiently enduring ashore, he would spend in a miscellaneous\nhunt; if by chance the White Whale, spending his vacation in seas far\nremote from his periodical feeding-grounds, should turn up his\nwrinkled brow off the Persian Gulf, or in the Bengal Bay, or China\nSeas, or in any other waters haunted by his race.  So that Monsoons,\nPampas, Nor'-Westers, Harmattans, Trades; any wind but the Levanter\nand Simoon, might blow Moby Dick into the devious zig-zag\nworld-circle of the Pequod's circumnavigating wake.\n\nBut granting all this; yet, regarded discreetly and coolly, seems it\nnot but a mad idea, this; that in the broad boundless ocean, one\nsolitary whale, even if encountered, should be thought capable of\nindividual recognition from his hunter, even as a white-bearded Mufti\nin the thronged thoroughfares of Constantinople?  Yes.  For the\npeculiar snow-white brow of Moby Dick, and his snow-white hump, could\nnot but be unmistakable.  And have I not tallied the whale, Ahab\nwould mutter to himself, as after poring over his charts till long\nafter midnight he would throw himself back in reveries--tallied him,\nand shall he escape?  His broad fins are bored, and scalloped out\nlike a lost sheep's ear!  And here, his mad mind would run on in a\nbreathless race; till a weariness and faintness of pondering came\nover him; and in the open air of the deck he would seek to recover\nhis strength.  Ah, God! what trances of torments does that man endure\nwho is consumed with one unachieved revengeful desire.  He sleeps\nwith clenched hands; and wakes with his own bloody nails in his\npalms.\n\nOften, when forced from his hammock by exhausting and intolerably\nvivid dreams of the night, which, resuming his own intense thoughts\nthrough the day, carried them on amid a clashing of phrensies, and\nwhirled them round and round and round in his blazing brain, till\nthe very throbbing of his life-spot became insufferable anguish; and\nwhen, as was sometimes the case, these spiritual throes in him heaved\nhis being up from its base, and a chasm seemed opening in him, from\nwhich forked flames and lightnings shot up, and accursed fiends\nbeckoned him to leap down among them; when this hell in himself\nyawned beneath him, a wild cry would be heard through the ship; and\nwith glaring eyes Ahab would burst from his state room, as though\nescaping from a bed that was on fire.  Yet these, perhaps, instead of\nbeing the unsuppressable symptoms of some latent weakness, or fright\nat his own resolve, were but the plainest tokens of its intensity.\nFor, at such times, crazy Ahab, the scheming, unappeasedly steadfast\nhunter of the white whale; this Ahab that had gone to his hammock,\nwas not the agent that so caused him to burst from it in horror\nagain.  The latter was the eternal, living principle or soul in him;\nand in sleep, being for the time dissociated from the characterizing\nmind, which at other times employed it for its outer vehicle or\nagent, it spontaneously sought escape from the scorching contiguity\nof the frantic thing, of which, for the time, it was no longer an\nintegral.  But as the mind does not exist unless leagued with the\nsoul, therefore it must have been that, in Ahab's case, yielding up\nall his thoughts and fancies to his one supreme purpose; that\npurpose, by its own sheer inveteracy of will, forced itself against\ngods and devils into a kind of self-assumed, independent being of its\nown.  Nay, could grimly live and burn, while the common vitality to\nwhich it was conjoined, fled horror-stricken from the unbidden and\nunfathered birth.  Therefore, the tormented spirit that glared out of\nbodily eyes, when what seemed Ahab rushed from his room, was for the\ntime but a vacated thing, a formless somnambulistic being, a ray of\nliving light, to be sure, but without an object to colour, and\ntherefore a blankness in itself.  God help thee, old man, thy\nthoughts have created a creature in thee; and he whose intense\nthinking thus makes him a Prometheus; a vulture feeds upon that heart\nfor ever; that vulture the very creature he creates.\n\n\n\nCHAPTER 45\n\nThe Affidavit.\n\n\nSo far as what there may be of a narrative in this book; and, indeed,\nas indirectly touching one or two very interesting and curious\nparticulars in the habits of sperm whales, the foregoing chapter, in\nits earlier part, is as important a one as will be found in this\nvolume; but the leading matter of it requires to be still further and\nmore familiarly enlarged upon, in order to be adequately understood,\nand moreover to take away any incredulity which a profound ignorance\nof the entire subject may induce in some minds, as to the natural\nverity of the main points of this affair.\n\nI care not to perform this part of my task methodically; but shall be\ncontent to produce the desired impression by separate citations of\nitems, practically or reliably known to me as a whaleman; and from\nthese citations, I take it--the conclusion aimed at will naturally\nfollow of itself.\n\nFirst: I have personally known three instances where a whale, after\nreceiving a harpoon, has effected a complete escape; and, after an\ninterval (in one instance of three years), has been again struck by\nthe same hand, and slain; when the two irons, both marked by the same\nprivate cypher, have been taken from the body.  In the instance where\nthree years intervened between the flinging of the two harpoons; and\nI think it may have been something more than that; the man who darted\nthem happening, in the interval, to go in a trading ship on a voyage\nto Africa, went ashore there, joined a discovery party, and\npenetrated far into the interior, where he travelled for a period of\nnearly two years, often endangered by serpents, savages, tigers,\npoisonous miasmas, with all the other common perils incident to\nwandering in the heart of unknown regions.  Meanwhile, the whale he\nhad struck must also have been on its travels; no doubt it had thrice\ncircumnavigated the globe, brushing with its flanks all the coasts of\nAfrica; but to no purpose.  This man and this whale again came\ntogether, and the one vanquished the other.  I say I, myself, have\nknown three instances similar to this; that is in two of them I saw\nthe whales struck; and, upon the second attack, saw the two irons\nwith the respective marks cut in them, afterwards taken from the dead\nfish.  In the three-year instance, it so fell out that I was in the\nboat both times, first and last, and the last time distinctly\nrecognised a peculiar sort of huge mole under the whale's eye, which\nI had observed there three years previous.  I say three years, but I\nam pretty sure it was more than that.  Here are three instances,\nthen, which I personally know the truth of; but I have heard of many\nother instances from persons whose veracity in the matter there is no\ngood ground to impeach.\n\nSecondly: It is well known in the Sperm Whale Fishery, however\nignorant the world ashore may be of it, that there have been several\nmemorable historical instances where a particular whale in the ocean\nhas been at distant times and places popularly cognisable.  Why such\na whale became thus marked was not altogether and originally owing to\nhis bodily peculiarities as distinguished from other whales; for\nhowever peculiar in that respect any chance whale may be, they soon\nput an end to his peculiarities by killing him, and boiling him down\ninto a peculiarly valuable oil.  No: the reason was this: that from\nthe fatal experiences of the fishery there hung a terrible prestige\nof perilousness about such a whale as there did about Rinaldo\nRinaldini, insomuch that most fishermen were content to recognise him\nby merely touching their tarpaulins when he would be discovered\nlounging by them on the sea, without seeking to cultivate a more\nintimate acquaintance.  Like some poor devils ashore that happen to\nknow an irascible great man, they make distant unobtrusive\nsalutations to him in the street, lest if they pursued the\nacquaintance further, they might receive a summary thump for their\npresumption.\n\nBut not only did each of these famous whales enjoy great individual\ncelebrity--Nay, you may call it an ocean-wide renown; not only was he\nfamous in life and now is immortal in forecastle stories after death,\nbut he was admitted into all the rights, privileges, and distinctions\nof a name; had as much a name indeed as Cambyses or Caesar.  Was it\nnot so, O Timor Tom! thou famed leviathan, scarred like an iceberg,\nwho so long did'st lurk in the Oriental straits of that name, whose\nspout was oft seen from the palmy beach of Ombay?  Was it not so, O\nNew Zealand Jack! thou terror of all cruisers that crossed their\nwakes in the vicinity of the Tattoo Land?  Was it not so, O Morquan!\nKing of Japan, whose lofty jet they say at times assumed the\nsemblance of a snow-white cross against the sky?  Was it not so, O\nDon Miguel! thou Chilian whale, marked like an old tortoise with\nmystic hieroglyphics upon the back!  In plain prose, here are four\nwhales as well known to the students of Cetacean History as Marius or\nSylla to the classic scholar.\n\nBut this is not all.  New Zealand Tom and Don Miguel, after at\nvarious times creating great havoc among the boats of different\nvessels, were finally gone in quest of, systematically hunted out,\nchased and killed by valiant whaling captains, who heaved up their\nanchors with that express object as much in view, as in setting out\nthrough the Narragansett Woods, Captain Butler of old had it in his\nmind to capture that notorious murderous savage Annawon, the headmost\nwarrior of the Indian King Philip.\n\nI do not know where I can find a better place than just here, to make\nmention of one or two other things, which to me seem important, as in\nprinted form establishing in all respects the reasonableness of the\nwhole story of the White Whale, more especially the catastrophe.  For\nthis is one of those disheartening instances where truth requires\nfull as much bolstering as error.  So ignorant are most landsmen of\nsome of the plainest and most palpable wonders of the world, that\nwithout some hints touching the plain facts, historical and\notherwise, of the fishery, they might scout at Moby Dick as a\nmonstrous fable, or still worse and more detestable, a hideous and\nintolerable allegory.\n\nFirst: Though most men have some vague flitting ideas of the general\nperils of the grand fishery, yet they have nothing like a fixed,\nvivid conception of those perils, and the frequency with which they\nrecur.  One reason perhaps is, that not one in fifty of the actual\ndisasters and deaths by casualties in the fishery, ever finds a\npublic record at home, however transient and immediately forgotten\nthat record.  Do you suppose that that poor fellow there, who this\nmoment perhaps caught by the whale-line off the coast of New Guinea,\nis being carried down to the bottom of the sea by the sounding\nleviathan--do you suppose that that poor fellow's name will appear in\nthe newspaper obituary you will read to-morrow at your breakfast?\nNo: because the mails are very irregular between here and New Guinea.\nIn fact, did you ever hear what might be called regular news direct\nor indirect from New Guinea?  Yet I tell you that upon one particular\nvoyage which I made to the Pacific, among many others we spoke thirty\ndifferent ships, every one of which had had a death by a whale, some\nof them more than one, and three that had each lost a boat's crew.\nFor God's sake, be economical with your lamps and candles! not a\ngallon you burn, but at least one drop of man's blood was spilled for\nit.\n\nSecondly: People ashore have indeed some indefinite idea that a whale\nis an enormous creature of enormous power; but I have ever found that\nwhen narrating to them some specific example of this two-fold\nenormousness, they have significantly complimented me upon my\nfacetiousness; when, I declare upon my soul, I had no more idea of\nbeing facetious than Moses, when he wrote the history of the plagues\nof Egypt.\n\nBut fortunately the special point I here seek can be established upon\ntestimony entirely independent of my own.  That point is this: The\nSperm Whale is in some cases sufficiently powerful, knowing, and\njudiciously malicious, as with direct aforethought to stave in,\nutterly destroy, and sink a large ship; and what is more, the Sperm\nWhale HAS done it.\n\nFirst: In the year 1820 the ship Essex, Captain Pollard, of\nNantucket, was cruising in the Pacific Ocean.  One day she saw\nspouts, lowered her boats, and gave chase to a shoal of sperm whales.\nEre long, several of the whales were wounded; when, suddenly, a very\nlarge whale escaping from the boats, issued from the shoal, and bore\ndirectly down upon the ship.  Dashing his forehead against her hull,\nhe so stove her in, that in less than \"ten minutes\" she settled down\nand fell over.  Not a surviving plank of her has been seen since.\nAfter the severest exposure, part of the crew reached the land in\ntheir boats.  Being returned home at last, Captain Pollard once more\nsailed for the Pacific in command of another ship, but the gods\nshipwrecked him again upon unknown rocks and breakers; for the second\ntime his ship was utterly lost, and forthwith forswearing the sea, he\nhas never tempted it since.  At this day Captain Pollard is a\nresident of Nantucket.  I have seen Owen Chace, who was chief mate of\nthe Essex at the time of the tragedy; I have read his plain and\nfaithful narrative; I have conversed with his son; and all this\nwithin a few miles of the scene of the catastrophe.*\n\n\n*The following are extracts from Chace's narrative: \"Every fact\nseemed to warrant me in concluding that it was anything but chance\nwhich directed his operations; he made two several attacks upon the\nship, at a short interval between them, both of which, according to\ntheir direction, were calculated to do us the most injury, by being\nmade ahead, and thereby combining the speed of the two objects for\nthe shock; to effect which, the exact manoeuvres which he made were\nnecessary.  His aspect was most horrible, and such as indicated\nresentment and fury.  He came directly from the shoal which we had\njust before entered, and in which we had struck three of his\ncompanions, as if fired with revenge for their sufferings.\"  Again:\n\"At all events, the whole circumstances taken together, all happening\nbefore my own eyes, and producing, at the time, impressions in my\nmind of decided, calculating mischief, on the part of the whale (many\nof which impressions I cannot now recall), induce me to be satisfied\nthat I am correct in my opinion.\"\n\nHere are his reflections some time after quitting the ship, during a\nblack night an open boat, when almost despairing of reaching any\nhospitable shore.  \"The dark ocean and swelling waters were nothing;\nthe fears of being swallowed up by some dreadful tempest, or dashed\nupon hidden rocks, with all the other ordinary subjects of fearful\ncontemplation, seemed scarcely entitled to a moment's thought; the\ndismal looking wreck, and THE HORRID ASPECT AND REVENGE OF THE WHALE,\nwholly engrossed my reflections, until day again made its\nappearance.\"\n\nIn another place--p. 45,--he speaks of \"THE MYSTERIOUS AND MORTAL\nATTACK OF THE ANIMAL.\"\n\n\nSecondly: The ship Union, also of Nantucket, was in the year 1807\ntotally lost off the Azores by a similar onset, but the authentic\nparticulars of this catastrophe I have never chanced to encounter,\nthough from the whale hunters I have now and then heard casual\nallusions to it.\n\nThirdly: Some eighteen or twenty years ago Commodore J---, then\ncommanding an American sloop-of-war of the first class, happened to\nbe dining with a party of whaling captains, on board a Nantucket ship\nin the harbor of Oahu, Sandwich Islands.  Conversation turning upon\nwhales, the Commodore was pleased to be sceptical touching the\namazing strength ascribed to them by the professional gentlemen\npresent.  He peremptorily denied for example, that any whale could so\nsmite his stout sloop-of-war as to cause her to leak so much as a\nthimbleful.  Very good; but there is more coming.  Some weeks after,\nthe Commodore set sail in this impregnable craft for Valparaiso.  But\nhe was stopped on the way by a portly sperm whale, that begged a few\nmoments' confidential business with him.  That business consisted in\nfetching the Commodore's craft such a thwack, that with all his pumps\ngoing he made straight for the nearest port to heave down and repair.\nI am not superstitious, but I consider the Commodore's interview\nwith that whale as providential.  Was not Saul of Tarsus converted\nfrom unbelief by a similar fright?  I tell you, the sperm whale will\nstand no nonsense.\n\nI will now refer you to Langsdorff's Voyages for a little\ncircumstance in point, peculiarly interesting to the writer hereof.\nLangsdorff, you must know by the way, was attached to the Russian\nAdmiral Krusenstern's famous Discovery Expedition in the beginning of\nthe present century.  Captain Langsdorff thus begins his seventeenth\nchapter:\n\n\"By the thirteenth of May our ship was ready to sail, and the next\nday we were out in the open sea, on our way to Ochotsh.  The weather\nwas very clear and fine, but so intolerably cold that we were obliged\nto keep on our fur clothing.  For some days we had very little wind;\nit was not till the nineteenth that a brisk gale from the northwest\nsprang up.  An uncommon large whale, the body of which was larger\nthan the ship itself, lay almost at the surface of the water, but was\nnot perceived by any one on board till the moment when the ship,\nwhich was in full sail, was almost upon him, so that it was\nimpossible to prevent its striking against him.  We were thus placed\nin the most imminent danger, as this gigantic creature, setting up\nits back, raised the ship three feet at least out of the water.  The\nmasts reeled, and the sails fell altogether, while we who were below\nall sprang instantly upon the deck, concluding that we had struck\nupon some rock; instead of this we saw the monster sailing off with\nthe utmost gravity and solemnity.  Captain D'Wolf applied immediately\nto the pumps to examine whether or not the vessel had received any\ndamage from the shock, but we found that very happily it had escaped\nentirely uninjured.\"\n\nNow, the Captain D'Wolf here alluded to as commanding the ship in\nquestion, is a New Englander, who, after a long life of unusual\nadventures as a sea-captain, this day resides in the village of\nDorchester near Boston.  I have the honour of being a nephew of his.\nI have particularly questioned him concerning this passage in\nLangsdorff.  He substantiates every word.  The ship, however, was by\nno means a large one: a Russian craft built on the Siberian coast,\nand purchased by my uncle after bartering away the vessel in which he\nsailed from home.\n\nIn that up and down manly book of old-fashioned adventure, so full,\ntoo, of honest wonders--the voyage of Lionel Wafer, one of ancient\nDampier's old chums--I found a little matter set down so like that\njust quoted from Langsdorff, that I cannot forbear inserting it here\nfor a corroborative example, if such be needed.\n\nLionel, it seems, was on his way to \"John Ferdinando,\" as he calls\nthe modern Juan Fernandes.  \"In our way thither,\" he says, \"about\nfour o'clock in the morning, when we were about one hundred and fifty\nleagues from the Main of America, our ship felt a terrible shock,\nwhich put our men in such consternation that they could hardly tell\nwhere they were or what to think; but every one began to prepare for\ndeath.  And, indeed, the shock was so sudden and violent, that we\ntook it for granted the ship had struck against a rock; but when the\namazement was a little over, we cast the lead, and sounded, but found\nno ground.  ....  The suddenness of the shock made the guns leap in\ntheir carriages, and several of the men were shaken out of their\nhammocks.  Captain Davis, who lay with his head on a gun, was thrown\nout of his cabin!\"  Lionel then goes on to impute the shock to an\nearthquake, and seems to substantiate the imputation by stating that\na great earthquake, somewhere about that time, did actually do great\nmischief along the Spanish land.  But I should not much wonder if, in\nthe darkness of that early hour of the morning, the shock was after\nall caused by an unseen whale vertically bumping the hull from\nbeneath.\n\nI might proceed with several more examples, one way or another known\nto me, of the great power and malice at times of the sperm whale.  In\nmore than one instance, he has been known, not only to chase the\nassailing boats back to their ships, but to pursue the ship itself,\nand long withstand all the lances hurled at him from its decks.  The\nEnglish ship Pusie Hall can tell a story on that head; and, as for\nhis strength, let me say, that there have been examples where the\nlines attached to a running sperm whale have, in a calm, been\ntransferred to the ship, and secured there; the whale towing her\ngreat hull through the water, as a horse walks off with a cart.\nAgain, it is very often observed that, if the sperm whale, once\nstruck, is allowed time to rally, he then acts, not so often with\nblind rage, as with wilful, deliberate designs of destruction to his\npursuers; nor is it without conveying some eloquent indication of his\ncharacter, that upon being attacked he will frequently open his\nmouth, and retain it in that dread expansion for several consecutive\nminutes.  But I must be content with only one more and a concluding\nillustration; a remarkable and most significant one, by which you\nwill not fail to see, that not only is the most marvellous event in\nthis book corroborated by plain facts of the present day, but that\nthese marvels (like all marvels) are mere repetitions of the ages; so\nthat for the millionth time we say amen with Solomon--Verily there is\nnothing new under the sun.\n\nIn the sixth Christian century lived Procopius, a Christian\nmagistrate of Constantinople, in the days when Justinian was Emperor\nand Belisarius general.  As many know, he wrote the history of his\nown times, a work every way of uncommon value.  By the best\nauthorities, he has always been considered a most trustworthy and\nunexaggerating historian, except in some one or two particulars, not\nat all affecting the matter presently to be mentioned.\n\nNow, in this history of his, Procopius mentions that, during the term\nof his prefecture at Constantinople, a great sea-monster was captured\nin the neighboring Propontis, or Sea of Marmora, after having\ndestroyed vessels at intervals in those waters for a period of more\nthan fifty years.  A fact thus set down in substantial history cannot\neasily be gainsaid.  Nor is there any reason it should be.  Of what\nprecise species this sea-monster was, is not mentioned.  But as he\ndestroyed ships, as well as for other reasons, he must have been a\nwhale; and I am strongly inclined to think a sperm whale.  And I will\ntell you why.  For a long time I fancied that the sperm whale had\nbeen always unknown in the Mediterranean and the deep waters\nconnecting with it.  Even now I am certain that those seas are not,\nand perhaps never can be, in the present constitution of things, a\nplace for his habitual gregarious resort.  But further investigations\nhave recently proved to me, that in modern times there have been\nisolated instances of the presence of the sperm whale in the\nMediterranean.  I am told, on good authority, that on the Barbary\ncoast, a Commodore Davis of the British navy found the skeleton of a\nsperm whale.  Now, as a vessel of war readily passes through the\nDardanelles, hence a sperm whale could, by the same route, pass out\nof the Mediterranean into the Propontis.\n\nIn the Propontis, as far as I can learn, none of that peculiar\nsubstance called BRIT is to be found, the aliment of the right whale.\nBut I have every reason to believe that the food of the sperm\nwhale--squid or cuttle-fish--lurks at the bottom of that sea, because\nlarge creatures, but by no means the largest of that sort, have been\nfound at its surface.  If, then, you properly put these statements\ntogether, and reason upon them a bit, you will clearly perceive that,\naccording to all human reasoning, Procopius's sea-monster, that for\nhalf a century stove the ships of a Roman Emperor, must in all\nprobability have been a sperm whale.\n\n\n\nCHAPTER 46\n\nSurmises.\n\n\nThough, consumed with the hot fire of his purpose, Ahab in all his\nthoughts and actions ever had in view the ultimate capture of Moby\nDick; though he seemed ready to sacrifice all mortal interests to\nthat one passion; nevertheless it may have been that he was by nature\nand long habituation far too wedded to a fiery whaleman's ways,\naltogether to abandon the collateral prosecution of the voyage.  Or\nat least if this were otherwise, there were not wanting other motives\nmuch more influential with him.  It would be refining too much,\nperhaps, even considering his monomania, to hint that his\nvindictiveness towards the White Whale might have possibly extended\nitself in some degree to all sperm whales, and that the more monsters\nhe slew by so much the more he multiplied the chances that each\nsubsequently encountered whale would prove to be the hated one he\nhunted.  But if such an hypothesis be indeed exceptionable, there\nwere still additional considerations which, though not so strictly\naccording with the wildness of his ruling passion, yet were by no\nmeans incapable of swaying him.\n\nTo accomplish his object Ahab must use tools; and of all tools used\nin the shadow of the moon, men are most apt to get out of order.  He\nknew, for example, that however magnetic his ascendency in some\nrespects was over Starbuck, yet that ascendency did not cover the\ncomplete spiritual man any more than mere corporeal superiority\ninvolves intellectual mastership; for to the purely spiritual, the\nintellectual but stand in a sort of corporeal relation.  Starbuck's\nbody and Starbuck's coerced will were Ahab's, so long as Ahab kept\nhis magnet at Starbuck's brain; still he knew that for all this the\nchief mate, in his soul, abhorred his captain's quest, and could he,\nwould joyfully disintegrate himself from it, or even frustrate it.\nIt might be that a long interval would elapse ere the White Whale was\nseen.  During that long interval Starbuck would ever be apt to fall\ninto open relapses of rebellion against his captain's leadership,\nunless some ordinary, prudential, circumstantial influences were\nbrought to bear upon him.  Not only that, but the subtle insanity of\nAhab respecting Moby Dick was noways more significantly manifested\nthan in his superlative sense and shrewdness in foreseeing that, for\nthe present, the hunt should in some way be stripped of that strange\nimaginative impiousness which naturally invested it; that the full\nterror of the voyage must be kept withdrawn into the obscure\nbackground (for few men's courage is proof against protracted\nmeditation unrelieved by action); that when they stood their long\nnight watches, his officers and men must have some nearer things to\nthink of than Moby Dick.  For however eagerly and impetuously the\nsavage crew had hailed the announcement of his quest; yet all sailors\nof all sorts are more or less capricious and unreliable--they live in\nthe varying outer weather, and they inhale its fickleness--and when\nretained for any object remote and blank in the pursuit, however\npromissory of life and passion in the end, it is above all things\nrequisite that temporary interests and employments should intervene\nand hold them healthily suspended for the final dash.\n\nNor was Ahab unmindful of another thing.  In times of strong emotion\nmankind disdain all base considerations; but such times are\nevanescent.  The permanent constitutional condition of the\nmanufactured man, thought Ahab, is sordidness.  Granting that the\nWhite Whale fully incites the hearts of this my savage crew, and\nplaying round their savageness even breeds a certain generous\nknight-errantism in them, still, while for the love of it they give\nchase to Moby Dick, they must also have food for their more common,\ndaily appetites.  For even the high lifted and chivalric Crusaders of\nold times were not content to traverse two thousand miles of land to\nfight for their holy sepulchre, without committing burglaries,\npicking pockets, and gaining other pious perquisites by the way.  Had\nthey been strictly held to their one final and romantic object--that\nfinal and romantic object, too many would have turned from in\ndisgust.  I will not strip these men, thought Ahab, of all hopes of\ncash--aye, cash.  They may scorn cash now; but let some months go by,\nand no perspective promise of it to them, and then this same\nquiescent cash all at once mutinying in them, this same cash would\nsoon cashier Ahab.\n\nNor was there wanting still another precautionary motive more related\nto Ahab personally.  Having impulsively, it is probable, and perhaps\nsomewhat prematurely revealed the prime but private purpose of the\nPequod's voyage, Ahab was now entirely conscious that, in so doing,\nhe had indirectly laid himself open to the unanswerable charge of\nusurpation; and with perfect impunity, both moral and legal, his crew\nif so disposed, and to that end competent, could refuse all further\nobedience to him, and even violently wrest from him the command.\nFrom even the barely hinted imputation of usurpation, and the\npossible consequences of such a suppressed impression gaining ground,\nAhab must of course have been most anxious to protect himself.  That\nprotection could only consist in his own predominating brain and\nheart and hand, backed by a heedful, closely calculating attention to\nevery minute atmospheric influence which it was possible for his crew\nto be subjected to.\n\nFor all these reasons then, and others perhaps too analytic to be\nverbally developed here, Ahab plainly saw that he must still in a\ngood degree continue true to the natural, nominal purpose of the\nPequod's voyage; observe all customary usages; and not only that, but\nforce himself to evince all his well known passionate interest in the\ngeneral pursuit of his profession.\n\nBe all this as it may, his voice was now often heard hailing the\nthree mast-heads and admonishing them to keep a bright look-out, and\nnot omit reporting even a porpoise.  This vigilance was not long\nwithout reward.\n\n\n\nCHAPTER 47\n\nThe Mat-Maker.\n\n\nIt was a cloudy, sultry afternoon; the seamen were lazily lounging\nabout the decks, or vacantly gazing over into the lead-coloured\nwaters.  Queequeg and I were mildly employed weaving what is called a\nsword-mat, for an additional lashing to our boat.  So still and\nsubdued and yet somehow preluding was all the scene, and such an\nincantation of reverie lurked in the air, that each silent sailor\nseemed resolved into his own invisible self.\n\nI was the attendant or page of Queequeg, while busy at the mat.  As I\nkept passing and repassing the filling or woof of marline between the\nlong yarns of the warp, using my own hand for the shuttle, and as\nQueequeg, standing sideways, ever and anon slid his heavy oaken sword\nbetween the threads, and idly looking off upon the water, carelessly\nand unthinkingly drove home every yarn: I say so strange a\ndreaminess did there then reign all over the ship and all over the\nsea, only broken by the intermitting dull sound of the sword, that it\nseemed as if this were the Loom of Time, and I myself were a shuttle\nmechanically weaving and weaving away at the Fates.  There lay the\nfixed threads of the warp subject to but one single, ever returning,\nunchanging vibration, and that vibration merely enough to admit of\nthe crosswise interblending of other threads with its own.  This warp\nseemed necessity; and here, thought I, with my own hand I ply my own\nshuttle and weave my own destiny into these unalterable threads.\nMeantime, Queequeg's impulsive, indifferent sword, sometimes hitting\nthe woof slantingly, or crookedly, or strongly, or weakly, as the\ncase might be; and by this difference in the concluding blow\nproducing a corresponding contrast in the final aspect of the\ncompleted fabric; this savage's sword, thought I, which thus finally\nshapes and fashions both warp and woof; this easy, indifferent sword\nmust be chance--aye, chance, free will, and necessity--nowise\nincompatible--all interweavingly working together.  The straight warp\nof necessity, not to be swerved from its ultimate course--its every\nalternating vibration, indeed, only tending to that; free will still\nfree to ply her shuttle between given threads; and chance, though\nrestrained in its play within the right lines of necessity, and\nsideways in its motions directed by free will, though thus prescribed\nto by both, chance by turns rules either, and has the last featuring\nblow at events.\n\n\nThus we were weaving and weaving away when I started at a sound so\nstrange, long drawn, and musically wild and unearthly, that the ball\nof free will dropped from my hand, and I stood gazing up at the\nclouds whence that voice dropped like a wing.  High aloft in the\ncross-trees was that mad Gay-Header, Tashtego.  His body was reaching\neagerly forward, his hand stretched out like a wand, and at brief\nsudden intervals he continued his cries.  To be sure the same sound\nwas that very moment perhaps being heard all over the seas, from\nhundreds of whalemen's look-outs perched as high in the air; but from\nfew of those lungs could that accustomed old cry have derived such a\nmarvellous cadence as from Tashtego the Indian's.\n\nAs he stood hovering over you half suspended in air, so wildly and\neagerly peering towards the horizon, you would have thought him some\nprophet or seer beholding the shadows of Fate, and by those wild\ncries announcing their coming.\n\n\"There she blows! there! there! there! she blows! she blows!\"\n\n\"Where-away?\"\n\n\"On the lee-beam, about two miles off! a school of them!\"\n\nInstantly all was commotion.\n\nThe Sperm Whale blows as a clock ticks, with the same undeviating and\nreliable uniformity.  And thereby whalemen distinguish this fish from\nother tribes of his genus.\n\n\"There go flukes!\" was now the cry from Tashtego; and the whales\ndisappeared.\n\n\"Quick, steward!\" cried Ahab.  \"Time! time!\"\n\nDough-Boy hurried below, glanced at the watch, and reported the exact\nminute to Ahab.\n\nThe ship was now kept away from the wind, and she went gently rolling\nbefore it.  Tashtego reporting that the whales had gone down heading\nto leeward, we confidently looked to see them again directly in\nadvance of our bows.  For that singular craft at times evinced by the\nSperm Whale when, sounding with his head in one direction, he\nnevertheless, while concealed beneath the surface, mills round, and\nswiftly swims off in the opposite quarter--this deceitfulness of his\ncould not now be in action; for there was no reason to suppose that\nthe fish seen by Tashtego had been in any way alarmed, or indeed knew\nat all of our vicinity.  One of the men selected for\nshipkeepers--that is, those not appointed to the boats, by this time\nrelieved the Indian at the main-mast head.  The sailors at the fore\nand mizzen had come down; the line tubs were fixed in their places;\nthe cranes were thrust out; the mainyard was backed, and the three\nboats swung over the sea like three samphire baskets over high\ncliffs.  Outside of the bulwarks their eager crews with one hand\nclung to the rail, while one foot was expectantly poised on the\ngunwale.  So look the long line of man-of-war's men about to throw\nthemselves on board an enemy's ship.\n\nBut at this critical instant a sudden exclamation was heard that took\nevery eye from the whale.  With a start all glared at dark Ahab, who\nwas surrounded by five dusky phantoms that seemed fresh formed out of\nair.\n\n\n\nCHAPTER 48\n\nThe First Lowering.\n\n\nThe phantoms, for so they then seemed, were flitting on the other\nside of the deck, and, with a noiseless celerity, were casting loose\nthe tackles and bands of the boat which swung there.  This boat had\nalways been deemed one of the spare boats, though technically called\nthe captain's, on account of its hanging from the starboard quarter.\nThe figure that now stood by its bows was tall and swart, with one\nwhite tooth evilly protruding from its steel-like lips.  A rumpled\nChinese jacket of black cotton funereally invested him, with wide\nblack trowsers of the same dark stuff.  But strangely crowning this\nebonness was a glistening white plaited turban, the living hair\nbraided and coiled round and round upon his head.  Less swart in\naspect, the companions of this figure were of that vivid,\ntiger-yellow complexion peculiar to some of the aboriginal natives of\nthe Manillas;--a race notorious for a certain diabolism of subtilty,\nand by some honest white mariners supposed to be the paid spies and\nsecret confidential agents on the water of the devil, their lord,\nwhose counting-room they suppose to be elsewhere.\n\nWhile yet the wondering ship's company were gazing upon these\nstrangers, Ahab cried out to the white-turbaned old man at their\nhead, \"All ready there, Fedallah?\"\n\n\"Ready,\" was the half-hissed reply.\n\n\"Lower away then; d'ye hear?\" shouting across the deck.  \"Lower away\nthere, I say.\"\n\nSuch was the thunder of his voice, that spite of their amazement the\nmen sprang over the rail; the sheaves whirled round in the blocks;\nwith a wallow, the three boats dropped into the sea; while, with a\ndexterous, off-handed daring, unknown in any other vocation, the\nsailors, goat-like, leaped down the rolling ship's side into the\ntossed boats below.\n\nHardly had they pulled out from under the ship's lee, when a fourth\nkeel, coming from the windward side, pulled round under the stern,\nand showed the five strangers rowing Ahab, who, standing erect in the\nstern, loudly hailed Starbuck, Stubb, and Flask, to spread themselves\nwidely, so as to cover a large expanse of water.  But with all their\neyes again riveted upon the swart Fedallah and his crew, the inmates\nof the other boats obeyed not the command.\n\n\"Captain Ahab?--\" said Starbuck.\n\n\"Spread yourselves,\" cried Ahab; \"give way, all four boats.  Thou,\nFlask, pull out more to leeward!\"\n\n\"Aye, aye, sir,\" cheerily cried little King-Post, sweeping round his\ngreat steering oar.  \"Lay back!\" addressing his crew.\n\"There!--there!--there again!  There she blows right ahead,\nboys!--lay back!\"\n\n\"Never heed yonder yellow boys, Archy.\"\n\n\"Oh, I don't mind'em, sir,\" said Archy; \"I knew it all before now.\nDidn't I hear 'em in the hold?  And didn't I tell Cabaco here of it?\nWhat say ye, Cabaco?  They are stowaways, Mr. Flask.\"\n\n\"Pull, pull, my fine hearts-alive; pull, my children; pull, my little\nones,\" drawlingly and soothingly sighed Stubb to his crew, some of\nwhom still showed signs of uneasiness.  \"Why don't you break your\nbackbones, my boys?  What is it you stare at?  Those chaps in yonder\nboat?  Tut!  They are only five more hands come to help us--never\nmind from where--the more the merrier.  Pull, then, do pull; never\nmind the brimstone--devils are good fellows enough.  So, so; there\nyou are now; that's the stroke for a thousand pounds; that's the\nstroke to sweep the stakes!  Hurrah for the gold cup of sperm oil, my\nheroes!  Three cheers, men--all hearts alive!  Easy, easy; don't be\nin a hurry--don't be in a hurry.  Why don't you snap your oars, you\nrascals?  Bite something, you dogs!  So, so, so, then:--softly,\nsoftly!  That's it--that's it! long and strong.  Give way there, give\nway!  The devil fetch ye, ye ragamuffin rapscallions; ye are all\nasleep.  Stop snoring, ye sleepers, and pull.  Pull, will ye? pull,\ncan't ye? pull, won't ye?  Why in the name of gudgeons and\nginger-cakes don't ye pull?--pull and break something! pull, and\nstart your eyes out!  Here!\" whipping out the sharp knife from his\ngirdle; \"every mother's son of ye draw his knife, and pull with the\nblade between his teeth.  That's it--that's it.  Now ye do something;\nthat looks like it, my steel-bits.  Start her--start her, my\nsilver-spoons!  Start her, marling-spikes!\"\n\nStubb's exordium to his crew is given here at large, because he had\nrather a peculiar way of talking to them in general, and especially\nin inculcating the religion of rowing.  But you must not suppose from\nthis specimen of his sermonizings that he ever flew into downright\npassions with his congregation.  Not at all; and therein consisted\nhis chief peculiarity.  He would say the most terrific things to his\ncrew, in a tone so strangely compounded of fun and fury, and the fury\nseemed so calculated merely as a spice to the fun, that no oarsman\ncould hear such queer invocations without pulling for dear life, and\nyet pulling for the mere joke of the thing.  Besides he all the time\nlooked so easy and indolent himself, so loungingly managed his\nsteering-oar, and so broadly gaped--open-mouthed at times--that the\nmere sight of such a yawning commander, by sheer force of contrast,\nacted like a charm upon the crew.  Then again, Stubb was one of those\nodd sort of humorists, whose jollity is sometimes so curiously\nambiguous, as to put all inferiors on their guard in the matter of\nobeying them.\n\nIn obedience to a sign from Ahab, Starbuck was now pulling obliquely\nacross Stubb's bow; and when for a minute or so the two boats were\npretty near to each other, Stubb hailed the mate.\n\n\"Mr. Starbuck! larboard boat there, ahoy! a word with ye, sir, if ye\nplease!\"\n\n\"Halloa!\" returned Starbuck, turning round not a single inch as he\nspoke; still earnestly but whisperingly urging his crew; his face set\nlike a flint from Stubb's.\n\n\"What think ye of those yellow boys, sir!\n\n\"Smuggled on board, somehow, before the ship sailed. (Strong, strong,\nboys!)\" in a whisper to his crew, then speaking out loud again: \"A\nsad business, Mr. Stubb! (seethe her, seethe her, my lads!) but never\nmind, Mr. Stubb, all for the best.  Let all your crew pull strong,\ncome what will. (Spring, my men, spring!) There's hogsheads of sperm\nahead, Mr. Stubb, and that's what ye came for. (Pull, my boys!)\nSperm, sperm's the play!  This at least is duty; duty and profit hand\nin hand.\"\n\n\"Aye, aye, I thought as much,\" soliloquized Stubb, when the boats\ndiverged, \"as soon as I clapt eye on 'em, I thought so.  Aye, and\nthat's what he went into the after hold for, so often, as Dough-Boy\nlong suspected.  They were hidden down there.  The White Whale's at\nthe bottom of it.  Well, well, so be it!  Can't be helped!  All\nright!  Give way, men!  It ain't the White Whale to-day!  Give way!\"\n\nNow the advent of these outlandish strangers at such a critical\ninstant as the lowering of the boats from the deck, this had not\nunreasonably awakened a sort of superstitious amazement in some of\nthe ship's company; but Archy's fancied discovery having some time\nprevious got abroad among them, though indeed not credited then, this\nhad in some small measure prepared them for the event.  It took off\nthe extreme edge of their wonder; and so what with all this and\nStubb's confident way of accounting for their appearance, they were\nfor the time freed from superstitious surmisings; though the affair\nstill left abundant room for all manner of wild conjectures as to\ndark Ahab's precise agency in the matter from the beginning.  For me,\nI silently recalled the mysterious shadows I had seen creeping on\nboard the Pequod during the dim Nantucket dawn, as well as the\nenigmatical hintings of the unaccountable Elijah.\n\nMeantime, Ahab, out of hearing of his officers, having sided the\nfurthest to windward, was still ranging ahead of the other boats; a\ncircumstance bespeaking how potent a crew was pulling him.  Those\ntiger yellow creatures of his seemed all steel and whalebone; like\nfive trip-hammers they rose and fell with regular strokes of\nstrength, which periodically started the boat along the water like a\nhorizontal burst boiler out of a Mississippi steamer.  As for\nFedallah, who was seen pulling the harpooneer oar, he had thrown\naside his black jacket, and displayed his naked chest with the whole\npart of his body above the gunwale, clearly cut against the\nalternating depressions of the watery horizon; while at the other end\nof the boat Ahab, with one arm, like a fencer's, thrown half backward\ninto the air, as if to counterbalance any tendency to trip; Ahab was\nseen steadily managing his steering oar as in a thousand boat\nlowerings ere the White Whale had torn him.  All at once the\noutstretched arm gave a peculiar motion and then remained fixed,\nwhile the boat's five oars were seen simultaneously peaked.  Boat and\ncrew sat motionless on the sea.  Instantly the three spread boats in\nthe rear paused on their way.  The whales had irregularly settled\nbodily down into the blue, thus giving no distantly discernible token\nof the movement, though from his closer vicinity Ahab had observed\nit.\n\n\"Every man look out along his oars!\" cried Starbuck.  \"Thou,\nQueequeg, stand up!\"\n\nNimbly springing up on the triangular raised box in the bow, the\nsavage stood erect there, and with intensely eager eyes gazed off\ntowards the spot where the chase had last been descried.  Likewise\nupon the extreme stern of the boat where it was also triangularly\nplatformed level with the gunwale, Starbuck himself was seen coolly\nand adroitly balancing himself to the jerking tossings of his chip of\na craft, and silently eyeing the vast blue eye of the sea.\n\nNot very far distant Flask's boat was also lying breathlessly still;\nits commander recklessly standing upon the top of the loggerhead, a\nstout sort of post rooted in the keel, and rising some two feet above\nthe level of the stern platform.  It is used for catching turns with\nthe whale line.  Its top is not more spacious than the palm of a\nman's hand, and standing upon such a base as that, Flask seemed\nperched at the mast-head of some ship which had sunk to all but her\ntrucks.  But little King-Post was small and short, and at the same\ntime little King-Post was full of a large and tall ambition, so that\nthis loggerhead stand-point of his did by no means satisfy King-Post.\n\n\"I can't see three seas off; tip us up an oar there, and let me on to\nthat.\"\n\nUpon this, Daggoo, with either hand upon the gunwale to steady his\nway, swiftly slid aft, and then erecting himself volunteered his\nlofty shoulders for a pedestal.\n\n\"Good a mast-head as any, sir.  Will you mount?\"\n\n\"That I will, and thank ye very much, my fine fellow; only I wish you\nfifty feet taller.\"\n\nWhereupon planting his feet firmly against two opposite planks of the\nboat, the gigantic negro, stooping a little, presented his flat palm\nto Flask's foot, and then putting Flask's hand on his hearse-plumed\nhead and bidding him spring as he himself should toss, with one\ndexterous fling landed the little man high and dry on his shoulders.\nAnd here was Flask now standing, Daggoo with one lifted arm\nfurnishing him with a breastband to lean against and steady himself\nby.\n\nAt any time it is a strange sight to the tyro to see with what\nwondrous habitude of unconscious skill the whaleman will maintain an\nerect posture in his boat, even when pitched about by the most\nriotously perverse and cross-running seas.  Still more strange to see\nhim giddily perched upon the loggerhead itself, under such\ncircumstances.  But the sight of little Flask mounted upon gigantic\nDaggoo was yet more curious; for sustaining himself with a cool,\nindifferent, easy, unthought of, barbaric majesty, the noble negro to\nevery roll of the sea harmoniously rolled his fine form.  On his\nbroad back, flaxen-haired Flask seemed a snow-flake.  The bearer\nlooked nobler than the rider.  Though truly vivacious, tumultuous,\nostentatious little Flask would now and then stamp with impatience;\nbut not one added heave did he thereby give to the negro's lordly\nchest.  So have I seen Passion and Vanity stamping the living\nmagnanimous earth, but the earth did not alter her tides and her\nseasons for that.\n\nMeanwhile Stubb, the third mate, betrayed no such far-gazing\nsolicitudes.  The whales might have made one of their regular\nsoundings, not a temporary dive from mere fright; and if that were\nthe case, Stubb, as his wont in such cases, it seems, was resolved to\nsolace the languishing interval with his pipe.  He withdrew it from\nhis hatband, where he always wore it aslant like a feather.  He\nloaded it, and rammed home the loading with his thumb-end; but hardly\nhad he ignited his match across the rough sandpaper of his hand,\nwhen Tashtego, his harpooneer, whose eyes had been setting to\nwindward like two fixed stars, suddenly dropped like light from his\nerect attitude to his seat, crying out in a quick phrensy of hurry,\n\"Down, down all, and give way!--there they are!\"\n\nTo a landsman, no whale, nor any sign of a herring, would have been\nvisible at that moment; nothing but a troubled bit of greenish white\nwater, and thin scattered puffs of vapour hovering over it, and\nsuffusingly blowing off to leeward, like the confused scud from white\nrolling billows.  The air around suddenly vibrated and tingled, as it\nwere, like the air over intensely heated plates of iron.  Beneath\nthis atmospheric waving and curling, and partially beneath a thin\nlayer of water, also, the whales were swimming.  Seen in advance of\nall the other indications, the puffs of vapour they spouted, seemed\ntheir forerunning couriers and detached flying outriders.\n\nAll four boats were now in keen pursuit of that one spot of troubled\nwater and air.  But it bade fair to outstrip them; it flew on and on,\nas a mass of interblending bubbles borne down a rapid stream from the\nhills.\n\n\"Pull, pull, my good boys,\" said Starbuck, in the lowest possible but\nintensest concentrated whisper to his men; while the sharp fixed\nglance from his eyes darted straight ahead of the bow, almost seemed\nas two visible needles in two unerring binnacle compasses.  He did\nnot say much to his crew, though, nor did his crew say anything to\nhim.  Only the silence of the boat was at intervals startlingly\npierced by one of his peculiar whispers, now harsh with command, now\nsoft with entreaty.\n\nHow different the loud little King-Post.  \"Sing out and say\nsomething, my hearties.  Roar and pull, my thunderbolts!  Beach me,\nbeach me on their black backs, boys; only do that for me, and I'll\nsign over to you my Martha's Vineyard plantation, boys; including\nwife and children, boys.  Lay me on--lay me on!  O Lord, Lord! but I\nshall go stark, staring mad!  See! see that white water!\"  And so\nshouting, he pulled his hat from his head, and stamped up and down on\nit; then picking it up, flirted it far off upon the sea; and finally\nfell to rearing and plunging in the boat's stern like a crazed colt\nfrom the prairie.\n\n\"Look at that chap now,\" philosophically drawled Stubb, who, with his\nunlighted short pipe, mechanically retained between his teeth, at a\nshort distance, followed after--\"He's got fits, that Flask has.\nFits? yes, give him fits--that's the very word--pitch fits into 'em.\nMerrily, merrily, hearts-alive.  Pudding for supper, you\nknow;--merry's the word.  Pull, babes--pull, sucklings--pull, all.\nBut what the devil are you hurrying about?  Softly, softly, and\nsteadily, my men.  Only pull, and keep pulling; nothing more.  Crack\nall your backbones, and bite your knives in two--that's all.  Take it\neasy--why don't ye take it easy, I say, and burst all your livers and\nlungs!\"\n\nBut what it was that inscrutable Ahab said to that tiger-yellow crew\nof his--these were words best omitted here; for you live under the\nblessed light of the evangelical land.  Only the infidel sharks in\nthe audacious seas may give ear to such words, when, with tornado\nbrow, and eyes of red murder, and foam-glued lips, Ahab leaped after\nhis prey.\n\nMeanwhile, all the boats tore on.  The repeated specific allusions of\nFlask to \"that whale,\" as he called the fictitious monster which he\ndeclared to be incessantly tantalizing his boat's bow with its\ntail--these allusions of his were at times so vivid and life-like,\nthat they would cause some one or two of his men to snatch a fearful\nlook over the shoulder.  But this was against all rule; for the\noarsmen must put out their eyes, and ram a skewer through their\nnecks; usage pronouncing that they must have no organs but ears, and\nno limbs but arms, in these critical moments.\n\nIt was a sight full of quick wonder and awe!  The vast swells of the\nomnipotent sea; the surging, hollow roar they made, as they rolled\nalong the eight gunwales, like gigantic bowls in a boundless\nbowling-green; the brief suspended agony of the boat, as it would tip\nfor an instant on the knife-like edge of the sharper waves, that\nalmost seemed threatening to cut it in two; the sudden profound dip\ninto the watery glens and hollows; the keen spurrings and goadings to\ngain the top of the opposite hill; the headlong, sled-like slide down\nits other side;--all these, with the cries of the headsmen and\nharpooneers, and the shuddering gasps of the oarsmen, with the\nwondrous sight of the ivory Pequod bearing down upon her boats with\noutstretched sails, like a wild hen after her screaming brood;--all\nthis was thrilling.\n\nNot the raw recruit, marching from the bosom of his wife into the\nfever heat of his first battle; not the dead man's ghost encountering\nthe first unknown phantom in the other world;--neither of these can\nfeel stranger and stronger emotions than that man does, who for the\nfirst time finds himself pulling into the charmed, churned circle of\nthe hunted sperm whale.\n\nThe dancing white water made by the chase was now becoming more and\nmore visible, owing to the increasing darkness of the dun\ncloud-shadows flung upon the sea.  The jets of vapour no longer\nblended, but tilted everywhere to right and left; the whales seemed\nseparating their wakes.  The boats were pulled more apart; Starbuck\ngiving chase to three whales running dead to leeward.  Our sail was\nnow set, and, with the still rising wind, we rushed along; the boat\ngoing with such madness through the water, that the lee oars could\nscarcely be worked rapidly enough to escape being torn from the\nrow-locks.\n\nSoon we were running through a suffusing wide veil of mist; neither\nship nor boat to be seen.\n\n\"Give way, men,\" whispered Starbuck, drawing still further aft the\nsheet of his sail; \"there is time to kill a fish yet before the\nsquall comes.  There's white water again!--close to!  Spring!\"\n\nSoon after, two cries in quick succession on each side of us denoted\nthat the other boats had got fast; but hardly were they overheard,\nwhen with a lightning-like hurtling whisper Starbuck said: \"Stand\nup!\" and Queequeg, harpoon in hand, sprang to his feet.\n\nThough not one of the oarsmen was then facing the life and death\nperil so close to them ahead, yet with their eyes on the intense\ncountenance of the mate in the stern of the boat, they knew that the\nimminent instant had come; they heard, too, an enormous wallowing\nsound as of fifty elephants stirring in their litter.  Meanwhile the\nboat was still booming through the mist, the waves curling and\nhissing around us like the erected crests of enraged serpents.\n\n\"That's his hump.  THERE, THERE, give it to him!\" whispered Starbuck.\n\nA short rushing sound leaped out of the boat; it was the darted iron\nof Queequeg.  Then all in one welded commotion came an invisible push\nfrom astern, while forward the boat seemed striking on a ledge; the\nsail collapsed and exploded; a gush of scalding vapour shot up near\nby; something rolled and tumbled like an earthquake beneath us.  The\nwhole crew were half suffocated as they were tossed helter-skelter\ninto the white curdling cream of the squall.  Squall, whale, and\nharpoon had all blended together; and the whale, merely grazed by the\niron, escaped.\n\nThough completely swamped, the boat was nearly unharmed.  Swimming\nround it we picked up the floating oars, and lashing them across the\ngunwale, tumbled back to our places.  There we sat up to our knees in\nthe sea, the water covering every rib and plank, so that to our\ndownward gazing eyes the suspended craft seemed a coral boat grown up\nto us from the bottom of the ocean.\n\nThe wind increased to a howl; the waves dashed their bucklers\ntogether; the whole squall roared, forked, and crackled around us\nlike a white fire upon the prairie, in which, unconsumed, we were\nburning; immortal in these jaws of death!  In vain we hailed the\nother boats; as well roar to the live coals down the chimney of a\nflaming furnace as hail those boats in that storm.  Meanwhile the\ndriving scud, rack, and mist, grew darker with the shadows of night;\nno sign of the ship could be seen.  The rising sea forbade all\nattempts to bale out the boat.  The oars were useless as propellers,\nperforming now the office of life-preservers.  So, cutting the\nlashing of the waterproof match keg, after many failures Starbuck\ncontrived to ignite the lamp in the lantern; then stretching it on a\nwaif pole, handed it to Queequeg as the standard-bearer of this\nforlorn hope.  There, then, he sat, holding up that imbecile candle\nin the heart of that almighty forlornness.  There, then, he sat, the\nsign and symbol of a man without faith, hopelessly holding up hope in\nthe midst of despair.\n\nWet, drenched through, and shivering cold, despairing of ship or\nboat, we lifted up our eyes as the dawn came on.  The mist still\nspread over the sea, the empty lantern lay crushed in the bottom of\nthe boat.  Suddenly Queequeg started to his feet, hollowing his hand\nto his ear.  We all heard a faint creaking, as of ropes and yards\nhitherto muffled by the storm.  The sound came nearer and nearer; the\nthick mists were dimly parted by a huge, vague form.  Affrighted, we\nall sprang into the sea as the ship at last loomed into view, bearing\nright down upon us within a distance of not much more than its\nlength.\n\nFloating on the waves we saw the abandoned boat, as for one instant\nit tossed and gaped beneath the ship's bows like a chip at the base\nof a cataract; and then the vast hull rolled over it, and it was seen\nno more till it came up weltering astern.  Again we swam for it, were\ndashed against it by the seas, and were at last taken up and safely\nlanded on board.  Ere the squall came close to, the other boats had\ncut loose from their fish and returned to the ship in good time.  The\nship had given us up, but was still cruising, if haply it might light\nupon some token of our perishing,--an oar or a lance pole.\n\n\n\nCHAPTER 49\n\nThe Hyena.\n\n\nThere are certain queer times and occasions in this strange mixed\naffair we call life when a man takes this whole universe for a vast\npractical joke, though the wit thereof he but dimly discerns, and\nmore than suspects that the joke is at nobody's expense but his own.\nHowever, nothing dispirits, and nothing seems worth while disputing.\nHe bolts down all events, all creeds, and beliefs, and persuasions,\nall hard things visible and invisible, never mind how knobby; as an\nostrich of potent digestion gobbles down bullets and gun flints.  And\nas for small difficulties and worryings, prospects of sudden\ndisaster, peril of life and limb; all these, and death itself, seem\nto him only sly, good-natured hits, and jolly punches in the side\nbestowed by the unseen and unaccountable old joker.  That odd sort of\nwayward mood I am speaking of, comes over a man only in some time of\nextreme tribulation; it comes in the very midst of his earnestness,\nso that what just before might have seemed to him a thing most\nmomentous, now seems but a part of the general joke.  There is\nnothing like the perils of whaling to breed this free and easy sort\nof genial, desperado philosophy; and with it I now regarded this\nwhole voyage of the Pequod, and the great White Whale its object.\n\n\"Queequeg,\" said I, when they had dragged me, the last man, to the\ndeck, and I was still shaking myself in my jacket to fling off the\nwater; \"Queequeg, my fine friend, does this sort of thing often\nhappen?\"  Without much emotion, though soaked through just like me,\nhe gave me to understand that such things did often happen.\n\n\"Mr. Stubb,\" said I, turning to that worthy, who, buttoned up in his\noil-jacket, was now calmly smoking his pipe in the rain; \"Mr. Stubb,\nI think I have heard you say that of all whalemen you ever met, our\nchief mate, Mr. Starbuck, is by far the most careful and prudent.  I\nsuppose then, that going plump on a flying whale with your sail set\nin a foggy squall is the height of a whaleman's discretion?\"\n\n\"Certain.  I've lowered for whales from a leaking ship in a gale off\nCape Horn.\"\n\n\"Mr. Flask,\" said I, turning to little King-Post, who was standing\nclose by; \"you are experienced in these things, and I am not.  Will\nyou tell me whether it is an unalterable law in this fishery, Mr.\nFlask, for an oarsman to break his own back pulling himself\nback-foremost into death's jaws?\"\n\n\"Can't you twist that smaller?\" said Flask.  \"Yes, that's the law.  I\nshould like to see a boat's crew backing water up to a whale face\nforemost.  Ha, ha! the whale would give them squint for squint, mind\nthat!\"\n\nHere then, from three impartial witnesses, I had a deliberate\nstatement of the entire case.  Considering, therefore, that squalls\nand capsizings in the water and consequent bivouacks on the deep,\nwere matters of common occurrence in this kind of life; considering\nthat at the superlatively critical instant of going on to the whale I\nmust resign my life into the hands of him who steered the\nboat--oftentimes a fellow who at that very moment is in his\nimpetuousness upon the point of scuttling the craft with his own\nfrantic stampings; considering that the particular disaster to our\nown particular boat was chiefly to be imputed to Starbuck's driving\non to his whale almost in the teeth of a squall, and considering that\nStarbuck, notwithstanding, was famous for his great heedfulness in\nthe fishery; considering that I belonged to this uncommonly prudent\nStarbuck's boat; and finally considering in what a devil's chase I\nwas implicated, touching the White Whale: taking all things together,\nI say, I thought I might as well go below and make a rough draft of\nmy will.  \"Queequeg,\" said I, \"come along, you shall be my lawyer,\nexecutor, and legatee.\"\n\nIt may seem strange that of all men sailors should be tinkering at\ntheir last wills and testaments, but there are no people in the world\nmore fond of that diversion.  This was the fourth time in my nautical\nlife that I had done the same thing.  After the ceremony was\nconcluded upon the present occasion, I felt all the easier; a stone\nwas rolled away from my heart.  Besides, all the days I should now\nlive would be as good as the days that Lazarus lived after his\nresurrection; a supplementary clean gain of so many months or weeks\nas the case might be.  I survived myself; my death and burial were\nlocked up in my chest.  I looked round me tranquilly and contentedly,\nlike a quiet ghost with a clean conscience sitting inside the bars of\na snug family vault.\n\nNow then, thought I, unconsciously rolling up the sleeves of my\nfrock, here goes for a cool, collected dive at death and destruction,\nand the devil fetch the hindmost.\n\n\n\nCHAPTER 50\n\nAhab's Boat and Crew.  Fedallah.\n\n\n\"Who would have thought it, Flask!\" cried Stubb; \"if I had but one\nleg you would not catch me in a boat, unless maybe to stop the\nplug-hole with my timber toe.  Oh! he's a wonderful old man!\"\n\n\"I don't think it so strange, after all, on that account,\" said\nFlask.  \"If his leg were off at the hip, now, it would be a different\nthing.  That would disable him; but he has one knee, and good part of\nthe other left, you know.\"\n\n\"I don't know that, my little man; I never yet saw him kneel.\"\n\n\nAmong whale-wise people it has often been argued whether, considering\nthe paramount importance of his life to the success of the voyage, it\nis right for a whaling captain to jeopardize that life in the active\nperils of the chase.  So Tamerlane's soldiers often argued with tears\nin their eyes, whether that invaluable life of his ought to be\ncarried into the thickest of the fight.\n\nBut with Ahab the question assumed a modified aspect.  Considering\nthat with two legs man is but a hobbling wight in all times of\ndanger; considering that the pursuit of whales is always under great\nand extraordinary difficulties; that every individual moment, indeed,\nthen comprises a peril; under these circumstances is it wise for any\nmaimed man to enter a whale-boat in the hunt?  As a general thing,\nthe joint-owners of the Pequod must have plainly thought not.\n\nAhab well knew that although his friends at home would think little\nof his entering a boat in certain comparatively harmless vicissitudes\nof the chase, for the sake of being near the scene of action and\ngiving his orders in person, yet for Captain Ahab to have a boat\nactually apportioned to him as a regular headsman in the hunt--above\nall for Captain Ahab to be supplied with five extra men, as that same\nboat's crew, he well knew that such generous conceits never entered the\nheads of the owners of the Pequod.  Therefore he had not solicited a\nboat's crew from them, nor had he in any way hinted his desires on\nthat head.  Nevertheless he had taken private measures of his own\ntouching all that matter.  Until Cabaco's published discovery, the\nsailors had little foreseen it, though to be sure when, after being a\nlittle while out of port, all hands had concluded the customary\nbusiness of fitting the whaleboats for service; when some time after\nthis Ahab was now and then found bestirring himself in the matter of\nmaking thole-pins with his own hands for what was thought to be one\nof the spare boats, and even solicitously cutting the small wooden\nskewers, which when the line is running out are pinned over the\ngroove in the bow: when all this was observed in him, and\nparticularly his solicitude in having an extra coat of sheathing in\nthe bottom of the boat, as if to make it better withstand the pointed\npressure of his ivory limb; and also the anxiety he evinced in\nexactly shaping the thigh board, or clumsy cleat, as it is sometimes\ncalled, the horizontal piece in the boat's bow for bracing the knee\nagainst in darting or stabbing at the whale; when it was observed how\noften he stood up in that boat with his solitary knee fixed in the\nsemi-circular depression in the cleat, and with the carpenter's\nchisel gouged out a little here and straightened it a little there;\nall these things, I say, had awakened much interest and curiosity at\nthe time.  But almost everybody supposed that this particular\npreparative heedfulness in Ahab must only be with a view to the\nultimate chase of Moby Dick; for he had already revealed his\nintention to hunt that mortal monster in person.  But such a\nsupposition did by no means involve the remotest suspicion as to any\nboat's crew being assigned to that boat.\n\nNow, with the subordinate phantoms, what wonder remained soon waned\naway; for in a whaler wonders soon wane.  Besides, now and then such\nunaccountable odds and ends of strange nations come up from the\nunknown nooks and ash-holes of the earth to man these floating\noutlaws of whalers; and the ships themselves often pick up such queer\ncastaway creatures found tossing about the open sea on planks, bits\nof wreck, oars, whaleboats, canoes, blown-off Japanese junks, and\nwhat not; that Beelzebub himself might climb up the side and step\ndown into the cabin to chat with the captain, and it would not create\nany unsubduable excitement in the forecastle.\n\nBut be all this as it may, certain it is that while the subordinate\nphantoms soon found their place among the crew, though still as it\nwere somehow distinct from them, yet that hair-turbaned Fedallah\nremained a muffled mystery to the last.  Whence he came in a mannerly\nworld like this, by what sort of unaccountable tie he soon evinced\nhimself to be linked with Ahab's peculiar fortunes; nay, so far as to\nhave some sort of a half-hinted influence; Heaven knows, but it might\nhave been even authority over him; all this none knew.  But one\ncannot sustain an indifferent air concerning Fedallah.  He was such a\ncreature as civilized, domestic people in the temperate zone only see\nin their dreams, and that but dimly; but the like of whom now and\nthen glide among the unchanging Asiatic communities, especially the\nOriental isles to the east of the continent--those insulated,\nimmemorial, unalterable countries, which even in these modern days\nstill preserve much of the ghostly aboriginalness of earth's primal\ngenerations, when the memory of the first man was a distinct\nrecollection, and all men his descendants, unknowing whence he came,\neyed each other as real phantoms, and asked of the sun and the moon\nwhy they were created and to what end; when though, according to\nGenesis, the angels indeed consorted with the daughters of men, the\ndevils also, add the uncanonical Rabbins, indulged in mundane amours.\n\n\n\nCHAPTER 51\n\nThe Spirit-Spout.\n\n\nDays, weeks passed, and under easy sail, the ivory Pequod had slowly\nswept across four several cruising-grounds; that off the Azores; off\nthe Cape de Verdes; on the Plate (so called), being off the mouth of\nthe Rio de la Plata; and the Carrol Ground, an unstaked, watery\nlocality, southerly from St. Helena.\n\nIt was while gliding through these latter waters that one serene and\nmoonlight night, when all the waves rolled by like scrolls of silver;\nand, by their soft, suffusing seethings, made what seemed a silvery\nsilence, not a solitude; on such a silent night a silvery jet was\nseen far in advance of the white bubbles at the bow.  Lit up by the\nmoon, it looked celestial; seemed some plumed and glittering god\nuprising from the sea.  Fedallah first descried this jet.  For of\nthese moonlight nights, it was his wont to mount to the main-mast\nhead, and stand a look-out there, with the same precision as if it\nhad been day.  And yet, though herds of whales were seen by night,\nnot one whaleman in a hundred would venture a lowering for them.  You\nmay think with what emotions, then, the seamen beheld this old\nOriental perched aloft at such unusual hours; his turban and the\nmoon, companions in one sky.  But when, after spending his uniform\ninterval there for several successive nights without uttering a\nsingle sound; when, after all this silence, his unearthly voice was\nheard announcing that silvery, moon-lit jet, every reclining mariner\nstarted to his feet as if some winged spirit had lighted in the\nrigging, and hailed the mortal crew.  \"There she blows!\"  Had the\ntrump of judgment blown, they could not have quivered more; yet still\nthey felt no terror; rather pleasure.  For though it was a most\nunwonted hour, yet so impressive was the cry, and so deliriously\nexciting, that almost every soul on board instinctively desired a\nlowering.\n\nWalking the deck with quick, side-lunging strides, Ahab commanded the\nt'gallant sails and royals to be set, and every stunsail spread.  The\nbest man in the ship must take the helm.  Then, with every mast-head\nmanned, the piled-up craft rolled down before the wind.  The strange,\nupheaving, lifting tendency of the taffrail breeze filling the\nhollows of so many sails, made the buoyant, hovering deck to feel\nlike air beneath the feet; while still she rushed along, as if two\nantagonistic influences were struggling in her--one to mount direct\nto heaven, the other to drive yawingly to some horizontal goal.  And\nhad you watched Ahab's face that night, you would have thought that\nin him also two different things were warring.  While his one live\nleg made lively echoes along the deck, every stroke of his dead limb\nsounded like a coffin-tap.  On life and death this old man walked.\nBut though the ship so swiftly sped, and though from every eye, like\narrows, the eager glances shot, yet the silvery jet was no more seen\nthat night.  Every sailor swore he saw it once, but not a second\ntime.\n\nThis midnight-spout had almost grown a forgotten thing, when, some\ndays after, lo! at the same silent hour, it was again announced:\nagain it was descried by all; but upon making sail to overtake it,\nonce more it disappeared as if it had never been.  And so it served\nus night after night, till no one heeded it but to wonder at it.\nMysteriously jetted into the clear moonlight, or starlight, as the\ncase might be; disappearing again for one whole day, or two days, or\nthree; and somehow seeming at every distinct repetition to be\nadvancing still further and further in our van, this solitary jet\nseemed for ever alluring us on.\n\nNor with the immemorial superstition of their race, and in accordance\nwith the preternaturalness, as it seemed, which in many things\ninvested the Pequod, were there wanting some of the seamen who swore\nthat whenever and wherever descried; at however remote times, or in\nhowever far apart latitudes and longitudes, that unnearable spout was\ncast by one self-same whale; and that whale, Moby Dick.  For a time,\nthere reigned, too, a sense of peculiar dread at this flitting\napparition, as if it were treacherously beckoning us on and on, in\norder that the monster might turn round upon us, and rend us at last\nin the remotest and most savage seas.\n\nThese temporary apprehensions, so vague but so awful, derived a\nwondrous potency from the contrasting serenity of the weather, in\nwhich, beneath all its blue blandness, some thought there lurked a\ndevilish charm, as for days and days we voyaged along, through seas\nso wearily, lonesomely mild, that all space, in repugnance to our\nvengeful errand, seemed vacating itself of life before our urn-like\nprow.\n\nBut, at last, when turning to the eastward, the Cape winds began\nhowling around us, and we rose and fell upon the long, troubled seas\nthat are there; when the ivory-tusked Pequod sharply bowed to the\nblast, and gored the dark waves in her madness, till, like showers of\nsilver chips, the foam-flakes flew over her bulwarks; then all this\ndesolate vacuity of life went away, but gave place to sights more\ndismal than before.\n\nClose to our bows, strange forms in the water darted hither and\nthither before us; while thick in our rear flew the inscrutable\nsea-ravens.  And every morning, perched on our stays, rows of these\nbirds were seen; and spite of our hootings, for a long time\nobstinately clung to the hemp, as though they deemed our ship some\ndrifting, uninhabited craft; a thing appointed to desolation, and\ntherefore fit roosting-place for their homeless selves.  And heaved\nand heaved, still unrestingly heaved the black sea, as if its vast\ntides were a conscience; and the great mundane soul were in anguish\nand remorse for the long sin and suffering it had bred.\n\nCape of Good Hope, do they call ye?  Rather Cape Tormentoto, as\ncalled of yore; for long allured by the perfidious silences that\nbefore had attended us, we found ourselves launched into this\ntormented sea, where guilty beings transformed into those fowls and\nthese fish, seemed condemned to swim on everlastingly without any\nhaven in store, or beat that black air without any horizon.  But\ncalm, snow-white, and unvarying; still directing its fountain of\nfeathers to the sky; still beckoning us on from before, the solitary\njet would at times be descried.\n\nDuring all this blackness of the elements, Ahab, though assuming for\nthe time the almost continual command of the drenched and dangerous\ndeck, manifested the gloomiest reserve; and more seldom than ever\naddressed his mates.  In tempestuous times like these, after\neverything above and aloft has been secured, nothing more can be done\nbut passively to await the issue of the gale.  Then Captain and crew\nbecome practical fatalists.  So, with his ivory leg inserted into its\naccustomed hole, and with one hand firmly grasping a shroud, Ahab for\nhours and hours would stand gazing dead to windward, while an\noccasional squall of sleet or snow would all but congeal his very\neyelashes together.  Meantime, the crew driven from the forward part\nof the ship by the perilous seas that burstingly broke over its bows,\nstood in a line along the bulwarks in the waist; and the better to\nguard against the leaping waves, each man had slipped himself into a\nsort of bowline secured to the rail, in which he swung as in a\nloosened belt.  Few or no words were spoken; and the silent ship, as\nif manned by painted sailors in wax, day after day tore on through\nall the swift madness and gladness of the demoniac waves.  By night\nthe same muteness of humanity before the shrieks of the ocean\nprevailed; still in silence the men swung in the bowlines; still\nwordless Ahab stood up to the blast.  Even when wearied nature seemed\ndemanding repose he would not seek that repose in his hammock.\nNever could Starbuck forget the old man's aspect, when one night\ngoing down into the cabin to mark how the barometer stood, he saw him\nwith closed eyes sitting straight in his floor-screwed chair; the\nrain and half-melted sleet of the storm from which he had some time\nbefore emerged, still slowly dripping from the unremoved hat and\ncoat.  On the table beside him lay unrolled one of those charts of\ntides and currents which have previously been spoken of.  His lantern\nswung from his tightly clenched hand.  Though the body was erect, the\nhead was thrown back so that the closed eyes were pointed towards the\nneedle of the tell-tale that swung from a beam in the ceiling.*\n\n\n*The cabin-compass is called the tell-tale, because without going to\nthe compass at the helm, the Captain, while below, can inform himself\nof the course of the ship.\n\n\nTerrible old man! thought Starbuck with a shudder, sleeping in this\ngale, still thou steadfastly eyest thy purpose.\n\n\n\nCHAPTER 52\n\nThe Albatross.\n\n\nSouth-eastward from the Cape, off the distant Crozetts, a good\ncruising ground for Right Whalemen, a sail loomed ahead, the Goney\n(Albatross) by name.  As she slowly drew nigh, from my lofty perch at\nthe fore-mast-head, I had a good view of that sight so remarkable to\na tyro in the far ocean fisheries--a whaler at sea, and long absent\nfrom home.\n\nAs if the waves had been fullers, this craft was bleached like the\nskeleton of a stranded walrus.  All down her sides, this spectral\nappearance was traced with long channels of reddened rust, while all\nher spars and her rigging were like the thick branches of trees\nfurred over with hoar-frost.  Only her lower sails were set.  A wild\nsight it was to see her long-bearded look-outs at those three\nmast-heads.  They seemed clad in the skins of beasts, so torn and\nbepatched the raiment that had survived nearly four years of\ncruising.  Standing in iron hoops nailed to the mast, they swayed and\nswung over a fathomless sea; and though, when the ship slowly glided\nclose under our stern, we six men in the air came so nigh to each\nother that we might almost have leaped from the mast-heads of one\nship to those of the other; yet, those forlorn-looking fishermen,\nmildly eyeing us as they passed, said not one word to our own\nlook-outs, while the quarter-deck hail was being heard from below.\n\n\"Ship ahoy!  Have ye seen the White Whale?\"\n\nBut as the strange captain, leaning over the pallid bulwarks, was in\nthe act of putting his trumpet to his mouth, it somehow fell from his\nhand into the sea; and the wind now rising amain, he in vain strove\nto make himself heard without it.  Meantime his ship was still\nincreasing the distance between.  While in various silent ways\nthe seamen of the Pequod were evincing their observance of this\nominous incident at the first mere mention of the White Whale's name\nto another ship, Ahab for a moment paused; it almost seemed as though\nhe would have lowered a boat to board the stranger, had not the\nthreatening wind forbade.  But taking advantage of his windward\nposition, he again seized his trumpet, and knowing by her aspect that\nthe stranger vessel was a Nantucketer and shortly bound home, he\nloudly hailed--\"Ahoy there!  This is the Pequod, bound round the\nworld!  Tell them to address all future letters to the Pacific ocean!\nand this time three years, if I am not at home, tell them to address\nthem to--\"\n\nAt that moment the two wakes were fairly crossed, and instantly,\nthen, in accordance with their singular ways, shoals of small\nharmless fish, that for some days before had been placidly swimming\nby our side, darted away with what seemed shuddering fins, and ranged\nthemselves fore and aft with the stranger's flanks.  Though in the\ncourse of his continual voyagings Ahab must often before have noticed\na similar sight, yet, to any monomaniac man, the veriest trifles\ncapriciously carry meanings.\n\n\"Swim away from me, do ye?\" murmured Ahab, gazing over into the\nwater.  There seemed but little in the words, but the tone conveyed\nmore of deep helpless sadness than the insane old man had ever before\nevinced.  But turning to the steersman, who thus far had been holding\nthe ship in the wind to diminish her headway, he cried out in his old\nlion voice,--\"Up helm!  Keep her off round the world!\"\n\nRound the world!  There is much in that sound to inspire proud\nfeelings; but whereto does all that circumnavigation conduct?  Only\nthrough numberless perils to the very point whence we started, where\nthose that we left behind secure, were all the time before us.\n\nWere this world an endless plain, and by sailing eastward we could\nfor ever reach new distances, and discover sights more sweet and\nstrange than any Cyclades or Islands of King Solomon, then there were\npromise in the voyage.  But in pursuit of those far mysteries we\ndream of, or in tormented chase of that demon phantom that, some time\nor other, swims before all human hearts; while chasing such over this\nround globe, they either lead us on in barren mazes or midway leave\nus whelmed.\n\n\n\nCHAPTER 53\n\nThe Gam.\n\n\nThe ostensible reason why Ahab did not go on board of the whaler we\nhad spoken was this: the wind and sea betokened storms.  But even had\nthis not been the case, he would not after all, perhaps, have boarded\nher--judging by his subsequent conduct on similar occasions--if so it\nhad been that, by the process of hailing, he had obtained a negative\nanswer to the question he put.  For, as it eventually turned out, he\ncared not to consort, even for five minutes, with any stranger\ncaptain, except he could contribute some of that information he so\nabsorbingly sought.  But all this might remain inadequately\nestimated, were not something said here of the peculiar usages of\nwhaling-vessels when meeting each other in foreign seas, and\nespecially on a common cruising-ground.\n\nIf two strangers crossing the Pine Barrens in New York State, or the\nequally desolate Salisbury Plain in England; if casually encountering\neach other in such inhospitable wilds, these twain, for the life of\nthem, cannot well avoid a mutual salutation; and stopping for a\nmoment to interchange the news; and, perhaps, sitting down for a\nwhile and resting in concert: then, how much more natural that upon\nthe illimitable Pine Barrens and Salisbury Plains of the sea, two\nwhaling vessels descrying each other at the ends of the earth--off\nlone Fanning's Island, or the far away King's Mills; how much more\nnatural, I say, that under such circumstances these ships should not\nonly interchange hails, but come into still closer, more friendly and\nsociable contact.  And especially would this seem to be a matter of\ncourse, in the case of vessels owned in one seaport, and whose\ncaptains, officers, and not a few of the men are personally known to\neach other; and consequently, have all sorts of dear domestic things\nto talk about.\n\nFor the long absent ship, the outward-bounder, perhaps, has letters\non board; at any rate, she will be sure to let her have some papers\nof a date a year or two later than the last one on her blurred and\nthumb-worn files.  And in return for that courtesy, the outward-bound\nship would receive the latest whaling intelligence from the\ncruising-ground to which she may be destined, a thing of the utmost\nimportance to her.  And in degree, all this will hold true concerning\nwhaling vessels crossing each other's track on the cruising-ground\nitself, even though they are equally long absent from home.  For one\nof them may have received a transfer of letters from some third, and\nnow far remote vessel; and some of those letters may be for the\npeople of the ship she now meets.  Besides, they would exchange the\nwhaling news, and have an agreeable chat.  For not only would they\nmeet with all the sympathies of sailors, but likewise with all the\npeculiar congenialities arising from a common pursuit and mutually\nshared privations and perils.\n\nNor would difference of country make any very essential difference;\nthat is, so long as both parties speak one language, as is the case\nwith Americans and English.  Though, to be sure, from the small\nnumber of English whalers, such meetings do not very often occur, and\nwhen they do occur there is too apt to be a sort of shyness between\nthem; for your Englishman is rather reserved, and your Yankee, he\ndoes not fancy that sort of thing in anybody but himself.  Besides,\nthe English whalers sometimes affect a kind of metropolitan\nsuperiority over the American whalers; regarding the long, lean\nNantucketer, with his nondescript provincialisms, as a sort of\nsea-peasant.  But where this superiority in the English whalemen\ndoes really consist, it would be hard to say, seeing that the Yankees\nin one day, collectively, kill more whales than all the English,\ncollectively, in ten years.  But this is a harmless little foible in\nthe English whale-hunters, which the Nantucketer does not take much\nto heart; probably, because he knows that he has a few foibles\nhimself.\n\nSo, then, we see that of all ships separately sailing the sea, the\nwhalers have most reason to be sociable--and they are so.  Whereas,\nsome merchant ships crossing each other's wake in the mid-Atlantic,\nwill oftentimes pass on without so much as a single word of\nrecognition, mutually cutting each other on the high seas, like a\nbrace of dandies in Broadway; and all the time indulging, perhaps, in\nfinical criticism upon each other's rig.  As for Men-of-War, when\nthey chance to meet at sea, they first go through such a string of\nsilly bowings and scrapings, such a ducking of ensigns, that there\ndoes not seem to be much right-down hearty good-will and brotherly\nlove about it at all.  As touching Slave-ships meeting, why, they are\nin such a prodigious hurry, they run away from each other as soon as\npossible.  And as for Pirates, when they chance to cross each other's\ncross-bones, the first hail is--\"How many skulls?\"--the same way that\nwhalers hail--\"How many barrels?\"  And that question once answered,\npirates straightway steer apart, for they are infernal villains on\nboth sides, and don't like to see overmuch of each other's villanous\nlikenesses.\n\nBut look at the godly, honest, unostentatious, hospitable, sociable,\nfree-and-easy whaler!  What does the whaler do when she meets another\nwhaler in any sort of decent weather?  She has a \"GAM,\" a thing so\nutterly unknown to all other ships that they never heard of the name\neven; and if by chance they should hear of it, they only grin at it,\nand repeat gamesome stuff about \"spouters\" and \"blubber-boilers,\" and\nsuch like pretty exclamations.  Why it is that all Merchant-seamen,\nand also all Pirates and Man-of-War's men, and Slave-ship sailors,\ncherish such a scornful feeling towards Whale-ships; this is a\nquestion it would be hard to answer.  Because, in the case of\npirates, say, I should like to know whether that profession of theirs\nhas any peculiar glory about it.  It sometimes ends in uncommon\nelevation, indeed; but only at the gallows.  And besides, when a man\nis elevated in that odd fashion, he has no proper foundation for his\nsuperior altitude.  Hence, I conclude, that in boasting himself to be\nhigh lifted above a whaleman, in that assertion the pirate has no\nsolid basis to stand on.\n\nBut what is a GAM?  You might wear out your index-finger running up\nand down the columns of dictionaries, and never find the word.  Dr.\nJohnson never attained to that erudition; Noah Webster's ark does not\nhold it.  Nevertheless, this same expressive word has now for many\nyears been in constant use among some fifteen thousand true born\nYankees.  Certainly, it needs a definition, and should be\nincorporated into the Lexicon.  With that view, let me learnedly\ndefine it.\n\nGAM.  NOUN--A SOCIAL MEETING OF TWO (OR MORE) WHALESHIPS, GENERALLY\nON A CRUISING-GROUND; WHEN, AFTER EXCHANGING HAILS, THEY EXCHANGE\nVISITS BY BOATS' CREWS; THE TWO CAPTAINS REMAINING, FOR THE TIME, ON\nBOARD OF ONE SHIP, AND THE TWO CHIEF MATES ON THE OTHER.\n\nThere is another little item about Gamming which must not be\nforgotten here.  All professions have their own little peculiarities\nof detail; so has the whale fishery.  In a pirate, man-of-war, or\nslave ship, when the captain is rowed anywhere in his boat, he always\nsits in the stern sheets on a comfortable, sometimes cushioned seat\nthere, and often steers himself with a pretty little milliner's\ntiller decorated with gay cords and ribbons.  But the whale-boat has\nno seat astern, no sofa of that sort whatever, and no tiller at all.\nHigh times indeed, if whaling captains were wheeled about the water\non castors like gouty old aldermen in patent chairs.  And as for a\ntiller, the whale-boat never admits of any such effeminacy; and\ntherefore as in gamming a complete boat's crew must leave the ship,\nand hence as the boat steerer or harpooneer is of the number, that\nsubordinate is the steersman upon the occasion, and the captain,\nhaving no place to sit in, is pulled off to his visit all standing\nlike a pine tree.  And often you will notice that being conscious of\nthe eyes of the whole visible world resting on him from the sides of\nthe two ships, this standing captain is all alive to the importance\nof sustaining his dignity by maintaining his legs.  Nor is this any\nvery easy matter; for in his rear is the immense projecting steering\noar hitting him now and then in the small of his back, the after-oar\nreciprocating by rapping his knees in front.  He is thus completely\nwedged before and behind, and can only expand himself sideways by\nsettling down on his stretched legs; but a sudden, violent pitch of\nthe boat will often go far to topple him, because length of\nfoundation is nothing without corresponding breadth.  Merely make a\nspread angle of two poles, and you cannot stand them up.  Then,\nagain, it would never do in plain sight of the world's riveted eyes,\nit would never do, I say, for this straddling captain to be seen\nsteadying himself the slightest particle by catching hold of anything\nwith his hands; indeed, as token of his entire, buoyant self-command,\nhe generally carries his hands in his trowsers' pockets; but perhaps\nbeing generally very large, heavy hands, he carries them there for\nballast.  Nevertheless there have occurred instances, well\nauthenticated ones too, where the captain has been known for an\nuncommonly critical moment or two, in a sudden squall say--to seize\nhold of the nearest oarsman's hair, and hold on there like grim\ndeath.\n\n\n\nCHAPTER 54\n\nThe Town-Ho's Story.\n\n\n(AS TOLD AT THE GOLDEN INN)\n\n\nThe Cape of Good Hope, and all the watery region round about there,\nis much like some noted four corners of a great highway, where you\nmeet more travellers than in any other part.\n\nIt was not very long after speaking the Goney that another\nhomeward-bound whaleman, the Town-Ho,* was encountered.  She was\nmanned almost wholly by Polynesians.  In the short gam that ensued\nshe gave us strong news of Moby Dick.  To some the general interest\nin the White Whale was now wildly heightened by a circumstance of the\nTown-Ho's story, which seemed obscurely to involve with the whale a\ncertain wondrous, inverted visitation of one of those so called\njudgments of God which at times are said to overtake some men.  This\nlatter circumstance, with its own particular accompaniments, forming\nwhat may be called the secret part of the tragedy about to be\nnarrated, never reached the ears of Captain Ahab or his mates.  For\nthat secret part of the story was unknown to the captain of the\nTown-Ho himself.  It was the private property of three confederate\nwhite seamen of that ship, one of whom, it seems, communicated it to\nTashtego with Romish injunctions of secrecy, but the following night\nTashtego rambled in his sleep, and revealed so much of it in that\nway, that when he was wakened he could not well withhold the rest.\nNevertheless, so potent an influence did this thing have on those\nseamen in the Pequod who came to the full knowledge of it, and by\nsuch a strange delicacy, to call it so, were they governed in this\nmatter, that they kept the secret among themselves so that it never\ntranspired abaft the Pequod's main-mast.  Interweaving in its proper\nplace this darker thread with the story as publicly narrated on the\nship, the whole of this strange affair I now proceed to put on\nlasting record.\n\n\n*The ancient whale-cry upon first sighting a whale from the\nmast-head, still used by whalemen in hunting the famous Gallipagos\nterrapin.\n\n\nFor my humor's sake, I shall preserve the style in which I once\nnarrated it at Lima, to a lounging circle of my Spanish friends, one\nsaint's eve, smoking upon the thick-gilt tiled piazza of the Golden\nInn.  Of those fine cavaliers, the young Dons, Pedro and Sebastian,\nwere on the closer terms with me; and hence the interluding questions\nthey occasionally put, and which are duly answered at the time.\n\n\"Some two years prior to my first learning the events which I am\nabout rehearsing to you, gentlemen, the Town-Ho, Sperm Whaler of\nNantucket, was cruising in your Pacific here, not very many days'\nsail eastward from the eaves of this good Golden Inn.  She was\nsomewhere to the northward of the Line.  One morning upon handling\nthe pumps, according to daily usage, it was observed that she made\nmore water in her hold than common.  They supposed a sword-fish had\nstabbed her, gentlemen.  But the captain, having some unusual reason\nfor believing that rare good luck awaited him in those latitudes; and\ntherefore being very averse to quit them, and the leak not being then\nconsidered at all dangerous, though, indeed, they could not find it\nafter searching the hold as low down as was possible in rather heavy\nweather, the ship still continued her cruisings, the mariners working\nat the pumps at wide and easy intervals; but no good luck came; more\ndays went by, and not only was the leak yet undiscovered, but it\nsensibly increased.  So much so, that now taking some alarm, the\ncaptain, making all sail, stood away for the nearest harbor among the\nislands, there to have his hull hove out and repaired.\n\n\"Though no small passage was before her, yet, if the commonest chance\nfavoured, he did not at all fear that his ship would founder by the\nway, because his pumps were of the best, and being periodically\nrelieved at them, those six-and-thirty men of his could easily keep\nthe ship free; never mind if the leak should double on her.  In\ntruth, well nigh the whole of this passage being attended by very\nprosperous breezes, the Town-Ho had all but certainly arrived in\nperfect safety at her port without the occurrence of the least\nfatality, had it not been for the brutal overbearing of Radney, the\nmate, a Vineyarder, and the bitterly provoked vengeance of Steelkilt,\na Lakeman and desperado from Buffalo.\n\n\"'Lakeman!--Buffalo!  Pray, what is a Lakeman, and where is Buffalo?'\nsaid Don Sebastian, rising in his swinging mat of grass.\n\n\"On the eastern shore of our Lake Erie, Don; but--I crave your\ncourtesy--may be, you shall soon hear further of all that.  Now,\ngentlemen, in square-sail brigs and three-masted ships, well-nigh as\nlarge and stout as any that ever sailed out of your old Callao to far\nManilla; this Lakeman, in the land-locked heart of our America, had\nyet been nurtured by all those agrarian freebooting impressions\npopularly connected with the open ocean.  For in their interflowing\naggregate, those grand fresh-water seas of ours,--Erie, and Ontario,\nand Huron, and Superior, and Michigan,--possess an ocean-like\nexpansiveness, with many of the ocean's noblest traits; with many of\nits rimmed varieties of races and of climes.  They contain round\narchipelagoes of romantic isles, even as the Polynesian waters do; in\nlarge part, are shored by two great contrasting nations, as the\nAtlantic is; they furnish long maritime approaches to our numerous\nterritorial colonies from the East, dotted all round their banks;\nhere and there are frowned upon by batteries, and by the goat-like\ncraggy guns of lofty Mackinaw; they have heard the fleet thunderings\nof naval victories; at intervals, they yield their beaches to wild\nbarbarians, whose red painted faces flash from out their peltry\nwigwams; for leagues and leagues are flanked by ancient and unentered\nforests, where the gaunt pines stand like serried lines of kings in\nGothic genealogies; those same woods harboring wild Afric beasts of\nprey, and silken creatures whose exported furs give robes to Tartar\nEmperors; they mirror the paved capitals of Buffalo and Cleveland, as\nwell as Winnebago villages; they float alike the full-rigged merchant\nship, the armed cruiser of the State, the steamer, and the beech\ncanoe; they are swept by Borean and dismasting blasts as direful as\nany that lash the salted wave; they know what shipwrecks are, for out\nof sight of land, however inland, they have drowned full many a\nmidnight ship with all its shrieking crew.  Thus, gentlemen, though\nan inlander, Steelkilt was wild-ocean born, and wild-ocean nurtured;\nas much of an audacious mariner as any.  And for Radney, though in\nhis infancy he may have laid him down on the lone Nantucket beach, to\nnurse at his maternal sea; though in after life he had long followed\nour austere Atlantic and your contemplative Pacific; yet was he quite\nas vengeful and full of social quarrel as the backwoods seaman, fresh\nfrom the latitudes of buck-horn handled bowie-knives.  Yet was this\nNantucketer a man with some good-hearted traits; and this Lakeman, a\nmariner, who though a sort of devil indeed, might yet by inflexible\nfirmness, only tempered by that common decency of human recognition\nwhich is the meanest slave's right; thus treated, this Steelkilt had\nlong been retained harmless and docile.  At all events, he had proved\nso thus far; but Radney was doomed and made mad, and Steelkilt--but,\ngentlemen, you shall hear.\n\n\"It was not more than a day or two at the furthest after pointing her\nprow for her island haven, that the Town-Ho's leak seemed again\nincreasing, but only so as to require an hour or more at the pumps\nevery day.  You must know that in a settled and civilized ocean like\nour Atlantic, for example, some skippers think little of pumping\ntheir whole way across it; though of a still, sleepy night, should\nthe officer of the deck happen to forget his duty in that respect,\nthe probability would be that he and his shipmates would never again\nremember it, on account of all hands gently subsiding to the bottom.\nNor in the solitary and savage seas far from you to the westward,\ngentlemen, is it altogether unusual for ships to keep clanging at\ntheir pump-handles in full chorus even for a voyage of considerable\nlength; that is, if it lie along a tolerably accessible coast, or if\nany other reasonable retreat is afforded them.  It is only when a\nleaky vessel is in some very out of the way part of those waters,\nsome really landless latitude, that her captain begins to feel a\nlittle anxious.\n\n\"Much this way had it been with the Town-Ho; so when her leak was\nfound gaining once more, there was in truth some small concern\nmanifested by several of her company; especially by Radney the mate.\nHe commanded the upper sails to be well hoisted, sheeted home anew,\nand every way expanded to the breeze.  Now this Radney, I suppose,\nwas as little of a coward, and as little inclined to any sort of\nnervous apprehensiveness touching his own person as any fearless,\nunthinking creature on land or on sea that you can conveniently\nimagine, gentlemen.  Therefore when he betrayed this solicitude about\nthe safety of the ship, some of the seamen declared that it was only\non account of his being a part owner in her.  So when they were\nworking that evening at the pumps, there was on this head no small\ngamesomeness slily going on among them, as they stood with their feet\ncontinually overflowed by the rippling clear water; clear as any\nmountain spring, gentlemen--that bubbling from the pumps ran across\nthe deck, and poured itself out in steady spouts at the lee\nscupper-holes.\n\n\"Now, as you well know, it is not seldom the case in this\nconventional world of ours--watery or otherwise; that when a person\nplaced in command over his fellow-men finds one of them to be very\nsignificantly his superior in general pride of manhood, straightway\nagainst that man he conceives an unconquerable dislike and\nbitterness; and if he have a chance he will pull down and pulverize\nthat subaltern's tower, and make a little heap of dust of it.  Be\nthis conceit of mine as it may, gentlemen, at all events Steelkilt\nwas a tall and noble animal with a head like a Roman, and a flowing\ngolden beard like the tasseled housings of your last viceroy's\nsnorting charger; and a brain, and a heart, and a soul in him,\ngentlemen, which had made Steelkilt Charlemagne, had he been born son\nto Charlemagne's father.  But Radney, the mate, was ugly as a mule;\nyet as hardy, as stubborn, as malicious.  He did not love Steelkilt,\nand Steelkilt knew it.\n\n\"Espying the mate drawing near as he was toiling at the pump with the\nrest, the Lakeman affected not to notice him, but unawed, went on\nwith his gay banterings.\n\n\"'Aye, aye, my merry lads, it's a lively leak this; hold a cannikin,\none of ye, and let's have a taste.  By the Lord, it's worth bottling!\nI tell ye what, men, old Rad's investment must go for it! he had\nbest cut away his part of the hull and tow it home.  The fact is,\nboys, that sword-fish only began the job; he's come back again with a\ngang of ship-carpenters, saw-fish, and file-fish, and what not; and\nthe whole posse of 'em are now hard at work cutting and slashing at\nthe bottom; making improvements, I suppose.  If old Rad were here\nnow, I'd tell him to jump overboard and scatter 'em.  They're playing\nthe devil with his estate, I can tell him.  But he's a simple old\nsoul,--Rad, and a beauty too.  Boys, they say the rest of his\nproperty is invested in looking-glasses.  I wonder if he'd give a\npoor devil like me the model of his nose.'\n\n\"'Damn your eyes! what's that pump stopping for?' roared Radney,\npretending not to have heard the sailors' talk.  'Thunder away at\nit!'\n\n'Aye, aye, sir,' said Steelkilt, merry as a cricket.  'Lively, boys,\nlively, now!'  And with that the pump clanged like fifty\nfire-engines; the men tossed their hats off to it, and ere long that\npeculiar gasping of the lungs was heard which denotes the fullest\ntension of life's utmost energies.\n\n\"Quitting the pump at last, with the rest of his band, the Lakeman\nwent forward all panting, and sat himself down on the windlass; his\nface fiery red, his eyes bloodshot, and wiping the profuse sweat from\nhis brow.  Now what cozening fiend it was, gentlemen, that possessed\nRadney to meddle with such a man in that corporeally exasperated\nstate, I know not; but so it happened.  Intolerably striding along\nthe deck, the mate commanded him to get a broom and sweep down the\nplanks, and also a shovel, and remove some offensive matters\nconsequent upon allowing a pig to run at large.\n\n\"Now, gentlemen, sweeping a ship's deck at sea is a piece of\nhousehold work which in all times but raging gales is regularly\nattended to every evening; it has been known to be done in the case\nof ships actually foundering at the time.  Such, gentlemen, is the\ninflexibility of sea-usages and the instinctive love of neatness in\nseamen; some of whom would not willingly drown without first washing\ntheir faces.  But in all vessels this broom business is the\nprescriptive province of the boys, if boys there be aboard.  Besides,\nit was the stronger men in the Town-Ho that had been divided into\ngangs, taking turns at the pumps; and being the most athletic seaman\nof them all, Steelkilt had been regularly assigned captain of one of\nthe gangs; consequently he should have been freed from any trivial\nbusiness not connected with truly nautical duties, such being the\ncase with his comrades.  I mention all these particulars so that you\nmay understand exactly how this affair stood between the two men.\n\n\"But there was more than this: the order about the shovel was almost\nas plainly meant to sting and insult Steelkilt, as though Radney had\nspat in his face.  Any man who has gone sailor in a whale-ship will\nunderstand this; and all this and doubtless much more, the Lakeman\nfully comprehended when the mate uttered his command.  But as he sat\nstill for a moment, and as he steadfastly looked into the mate's\nmalignant eye and perceived the stacks of powder-casks heaped up in\nhim and the slow-match silently burning along towards them; as he\ninstinctively saw all this, that strange forbearance and\nunwillingness to stir up the deeper passionateness in any already\nireful being--a repugnance most felt, when felt at all, by really\nvaliant men even when aggrieved--this nameless phantom feeling,\ngentlemen, stole over Steelkilt.\n\n\"Therefore, in his ordinary tone, only a little broken by the bodily\nexhaustion he was temporarily in, he answered him saying that\nsweeping the deck was not his business, and he would not do it.  And\nthen, without at all alluding to the shovel, he pointed to three\nlads as the customary sweepers; who, not being billeted at the\npumps, had done little or nothing all day.  To this, Radney replied\nwith an oath, in a most domineering and outrageous manner\nunconditionally reiterating his command; meanwhile advancing upon the\nstill seated Lakeman, with an uplifted cooper's club hammer which he\nhad snatched from a cask near by.\n\n\"Heated and irritated as he was by his spasmodic toil at the pumps,\nfor all his first nameless feeling of forbearance the sweating\nSteelkilt could but ill brook this bearing in the mate; but somehow\nstill smothering the conflagration within him, without speaking he\nremained doggedly rooted to his seat, till at last the incensed\nRadney shook the hammer within a few inches of his face, furiously\ncommanding him to do his bidding.\n\n\"Steelkilt rose, and slowly retreating round the windlass, steadily\nfollowed by the mate with his menacing hammer, deliberately repeated\nhis intention not to obey.  Seeing, however, that his forbearance had\nnot the slightest effect, by an awful and unspeakable intimation with\nhis twisted hand he warned off the foolish and infatuated man; but it\nwas to no purpose.  And in this way the two went once slowly round\nthe windlass; when, resolved at last no longer to retreat, bethinking\nhim that he had now forborne as much as comported with his humor, the\nLakeman paused on the hatches and thus spoke to the officer:\n\n\"'Mr. Radney, I will not obey you.  Take that hammer away, or look to\nyourself.'  But the predestinated mate coming still closer to him,\nwhere the Lakeman stood fixed, now shook the heavy hammer within an\ninch of his teeth; meanwhile repeating a string of insufferable\nmaledictions.  Retreating not the thousandth part of an inch;\nstabbing him in the eye with the unflinching poniard of his glance,\nSteelkilt, clenching his right hand behind him and creepingly drawing\nit back, told his persecutor that if the hammer but grazed his cheek\nhe (Steelkilt) would murder him.  But, gentlemen, the fool had been\nbranded for the slaughter by the gods.  Immediately the hammer\ntouched the cheek; the next instant the lower jaw of the mate was\nstove in his head; he fell on the hatch spouting blood like a whale.\n\n\"Ere the cry could go aft Steelkilt was shaking one of the backstays\nleading far aloft to where two of his comrades were standing their\nmastheads.  They were both Canallers.\n\n\"'Canallers!' cried Don Pedro.  'We have seen many whale-ships in our\nharbours, but never heard of your Canallers.  Pardon: who and what are\nthey?'\n\n\"'Canallers, Don, are the boatmen belonging to our grand Erie Canal.\nYou must have heard of it.'\n\n\"'Nay, Senor; hereabouts in this dull, warm, most lazy, and\nhereditary land, we know but little of your vigorous North.'\n\n\"'Aye?  Well then, Don, refill my cup.  Your chicha's very fine; and\nere proceeding further I will tell ye what our Canallers are; for\nsuch information may throw side-light upon my story.'\n\n\"For three hundred and sixty miles, gentlemen, through the entire\nbreadth of the state of New York; through numerous populous cities\nand most thriving villages; through long, dismal, uninhabited swamps,\nand affluent, cultivated fields, unrivalled for fertility; by\nbilliard-room and bar-room; through the holy-of-holies of great\nforests; on Roman arches over Indian rivers; through sun and shade;\nby happy hearts or broken; through all the wide contrasting scenery\nof those noble Mohawk counties; and especially, by rows of snow-white\nchapels, whose spires stand almost like milestones, flows one\ncontinual stream of Venetianly corrupt and often lawless life.\nThere's your true Ashantee, gentlemen; there howl your pagans; where\nyou ever find them, next door to you; under the long-flung shadow,\nand the snug patronising lee of churches.  For by some curious\nfatality, as it is often noted of your metropolitan freebooters that\nthey ever encamp around the halls of justice, so sinners, gentlemen,\nmost abound in holiest vicinities.\n\n\"'Is that a friar passing?' said Don Pedro, looking downwards into\nthe crowded plazza, with humorous concern.\n\n\"'Well for our northern friend, Dame Isabella's Inquisition wanes in\nLima,' laughed Don Sebastian.  'Proceed, Senor.'\n\n\"'A moment!  Pardon!' cried another of the company.  'In the name of\nall us Limeese, I but desire to express to you, sir sailor, that we\nhave by no means overlooked your delicacy in not substituting present\nLima for distant Venice in your corrupt comparison.  Oh! do not bow\nand look surprised; you know the proverb all along this\ncoast--\"Corrupt as Lima.\"  It but bears out your saying, too;\nchurches more plentiful than billiard-tables, and for ever open--and\n\"Corrupt as Lima.\"  So, too, Venice; I have been there; the holy city\nof the blessed evangelist, St. Mark!--St. Dominic, purge it!  Your\ncup!  Thanks: here I refill; now, you pour out again.'\n\n\"Freely depicted in his own vocation, gentlemen, the Canaller would\nmake a fine dramatic hero, so abundantly and picturesquely wicked is\nhe.  Like Mark Antony, for days and days along his green-turfed,\nflowery Nile, he indolently floats, openly toying with his\nred-cheeked Cleopatra, ripening his apricot thigh upon the sunny\ndeck.  But ashore, all this effeminacy is dashed.  The brigandish\nguise which the Canaller so proudly sports; his slouched and\ngaily-ribboned hat betoken his grand features.  A terror to the\nsmiling innocence of the villages through which he floats; his swart\nvisage and bold swagger are not unshunned in cities.  Once a vagabond\non his own canal, I have received good turns from one of these\nCanallers; I thank him heartily; would fain be not ungrateful; but it\nis often one of the prime redeeming qualities of your man of\nviolence, that at times he has as stiff an arm to back a poor\nstranger in a strait, as to plunder a wealthy one.  In sum,\ngentlemen, what the wildness of this canal life is, is emphatically\nevinced by this; that our wild whale-fishery contains so many of its\nmost finished graduates, and that scarce any race of mankind, except\nSydney men, are so much distrusted by our whaling captains.  Nor does\nit at all diminish the curiousness of this matter, that to many\nthousands of our rural boys and young men born along its line, the\nprobationary life of the Grand Canal furnishes the sole transition\nbetween quietly reaping in a Christian corn-field, and recklessly\nploughing the waters of the most barbaric seas.\n\n\"'I see!  I see!' impetuously exclaimed Don Pedro, spilling his\nchicha upon his silvery ruffles.  'No need to travel!  The world's\none Lima.  I had thought, now, that at your temperate North the\ngenerations were cold and holy as the hills.--But the story.'\n\n\"I left off, gentlemen, where the Lakeman shook the backstay.\nHardly had he done so, when he was surrounded by the three junior\nmates and the four harpooneers, who all crowded him to the deck.  But\nsliding down the ropes like baleful comets, the two Canallers rushed\ninto the uproar, and sought to drag their man out of it towards the\nforecastle.  Others of the sailors joined with them in this attempt,\nand a twisted turmoil ensued; while standing out of harm's way, the\nvaliant captain danced up and down with a whale-pike, calling upon\nhis officers to manhandle that atrocious scoundrel, and smoke him\nalong to the quarter-deck.  At intervals, he ran close up to the\nrevolving border of the confusion, and prying into the heart of it\nwith his pike, sought to prick out the object of his resentment.  But\nSteelkilt and his desperadoes were too much for them all; they\nsucceeded in gaining the forecastle deck, where, hastily slewing\nabout three or four large casks in a line with the windlass, these\nsea-Parisians entrenched themselves behind the barricade.\n\n\"'Come out of that, ye pirates!' roared the captain, now menacing\nthem with a pistol in each hand, just brought to him by the steward.\n'Come out of that, ye cut-throats!'\n\n\"Steelkilt leaped on the barricade, and striding up and down there,\ndefied the worst the pistols could do; but gave the captain to\nunderstand distinctly, that his (Steelkilt's) death would be the\nsignal for a murderous mutiny on the part of all hands.  Fearing in\nhis heart lest this might prove but too true, the captain a little\ndesisted, but still commanded the insurgents instantly to return to\ntheir duty.\n\n\"'Will you promise not to touch us, if we do?' demanded their\nringleader.\n\n\"'Turn to! turn to!--I make no promise;--to your duty!  Do you want\nto sink the ship, by knocking off at a time like this?  Turn to!' and\nhe once more raised a pistol.\n\n\"'Sink the ship?' cried Steelkilt.  'Aye, let her sink.  Not a man of\nus turns to, unless you swear not to raise a rope-yarn against us.\nWhat say ye, men?' turning to his comrades.  A fierce cheer was their\nresponse.\n\n\"The Lakeman now patrolled the barricade, all the while keeping his\neye on the Captain, and jerking out such sentences as these:--'It's\nnot our fault; we didn't want it; I told him to take his hammer away;\nit was boy's business; he might have known me before this; I told him\nnot to prick the buffalo; I believe I have broken a finger here\nagainst his cursed jaw; ain't those mincing knives down in the\nforecastle there, men? look to those handspikes, my hearties.\nCaptain, by God, look to yourself; say the word; don't be a fool;\nforget it all; we are ready to turn to; treat us decently, and we're\nyour men; but we won't be flogged.'\n\n\"'Turn to!  I make no promises, turn to, I say!'\n\n\"'Look ye, now,' cried the Lakeman, flinging out his arm towards him,\n'there are a few of us here (and I am one of them) who have shipped\nfor the cruise, d'ye see; now as you well know, sir, we can claim our\ndischarge as soon as the anchor is down; so we don't want a row; it's\nnot our interest; we want to be peaceable; we are ready to work, but\nwe won't be flogged.'\n\n\"'Turn to!' roared the Captain.\n\n\"Steelkilt glanced round him a moment, and then said:--'I tell you\nwhat it is now, Captain, rather than kill ye, and be hung for such a\nshabby rascal, we won't lift a hand against ye unless ye attack us;\nbut till you say the word about not flogging us, we don't do a hand's\nturn.'\n\n\"'Down into the forecastle then, down with ye, I'll keep ye there\ntill ye're sick of it.  Down ye go.'\n\n\"'Shall we?' cried the ringleader to his men.  Most of them were\nagainst it; but at length, in obedience to Steelkilt, they preceded\nhim down into their dark den, growlingly disappearing, like bears\ninto a cave.\n\n\"As the Lakeman's bare head was just level with the planks, the\nCaptain and his posse leaped the barricade, and rapidly drawing over\nthe slide of the scuttle, planted their group of hands upon it, and\nloudly called for the steward to bring the heavy brass padlock\nbelonging to the companionway.\n\nThen opening the slide a little, the Captain whispered something down\nthe crack, closed it, and turned the key upon them--ten in\nnumber--leaving on deck some twenty or more, who thus far had\nremained neutral.\n\n\"All night a wide-awake watch was kept by all the officers, forward\nand aft, especially about the forecastle scuttle and fore hatchway;\nat which last place it was feared the insurgents might emerge, after\nbreaking through the bulkhead below.  But the hours of darkness\npassed in peace; the men who still remained at their duty toiling\nhard at the pumps, whose clinking and clanking at intervals through\nthe dreary night dismally resounded through the ship.\n\n\"At sunrise the Captain went forward, and knocking on the deck,\nsummoned the prisoners to work; but with a yell they refused.  Water\nwas then lowered down to them, and a couple of handfuls of biscuit\nwere tossed after it; when again turning the key upon them and\npocketing it, the Captain returned to the quarter-deck.  Twice every\nday for three days this was repeated; but on the fourth morning a\nconfused wrangling, and then a scuffling was heard, as the customary\nsummons was delivered; and suddenly four men burst up from the\nforecastle, saying they were ready to turn to.  The fetid closeness\nof the air, and a famishing diet, united perhaps to some fears of\nultimate retribution, had constrained them to surrender at\ndiscretion.  Emboldened by this, the Captain reiterated his demand to\nthe rest, but Steelkilt shouted up to him a terrific hint to stop his\nbabbling and betake himself where he belonged.  On the fifth morning\nthree others of the mutineers bolted up into the air from the\ndesperate arms below that sought to restrain them.  Only three were\nleft.\n\n\"'Better turn to, now?' said the Captain with a heartless jeer.\n\n\"'Shut us up again, will ye!' cried Steelkilt.\n\n\"'Oh certainly,' the Captain, and the key clicked.\n\n\"It was at this point, gentlemen, that enraged by the defection of\nseven of his former associates, and stung by the mocking voice that\nhad last hailed him, and maddened by his long entombment in a place\nas black as the bowels of despair; it was then that Steelkilt\nproposed to the two Canallers, thus far apparently of one mind with\nhim, to burst out of their hole at the next summoning of the\ngarrison; and armed with their keen mincing knives (long, crescentic,\nheavy implements with a handle at each end) run amuck from the\nbowsprit to the taffrail; and if by any devilishness of desperation\npossible, seize the ship.  For himself, he would do this, he said,\nwhether they joined him or not.  That was the last night he should\nspend in that den.  But the scheme met with no opposition on the part\nof the other two; they swore they were ready for that, or for any\nother mad thing, for anything in short but a surrender.  And what was\nmore, they each insisted upon being the first man on deck, when the\ntime to make the rush should come.  But to this their leader as\nfiercely objected, reserving that priority for himself; particularly\nas his two comrades would not yield, the one to the other, in the\nmatter; and both of them could not be first, for the ladder would but\nadmit one man at a time.  And here, gentlemen, the foul play of these\nmiscreants must come out.\n\n\"Upon hearing the frantic project of their leader, each in his own\nseparate soul had suddenly lighted, it would seem, upon the same\npiece of treachery, namely: to be foremost in breaking out, in\norder to be the first of the three, though the last of the ten, to\nsurrender; and thereby secure whatever small chance of pardon such\nconduct might merit.  But when Steelkilt made known his determination\nstill to lead them to the last, they in some way, by some subtle\nchemistry of villany, mixed their before secret treacheries together;\nand when their leader fell into a doze, verbally opened their souls\nto each other in three sentences; and bound the sleeper with cords,\nand gagged him with cords; and shrieked out for the Captain at\nmidnight.\n\n\"Thinking murder at hand, and smelling in the dark for the blood, he\nand all his armed mates and harpooneers rushed for the forecastle.\nIn a few minutes the scuttle was opened, and, bound hand and foot,\nthe still struggling ringleader was shoved up into the air by his\nperfidious allies, who at once claimed the honour of securing a man\nwho had been fully ripe for murder.  But all these were collared, and\ndragged along the deck like dead cattle; and, side by side, were\nseized up into the mizzen rigging, like three quarters of meat, and\nthere they hung till morning.  'Damn ye,' cried the Captain, pacing\nto and fro before them, 'the vultures would not touch ye, ye\nvillains!'\n\n\"At sunrise he summoned all hands; and separating those who had\nrebelled from those who had taken no part in the mutiny, he told the\nformer that he had a good mind to flog them all round--thought, upon\nthe whole, he would do so--he ought to--justice demanded it; but for\nthe present, considering their timely surrender, he would let them go\nwith a reprimand, which he accordingly administered in the vernacular.\n\n\"'But as for you, ye carrion rogues,' turning to the three men in the\nrigging--'for you, I mean to mince ye up for the try-pots;' and,\nseizing a rope, he applied it with all his might to the backs of the\ntwo traitors, till they yelled no more, but lifelessly hung their\nheads sideways, as the two crucified thieves are drawn.\n\n\"'My wrist is sprained with ye!' he cried, at last; 'but there is\nstill rope enough left for you, my fine bantam, that wouldn't give\nup.  Take that gag from his mouth, and let us hear what he can say\nfor himself.'\n\n\"For a moment the exhausted mutineer made a tremulous motion of his\ncramped jaws, and then painfully twisting round his head, said in a\nsort of hiss, 'What I say is this--and mind it well--if you flog me,\nI murder you!'\n\n\"'Say ye so? then see how ye frighten me'--and the Captain drew off\nwith the rope to strike.\n\n\"'Best not,' hissed the Lakeman.\n\n\"'But I must,'--and the rope was once more drawn back for the stroke.\n\n\"Steelkilt here hissed out something, inaudible to all but the\nCaptain; who, to the amazement of all hands, started back, paced the\ndeck rapidly two or three times, and then suddenly throwing down his\nrope, said, 'I won't do it--let him go--cut him down: d'ye hear?'\n\nBut as the junior mates were hurrying to execute the order, a pale\nman, with a bandaged head, arrested them--Radney the chief mate.\nEver since the blow, he had lain in his berth; but that morning,\nhearing the tumult on the deck, he had crept out, and thus far had\nwatched the whole scene.  Such was the state of his mouth, that he\ncould hardly speak; but mumbling something about his being willing\nand able to do what the captain dared not attempt, he snatched the\nrope and advanced to his pinioned foe.\n\n\"'You are a coward!' hissed the Lakeman.\n\n\"'So I am, but take that.'  The mate was in the very act of striking,\nwhen another hiss stayed his uplifted arm.  He paused: and then\npausing no more, made good his word, spite of Steelkilt's threat,\nwhatever that might have been.  The three men were then cut down, all\nhands were turned to, and, sullenly worked by the moody seamen, the\niron pumps clanged as before.\n\n\"Just after dark that day, when one watch had retired below, a clamor\nwas heard in the forecastle; and the two trembling traitors running\nup, besieged the cabin door, saying they durst not consort with the\ncrew.  Entreaties, cuffs, and kicks could not drive them back, so at\ntheir own instance they were put down in the ship's run for\nsalvation.  Still, no sign of mutiny reappeared among the rest.  On\nthe contrary, it seemed, that mainly at Steelkilt's instigation, they\nhad resolved to maintain the strictest peacefulness, obey all orders\nto the last, and, when the ship reached port, desert her in a body.\nBut in order to insure the speediest end to the voyage, they all\nagreed to another thing--namely, not to sing out for whales, in case\nany should be discovered.  For, spite of her leak, and spite of all her\nother perils, the Town-Ho still maintained her mast-heads, and her\ncaptain was just as willing to lower for a fish that moment, as on\nthe day his craft first struck the cruising ground; and Radney the mate\nwas quite as ready to change his berth for a boat, and with his\nbandaged mouth seek to gag in death the vital jaw of the whale.\n\n\"But though the Lakeman had induced the seamen to adopt this sort of\npassiveness in their conduct, he kept his own counsel (at least till\nall was over) concerning his own proper and private revenge upon the\nman who had stung him in the ventricles of his heart.  He was in\nRadney the chief mate's watch; and as if the infatuated man sought to\nrun more than half way to meet his doom, after the scene at the\nrigging, he insisted, against the express counsel of the captain,\nupon resuming the head of his watch at night.  Upon this, and one or\ntwo other circumstances, Steelkilt systematically built the plan of\nhis revenge.\n\n\"During the night, Radney had an unseamanlike way of sitting on the\nbulwarks of the quarter-deck, and leaning his arm upon the gunwale of\nthe boat which was hoisted up there, a little above the ship's side.\nIn this attitude, it was well known, he sometimes dozed.  There was a\nconsiderable vacancy between the boat and the ship, and down between\nthis was the sea.  Steelkilt calculated his time, and found that his\nnext trick at the helm would come round at two o'clock, in the\nmorning of the third day from that in which he had been betrayed.  At\nhis leisure, he employed the interval in braiding something very\ncarefully in his watches below.\n\n\"'What are you making there?' said a shipmate.\n\n\"'What do you think? what does it look like?'\n\n\"'Like a lanyard for your bag; but it's an odd one, seems to me.'\n\n'Yes, rather oddish,' said the Lakeman, holding it at arm's length\nbefore him; 'but I think it will answer.  Shipmate, I haven't enough\ntwine,--have you any?'\n\n\"But there was none in the forecastle.\n\n\"'Then I must get some from old Rad;' and he rose to go aft.\n\n\"'You don't mean to go a begging to HIM!' said a sailor.\n\n\"'Why not?  Do you think he won't do me a turn, when it's to help\nhimself in the end, shipmate?' and going to the mate, he looked at\nhim quietly, and asked him for some twine to mend his hammock.  It\nwas given him--neither twine nor lanyard were seen again; but the\nnext night an iron ball, closely netted, partly rolled from the\npocket of the Lakeman's monkey jacket, as he was tucking the coat\ninto his hammock for a pillow.  Twenty-four hours after, his trick at\nthe silent helm--nigh to the man who was apt to doze over the grave\nalways ready dug to the seaman's hand--that fatal hour was then to\ncome; and in the fore-ordaining soul of Steelkilt, the mate was\nalready stark and stretched as a corpse, with his forehead crushed\nin.\n\n\"But, gentlemen, a fool saved the would-be murderer from the bloody\ndeed he had planned.  Yet complete revenge he had, and without being\nthe avenger.  For by a mysterious fatality, Heaven itself seemed to\nstep in to take out of his hands into its own the damning thing he\nwould have done.\n\n\"It was just between daybreak and sunrise of the morning of the\nsecond day, when they were washing down the decks, that a stupid\nTeneriffe man, drawing water in the main-chains, all at once shouted\nout, 'There she rolls! there she rolls!'  Jesu, what a whale!  It was\nMoby Dick.\n\n\"'Moby Dick!' cried Don Sebastian; 'St. Dominic!  Sir sailor, but do\nwhales have christenings?  Whom call you Moby Dick?'\n\n\"'A very white, and famous, and most deadly immortal monster,\nDon;--but that would be too long a story.'\n\n\"'How? how?' cried all the young Spaniards, crowding.\n\n\"'Nay, Dons, Dons--nay, nay!  I cannot rehearse that now.  Let me get\nmore into the air, Sirs.'\n\n\"'The chicha! the chicha!' cried Don Pedro; 'our vigorous friend looks\nfaint;--fill up his empty glass!'\n\n\"No need, gentlemen; one moment, and I proceed.--Now, gentlemen, so\nsuddenly perceiving the snowy whale within fifty yards of the\nship--forgetful of the compact among the crew--in the excitement of\nthe moment, the Teneriffe man had instinctively and involuntarily\nlifted his voice for the monster, though for some little time past it\nhad been plainly beheld from the three sullen mast-heads.  All was\nnow a phrensy.  'The White Whale--the White Whale!' was the cry from\ncaptain, mates, and harpooneers, who, undeterred by fearful rumours,\nwere all anxious to capture so famous and precious a fish; while the\ndogged crew eyed askance, and with curses, the appalling beauty of\nthe vast milky mass, that lit up by a horizontal spangling sun,\nshifted and glistened like a living opal in the blue morning sea.\nGentlemen, a strange fatality pervades the whole career of these\nevents, as if verily mapped out before the world itself was charted.\nThe mutineer was the bowsman of the mate, and when fast to a fish, it\nwas his duty to sit next him, while Radney stood up with his lance in\nthe prow, and haul in or slacken the line, at the word of command.\nMoreover, when the four boats were lowered, the mate's got the start;\nand none howled more fiercely with delight than did Steelkilt, as he\nstrained at his oar.  After a stiff pull, their harpooneer got fast,\nand, spear in hand, Radney sprang to the bow.  He was always a\nfurious man, it seems, in a boat.  And now his bandaged cry was, to\nbeach him on the whale's topmost back.  Nothing loath, his bowsman\nhauled him up and up, through a blinding foam that blent two\nwhitenesses together; till of a sudden the boat struck as against a\nsunken ledge, and keeling over, spilled out the standing mate.  That\ninstant, as he fell on the whale's slippery back, the boat righted,\nand was dashed aside by the swell, while Radney was tossed over into\nthe sea, on the other flank of the whale.  He struck out through the\nspray, and, for an instant, was dimly seen through that veil, wildly\nseeking to remove himself from the eye of Moby Dick.  But the whale\nrushed round in a sudden maelstrom; seized the swimmer between his\njaws; and rearing high up with him, plunged headlong again, and went\ndown.\n\n\"Meantime, at the first tap of the boat's bottom, the Lakeman had\nslackened the line, so as to drop astern from the whirlpool; calmly\nlooking on, he thought his own thoughts.  But a sudden, terrific,\ndownward jerking of the boat, quickly brought his knife to the line.\nHe cut it; and the whale was free.  But, at some distance, Moby Dick\nrose again, with some tatters of Radney's red woollen shirt, caught\nin the teeth that had destroyed him.  All four boats gave chase\nagain; but the whale eluded them, and finally wholly disappeared.\n\n\"In good time, the Town-Ho reached her port--a savage, solitary\nplace--where no civilized creature resided.  There, headed by the\nLakeman, all but five or six of the foremastmen deliberately\ndeserted among the palms; eventually, as it turned out, seizing a\nlarge double war-canoe of the savages, and setting sail for some\nother harbor.\n\n\"The ship's company being reduced to but a handful, the captain\ncalled upon the Islanders to assist him in the laborious business of\nheaving down the ship to stop the leak.  But to such unresting\nvigilance over their dangerous allies was this small band of whites\nnecessitated, both by night and by day, and so extreme was the hard\nwork they underwent, that upon the vessel being ready again for sea,\nthey were in such a weakened condition that the captain durst not put\noff with them in so heavy a vessel.  After taking counsel with his\nofficers, he anchored the ship as far off shore as possible; loaded\nand ran out his two cannon from the bows; stacked his muskets on the\npoop; and warning the Islanders not to approach the ship at their\nperil, took one man with him, and setting the sail of his best\nwhale-boat, steered straight before the wind for Tahiti, five hundred\nmiles distant, to procure a reinforcement to his crew.\n\n\"On the fourth day of the sail, a large canoe was descried, which\nseemed to have touched at a low isle of corals.  He steered away from\nit; but the savage craft bore down on him; and soon the voice of\nSteelkilt hailed him to heave to, or he would run him under water.\nThe captain presented a pistol.  With one foot on each prow of the\nyoked war-canoes, the Lakeman laughed him to scorn; assuring him that\nif the pistol so much as clicked in the lock, he would bury him in\nbubbles and foam.\n\n\"'What do you want of me?' cried the captain.\n\n\"'Where are you bound? and for what are you bound?' demanded\nSteelkilt; 'no lies.'\n\n\"'I am bound to Tahiti for more men.'\n\n\"'Very good.  Let me board you a moment--I come in peace.'  With that\nhe leaped from the canoe, swam to the boat; and climbing the gunwale,\nstood face to face with the captain.\n\n\"'Cross your arms, sir; throw back your head.  Now, repeat after me.\nAs soon as Steelkilt leaves me, I swear to beach this boat on yonder\nisland, and remain there six days.  If I do not, may lightning strike\nme!'\n\n\"'A pretty scholar,' laughed the Lakeman.  'Adios, Senor!' and\nleaping into the sea, he swam back to his comrades.\n\n\"Watching the boat till it was fairly beached, and drawn up to the\nroots of the cocoa-nut trees, Steelkilt made sail again, and in due\ntime arrived at Tahiti, his own place of destination.  There, luck\nbefriended him; two ships were about to sail for France, and were\nprovidentially in want of precisely that number of men which the\nsailor headed.  They embarked; and so for ever got the start of\ntheir former captain, had he been at all minded to work them legal\nretribution.\n\n\"Some ten days after the French ships sailed, the whale-boat arrived,\nand the captain was forced to enlist some of the more civilized\nTahitians, who had been somewhat used to the sea.  Chartering a small\nnative schooner, he returned with them to his vessel; and finding all\nright there, again resumed his cruisings.\n\n\"Where Steelkilt now is, gentlemen, none know; but upon the island of\nNantucket, the widow of Radney still turns to the sea which refuses\nto give up its dead; still in dreams sees the awful white whale that\ndestroyed him.\n\n\"'Are you through?' said Don Sebastian, quietly.\n\n\"'I am, Don.'\n\n\"'Then I entreat you, tell me if to the best of your own convictions,\nthis your story is in substance really true?  It is so passing\nwonderful!  Did you get it from an unquestionable source?  Bear with\nme if I seem to press.'\n\n\"'Also bear with all of us, sir sailor; for we all join in Don\nSebastian's suit,' cried the company, with exceeding interest.\n\n\"'Is there a copy of the Holy Evangelists in the Golden Inn,\ngentlemen?'\n\n\"'Nay,' said Don Sebastian; 'but I know a worthy priest near by, who\nwill quickly procure one for me.  I go for it; but are you well\nadvised? this may grow too serious.'\n\n\"'Will you be so good as to bring the priest also, Don?'\n\n\"'Though there are no Auto-da-Fe's in Lima now,' said one of the\ncompany to another; 'I fear our sailor friend runs risk of the\narchiepiscopacy.  Let us withdraw more out of the moonlight.  I see\nno need of this.'\n\n\"'Excuse me for running after you, Don Sebastian; but may I also beg\nthat you will be particular in procuring the largest sized\nEvangelists you can.'\n\n\n'This is the priest, he brings you the Evangelists,' said Don\nSebastian, gravely, returning with a tall and solemn figure.\n\n\"'Let me remove my hat.  Now, venerable priest, further into the\nlight, and hold the Holy Book before me that I may touch it.\n\n\"'So help me Heaven, and on my honour the story I have told ye,\ngentlemen, is in substance and its great items, true.  I know it to\nbe true; it happened on this ball; I trod the ship; I knew the crew;\nI have seen and talked with Steelkilt since the death of Radney.'\"\n\n\n\nCHAPTER 55\n\nOf the Monstrous Pictures of Whales.\n\n\nI shall ere long paint to you as well as one can without canvas,\nsomething like the true form of the whale as he actually appears to\nthe eye of the whaleman when in his own absolute body the whale is\nmoored alongside the whale-ship so that he can be fairly stepped upon\nthere.  It may be worth while, therefore, previously to advert to\nthose curious imaginary portraits of him which even down to the\npresent day confidently challenge the faith of the landsman.  It is\ntime to set the world right in this matter, by proving such pictures\nof the whale all wrong.\n\nIt may be that the primal source of all those pictorial delusions\nwill be found among the oldest Hindoo, Egyptian, and Grecian\nsculptures.  For ever since those inventive but unscrupulous times\nwhen on the marble panellings of temples, the pedestals of statues,\nand on shields, medallions, cups, and coins, the dolphin was drawn in\nscales of chain-armor like Saladin's, and a helmeted head like St.\nGeorge's; ever since then has something of the same sort of license\nprevailed, not only in most popular pictures of the whale, but in\nmany scientific presentations of him.\n\nNow, by all odds, the most ancient extant portrait anyways purporting\nto be the whale's, is to be found in the famous cavern-pagoda of\nElephanta, in India.  The Brahmins maintain that in the almost\nendless sculptures of that immemorial pagoda, all the trades and\npursuits, every conceivable avocation of man, were prefigured ages\nbefore any of them actually came into being.  No wonder then, that in\nsome sort our noble profession of whaling should have been there\nshadowed forth.  The Hindoo whale referred to, occurs in a separate\ndepartment of the wall, depicting the incarnation of Vishnu in the\nform of leviathan, learnedly known as the Matse Avatar.  But though\nthis sculpture is half man and half whale, so as only to give the\ntail of the latter, yet that small section of him is all wrong.  It\nlooks more like the tapering tail of an anaconda, than the broad palms\nof the true whale's majestic flukes.\n\nBut go to the old Galleries, and look now at a great Christian\npainter's portrait of this fish; for he succeeds no better than the\nantediluvian Hindoo.  It is Guido's picture of Perseus rescuing\nAndromeda from the sea-monster or whale.  Where did Guido get the\nmodel of such a strange creature as that?  Nor does Hogarth, in\npainting the same scene in his own \"Perseus Descending,\" make out one\nwhit better.  The huge corpulence of that Hogarthian monster\nundulates on the surface, scarcely drawing one inch of water.  It has\na sort of howdah on its back, and its distended tusked mouth into\nwhich the billows are rolling, might be taken for the Traitors' Gate\nleading from the Thames by water into the Tower.  Then, there are the\nProdromus whales of old Scotch Sibbald, and Jonah's whale, as\ndepicted in the prints of old Bibles and the cuts of old primers.\nWhat shall be said of these?  As for the book-binder's whale winding\nlike a vine-stalk round the stock of a descending anchor--as stamped\nand gilded on the backs and title-pages of many books both old and\nnew--that is a very picturesque but purely fabulous creature,\nimitated, I take it, from the like figures on antique vases.  Though\nuniversally denominated a dolphin, I nevertheless call this\nbook-binder's fish an attempt at a whale; because it was so intended\nwhen the device was first introduced.  It was introduced by an old\nItalian publisher somewhere about the 15th century, during the\nRevival of Learning; and in those days, and even down to a\ncomparatively late period, dolphins were popularly supposed to be a\nspecies of the Leviathan.\n\nIn the vignettes and other embellishments of some ancient books you\nwill at times meet with very curious touches at the whale, where all\nmanner of spouts, jets d'eau, hot springs and cold, Saratoga and\nBaden-Baden, come bubbling up from his unexhausted brain.  In the\ntitle-page of the original edition of the \"Advancement of Learning\"\nyou will find some curious whales.\n\nBut quitting all these unprofessional attempts, let us glance at\nthose pictures of leviathan purporting to be sober, scientific\ndelineations, by those who know.  In old Harris's collection of\nvoyages there are some plates of whales extracted from a Dutch book\nof voyages, A.D. 1671, entitled \"A Whaling Voyage to Spitzbergen in\nthe ship Jonas in the Whale, Peter Peterson of Friesland, master.\"\nIn one of those plates the whales, like great rafts of logs, are\nrepresented lying among ice-isles, with white bears running over\ntheir living backs.  In another plate, the prodigious blunder is made\nof representing the whale with perpendicular flukes.\n\nThen again, there is an imposing quarto, written by one Captain\nColnett, a Post Captain in the English navy, entitled \"A Voyage round\nCape Horn into the South Seas, for the purpose of extending the\nSpermaceti Whale Fisheries.\"  In this book is an outline purporting\nto be a \"Picture of a Physeter or Spermaceti whale, drawn by scale\nfrom one killed on the coast of Mexico, August, 1793, and hoisted on\ndeck.\"  I doubt not the captain had this veracious picture taken for\nthe benefit of his marines.  To mention but one thing about it, let\nme say that it has an eye which applied, according to the\naccompanying scale, to a full grown sperm whale, would make the eye\nof that whale a bow-window some five feet long.  Ah, my gallant\ncaptain, why did ye not give us Jonah looking out of that eye!\n\nNor are the most conscientious compilations of Natural History for\nthe benefit of the young and tender, free from the same heinousness\nof mistake.  Look at that popular work \"Goldsmith's Animated Nature.\"\nIn the abridged London edition of 1807, there are plates of an\nalleged \"whale\" and a \"narwhale.\"  I do not wish to seem inelegant,\nbut this unsightly whale looks much like an amputated sow; and, as\nfor the narwhale, one glimpse at it is enough to amaze one, that in\nthis nineteenth century such a hippogriff could be palmed for genuine\nupon any intelligent public of schoolboys.\n\nThen, again, in 1825, Bernard Germain, Count de Lacepede, a great\nnaturalist, published a scientific systemized whale book, wherein are\nseveral pictures of the different species of the Leviathan.  All\nthese are not only incorrect, but the picture of the Mysticetus or\nGreenland whale (that is to say, the Right whale), even Scoresby, a\nlong experienced man as touching that species, declares not to have\nits counterpart in nature.\n\nBut the placing of the cap-sheaf to all this blundering business was\nreserved for the scientific Frederick Cuvier, brother to the famous\nBaron.  In 1836, he published a Natural History of Whales, in which\nhe gives what he calls a picture of the Sperm Whale.  Before showing\nthat picture to any Nantucketer, you had best provide for your\nsummary retreat from Nantucket.  In a word, Frederick Cuvier's Sperm\nWhale is not a Sperm Whale, but a squash.  Of course, he never had\nthe benefit of a whaling voyage (such men seldom have), but whence he\nderived that picture, who can tell?  Perhaps he got it as his\nscientific predecessor in the same field, Desmarest, got one of his\nauthentic abortions; that is, from a Chinese drawing.  And what sort\nof lively lads with the pencil those Chinese are, many queer cups and\nsaucers inform us.\n\nAs for the sign-painters' whales seen in the streets hanging over the\nshops of oil-dealers, what shall be said of them?  They are generally\nRichard III. whales, with dromedary humps, and very savage;\nbreakfasting on three or four sailor tarts, that is whaleboats full\nof mariners: their deformities floundering in seas of blood and blue\npaint.\n\nBut these manifold mistakes in depicting the whale are not so very\nsurprising after all.  Consider!  Most of the scientific drawings\nhave been taken from the stranded fish; and these are about as\ncorrect as a drawing of a wrecked ship, with broken back, would\ncorrectly represent the noble animal itself in all its undashed pride\nof hull and spars.  Though elephants have stood for their\nfull-lengths, the living Leviathan has never yet fairly floated\nhimself for his portrait.  The living whale, in his full majesty and\nsignificance, is only to be seen at sea in unfathomable waters; and\nafloat the vast bulk of him is out of sight, like a launched\nline-of-battle ship; and out of that element it is a thing eternally\nimpossible for mortal man to hoist him bodily into the air, so as to\npreserve all his mighty swells and undulations.  And, not to speak of\nthe highly presumable difference of contour between a young sucking\nwhale and a full-grown Platonian Leviathan; yet, even in the case of\none of those young sucking whales hoisted to a ship's deck, such is\nthen the outlandish, eel-like, limbered, varying shape of him, that\nhis precise expression the devil himself could not catch.\n\nBut it may be fancied, that from the naked skeleton of the stranded\nwhale, accurate hints may be derived touching his true form.  Not at\nall.  For it is one of the more curious things about this Leviathan,\nthat his skeleton gives very little idea of his general shape.\nThough Jeremy Bentham's skeleton, which hangs for candelabra in the\nlibrary of one of his executors, correctly conveys the idea of a\nburly-browed utilitarian old gentleman, with all Jeremy's other\nleading personal characteristics; yet nothing of this kind could be\ninferred from any leviathan's articulated bones.  In fact, as the\ngreat Hunter says, the mere skeleton of the whale bears the same\nrelation to the fully invested and padded animal as the insect does\nto the chrysalis that so roundingly envelopes it.  This peculiarity\nis strikingly evinced in the head, as in some part of this book will\nbe incidentally shown.  It is also very curiously displayed in the\nside fin, the bones of which almost exactly answer to the bones of the\nhuman hand, minus only the thumb.  This fin has four regular\nbone-fingers, the index, middle, ring, and little finger.  But all\nthese are permanently lodged in their fleshy covering, as the human\nfingers in an artificial covering.  \"However recklessly the whale may\nsometimes serve us,\" said humorous Stubb one day, \"he can never be\ntruly said to handle us without mittens.\"\n\nFor all these reasons, then, any way you may look at it, you must\nneeds conclude that the great Leviathan is that one creature in the\nworld which must remain unpainted to the last.  True, one portrait\nmay hit the mark much nearer than another, but none can hit it with\nany very considerable degree of exactness.  So there is no earthly\nway of finding out precisely what the whale really looks like.  And\nthe only mode in which you can derive even a tolerable idea of his\nliving contour, is by going a whaling yourself; but by so doing, you\nrun no small risk of being eternally stove and sunk by him.\nWherefore, it seems to me you had best not be too fastidious in your\ncuriosity touching this Leviathan.\n\n\n\nCHAPTER 56\n\nOf the Less Erroneous Pictures of Whales, and the True Pictures of\nWhaling Scenes.\n\n\nIn connexion with the monstrous pictures of whales, I am strongly\ntempted here to enter upon those still more monstrous stories of them\nwhich are to be found in certain books, both ancient and modern,\nespecially in Pliny, Purchas, Hackluyt, Harris, Cuvier, etc.  But I\npass that matter by.\n\nI know of only four published outlines of the great Sperm Whale;\nColnett's, Huggins's, Frederick Cuvier's, and Beale's.  In the\nprevious chapter Colnett and Cuvier have been referred to.  Huggins's\nis far better than theirs; but, by great odds, Beale's is the best.\nAll Beale's drawings of this whale are good, excepting the middle\nfigure in the picture of three whales in various attitudes, capping\nhis second chapter.  His frontispiece, boats attacking Sperm Whales,\nthough no doubt calculated to excite the civil scepticism of some\nparlor men, is admirably correct and life-like in its general effect.\nSome of the Sperm Whale drawings in J.  Ross Browne are pretty\ncorrect in contour; but they are wretchedly engraved.  That is not\nhis fault though.\n\nOf the Right Whale, the best outline pictures are in Scoresby; but\nthey are drawn on too small a scale to convey a desirable impression.\nHe has but one picture of whaling scenes, and this is a sad\ndeficiency, because it is by such pictures only, when at all well\ndone, that you can derive anything like a truthful idea of the living\nwhale as seen by his living hunters.\n\nBut, taken for all in all, by far the finest, though in some details\nnot the most correct, presentations of whales and whaling scenes to\nbe anywhere found, are two large French engravings, well executed,\nand taken from paintings by one Garnery.  Respectively, they\nrepresent attacks on the Sperm and Right Whale.  In the first\nengraving a noble Sperm Whale is depicted in full majesty of might,\njust risen beneath the boat from the profundities of the ocean, and\nbearing high in the air upon his back the terrific wreck of the\nstoven planks.  The prow of the boat is partially unbroken, and is\ndrawn just balancing upon the monster's spine; and standing in that\nprow, for that one single incomputable flash of time, you behold an\noarsman, half shrouded by the incensed boiling spout of the whale,\nand in the act of leaping, as if from a precipice.  The action of the\nwhole thing is wonderfully good and true.  The half-emptied line-tub\nfloats on the whitened sea; the wooden poles of the spilled harpoons\nobliquely bob in it; the heads of the swimming crew are scattered\nabout the whale in contrasting expressions of affright; while in the\nblack stormy distance the ship is bearing down upon the scene.\nSerious fault might be found with the anatomical details of this\nwhale, but let that pass; since, for the life of me, I could not draw\nso good a one.\n\nIn the second engraving, the boat is in the act of drawing alongside\nthe barnacled flank of a large running Right Whale, that rolls his\nblack weedy bulk in the sea like some mossy rock-slide from the\nPatagonian cliffs.  His jets are erect, full, and black like soot; so\nthat from so abounding a smoke in the chimney, you would think there\nmust be a brave supper cooking in the great bowels below.  Sea fowls\nare pecking at the small crabs, shell-fish, and other sea candies and\nmaccaroni, which the Right Whale sometimes carries on his pestilent\nback.  And all the while the thick-lipped leviathan is rushing\nthrough the deep, leaving tons of tumultuous white curds in his wake,\nand causing the slight boat to rock in the swells like a skiff caught\nnigh the paddle-wheels of an ocean steamer.  Thus, the foreground is\nall raging commotion; but behind, in admirable artistic contrast, is\nthe glassy level of a sea becalmed, the drooping unstarched sails of\nthe powerless ship, and the inert mass of a dead whale, a conquered\nfortress, with the flag of capture lazily hanging from the whale-pole\ninserted into his spout-hole.\n\nWho Garnery the painter is, or was, I know not.  But my life for it\nhe was either practically conversant with his subject, or else\nmarvellously tutored by some experienced whaleman.  The French are\nthe lads for painting action.  Go and gaze upon all the paintings of\nEurope, and where will you find such a gallery of living and\nbreathing commotion on canvas, as in that triumphal hall at\nVersailles; where the beholder fights his way, pell-mell, through the\nconsecutive great battles of France; where every sword seems a flash\nof the Northern Lights, and the successive armed kings and Emperors\ndash by, like a charge of crowned centaurs?  Not wholly unworthy of a\nplace in that gallery, are these sea battle-pieces of Garnery.\n\nThe natural aptitude of the French for seizing the picturesqueness of\nthings seems to be peculiarly evinced in what paintings and\nengravings they have of their whaling scenes.  With not one tenth of\nEngland's experience in the fishery, and not the thousandth part of\nthat of the Americans, they have nevertheless furnished both nations\nwith the only finished sketches at all capable of conveying the real\nspirit of the whale hunt.  For the most part, the English and\nAmerican whale draughtsmen seem entirely content with presenting the\nmechanical outline of things, such as the vacant profile of the\nwhale; which, so far as picturesqueness of effect is concerned, is\nabout tantamount to sketching the profile of a pyramid.  Even\nScoresby, the justly renowned Right whaleman, after giving us a stiff\nfull length of the Greenland whale, and three or four delicate\nminiatures of narwhales and porpoises, treats us to a series of\nclassical engravings of boat hooks, chopping knives, and grapnels;\nand with the microscopic diligence of a Leuwenhoeck submits to the\ninspection of a shivering world ninety-six fac-similes of magnified\nArctic snow crystals.  I mean no disparagement to the excellent\nvoyager (I honour him for a veteran), but in so important a matter it\nwas certainly an oversight not to have procured for every crystal a\nsworn affidavit taken before a Greenland Justice of the Peace.\n\nIn addition to those fine engravings from Garnery, there are two\nother French engravings worthy of note, by some one who subscribes\nhimself \"H.  Durand.\"  One of them, though not precisely adapted to\nour present purpose, nevertheless deserves mention on other accounts.\nIt is a quiet noon-scene among the isles of the Pacific; a French\nwhaler anchored, inshore, in a calm, and lazily taking water on\nboard; the loosened sails of the ship, and the long leaves of the\npalms in the background, both drooping together in the breezeless\nair.  The effect is very fine, when considered with reference to its\npresenting the hardy fishermen under one of their few aspects of\noriental repose.  The other engraving is quite a different affair:\nthe ship hove-to upon the open sea, and in the very heart of the\nLeviathanic life, with a Right Whale alongside; the vessel (in the\nact of cutting-in) hove over to the monster as if to a quay; and a\nboat, hurriedly pushing off from this scene of activity, is about\ngiving chase to whales in the distance.  The harpoons and lances lie\nlevelled for use; three oarsmen are just setting the mast in its\nhole; while from a sudden roll of the sea, the little craft stands\nhalf-erect out of the water, like a rearing horse.  From the ship,\nthe smoke of the torments of the boiling whale is going up like the\nsmoke over a village of smithies; and to windward, a black cloud,\nrising up with earnest of squalls and rains, seems to quicken the\nactivity of the excited seamen.\n\n\n\nCHAPTER 57\n\nOf Whales in Paint; in Teeth; in Wood; in Sheet-Iron; in Stone; in\nMountains; in Stars.\n\n\nOn Tower-hill, as you go down to the London docks, you may have seen\na crippled beggar (or KEDGER, as the sailors say) holding a painted\nboard before him, representing the tragic scene in which he lost his\nleg.  There are three whales and three boats; and one of the boats\n(presumed to contain the missing leg in all its original integrity)\nis being crunched by the jaws of the foremost whale.  Any time these\nten years, they tell me, has that man held up that picture, and\nexhibited that stump to an incredulous world.  But the time of his\njustification has now come.  His three whales are as good whales as\nwere ever published in Wapping, at any rate; and his stump as\nunquestionable a stump as any you will find in the western clearings.\nBut, though for ever mounted on that stump, never a stump-speech\ndoes the poor whaleman make; but, with downcast eyes, stands ruefully\ncontemplating his own amputation.\n\nThroughout the Pacific, and also in Nantucket, and New Bedford, and\nSag Harbor, you will come across lively sketches of whales and\nwhaling-scenes, graven by the fishermen themselves on Sperm\nWhale-teeth, or ladies' busks wrought out of the Right Whale-bone,\nand other like skrimshander articles, as the whalemen call the\nnumerous little ingenious contrivances they elaborately carve out of\nthe rough material, in their hours of ocean leisure.  Some of them\nhave little boxes of dentistical-looking implements, specially\nintended for the skrimshandering business.  But, in general, they\ntoil with their jack-knives alone; and, with that almost omnipotent\ntool of the sailor, they will turn you out anything you please, in\nthe way of a mariner's fancy.\n\nLong exile from Christendom and civilization inevitably restores a\nman to that condition in which God placed him, i.e. what is called\nsavagery.  Your true whale-hunter is as much a savage as an Iroquois.\nI myself am a savage, owning no allegiance but to the King of the\nCannibals; and ready at any moment to rebel against him.\n\nNow, one of the peculiar characteristics of the savage in his\ndomestic hours, is his wonderful patience of industry.  An ancient\nHawaiian war-club or spear-paddle, in its full multiplicity and\nelaboration of carving, is as great a trophy of human perseverance as\na Latin lexicon.  For, with but a bit of broken sea-shell or a\nshark's tooth, that miraculous intricacy of wooden net-work has been\nachieved; and it has cost steady years of steady application.\n\nAs with the Hawaiian savage, so with the white sailor-savage.  With\nthe same marvellous patience, and with the same single shark's tooth,\nof his one poor jack-knife, he will carve you a bit of bone\nsculpture, not quite as workmanlike, but as close packed in its\nmaziness of design, as the Greek savage, Achilles's shield; and full\nof barbaric spirit and suggestiveness, as the prints of that fine old\nDutch savage, Albert Durer.\n\nWooden whales, or whales cut in profile out of the small dark slabs\nof the noble South Sea war-wood, are frequently met with in the\nforecastles of American whalers.  Some of them are done with much\naccuracy.\n\nAt some old gable-roofed country houses you will see brass whales\nhung by the tail for knockers to the road-side door.  When the porter\nis sleepy, the anvil-headed whale would be best.  But these knocking\nwhales are seldom remarkable as faithful essays.  On the spires of\nsome old-fashioned churches you will see sheet-iron whales placed\nthere for weather-cocks; but they are so elevated, and besides that\nare to all intents and purposes so labelled with \"HANDS OFF!\" you\ncannot examine them closely enough to decide upon their merit.\n\nIn bony, ribby regions of the earth, where at the base of high broken\ncliffs masses of rock lie strewn in fantastic groupings upon the\nplain, you will often discover images as of the petrified forms of\nthe Leviathan partly merged in grass, which of a windy day breaks\nagainst them in a surf of green surges.\n\nThen, again, in mountainous countries where the traveller is\ncontinually girdled by amphitheatrical heights; here and there from\nsome lucky point of view you will catch passing glimpses of the\nprofiles of whales defined along the undulating ridges.  But you must\nbe a thorough whaleman, to see these sights; and not only that, but\nif you wish to return to such a sight again, you must be sure and\ntake the exact intersecting latitude and longitude of your first\nstand-point, else so chance-like are such observations of the hills,\nthat your precise, previous stand-point would require a laborious\nre-discovery; like the Soloma Islands, which still remain incognita,\nthough once high-ruffed Mendanna trod them and old Figuera\nchronicled them.\n\nNor when expandingly lifted by your subject, can you fail to trace\nout great whales in the starry heavens, and boats in pursuit of them;\nas when long filled with thoughts of war the Eastern nations saw\narmies locked in battle among the clouds.  Thus at the North have I\nchased Leviathan round and round the Pole with the revolutions of the\nbright points that first defined him to me.  And beneath the\neffulgent Antarctic skies I have boarded the Argo-Navis, and joined\nthe chase against the starry Cetus far beyond the utmost stretch of\nHydrus and the Flying Fish.\n\nWith a frigate's anchors for my bridle-bitts and fasces of harpoons\nfor spurs, would I could mount that whale and leap the topmost skies,\nto see whether the fabled heavens with all their countless tents\nreally lie encamped beyond my mortal sight!\n\n\n\nCHAPTER 58\n\nBrit.\n\n\nSteering north-eastward from the Crozetts, we fell in with vast\nmeadows of brit, the minute, yellow substance, upon which the Right\nWhale largely feeds.  For leagues and leagues it undulated round us,\nso that we seemed to be sailing through boundless fields of ripe and\ngolden wheat.\n\nOn the second day, numbers of Right Whales were seen, who, secure\nfrom the attack of a Sperm Whaler like the Pequod, with open jaws\nsluggishly swam through the brit, which, adhering to the fringing\nfibres of that wondrous Venetian blind in their mouths, was in that\nmanner separated from the water that escaped at the lip.\n\nAs morning mowers, who side by side slowly and seethingly advance\ntheir scythes through the long wet grass of marshy meads; even so\nthese monsters swam, making a strange, grassy, cutting sound; and\nleaving behind them endless swaths of blue upon the yellow sea.*\n\n\n*That part of the sea known among whalemen as the \"Brazil Banks\" does\nnot bear that name as the Banks of Newfoundland do, because of there\nbeing shallows and soundings there, but because of this remarkable\nmeadow-like appearance, caused by the vast drifts of brit continually\nfloating in those latitudes, where the Right Whale is often chased.\n\n\nBut it was only the sound they made as they parted the brit which at\nall reminded one of mowers.  Seen from the mast-heads, especially\nwhen they paused and were stationary for a while, their vast black\nforms looked more like lifeless masses of rock than anything else.\nAnd as in the great hunting countries of India, the stranger at a\ndistance will sometimes pass on the plains recumbent elephants\nwithout knowing them to be such, taking them for bare, blackened\nelevations of the soil; even so, often, with him, who for the first\ntime beholds this species of the leviathans of the sea.  And even\nwhen recognised at last, their immense magnitude renders it very\nhard really to believe that such bulky masses of overgrowth can\npossibly be instinct, in all parts, with the same sort of life that\nlives in a dog or a horse.\n\nIndeed, in other respects, you can hardly regard any creatures of the\ndeep with the same feelings that you do those of the shore.  For\nthough some old naturalists have maintained that all creatures of the\nland are of their kind in the sea; and though taking a broad general\nview of the thing, this may very well be; yet coming to specialties,\nwhere, for example, does the ocean furnish any fish that in\ndisposition answers to the sagacious kindness of the dog?  The\naccursed shark alone can in any generic respect be said to bear\ncomparative analogy to him.\n\nBut though, to landsmen in general, the native inhabitants of the\nseas have ever been regarded with emotions unspeakably unsocial and\nrepelling; though we know the sea to be an everlasting terra\nincognita, so that Columbus sailed over numberless unknown worlds to\ndiscover his one superficial western one; though, by vast odds, the\nmost terrific of all mortal disasters have immemorially and\nindiscriminately befallen tens and hundreds of thousands of those who\nhave gone upon the waters; though but a moment's consideration will\nteach, that however baby man may brag of his science and skill, and\nhowever much, in a flattering future, that science and skill may\naugment; yet for ever and for ever, to the crack of doom, the sea\nwill insult and murder him, and pulverize the stateliest, stiffest\nfrigate he can make; nevertheless, by the continual repetition of\nthese very impressions, man has lost that sense of the full awfulness\nof the sea which aboriginally belongs to it.\n\nThe first boat we read of, floated on an ocean, that with Portuguese\nvengeance had whelmed a whole world without leaving so much as a\nwidow.  That same ocean rolls now; that same ocean destroyed the\nwrecked ships of last year.  Yea, foolish mortals, Noah's flood is\nnot yet subsided; two thirds of the fair world it yet covers.\n\nWherein differ the sea and the land, that a miracle upon one is not a\nmiracle upon the other?  Preternatural terrors rested upon the\nHebrews, when under the feet of Korah and his company the live ground\nopened and swallowed them up for ever; yet not a modern sun ever\nsets, but in precisely the same manner the live sea swallows up ships\nand crews.\n\nBut not only is the sea such a foe to man who is an alien to it, but\nit is also a fiend to its own off-spring; worse than the Persian host\nwho murdered his own guests; sparing not the creatures which itself\nhath spawned.  Like a savage tigress that tossing in the jungle\noverlays her own cubs, so the sea dashes even the mightiest whales\nagainst the rocks, and leaves them there side by side with the split\nwrecks of ships.  No mercy, no power but its own controls it.\nPanting and snorting like a mad battle steed that has lost its rider,\nthe masterless ocean overruns the globe.\n\nConsider the subtleness of the sea; how its most dreaded creatures\nglide under water, unapparent for the most part, and treacherously\nhidden beneath the loveliest tints of azure.  Consider also the\ndevilish brilliance and beauty of many of its most remorseless\ntribes, as the dainty embellished shape of many species of sharks.\nConsider, once more, the universal cannibalism of the sea; all whose\ncreatures prey upon each other, carrying on eternal war since the\nworld began.\n\nConsider all this; and then turn to this green, gentle, and most\ndocile earth; consider them both, the sea and the land; and do you\nnot find a strange analogy to something in yourself?  For as this\nappalling ocean surrounds the verdant land, so in the soul of man\nthere lies one insular Tahiti, full of peace and joy, but encompassed\nby all the horrors of the half known life.  God keep thee!  Push not\noff from that isle, thou canst never return!\n\n\nCHAPTER 59\n\nSquid.\n\n\nSlowly wading through the meadows of brit, the Pequod still held on\nher way north-eastward towards the island of Java; a gentle air\nimpelling her keel, so that in the surrounding serenity her three\ntall tapering masts mildly waved to that languid breeze, as three\nmild palms on a plain.  And still, at wide intervals in the silvery\nnight, the lonely, alluring jet would be seen.\n\nBut one transparent blue morning, when a stillness almost\npreternatural spread over the sea, however unattended with any\nstagnant calm; when the long burnished sun-glade on the waters seemed\na golden finger laid across them, enjoining some secrecy; when the\nslippered waves whispered together as they softly ran on; in this\nprofound hush of the visible sphere a strange spectre was seen by\nDaggoo from the main-mast-head.\n\nIn the distance, a great white mass lazily rose, and rising higher\nand higher, and disentangling itself from the azure, at last gleamed\nbefore our prow like a snow-slide, new slid from the hills.  Thus\nglistening for a moment, as slowly it subsided, and sank.  Then once\nmore arose, and silently gleamed.  It seemed not a whale; and yet is\nthis Moby Dick? thought Daggoo.  Again the phantom went down, but on\nre-appearing once more, with a stiletto-like cry that startled every\nman from his nod, the negro yelled out--\"There! there again! there\nshe breaches! right ahead!  The White Whale, the White Whale!\"\n\nUpon this, the seamen rushed to the yard-arms, as in swarming-time\nthe bees rush to the boughs.  Bare-headed in the sultry sun, Ahab\nstood on the bowsprit, and with one hand pushed far behind in\nreadiness to wave his orders to the helmsman, cast his eager glance\nin the direction indicated aloft by the outstretched motionless arm\nof Daggoo.\n\nWhether the flitting attendance of the one still and solitary jet had\ngradually worked upon Ahab, so that he was now prepared to connect\nthe ideas of mildness and repose with the first sight of the\nparticular whale he pursued; however this was, or whether his\neagerness betrayed him; whichever way it might have been, no sooner\ndid he distinctly perceive the white mass, than with a quick\nintensity he instantly gave orders for lowering.\n\nThe four boats were soon on the water; Ahab's in advance, and all\nswiftly pulling towards their prey.  Soon it went down, and while,\nwith oars suspended, we were awaiting its reappearance, lo! in the\nsame spot where it sank, once more it slowly rose.  Almost forgetting\nfor the moment all thoughts of Moby Dick, we now gazed at the most\nwondrous phenomenon which the secret seas have hitherto revealed to\nmankind.  A vast pulpy mass, furlongs in length and breadth, of a\nglancing cream-colour, lay floating on the water, innumerable long\narms radiating from its centre, and curling and twisting like a nest\nof anacondas, as if blindly to clutch at any hapless object within\nreach.  No perceptible face or front did it have; no conceivable\ntoken of either sensation or instinct; but undulated there on the\nbillows, an unearthly, formless, chance-like apparition of life.\n\nAs with a low sucking sound it slowly disappeared again, Starbuck\nstill gazing at the agitated waters where it had sunk, with a wild\nvoice exclaimed--\"Almost rather had I seen Moby Dick and fought him,\nthan to have seen thee, thou white ghost!\"\n\n\"What was it, Sir?\" said Flask.\n\n\"The great live squid, which, they say, few whale-ships ever beheld,\nand returned to their ports to tell of it.\"\n\nBut Ahab said nothing; turning his boat, he sailed back to the\nvessel; the rest as silently following.\n\nWhatever superstitions the sperm whalemen in general have connected\nwith the sight of this object, certain it is, that a glimpse of it\nbeing so very unusual, that circumstance has gone far to invest it\nwith portentousness.  So rarely is it beheld, that though one and all\nof them declare it to be the largest animated thing in the ocean, yet\nvery few of them have any but the most vague ideas concerning its\ntrue nature and form; notwithstanding, they believe it to furnish to\nthe sperm whale his only food.  For though other species of whales\nfind their food above water, and may be seen by man in the act of\nfeeding, the spermaceti whale obtains his whole food in unknown zones\nbelow the surface; and only by inference is it that any one can tell\nof what, precisely, that food consists.  At times, when closely\npursued, he will disgorge what are supposed to be the detached arms\nof the squid; some of them thus exhibited exceeding twenty and thirty\nfeet in length.  They fancy that the monster to which these arms\nbelonged ordinarily clings by them to the bed of the ocean; and that\nthe sperm whale, unlike other species, is supplied with teeth in\norder to attack and tear it.\n\nThere seems some ground to imagine that the great Kraken of Bishop\nPontoppodan may ultimately resolve itself into Squid.  The manner in\nwhich the Bishop describes it, as alternately rising and sinking,\nwith some other particulars he narrates, in all this the two\ncorrespond.  But much abatement is necessary with respect to the\nincredible bulk he assigns it.\n\nBy some naturalists who have vaguely heard rumors of the mysterious\ncreature, here spoken of, it is included among the class of\ncuttle-fish, to which, indeed, in certain external respects it would\nseem to belong, but only as the Anak of the tribe.\n\n\n\nCHAPTER 60\n\nThe Line.\n\n\nWith reference to the whaling scene shortly to be described, as well\nas for the better understanding of all similar scenes elsewhere\npresented, I have here to speak of the magical, sometimes horrible\nwhale-line.\n\nThe line originally used in the fishery was of the best hemp,\nslightly vapoured with tar, not impregnated with it, as in the case of\nordinary ropes; for while tar, as ordinarily used, makes the hemp\nmore pliable to the rope-maker, and also renders the rope itself more\nconvenient to the sailor for common ship use; yet, not only would the\nordinary quantity too much stiffen the whale-line for the close\ncoiling to which it must be subjected; but as most seamen are\nbeginning to learn, tar in general by no means adds to the rope's\ndurability or strength, however much it may give it compactness and\ngloss.\n\nOf late years the Manilla rope has in the American fishery almost\nentirely superseded hemp as a material for whale-lines; for, though\nnot so durable as hemp, it is stronger, and far more soft and\nelastic; and I will add (since there is an aesthetics in all things),\nis much more handsome and becoming to the boat, than hemp.  Hemp is a\ndusky, dark fellow, a sort of Indian; but Manilla is as a\ngolden-haired Circassian to behold.\n\nThe whale-line is only two-thirds of an inch in thickness.  At first\nsight, you would not think it so strong as it really is.  By\nexperiment its one and fifty yarns will each suspend a weight of one\nhundred and twenty pounds; so that the whole rope will bear a strain\nnearly equal to three tons.  In length, the common sperm whale-line\nmeasures something over two hundred fathoms.  Towards the stern of\nthe boat it is spirally coiled away in the tub, not like the\nworm-pipe of a still though, but so as to form one round,\ncheese-shaped mass of densely bedded \"sheaves,\" or layers of\nconcentric spiralizations, without any hollow but the \"heart,\" or\nminute vertical tube formed at the axis of the cheese.  As the least\ntangle or kink in the coiling would, in running out, infallibly take\nsomebody's arm, leg, or entire body off, the utmost precaution is\nused in stowing the line in its tub.  Some harpooneers will consume\nalmost an entire morning in this business, carrying the line high\naloft and then reeving it downwards through a block towards the tub,\nso as in the act of coiling to free it from all possible wrinkles and\ntwists.\n\nIn the English boats two tubs are used instead of one; the same line\nbeing continuously coiled in both tubs.  There is some advantage in\nthis; because these twin-tubs being so small they fit more readily\ninto the boat, and do not strain it so much; whereas, the American\ntub, nearly three feet in diameter and of proportionate depth, makes\na rather bulky freight for a craft whose planks are but one half-inch\nin thickness; for the bottom of the whale-boat is like critical ice,\nwhich will bear up a considerable distributed weight, but not very\nmuch of a concentrated one.  When the painted canvas cover is clapped\non the American line-tub, the boat looks as if it were pulling off\nwith a prodigious great wedding-cake to present to the whales.\n\nBoth ends of the line are exposed; the lower end terminating in an\neye-splice or loop coming up from the bottom against the side of the\ntub, and hanging over its edge completely disengaged from everything.\nThis arrangement of the lower end is necessary on two accounts.\nFirst: In order to facilitate the fastening to it of an additional\nline from a neighboring boat, in case the stricken whale should sound\nso deep as to threaten to carry off the entire line originally\nattached to the harpoon.  In these instances, the whale of course is\nshifted like a mug of ale, as it were, from the one boat to the\nother; though the first boat always hovers at hand to assist its\nconsort.  Second: This arrangement is indispensable for common\nsafety's sake; for were the lower end of the line in any way attached\nto the boat, and were the whale then to run the line out to the end\nalmost in a single, smoking minute as he sometimes does, he would not\nstop there, for the doomed boat would infallibly be dragged down\nafter him into the profundity of the sea; and in that case no\ntown-crier would ever find her again.\n\nBefore lowering the boat for the chase, the upper end of the line is\ntaken aft from the tub, and passing round the loggerhead there, is\nagain carried forward the entire length of the boat, resting\ncrosswise upon the loom or handle of every man's oar, so that it jogs\nagainst his wrist in rowing; and also passing between the men, as\nthey alternately sit at the opposite gunwales, to the leaded chocks\nor grooves in the extreme pointed prow of the boat, where a wooden\npin or skewer the size of a common quill, prevents it from slipping\nout.  From the chocks it hangs in a slight festoon over the bows, and\nis then passed inside the boat again; and some ten or twenty fathoms\n(called box-line) being coiled upon the box in the bows, it continues\nits way to the gunwale still a little further aft, and is then\nattached to the short-warp--the rope which is immediately connected\nwith the harpoon; but previous to that connexion, the short-warp goes\nthrough sundry mystifications too tedious to detail.\n\nThus the whale-line folds the whole boat in its complicated coils,\ntwisting and writhing around it in almost every direction.  All the\noarsmen are involved in its perilous contortions; so that to the\ntimid eye of the landsman, they seem as Indian jugglers, with the\ndeadliest snakes sportively festooning their limbs.  Nor can any son\nof mortal woman, for the first time, seat himself amid those hempen\nintricacies, and while straining his utmost at the oar, bethink him\nthat at any unknown instant the harpoon may be darted, and all these\nhorrible contortions be put in play like ringed lightnings; he cannot\nbe thus circumstanced without a shudder that makes the very marrow in\nhis bones to quiver in him like a shaken jelly.  Yet habit--strange\nthing! what cannot habit accomplish?--Gayer sallies, more merry\nmirth, better jokes, and brighter repartees, you never heard over\nyour mahogany, than you will hear over the half-inch white cedar of\nthe whale-boat, when thus hung in hangman's nooses; and, like the six\nburghers of Calais before King Edward, the six men composing the crew\npull into the jaws of death, with a halter around every neck, as you\nmay say.\n\nPerhaps a very little thought will now enable you to account for\nthose repeated whaling disasters--some few of which are casually\nchronicled--of this man or that man being taken out of the boat by\nthe line, and lost.  For, when the line is darting out, to be seated\nthen in the boat, is like being seated in the midst of the manifold\nwhizzings of a steam-engine in full play, when every flying beam, and\nshaft, and wheel, is grazing you.  It is worse; for you cannot sit\nmotionless in the heart of these perils, because the boat is rocking\nlike a cradle, and you are pitched one way and the other, without the\nslightest warning; and only by a certain self-adjusting buoyancy and\nsimultaneousness of volition and action, can you escape being made a\nMazeppa of, and run away with where the all-seeing sun himself could\nnever pierce you out.\n\nAgain: as the profound calm which only apparently precedes and\nprophesies of the storm, is perhaps more awful than the storm itself;\nfor, indeed, the calm is but the wrapper and envelope of the storm;\nand contains it in itself, as the seemingly harmless rifle holds the\nfatal powder, and the ball, and the explosion; so the graceful repose\nof the line, as it silently serpentines about the oarsmen before\nbeing brought into actual play--this is a thing which carries more of\ntrue terror than any other aspect of this dangerous affair.  But why\nsay more?  All men live enveloped in whale-lines.  All are born with\nhalters round their necks; but it is only when caught in the swift,\nsudden turn of death, that mortals realize the silent, subtle,\never-present perils of life.  And if you be a philosopher, though\nseated in the whale-boat, you would not at heart feel one whit more\nof terror, than though seated before your evening fire with a poker,\nand not a harpoon, by your side.\n\n\n\nCHAPTER 61\n\nStubb Kills a Whale.\n\n\nIf to Starbuck the apparition of the Squid was a thing of portents,\nto Queequeg it was quite a different object.\n\n\"When you see him 'quid,\" said the savage, honing his harpoon in the\nbow of his hoisted boat, \"then you quick see him 'parm whale.\"\n\nThe next day was exceedingly still and sultry, and with nothing\nspecial to engage them, the Pequod's crew could hardly resist the\nspell of sleep induced by such a vacant sea.  For this part of the\nIndian Ocean through which we then were voyaging is not what whalemen\ncall a lively ground; that is, it affords fewer glimpses of\nporpoises, dolphins, flying-fish, and other vivacious denizens of\nmore stirring waters, than those off the Rio de la Plata, or the\nin-shore ground off Peru.\n\nIt was my turn to stand at the foremast-head; and with my shoulders\nleaning against the slackened royal shrouds, to and fro I idly swayed\nin what seemed an enchanted air.  No resolution could withstand it;\nin that dreamy mood losing all consciousness, at last my soul went\nout of my body; though my body still continued to sway as a pendulum\nwill, long after the power which first moved it is withdrawn.\n\nEre forgetfulness altogether came over me, I had noticed that the\nseamen at the main and mizzen-mast-heads were already drowsy.  So\nthat at last all three of us lifelessly swung from the spars, and for\nevery swing that we made there was a nod from below from the\nslumbering helmsman.  The waves, too, nodded their indolent crests;\nand across the wide trance of the sea, east nodded to west, and the\nsun over all.\n\nSuddenly bubbles seemed bursting beneath my closed eyes; like vices\nmy hands grasped the shrouds; some invisible, gracious agency\npreserved me; with a shock I came back to life.  And lo! close under\nour lee, not forty fathoms off, a gigantic Sperm Whale lay rolling in\nthe water like the capsized hull of a frigate, his broad, glossy\nback, of an Ethiopian hue, glistening in the sun's rays like a\nmirror.  But lazily undulating in the trough of the sea, and ever and\nanon tranquilly spouting his vapoury jet, the whale looked like a\nportly burgher smoking his pipe of a warm afternoon.  But that pipe,\npoor whale, was thy last.  As if struck by some enchanter's wand, the\nsleepy ship and every sleeper in it all at once started into\nwakefulness; and more than a score of voices from all parts of the\nvessel, simultaneously with the three notes from aloft, shouted forth\nthe accustomed cry, as the great fish slowly and regularly spouted\nthe sparkling brine into the air.\n\n\"Clear away the boats!  Luff!\" cried Ahab.  And obeying his own\norder, he dashed the helm down before the helmsman could handle the\nspokes.\n\nThe sudden exclamations of the crew must have alarmed the whale; and\nere the boats were down, majestically turning, he swam away to the\nleeward, but with such a steady tranquillity, and making so few\nripples as he swam, that thinking after all he might not as yet be\nalarmed, Ahab gave orders that not an oar should be used, and no man\nmust speak but in whispers.  So seated like Ontario Indians on the\ngunwales of the boats, we swiftly but silently paddled along; the\ncalm not admitting of the noiseless sails being set.  Presently, as\nwe thus glided in chase, the monster perpendicularly flitted his tail\nforty feet into the air, and then sank out of sight like a tower\nswallowed up.\n\n\"There go flukes!\" was the cry, an announcement immediately followed\nby Stubb's producing his match and igniting his pipe, for now a\nrespite was granted.  After the full interval of his sounding had\nelapsed, the whale rose again, and being now in advance of the\nsmoker's boat, and much nearer to it than to any of the others, Stubb\ncounted upon the honour of the capture.  It was obvious, now, that the\nwhale had at length become aware of his pursuers.  All silence of\ncautiousness was therefore no longer of use.  Paddles were dropped,\nand oars came loudly into play.  And still puffing at his pipe, Stubb\ncheered on his crew to the assault.\n\nYes, a mighty change had come over the fish.  All alive to his\njeopardy, he was going \"head out\"; that part obliquely projecting\nfrom the mad yeast which he brewed.*\n\n\n*It will be seen in some other place of what a very light substance\nthe entire interior of the sperm whale's enormous head consists.\nThough apparently the most massive, it is by far the most buoyant\npart about him.  So that with ease he elevates it in the air, and\ninvariably does so when going at his utmost speed.  Besides, such is\nthe breadth of the upper part of the front of his head, and such the\ntapering cut-water formation of the lower part, that by obliquely\nelevating his head, he thereby may be said to transform himself from\na bluff-bowed sluggish galliot into a sharppointed New York\npilot-boat.\n\n\n\"Start her, start her, my men!  Don't hurry yourselves; take plenty\nof time--but start her; start her like thunder-claps, that's all,\"\ncried Stubb, spluttering out the smoke as he spoke.  \"Start her, now;\ngive 'em the long and strong stroke, Tashtego.  Start her, Tash, my\nboy--start her, all; but keep cool, keep cool--cucumbers is the\nword--easy, easy--only start her like grim death and grinning devils,\nand raise the buried dead perpendicular out of their graves,\nboys--that's all.  Start her!\"\n\n\"Woo-hoo!  Wa-hee!\" screamed the Gay-Header in reply, raising some\nold war-whoop to the skies; as every oarsman in the strained boat\ninvoluntarily bounced forward with the one tremendous leading stroke\nwhich the eager Indian gave.\n\nBut his wild screams were answered by others quite as wild.\n\"Kee-hee!  Kee-hee!\" yelled Daggoo, straining forwards and backwards\non his seat, like a pacing tiger in his cage.\n\n\"Ka-la!  Koo-loo!\" howled Queequeg, as if smacking his lips over a\nmouthful of Grenadier's steak.  And thus with oars and yells the\nkeels cut the sea.  Meanwhile, Stubb retaining his place in the\nvan, still encouraged his men to the onset, all the while puffing the\nsmoke from his mouth.  Like desperadoes they tugged and they\nstrained, till the welcome cry was heard--\"Stand up, Tashtego!--give\nit to him!\"  The harpoon was hurled.  \"Stern all!\"  The oarsmen\nbacked water; the same moment something went hot and hissing along\nevery one of their wrists.  It was the magical line.  An instant\nbefore, Stubb had swiftly caught two additional turns with it round\nthe loggerhead, whence, by reason of its increased rapid circlings, a\nhempen blue smoke now jetted up and mingled with the steady fumes\nfrom his pipe.  As the line passed round and round the loggerhead; so\nalso, just before reaching that point, it blisteringly passed through\nand through both of Stubb's hands, from which the hand-cloths, or\nsquares of quilted canvas sometimes worn at these times, had\naccidentally dropped.  It was like holding an enemy's sharp two-edged\nsword by the blade, and that enemy all the time striving to wrest it\nout of your clutch.\n\n\"Wet the line! wet the line!\" cried Stubb to the tub oarsman (him\nseated by the tub) who, snatching off his hat, dashed sea-water into\nit.*  More turns were taken, so that the line began holding its place.\nThe boat now flew through the boiling water like a shark all fins.\nStubb and Tashtego here changed places--stem for stern--a staggering\nbusiness truly in that rocking commotion.\n\n\n*Partly to show the indispensableness of this act, it may here be\nstated, that, in the old Dutch fishery, a mop was used to dash the\nrunning line with water; in many other ships, a wooden piggin, or\nbailer, is set apart for that purpose.  Your hat, however, is the\nmost convenient.\n\n\nFrom the vibrating line extending the entire length of the upper part\nof the boat, and from its now being more tight than a harpstring, you\nwould have thought the craft had two keels--one cleaving the water,\nthe other the air--as the boat churned on through both opposing\nelements at once.  A continual cascade played at the bows; a\nceaseless whirling eddy in her wake; and, at the slightest motion\nfrom within, even but of a little finger, the vibrating, cracking\ncraft canted over her spasmodic gunwale into the sea.  Thus they\nrushed; each man with might and main clinging to his seat, to prevent\nbeing tossed to the foam; and the tall form of Tashtego at the\nsteering oar crouching almost double, in order to bring down his\ncentre of gravity.  Whole Atlantics and Pacifics seemed passed as\nthey shot on their way, till at length the whale somewhat slackened\nhis flight.\n\n\"Haul in--haul in!\" cried Stubb to the bowsman! and, facing round\ntowards the whale, all hands began pulling the boat up to him, while\nyet the boat was being towed on.  Soon ranging up by his flank,\nStubb, firmly planting his knee in the clumsy cleat, darted dart\nafter dart into the flying fish; at the word of command, the boat\nalternately sterning out of the way of the whale's horrible wallow,\nand then ranging up for another fling.\n\nThe red tide now poured from all sides of the monster like brooks\ndown a hill.  His tormented body rolled not in brine but in blood,\nwhich bubbled and seethed for furlongs behind in their wake.  The\nslanting sun playing upon this crimson pond in the sea, sent back\nits reflection into every face, so that they all glowed to each other\nlike red men.  And all the while, jet after jet of white smoke was\nagonizingly shot from the spiracle of the whale, and vehement puff\nafter puff from the mouth of the excited headsman; as at every dart,\nhauling in upon his crooked lance (by the line attached to it), Stubb\nstraightened it again and again, by a few rapid blows against the\ngunwale, then again and again sent it into the whale.\n\n\"Pull up--pull up!\" he now cried to the bowsman, as the waning whale\nrelaxed in his wrath.  \"Pull up!--close to!\" and the boat ranged\nalong the fish's flank.  When reaching far over the bow, Stubb slowly\nchurned his long sharp lance into the fish, and kept it there,\ncarefully churning and churning, as if cautiously seeking to feel\nafter some gold watch that the whale might have swallowed, and which\nhe was fearful of breaking ere he could hook it out.  But that gold\nwatch he sought was the innermost life of the fish.  And now it is\nstruck; for, starting from his trance into that unspeakable thing\ncalled his \"flurry,\" the monster horribly wallowed in his blood,\noverwrapped himself in impenetrable, mad, boiling spray, so that the\nimperilled craft, instantly dropping astern, had much ado blindly to\nstruggle out from that phrensied twilight into the clear air of the\nday.\n\nAnd now abating in his flurry, the whale once more rolled out into\nview; surging from side to side; spasmodically dilating and\ncontracting his spout-hole, with sharp, cracking, agonized\nrespirations.  At last, gush after gush of clotted red gore, as if it\nhad been the purple lees of red wine, shot into the frighted air; and\nfalling back again, ran dripping down his motionless flanks into\nthe sea.  His heart had burst!\n\n\"He's dead, Mr. Stubb,\" said Daggoo.\n\n\"Yes; both pipes smoked out!\" and withdrawing his own from his mouth,\nStubb scattered the dead ashes over the water; and, for a moment,\nstood thoughtfully eyeing the vast corpse he had made.\n\n\n\nCHAPTER 62\n\nThe Dart.\n\n\nA word concerning an incident in the last chapter.\n\nAccording to the invariable usage of the fishery, the whale-boat\npushes off from the ship, with the headsman or whale-killer as\ntemporary steersman, and the harpooneer or whale-fastener pulling the\nforemost oar, the one known as the harpooneer-oar.  Now it needs a\nstrong, nervous arm to strike the first iron into the fish; for\noften, in what is called a long dart, the heavy implement has to be\nflung to the distance of twenty or thirty feet.  But however\nprolonged and exhausting the chase, the harpooneer is expected to\npull his oar meanwhile to the uttermost; indeed, he is expected to\nset an example of superhuman activity to the rest, not only by\nincredible rowing, but by repeated loud and intrepid exclamations;\nand what it is to keep shouting at the top of one's compass, while\nall the other muscles are strained and half started--what that is\nnone know but those who have tried it.  For one, I cannot bawl very\nheartily and work very recklessly at one and the same time.  In this\nstraining, bawling state, then, with his back to the fish, all at\nonce the exhausted harpooneer hears the exciting cry--\"Stand up, and\ngive it to him!\"  He now has to drop and secure his oar, turn round\non his centre half way, seize his harpoon from the crotch, and with\nwhat little strength may remain, he essays to pitch it somehow into\nthe whale.  No wonder, taking the whole fleet of whalemen in a body,\nthat out of fifty fair chances for a dart, not five are successful;\nno wonder that so many hapless harpooneers are madly cursed and\ndisrated; no wonder that some of them actually burst their\nblood-vessels in the boat; no wonder that some sperm whalemen are\nabsent four years with four barrels; no wonder that to many ship\nowners, whaling is but a losing concern; for it is the harpooneer\nthat makes the voyage, and if you take the breath out of his body how\ncan you expect to find it there when most wanted!\n\nAgain, if the dart be successful, then at the second critical\ninstant, that is, when the whale starts to run, the boatheader and\nharpooneer likewise start to running fore and aft, to the imminent\njeopardy of themselves and every one else.  It is then they change\nplaces; and the headsman, the chief officer of the little craft,\ntakes his proper station in the bows of the boat.\n\nNow, I care not who maintains the contrary, but all this is both\nfoolish and unnecessary.  The headsman should stay in the bows from\nfirst to last; he should both dart the harpoon and the lance, and no\nrowing whatever should be expected of him, except under circumstances\nobvious to any fisherman.  I know that this would sometimes involve a\nslight loss of speed in the chase; but long experience in various\nwhalemen of more than one nation has convinced me that in the vast\nmajority of failures in the fishery, it has not by any means been so\nmuch the speed of the whale as the before described exhaustion of the\nharpooneer that has caused them.\n\nTo insure the greatest efficiency in the dart, the harpooneers of\nthis world must start to their feet from out of idleness, and not\nfrom out of toil.\n\n\n\nCHAPTER 63\n\nThe Crotch.\n\n\nOut of the trunk, the branches grow; out of them, the twigs.  So, in\nproductive subjects, grow the chapters.\n\nThe crotch alluded to on a previous page deserves independent\nmention.  It is a notched stick of a peculiar form, some two feet in\nlength, which is perpendicularly inserted into the starboard gunwale\nnear the bow, for the purpose of furnishing a rest for the wooden\nextremity of the harpoon, whose other naked, barbed end slopingly\nprojects from the prow.  Thereby the weapon is instantly at hand to\nits hurler, who snatches it up as readily from its rest as a\nbackwoodsman swings his rifle from the wall.  It is customary to have\ntwo harpoons reposing in the crotch, respectively called the first\nand second irons.\n\nBut these two harpoons, each by its own cord, are both connected with\nthe line; the object being this: to dart them both, if possible, one\ninstantly after the other into the same whale; so that if, in the\ncoming drag, one should draw out, the other may still retain a hold.\nIt is a doubling of the chances.  But it very often happens that\nowing to the instantaneous, violent, convulsive running of the whale\nupon receiving the first iron, it becomes impossible for the\nharpooneer, however lightning-like in his movements, to pitch the\nsecond iron into him.  Nevertheless, as the second iron is already\nconnected with the line, and the line is running, hence that weapon\nmust, at all events, be anticipatingly tossed out of the boat,\nsomehow and somewhere; else the most terrible jeopardy would involve\nall hands.  Tumbled into the water, it accordingly is in such cases;\nthe spare coils of box line (mentioned in a preceding chapter) making\nthis feat, in most instances, prudently practicable.  But this\ncritical act is not always unattended with the saddest and most fatal\ncasualties.\n\nFurthermore: you must know that when the second iron is thrown\noverboard, it thenceforth becomes a dangling, sharp-edged terror,\nskittishly curvetting about both boat and whale, entangling the\nlines, or cutting them, and making a prodigious sensation in all\ndirections.  Nor, in general, is it possible to secure it again until\nthe whale is fairly captured and a corpse.\n\nConsider, now, how it must be in the case of four boats all engaging\none unusually strong, active, and knowing whale; when owing to these\nqualities in him, as well as to the thousand concurring accidents of\nsuch an audacious enterprise, eight or ten loose second irons may be\nsimultaneously dangling about him.  For, of course, each boat is\nsupplied with several harpoons to bend on to the line should the\nfirst one be ineffectually darted without recovery.  All these\nparticulars are faithfully narrated here, as they will not fail to\nelucidate several most important, however intricate passages, in\nscenes hereafter to be painted.\n\n\n\nCHAPTER 64\n\nStubb's Supper.\n\n\nStubb's whale had been killed some distance from the ship.  It was a\ncalm; so, forming a tandem of three boats, we commenced the slow\nbusiness of towing the trophy to the Pequod.  And now, as we eighteen\nmen with our thirty-six arms, and one hundred and eighty thumbs and\nfingers, slowly toiled hour after hour upon that inert, sluggish\ncorpse in the sea; and it seemed hardly to budge at all, except at\nlong intervals; good evidence was hereby furnished of the\nenormousness of the mass we moved.  For, upon the great canal of\nHang-Ho, or whatever they call it, in China, four or five laborers on\nthe foot-path will draw a bulky freighted junk at the rate of a mile\nan hour; but this grand argosy we towed heavily forged along, as if\nladen with pig-lead in bulk.\n\nDarkness came on; but three lights up and down in the Pequod's\nmain-rigging dimly guided our way; till drawing nearer we saw Ahab\ndropping one of several more lanterns over the bulwarks.  Vacantly\neyeing the heaving whale for a moment, he issued the usual orders for\nsecuring it for the night, and then handing his lantern to a seaman,\nwent his way into the cabin, and did not come forward again until\nmorning.\n\nThough, in overseeing the pursuit of this whale, Captain Ahab had\nevinced his customary activity, to call it so; yet now that the\ncreature was dead, some vague dissatisfaction, or impatience, or\ndespair, seemed working in him; as if the sight of that dead body\nreminded him that Moby Dick was yet to be slain; and though a\nthousand other whales were brought to his ship, all that would not\none jot advance his grand, monomaniac object.  Very soon you would\nhave thought from the sound on the Pequod's decks, that all hands\nwere preparing to cast anchor in the deep; for heavy chains are being\ndragged along the deck, and thrust rattling out of the port-holes.\nBut by those clanking links, the vast corpse itself, not the ship, is\nto be moored.  Tied by the head to the stern, and by the tail to the\nbows, the whale now lies with its black hull close to the vessel's\nand seen through the darkness of the night, which obscured the spars\nand rigging aloft, the two--ship and whale, seemed yoked together\nlike colossal bullocks, whereof one reclines while the other remains\nstanding.*\n\n\n*A little item may as well be related here.  The strongest and most\nreliable hold which the ship has upon the whale when moored\nalongside, is by the flukes or tail; and as from its greater density\nthat part is relatively heavier than any other (excepting the\nside-fins), its flexibility even in death, causes it to sink low\nbeneath the surface; so that with the hand you cannot get at it from\nthe boat, in order to put the chain round it.  But this difficulty is\ningeniously overcome: a small, strong line is prepared with a wooden\nfloat at its outer end, and a weight in its middle, while the other\nend is secured to the ship.  By adroit management the wooden float is\nmade to rise on the other side of the mass, so that now having\ngirdled the whale, the chain is readily made to follow suit; and\nbeing slipped along the body, is at last locked fast round the\nsmallest part of the tail, at the point of junction with its broad\nflukes or lobes.\n\n\nIf moody Ahab was now all quiescence, at least so far as could be\nknown on deck, Stubb, his second mate, flushed with conquest,\nbetrayed an unusual but still good-natured excitement.  Such an\nunwonted bustle was he in that the staid Starbuck, his official\nsuperior, quietly resigned to him for the time the sole management of\naffairs.  One small, helping cause of all this liveliness in Stubb,\nwas soon made strangely manifest.  Stubb was a high liver; he was\nsomewhat intemperately fond of the whale as a flavorish thing to his\npalate.\n\n\"A steak, a steak, ere I sleep!  You, Daggoo! overboard you go, and\ncut me one from his small!\"\n\nHere be it known, that though these wild fishermen do not, as a\ngeneral thing, and according to the great military maxim, make the\nenemy defray the current expenses of the war (at least before\nrealizing the proceeds of the voyage), yet now and then you find some\nof these Nantucketers who have a genuine relish for that particular\npart of the Sperm Whale designated by Stubb; comprising the tapering\nextremity of the body.\n\nAbout midnight that steak was cut and cooked; and lighted by two\nlanterns of sperm oil, Stubb stoutly stood up to his spermaceti\nsupper at the capstan-head, as if that capstan were a sideboard.  Nor\nwas Stubb the only banqueter on whale's flesh that night.  Mingling\ntheir mumblings with his own mastications, thousands on thousands of\nsharks, swarming round the dead leviathan, smackingly feasted on its\nfatness.  The few sleepers below in their bunks were often startled\nby the sharp slapping of their tails against the hull, within a few\ninches of the sleepers' hearts.  Peering over the side you could just\nsee them (as before you heard them) wallowing in the sullen, black\nwaters, and turning over on their backs as they scooped out huge\nglobular pieces of the whale of the bigness of a human head.  This\nparticular feat of the shark seems all but miraculous.  How at such\nan apparently unassailable surface, they contrive to gouge out such\nsymmetrical mouthfuls, remains a part of the universal problem of all\nthings.  The mark they thus leave on the whale, may best be likened\nto the hollow made by a carpenter in countersinking for a screw.\n\nThough amid all the smoking horror and diabolism of a sea-fight,\nsharks will be seen longingly gazing up to the ship's decks, like\nhungry dogs round a table where red meat is being carved, ready to\nbolt down every killed man that is tossed to them; and though, while\nthe valiant butchers over the deck-table are thus cannibally carving\neach other's live meat with carving-knives all gilded and tasselled,\nthe sharks, also, with their jewel-hilted mouths, are quarrelsomely\ncarving away under the table at the dead meat; and though, were you\nto turn the whole affair upside down, it would still be pretty much\nthe same thing, that is to say, a shocking sharkish business enough\nfor all parties; and though sharks also are the invariable outriders\nof all slave ships crossing the Atlantic, systematically trotting\nalongside, to be handy in case a parcel is to be carried anywhere, or\na dead slave to be decently buried; and though one or two other like\ninstances might be set down, touching the set terms, places, and\noccasions, when sharks do most socially congregate, and most\nhilariously feast; yet is there no conceivable time or occasion when\nyou will find them in such countless numbers, and in gayer or more\njovial spirits, than around a dead sperm whale, moored by night to a\nwhaleship at sea.  If you have never seen that sight, then suspend\nyour decision about the propriety of devil-worship, and the\nexpediency of conciliating the devil.\n\nBut, as yet, Stubb heeded not the mumblings of the banquet that was\ngoing on so nigh him, no more than the sharks heeded the smacking of\nhis own epicurean lips.\n\n\"Cook, cook!--where's that old Fleece?\" he cried at length, widening\nhis legs still further, as if to form a more secure base for his\nsupper; and, at the same time darting his fork into the dish, as if\nstabbing with his lance; \"cook, you cook!--sail this way, cook!\"\n\nThe old black, not in any very high glee at having been previously\nroused from his warm hammock at a most unseasonable hour, came\nshambling along from his galley, for, like many old blacks, there was\nsomething the matter with his knee-pans, which he did not keep well\nscoured like his other pans; this old Fleece, as they called him,\ncame shuffling and limping along, assisting his step with his tongs,\nwhich, after a clumsy fashion, were made of straightened iron hoops;\nthis old Ebony floundered along, and in obedience to the word of\ncommand, came to a dead stop on the opposite side of Stubb's\nsideboard; when, with both hands folded before him, and resting on\nhis two-legged cane, he bowed his arched back still further over, at\nthe same time sideways inclining his head, so as to bring his best\near into play.\n\n\"Cook,\" said Stubb, rapidly lifting a rather reddish morsel to his\nmouth, \"don't you think this steak is rather overdone?  You've been\nbeating this steak too much, cook; it's too tender.  Don't I always\nsay that to be good, a whale-steak must be tough?  There are those\nsharks now over the side, don't you see they prefer it tough and\nrare?  What a shindy they are kicking up!  Cook, go and talk to 'em;\ntell 'em they are welcome to help themselves civilly, and in\nmoderation, but they must keep quiet.  Blast me, if I can hear my own\nvoice.  Away, cook, and deliver my message.  Here, take this\nlantern,\" snatching one from his sideboard; \"now then, go and preach\nto 'em!\"\n\nSullenly taking the offered lantern, old Fleece limped across the\ndeck to the bulwarks; and then, with one hand dropping his light low\nover the sea, so as to get a good view of his congregation, with the\nother hand he solemnly flourished his tongs, and leaning far over the\nside in a mumbling voice began addressing the sharks, while Stubb,\nsoftly crawling behind, overheard all that was said.\n\n\"Fellow-critters: I'se ordered here to say dat you must stop dat dam\nnoise dare.  You hear?  Stop dat dam smackin' ob de lips!  Massa\nStubb say dat you can fill your dam bellies up to de hatchings, but\nby Gor! you must stop dat dam racket!\"\n\n\"Cook,\" here interposed Stubb, accompanying the word with a sudden\nslap on the shoulder,--\"Cook! why, damn your eyes, you mustn't swear\nthat way when you're preaching.  That's no way to convert sinners,\ncook!\"\n\n\"Who dat?  Den preach to him yourself,\" sullenly turning to go.\n\n\"No, cook; go on, go on.\"\n\n\"Well, den, Belubed fellow-critters:\"-\n\n\"Right!\" exclaimed Stubb, approvingly, \"coax 'em to it; try that,\"\nand Fleece continued.\n\n\"Do you is all sharks, and by natur wery woracious, yet I zay to you,\nfellow-critters, dat dat woraciousness--'top dat dam slappin' ob de\ntail!  How you tink to hear, spose you keep up such a dam slappin'\nand bitin' dare?\"\n\n\"Cook,\" cried Stubb, collaring him, \"I won't have that swearing.\nTalk to 'em gentlemanly.\"\n\nOnce more the sermon proceeded.\n\n\"Your woraciousness, fellow-critters, I don't blame ye so much for;\ndat is natur, and can't be helped; but to gobern dat wicked natur,\ndat is de pint.  You is sharks, sartin; but if you gobern de shark in\nyou, why den you be angel; for all angel is not'ing more dan de shark\nwell goberned.  Now, look here, bred'ren, just try wonst to be cibil,\na helping yourselbs from dat whale.  Don't be tearin' de blubber out\nyour neighbour's mout, I say.  Is not one shark dood right as toder\nto dat whale?  And, by Gor, none on you has de right to dat whale;\ndat whale belong to some one else.  I know some o' you has berry brig\nmout, brigger dan oders; but den de brig mouts sometimes has de\nsmall bellies; so dat de brigness of de mout is not to swaller wid,\nbut to bit off de blubber for de small fry ob sharks, dat can't get\ninto de scrouge to help demselves.\"\n\n\"Well done, old Fleece!\" cried Stubb, \"that's Christianity; go on.\"\n\n\"No use goin' on; de dam willains will keep a scougin' and slappin'\neach oder, Massa Stubb; dey don't hear one word; no use a-preaching\nto such dam g'uttons as you call 'em, till dare bellies is full, and\ndare bellies is bottomless; and when dey do get 'em full, dey wont\nhear you den; for den dey sink in the sea, go fast to sleep on de\ncoral, and can't hear noting at all, no more, for eber and eber.\"\n\n\"Upon my soul, I am about of the same opinion; so give the\nbenediction, Fleece, and I'll away to my supper.\"\n\nUpon this, Fleece, holding both hands over the fishy mob, raised his\nshrill voice, and cried--\n\n\"Cussed fellow-critters!  Kick up de damndest row as ever you can;\nfill your dam bellies 'till dey bust--and den die.\"\n\n\"Now, cook,\" said Stubb, resuming his supper at the capstan; \"stand\njust where you stood before, there, over against me, and pay\nparticular attention.\"\n\n\"All 'dention,\" said Fleece, again stooping over upon his tongs in\nthe desired position.\n\n\"Well,\" said Stubb, helping himself freely meanwhile; \"I shall now go\nback to the subject of this steak.  In the first place, how old are\nyou, cook?\"\n\n\"What dat do wid de 'teak,\" said the old black, testily.\n\n\"Silence!  How old are you, cook?\"\n\n\"'Bout ninety, dey say,\" he gloomily muttered.\n\n\"And you have lived in this world hard upon one hundred years, cook,\nand don't know yet how to cook a whale-steak?\" rapidly bolting\nanother mouthful at the last word, so that morsel seemed a\ncontinuation of the question.  \"Where were you born, cook?\"\n\n\"'Hind de hatchway, in ferry-boat, goin' ober de Roanoke.\"\n\n\"Born in a ferry-boat!  That's queer, too.  But I want to know what\ncountry you were born in, cook!\"\n\n\"Didn't I say de Roanoke country?\" he cried sharply.\n\n\"No, you didn't, cook; but I'll tell you what I'm coming to, cook.\nYou must go home and be born over again; you don't know how to cook a\nwhale-steak yet.\"\n\n\"Bress my soul, if I cook noder one,\" he growled, angrily, turning\nround to depart.\n\n\"Come back here, cook;--here, hand me those tongs;--now take that bit\nof steak there, and tell me if you think that steak cooked as it\nshould be?  Take it, I say\"--holding the tongs towards him--\"take it,\nand taste it.\"\n\nFaintly smacking his withered lips over it for a moment, the old\nnegro muttered, \"Best cooked 'teak I eber taste; joosy, berry joosy.\"\n\n\"Cook,\" said Stubb, squaring himself once more; \"do you belong to the\nchurch?\"\n\n\"Passed one once in Cape-Down,\" said the old man sullenly.\n\n\"And you have once in your life passed a holy church in Cape-Town,\nwhere you doubtless overheard a holy parson addressing his hearers as\nhis beloved fellow-creatures, have you, cook!  And yet you come here,\nand tell me such a dreadful lie as you did just now, eh?\" said Stubb.\n\"Where do you expect to go to, cook?\"\n\n\"Go to bed berry soon,\" he mumbled, half-turning as he spoke.\n\n\"Avast! heave to!  I mean when you die, cook.  It's an awful\nquestion.  Now what's your answer?\"\n\n\"When dis old brack man dies,\" said the negro slowly, changing his\nwhole air and demeanor, \"he hisself won't go nowhere; but some\nbressed angel will come and fetch him.\"\n\n\"Fetch him?  How?  In a coach and four, as they fetched Elijah?  And\nfetch him where?\"\n\n\"Up dere,\" said Fleece, holding his tongs straight over his head, and\nkeeping it there very solemnly.\n\n\"So, then, you expect to go up into our main-top, do you, cook, when\nyou are dead?  But don't you know the higher you climb, the colder it\ngets?  Main-top, eh?\"\n\n\"Didn't say dat t'all,\" said Fleece, again in the sulks.\n\n\"You said up there, didn't you? and now look yourself, and see where\nyour tongs are pointing.  But, perhaps you expect to get into heaven\nby crawling through the lubber's hole, cook; but, no, no, cook, you\ndon't get there, except you go the regular way, round by the rigging.\nIt's a ticklish business, but must be done, or else it's no go.  But\nnone of us are in heaven yet.  Drop your tongs, cook, and hear my\norders.  Do ye hear?  Hold your hat in one hand, and clap t'other\na'top of your heart, when I'm giving my orders, cook.  What! that\nyour heart, there?--that's your gizzard!  Aloft! aloft!--that's\nit--now you have it.  Hold it there now, and pay attention.\"\n\n\"All 'dention,\" said the old black, with both hands placed as\ndesired, vainly wriggling his grizzled head, as if to get both ears\nin front at one and the same time.\n\n\"Well then, cook, you see this whale-steak of yours was so very bad,\nthat I have put it out of sight as soon as possible; you see that,\ndon't you?  Well, for the future, when you cook another whale-steak\nfor my private table here, the capstan, I'll tell you what to do so\nas not to spoil it by overdoing.  Hold the steak in one hand, and\nshow a live coal to it with the other; that done, dish it; d'ye hear?\nAnd now to-morrow, cook, when we are cutting in the fish, be sure\nyou stand by to get the tips of his fins; have them put in pickle.\nAs for the ends of the flukes, have them soused, cook.  There, now ye\nmay go.\"\n\nBut Fleece had hardly got three paces off, when he was recalled.\n\n\"Cook, give me cutlets for supper to-morrow night in the mid-watch.\nD'ye hear? away you sail, then.--Halloa! stop! make a bow before you\ngo.--Avast heaving again!  Whale-balls for breakfast--don't forget.\"\n\n\"Wish, by gor! whale eat him, 'stead of him eat whale.  I'm bressed\nif he ain't more of shark dan Massa Shark hisself,\" muttered the old\nman, limping away; with which sage ejaculation he went to his\nhammock.\n\n\n\nCHAPTER 65\n\nThe Whale as a Dish.\n\n\nThat mortal man should feed upon the creature that feeds his lamp,\nand, like Stubb, eat him by his own light, as you may say; this seems\nso outlandish a thing that one must needs go a little into the\nhistory and philosophy of it.\n\nIt is upon record, that three centuries ago the tongue of the Right\nWhale was esteemed a great delicacy in France, and commanded large\nprices there.  Also, that in Henry VIIIth's time, a certain cook of\nthe court obtained a handsome reward for inventing an admirable sauce\nto be eaten with barbacued porpoises, which, you remember, are a\nspecies of whale.  Porpoises, indeed, are to this day considered fine\neating.  The meat is made into balls about the size of billiard\nballs, and being well seasoned and spiced might be taken for\nturtle-balls or veal balls.  The old monks of Dunfermline were very\nfond of them.  They had a great porpoise grant from the crown.\n\nThe fact is, that among his hunters at least, the whale would by all\nhands be considered a noble dish, were there not so much of him; but\nwhen you come to sit down before a meat-pie nearly one hundred feet\nlong, it takes away your appetite.  Only the most unprejudiced of men\nlike Stubb, nowadays partake of cooked whales; but the Esquimaux are\nnot so fastidious.  We all know how they live upon whales, and have\nrare old vintages of prime old train oil.  Zogranda, one of their\nmost famous doctors, recommends strips of blubber for infants, as\nbeing exceedingly juicy and nourishing.  And this reminds me that\ncertain Englishmen, who long ago were accidentally left in Greenland\nby a whaling vessel--that these men actually lived for several months\non the mouldy scraps of whales which had been left ashore after\ntrying out the blubber.  Among the Dutch whalemen these scraps are\ncalled \"fritters\"; which, indeed, they greatly resemble, being brown\nand crisp, and smelling something like old Amsterdam housewives'\ndough-nuts or oly-cooks, when fresh.  They have such an eatable look\nthat the most self-denying stranger can hardly keep his hands off.\n\nBut what further depreciates the whale as a civilized dish, is his\nexceeding richness.  He is the great prize ox of the sea, too fat to\nbe delicately good.  Look at his hump, which would be as fine eating\nas the buffalo's (which is esteemed a rare dish), were it not such a\nsolid pyramid of fat.  But the spermaceti itself, how bland and\ncreamy that is; like the transparent, half-jellied, white meat of a\ncocoanut in the third month of its growth, yet far too rich to supply\na substitute for butter.  Nevertheless, many whalemen have a method\nof absorbing it into some other substance, and then partaking of it.\nIn the long try watches of the night it is a common thing for the\nseamen to dip their ship-biscuit into the huge oil-pots and let them\nfry there awhile.  Many a good supper have I thus made.\n\nIn the case of a small Sperm Whale the brains are accounted a fine\ndish.  The casket of the skull is broken into with an axe, and the\ntwo plump, whitish lobes being withdrawn (precisely resembling two\nlarge puddings), they are then mixed with flour, and cooked into a\nmost delectable mess, in flavor somewhat resembling calves' head,\nwhich is quite a dish among some epicures; and every one knows that\nsome young bucks among the epicures, by continually dining upon\ncalves' brains, by and by get to have a little brains of their own,\nso as to be able to tell a calf's head from their own heads; which,\nindeed, requires uncommon discrimination.  And that is the reason why\na young buck with an intelligent looking calf's head before him, is\nsomehow one of the saddest sights you can see.  The head looks a sort\nof reproachfully at him, with an \"Et tu Brute!\" expression.\n\nIt is not, perhaps, entirely because the whale is so excessively\nunctuous that landsmen seem to regard the eating of him with\nabhorrence; that appears to result, in some way, from the\nconsideration before mentioned: i.e. that a man should eat a newly\nmurdered thing of the sea, and eat it too by its own light.  But no\ndoubt the first man that ever murdered an ox was regarded as a\nmurderer; perhaps he was hung; and if he had been put on his trial by\noxen, he certainly would have been; and he certainly deserved it if\nany murderer does.  Go to the meat-market of a Saturday night and see\nthe crowds of live bipeds staring up at the long rows of dead\nquadrupeds.  Does not that sight take a tooth out of the cannibal's\njaw?  Cannibals? who is not a cannibal?  I tell you it will be more\ntolerable for the Fejee that salted down a lean missionary in his\ncellar against a coming famine; it will be more tolerable for that\nprovident Fejee, I say, in the day of judgment, than for thee,\ncivilized and enlightened gourmand, who nailest geese to the ground\nand feastest on their bloated livers in thy pate-de-foie-gras.\n\nBut Stubb, he eats the whale by its own light, does he? and that is\nadding insult to injury, is it?  Look at your knife-handle, there, my\ncivilized and enlightened gourmand dining off that roast beef, what\nis that handle made of?--what but the bones of the brother of the\nvery ox you are eating?  And what do you pick your teeth with, after\ndevouring that fat goose?  With a feather of the same fowl.  And with\nwhat quill did the Secretary of the Society for the Suppression of\nCruelty to Ganders formally indite his circulars?  It is only within\nthe last month or two that that society passed a resolution to\npatronise nothing but steel pens.\n\n\n\nCHAPTER 66\n\nThe Shark Massacre.\n\n\nWhen in the Southern Fishery, a captured Sperm Whale, after long and\nweary toil, is brought alongside late at night, it is not, as a\ngeneral thing at least, customary to proceed at once to the business\nof cutting him in.  For that business is an exceedingly laborious\none; is not very soon completed; and requires all hands to set about\nit.  Therefore, the common usage is to take in all sail; lash the\nhelm a'lee; and then send every one below to his hammock till\ndaylight, with the reservation that, until that time, anchor-watches\nshall be kept; that is, two and two for an hour, each couple, the\ncrew in rotation shall mount the deck to see that all goes well.\n\nBut sometimes, especially upon the Line in the Pacific, this plan\nwill not answer at all; because such incalculable hosts of sharks\ngather round the moored carcase, that were he left so for six hours,\nsay, on a stretch, little more than the skeleton would be visible by\nmorning.  In most other parts of the ocean, however, where these fish\ndo not so largely abound, their wondrous voracity can be at times\nconsiderably diminished, by vigorously stirring them up with sharp\nwhaling-spades, a procedure notwithstanding, which, in some\ninstances, only seems to tickle them into still greater activity.\nBut it was not thus in the present case with the Pequod's sharks;\nthough, to be sure, any man unaccustomed to such sights, to have\nlooked over her side that night, would have almost thought the whole\nround sea was one huge cheese, and those sharks the maggots in it.\n\nNevertheless, upon Stubb setting the anchor-watch after his supper\nwas concluded; and when, accordingly, Queequeg and a forecastle\nseaman came on deck, no small excitement was created among the\nsharks; for immediately suspending the cutting stages over the side,\nand lowering three lanterns, so that they cast long gleams of light\nover the turbid sea, these two mariners, darting their long\nwhaling-spades, kept up an incessant murdering of the sharks,* by\nstriking the keen steel deep into their skulls, seemingly their only\nvital part.  But in the foamy confusion of their mixed and struggling\nhosts, the marksmen could not always hit their mark; and this brought\nabout new revelations of the incredible ferocity of the foe.  They\nviciously snapped, not only at each other's disembowelments, but like\nflexible bows, bent round, and bit their own; till those entrails\nseemed swallowed over and over again by the same mouth, to be\noppositely voided by the gaping wound.  Nor was this all.  It was\nunsafe to meddle with the corpses and ghosts of these creatures.  A\nsort of generic or Pantheistic vitality seemed to lurk in their very\njoints and bones, after what might be called the individual life had\ndeparted.  Killed and hoisted on deck for the sake of his skin, one\nof these sharks almost took poor Queequeg's hand off, when he tried\nto shut down the dead lid of his murderous jaw.\n\n\n*The whaling-spade used for cutting-in is made of the very best\nsteel; is about the bigness of a man's spread hand; and in general\nshape, corresponds to the garden implement after which it is named;\nonly its sides are perfectly flat, and its upper end considerably\nnarrower than the lower.  This weapon is always kept as sharp as\npossible; and when being used is occasionally honed, just like a\nrazor.  In its socket, a stiff pole, from twenty to thirty feet long,\nis inserted for a handle.\n\n\n\"Queequeg no care what god made him shark,\" said the savage,\nagonizingly lifting his hand up and down; \"wedder Fejee god or\nNantucket god; but de god wat made shark must be one dam Ingin.\"\n\n\n\nCHAPTER 67\n\nCutting In.\n\n\nIt was a Saturday night, and such a Sabbath as followed!  Ex officio\nprofessors of Sabbath breaking are all whalemen.  The ivory Pequod\nwas turned into what seemed a shamble; every sailor a butcher.  You\nwould have thought we were offering up ten thousand red oxen to the\nsea gods.\n\nIn the first place, the enormous cutting tackles, among other\nponderous things comprising a cluster of blocks generally painted\ngreen, and which no single man can possibly lift--this vast bunch of\ngrapes was swayed up to the main-top and firmly lashed to the lower\nmast-head, the strongest point anywhere above a ship's deck.  The end\nof the hawser-like rope winding through these intricacies, was then\nconducted to the windlass, and the huge lower block of the tackles\nwas swung over the whale; to this block the great blubber hook,\nweighing some one hundred pounds, was attached.  And now suspended in\nstages over the side, Starbuck and Stubb, the mates, armed with their\nlong spades, began cutting a hole in the body for the insertion of\nthe hook just above the nearest of the two side-fins.  This done, a\nbroad, semicircular line is cut round the hole, the hook is inserted,\nand the main body of the crew striking up a wild chorus, now commence\nheaving in one dense crowd at the windlass.  When instantly, the\nentire ship careens over on her side; every bolt in her starts like\nthe nail-heads of an old house in frosty weather; she trembles,\nquivers, and nods her frighted mast-heads to the sky.  More and more\nshe leans over to the whale, while every gasping heave of the\nwindlass is answered by a helping heave from the billows; till at\nlast, a swift, startling snap is heard; with a great swash the ship\nrolls upwards and backwards from the whale, and the triumphant tackle\nrises into sight dragging after it the disengaged semicircular end of\nthe first strip of blubber.  Now as the blubber envelopes the whale\nprecisely as the rind does an orange, so is it stripped off from the\nbody precisely as an orange is sometimes stripped by spiralizing it.\nFor the strain constantly kept up by the windlass continually keeps\nthe whale rolling over and over in the water, and as the blubber in\none strip uniformly peels off along the line called the \"scarf,\"\nsimultaneously cut by the spades of Starbuck and Stubb, the mates;\nand just as fast as it is thus peeled off, and indeed by that very\nact itself, it is all the time being hoisted higher and higher aloft\ntill its upper end grazes the main-top; the men at the windlass then\ncease heaving, and for a moment or two the prodigious blood-dripping\nmass sways to and fro as if let down from the sky, and every one\npresent must take good heed to dodge it when it swings, else it may\nbox his ears and pitch him headlong overboard.\n\nOne of the attending harpooneers now advances with a long, keen\nweapon called a boarding-sword, and watching his chance he\ndexterously slices out a considerable hole in the lower part of the\nswaying mass.  Into this hole, the end of the second alternating\ngreat tackle is then hooked so as to retain a hold upon the blubber,\nin order to prepare for what follows.  Whereupon, this accomplished\nswordsman, warning all hands to stand off, once more makes a\nscientific dash at the mass, and with a few sidelong, desperate,\nlunging slicings, severs it completely in twain; so that while the\nshort lower part is still fast, the long upper strip, called a\nblanket-piece, swings clear, and is all ready for lowering.  The\nheavers forward now resume their song, and while the one tackle is\npeeling and hoisting a second strip from the whale, the other is\nslowly slackened away, and down goes the first strip through the main\nhatchway right beneath, into an unfurnished parlor called the\nblubber-room.  Into this twilight apartment sundry nimble hands keep\ncoiling away the long blanket-piece as if it were a great live mass\nof plaited serpents.  And thus the work proceeds; the two tackles\nhoisting and lowering simultaneously; both whale and windlass\nheaving, the heavers singing, the blubber-room gentlemen coiling, the\nmates scarfing, the ship straining, and all hands swearing\noccasionally, by way of assuaging the general friction.\n\n\n\nCHAPTER 68\n\nThe Blanket.\n\n\nI have given no small attention to that not unvexed subject, the skin\nof the whale.  I have had controversies about it with experienced\nwhalemen afloat, and learned naturalists ashore.  My original opinion\nremains unchanged; but it is only an opinion.\n\nThe question is, what and where is the skin of the whale?  Already\nyou know what his blubber is.  That blubber is something of the\nconsistence of firm, close-grained beef, but tougher, more elastic\nand compact, and ranges from eight or ten to twelve and fifteen\ninches in thickness.\n\nNow, however preposterous it may at first seem to talk of any\ncreature's skin as being of that sort of consistence and thickness,\nyet in point of fact these are no arguments against such a\npresumption; because you cannot raise any other dense enveloping\nlayer from the whale's body but that same blubber; and the outermost\nenveloping layer of any animal, if reasonably dense, what can that be\nbut the skin?  True, from the unmarred dead body of the whale, you\nmay scrape off with your hand an infinitely thin, transparent\nsubstance, somewhat resembling the thinnest shreds of isinglass, only\nit is almost as flexible and soft as satin; that is, previous to\nbeing dried, when it not only contracts and thickens, but becomes\nrather hard and brittle.  I have several such dried bits, which I use\nfor marks in my whale-books.  It is transparent, as I said before;\nand being laid upon the printed page, I have sometimes pleased myself\nwith fancying it exerted a magnifying influence.  At any rate, it is\npleasant to read about whales through their own spectacles, as you\nmay say.  But what I am driving at here is this.  That same\ninfinitely thin, isinglass substance, which, I admit, invests the\nentire body of the whale, is not so much to be regarded as the skin\nof the creature, as the skin of the skin, so to speak; for it were\nsimply ridiculous to say, that the proper skin of the tremendous\nwhale is thinner and more tender than the skin of a new-born child.\nBut no more of this.\n\nAssuming the blubber to be the skin of the whale; then, when this\nskin, as in the case of a very large Sperm Whale, will yield the bulk\nof one hundred barrels of oil; and, when it is considered that, in\nquantity, or rather weight, that oil, in its expressed state, is only\nthree fourths, and not the entire substance of the coat; some idea\nmay hence be had of the enormousness of that animated mass, a mere\npart of whose mere integument yields such a lake of liquid as that.\nReckoning ten barrels to the ton, you have ten tons for the net\nweight of only three quarters of the stuff of the whale's skin.\n\nIn life, the visible surface of the Sperm Whale is not the least\namong the many marvels he presents.  Almost invariably it is all over\nobliquely crossed and re-crossed with numberless straight marks in\nthick array, something like those in the finest Italian line\nengravings.  But these marks do not seem to be impressed upon the\nisinglass substance above mentioned, but seem to be seen through it,\nas if they were engraved upon the body itself.  Nor is this all.  In\nsome instances, to the quick, observant eye, those linear marks, as\nin a veritable engraving, but afford the ground for far other\ndelineations.  These are hieroglyphical; that is, if you call those\nmysterious cyphers on the walls of pyramids hieroglyphics, then that\nis the proper word to use in the present connexion.  By my retentive\nmemory of the hieroglyphics upon one Sperm Whale in particular, I was\nmuch struck with a plate representing the old Indian characters\nchiselled on the famous hieroglyphic palisades on the banks of the\nUpper Mississippi.  Like those mystic rocks, too, the mystic-marked\nwhale remains undecipherable.  This allusion to the Indian rocks\nreminds me of another thing.  Besides all the other phenomena which\nthe exterior of the Sperm Whale presents, he not seldom displays the\nback, and more especially his flanks, effaced in great part of the\nregular linear appearance, by reason of numerous rude scratches,\naltogether of an irregular, random aspect.  I should say that those\nNew England rocks on the sea-coast, which Agassiz imagines to bear\nthe marks of violent scraping contact with vast floating icebergs--I\nshould say, that those rocks must not a little resemble the Sperm\nWhale in this particular.  It also seems to me that such scratches in\nthe whale are probably made by hostile contact with other whales; for\nI have most remarked them in the large, full-grown bulls of the\nspecies.\n\nA word or two more concerning this matter of the skin or blubber of\nthe whale.  It has already been said, that it is stript from him in\nlong pieces, called blanket-pieces.  Like most sea-terms, this one is\nvery happy and significant.  For the whale is indeed wrapt up in his\nblubber as in a real blanket or counterpane; or, still better, an\nIndian poncho slipt over his head, and skirting his extremity.  It is\nby reason of this cosy blanketing of his body, that the whale is\nenabled to keep himself comfortable in all weathers, in all seas,\ntimes, and tides.  What would become of a Greenland whale, say, in\nthose shuddering, icy seas of the North, if unsupplied with his cosy\nsurtout?  True, other fish are found exceedingly brisk in those\nHyperborean waters; but these, be it observed, are your cold-blooded,\nlungless fish, whose very bellies are refrigerators; creatures, that\nwarm themselves under the lee of an iceberg, as a traveller in winter\nwould bask before an inn fire; whereas, like man, the whale has lungs\nand warm blood.  Freeze his blood, and he dies.  How wonderful is it\nthen--except after explanation--that this great monster, to whom\ncorporeal warmth is as indispensable as it is to man; how wonderful\nthat he should be found at home, immersed to his lips for life in\nthose Arctic waters! where, when seamen fall overboard, they are\nsometimes found, months afterwards, perpendicularly frozen into the\nhearts of fields of ice, as a fly is found glued in amber.  But more\nsurprising is it to know, as has been proved by experiment, that the\nblood of a Polar whale is warmer than that of a Borneo negro in\nsummer.\n\nIt does seem to me, that herein we see the rare virtue of a strong\nindividual vitality, and the rare virtue of thick walls, and the rare\nvirtue of interior spaciousness.  Oh, man! admire and model thyself\nafter the whale!  Do thou, too, remain warm among ice.  Do thou, too,\nlive in this world without being of it.  Be cool at the equator; keep\nthy blood fluid at the Pole.  Like the great dome of St. Peter's, and\nlike the great whale, retain, O man! in all seasons a temperature of\nthine own.\n\nBut how easy and how hopeless to teach these fine things!  Of\nerections, how few are domed like St. Peter's! of creatures, how few\nvast as the whale!\n\n\n\nCHAPTER 69\n\nThe Funeral.\n\n\nHaul in the chains!  Let the carcase go astern!\n\nThe vast tackles have now done their duty.  The peeled white body of\nthe beheaded whale flashes like a marble sepulchre; though changed in\nhue, it has not perceptibly lost anything in bulk.  It is still\ncolossal.  Slowly it floats more and more away, the water round it\ntorn and splashed by the insatiate sharks, and the air above vexed\nwith rapacious flights of screaming fowls, whose beaks are like so\nmany insulting poniards in the whale.  The vast white headless\nphantom floats further and further from the ship, and every rod that\nit so floats, what seem square roods of sharks and cubic roods of\nfowls, augment the murderous din.  For hours and hours from the\nalmost stationary ship that hideous sight is seen.  Beneath the\nunclouded and mild azure sky, upon the fair face of the pleasant sea,\nwafted by the joyous breezes, that great mass of death floats on and\non, till lost in infinite perspectives.\n\nThere's a most doleful and most mocking funeral!  The sea-vultures\nall in pious mourning, the air-sharks all punctiliously in black or\nspeckled.  In life but few of them would have helped the whale, I\nween, if peradventure he had needed it; but upon the banquet of his\nfuneral they most piously do pounce.  Oh, horrible vultureism of\nearth! from which not the mightiest whale is free.\n\nNor is this the end.  Desecrated as the body is, a vengeful ghost\nsurvives and hovers over it to scare.  Espied by some timid\nman-of-war or blundering discovery-vessel from afar, when the\ndistance obscuring the swarming fowls, nevertheless still shows the\nwhite mass floating in the sun, and the white spray heaving high\nagainst it; straightway the whale's unharming corpse, with trembling\nfingers is set down in the log--SHOALS, ROCKS, AND BREAKERS\nHEREABOUTS: BEWARE!  And for years afterwards, perhaps, ships shun\nthe place; leaping over it as silly sheep leap over a vacuum, because\ntheir leader originally leaped there when a stick was held.  There's\nyour law of precedents; there's your utility of traditions; there's\nthe story of your obstinate survival of old beliefs never bottomed on\nthe earth, and now not even hovering in the air!  There's orthodoxy!\n\nThus, while in life the great whale's body may have been a real\nterror to his foes, in his death his ghost becomes a powerless panic\nto a world.\n\nAre you a believer in ghosts, my friend?  There are other ghosts than\nthe Cock-Lane one, and far deeper men than Doctor Johnson who believe\nin them.\n\n\n\nCHAPTER 70\n\nThe Sphynx.\n\n\nIt should not have been omitted that previous to completely stripping\nthe body of the leviathan, he was beheaded.  Now, the beheading of\nthe Sperm Whale is a scientific anatomical feat, upon which\nexperienced whale surgeons very much pride themselves: and not\nwithout reason.\n\nConsider that the whale has nothing that can properly be called a\nneck; on the contrary, where his head and body seem to join, there,\nin that very place, is the thickest part of him.  Remember, also,\nthat the surgeon must operate from above, some eight or ten feet\nintervening between him and his subject, and that subject almost\nhidden in a discoloured, rolling, and oftentimes tumultuous and\nbursting sea.  Bear in mind, too, that under these untoward\ncircumstances he has to cut many feet deep in the flesh; and in that\nsubterraneous manner, without so much as getting one single peep into\nthe ever-contracting gash thus made, he must skilfully steer clear\nof all adjacent, interdicted parts, and exactly divide the spine at a\ncritical point hard by its insertion into the skull.  Do you not\nmarvel, then, at Stubb's boast, that he demanded but ten minutes to\nbehead a sperm whale?\n\nWhen first severed, the head is dropped astern and held there by a\ncable till the body is stripped.  That done, if it belong to a small\nwhale it is hoisted on deck to be deliberately disposed of.  But,\nwith a full grown leviathan this is impossible; for the sperm whale's\nhead embraces nearly one third of his entire bulk, and completely to\nsuspend such a burden as that, even by the immense tackles of a\nwhaler, this were as vain a thing as to attempt weighing a Dutch barn\nin jewellers' scales.\n\nThe Pequod's whale being decapitated and the body stripped, the head\nwas hoisted against the ship's side--about half way out of the sea,\nso that it might yet in great part be buoyed up by its native\nelement.  And there with the strained craft steeply leaning over to it,\nby reason of the enormous downward drag from the lower mast-head, and\nevery yard-arm on that side projecting like a crane over the waves;\nthere, that blood-dripping head hung to the Pequod's waist like the\ngiant Holofernes's from the girdle of Judith.\n\nWhen this last task was accomplished it was noon, and the seamen went\nbelow to their dinner.  Silence reigned over the before tumultuous\nbut now deserted deck.  An intense copper calm, like a universal\nyellow lotus, was more and more unfolding its noiseless measureless\nleaves upon the sea.\n\nA short space elapsed, and up into this noiselessness came Ahab alone\nfrom his cabin.  Taking a few turns on the quarter-deck, he paused to\ngaze over the side, then slowly getting into the main-chains he took\nStubb's long spade--still remaining there after the whale's\nDecapitation--and striking it into the lower part of the\nhalf-suspended mass, placed its other end crutch-wise under one arm,\nand so stood leaning over with eyes attentively fixed on this head.\n\nIt was a black and hooded head; and hanging there in the midst of so\nintense a calm, it seemed the Sphynx's in the desert.  \"Speak, thou\nvast and venerable head,\" muttered Ahab, \"which, though ungarnished\nwith a beard, yet here and there lookest hoary with mosses; speak,\nmighty head, and tell us the secret thing that is in thee.  Of all\ndivers, thou hast dived the deepest.  That head upon which the upper\nsun now gleams, has moved amid this world's foundations.  Where\nunrecorded names and navies rust, and untold hopes and anchors rot;\nwhere in her murderous hold this frigate earth is ballasted with\nbones of millions of the drowned; there, in that awful water-land,\nthere was thy most familiar home.  Thou hast been where bell or diver\nnever went; hast slept by many a sailor's side, where sleepless\nmothers would give their lives to lay them down.  Thou saw'st the\nlocked lovers when leaping from their flaming ship; heart to heart\nthey sank beneath the exulting wave; true to each other, when heaven\nseemed false to them.  Thou saw'st the murdered mate when tossed by\npirates from the midnight deck; for hours he fell into the deeper\nmidnight of the insatiate maw; and his murderers still sailed on\nunharmed--while swift lightnings shivered the neighboring ship that\nwould have borne a righteous husband to outstretched, longing arms.\nO head! thou hast seen enough to split the planets and make an\ninfidel of Abraham, and not one syllable is thine!\"\n\n\"Sail ho!\" cried a triumphant voice from the main-mast-head.\n\n\"Aye?  Well, now, that's cheering,\" cried Ahab, suddenly erecting\nhimself, while whole thunder-clouds swept aside from his brow.  \"That\nlively cry upon this deadly calm might almost convert a better\nman.--Where away?\"\n\n\"Three points on the starboard bow, sir, and bringing down her breeze\nto us!\n\n\"Better and better, man.  Would now St. Paul would come along that\nway, and to my breezelessness bring his breeze!  O Nature, and O soul\nof man! how far beyond all utterance are your linked analogies! not\nthe smallest atom stirs or lives on matter, but has its cunning\nduplicate in mind.\"\n\n\n\nCHAPTER 71\n\nThe Jeroboam's Story.\n\n\nHand in hand, ship and breeze blew on; but the breeze came faster\nthan the ship, and soon the Pequod began to rock.\n\nBy and by, through the glass the stranger's boats and manned\nmast-heads proved her a whale-ship.  But as she was so far to\nwindward, and shooting by, apparently making a passage to some other\nground, the Pequod could not hope to reach her.  So the signal was\nset to see what response would be made.\n\nHere be it said, that like the vessels of military marines, the ships\nof the American Whale Fleet have each a private signal; all which\nsignals being collected in a book with the names of the respective\nvessels attached, every captain is provided with it.  Thereby, the\nwhale commanders are enabled to recognise each other upon the ocean,\neven at considerable distances and with no small facility.\n\nThe Pequod's signal was at last responded to by the stranger's\nsetting her own; which proved the ship to be the Jeroboam of\nNantucket.  Squaring her yards, she bore down, ranged abeam under the\nPequod's lee, and lowered a boat; it soon drew nigh; but, as the\nside-ladder was being rigged by Starbuck's order to accommodate the\nvisiting captain, the stranger in question waved his hand from his\nboat's stern in token of that proceeding being entirely unnecessary.\nIt turned out that the Jeroboam had a malignant epidemic on board,\nand that Mayhew, her captain, was fearful of infecting the Pequod's\ncompany.  For, though himself and boat's crew remained untainted, and\nthough his ship was half a rifle-shot off, and an incorruptible sea\nand air rolling and flowing between; yet conscientiously adhering to\nthe timid quarantine of the land, he peremptorily refused to come\ninto direct contact with the Pequod.\n\nBut this did by no means prevent all communications.  Preserving an\ninterval of some few yards between itself and the ship, the\nJeroboam's boat by the occasional use of its oars contrived to keep\nparallel to the Pequod, as she heavily forged through the sea (for by\nthis time it blew very fresh), with her main-topsail aback; though,\nindeed, at times by the sudden onset of a large rolling wave, the\nboat would be pushed some way ahead; but would be soon skilfully\nbrought to her proper bearings again.  Subject to this, and other the\nlike interruptions now and then, a conversation was sustained between\nthe two parties; but at intervals not without still another\ninterruption of a very different sort.\n\nPulling an oar in the Jeroboam's boat, was a man of a singular\nappearance, even in that wild whaling life where individual\nnotabilities make up all totalities.  He was a small, short, youngish\nman, sprinkled all over his face with freckles, and wearing redundant\nyellow hair.  A long-skirted, cabalistically-cut coat of a faded\nwalnut tinge enveloped him; the overlapping sleeves of which were\nrolled up on his wrists.  A deep, settled, fanatic delirium was in\nhis eyes.\n\nSo soon as this figure had been first descried, Stubb had\nexclaimed--\"That's he! that's he!--the long-togged scaramouch the\nTown-Ho's company told us of!\"  Stubb here alluded to a strange story\ntold of the Jeroboam, and a certain man among her crew, some time\nprevious when the Pequod spoke the Town-Ho.  According to this\naccount and what was subsequently learned, it seemed that the\nscaramouch in question had gained a wonderful ascendency over almost\neverybody in the Jeroboam.  His story was this:\n\nHe had been originally nurtured among the crazy society of Neskyeuna\nShakers, where he had been a great prophet; in their cracked, secret\nmeetings having several times descended from heaven by the way of a\ntrap-door, announcing the speedy opening of the seventh vial, which\nhe carried in his vest-pocket; but, which, instead of containing\ngunpowder, was supposed to be charged with laudanum.  A strange,\napostolic whim having seized him, he had left Neskyeuna for\nNantucket, where, with that cunning peculiar to craziness, he assumed\na steady, common-sense exterior, and offered himself as a green-hand\ncandidate for the Jeroboam's whaling voyage.  They engaged him; but\nstraightway upon the ship's getting out of sight of land, his\ninsanity broke out in a freshet.  He announced himself as the\narchangel Gabriel, and commanded the captain to jump overboard.  He\npublished his manifesto, whereby he set himself forth as the\ndeliverer of the isles of the sea and vicar-general of all Oceanica.\nThe unflinching earnestness with which he declared these things;--the\ndark, daring play of his sleepless, excited imagination, and all the\npreternatural terrors of real delirium, united to invest this Gabriel\nin the minds of the majority of the ignorant crew, with an atmosphere\nof sacredness.  Moreover, they were afraid of him.  As such a man,\nhowever, was not of much practical use in the ship, especially as he\nrefused to work except when he pleased, the incredulous captain would\nfain have been rid of him; but apprised that that individual's\nintention was to land him in the first convenient port, the archangel\nforthwith opened all his seals and vials--devoting the ship and all\nhands to unconditional perdition, in case this intention was carried\nout.  So strongly did he work upon his disciples among the crew, that\nat last in a body they went to the captain and told him if Gabriel\nwas sent from the ship, not a man of them would remain.  He was\ntherefore forced to relinquish his plan.  Nor would they permit\nGabriel to be any way maltreated, say or do what he would; so that it\ncame to pass that Gabriel had the complete freedom of the ship.  The\nconsequence of all this was, that the archangel cared little or\nnothing for the captain and mates; and since the epidemic had broken\nout, he carried a higher hand than ever; declaring that the plague,\nas he called it, was at his sole command; nor should it be stayed but\naccording to his good pleasure.  The sailors, mostly poor devils,\ncringed, and some of them fawned before him; in obedience to his\ninstructions, sometimes rendering him personal homage, as to a god.\nSuch things may seem incredible; but, however wondrous, they are\ntrue.  Nor is the history of fanatics half so striking in respect to\nthe measureless self-deception of the fanatic himself, as his\nmeasureless power of deceiving and bedevilling so many others.  But\nit is time to return to the Pequod.\n\n\"I fear not thy epidemic, man,\" said Ahab from the bulwarks, to\nCaptain Mayhew, who stood in the boat's stern; \"come on board.\"\n\nBut now Gabriel started to his feet.\n\n\"Think, think of the fevers, yellow and bilious!  Beware of the\nhorrible plague!\"\n\n\"Gabriel!  Gabriel!\" cried Captain Mayhew; \"thou must either--\"  But\nthat instant a headlong wave shot the boat far ahead, and its\nseethings drowned all speech.\n\n\"Hast thou seen the White Whale?\" demanded Ahab, when the boat\ndrifted back.\n\n\"Think, think of thy whale-boat, stoven and sunk!  Beware of the\nhorrible tail!\"\n\n\"I tell thee again, Gabriel, that--\"  But again the boat tore ahead\nas if dragged by fiends.  Nothing was said for some moments, while a\nsuccession of riotous waves rolled by, which by one of those\noccasional caprices of the seas were tumbling, not heaving it.\nMeantime, the hoisted sperm whale's head jogged about very violently,\nand Gabriel was seen eyeing it with rather more apprehensiveness than\nhis archangel nature seemed to warrant.\n\nWhen this interlude was over, Captain Mayhew began a dark story\nconcerning Moby Dick; not, however, without frequent interruptions\nfrom Gabriel, whenever his name was mentioned, and the crazy sea that\nseemed leagued with him.\n\nIt seemed that the Jeroboam had not long left home, when upon\nspeaking a whale-ship, her people were reliably apprised of the\nexistence of Moby Dick, and the havoc he had made.  Greedily sucking\nin this intelligence, Gabriel solemnly warned the captain against\nattacking the White Whale, in case the monster should be seen; in his\ngibbering insanity, pronouncing the White Whale to be no less a being\nthan the Shaker God incarnated; the Shakers receiving the Bible.  But\nwhen, some year or two afterwards, Moby Dick was fairly sighted from\nthe mast-heads, Macey, the chief mate, burned with ardour to encounter\nhim; and the captain himself being not unwilling to let him have the\nopportunity, despite all the archangel's denunciations and\nforewarnings, Macey succeeded in persuading five men to man his boat.\nWith them he pushed off; and, after much weary pulling, and many\nperilous, unsuccessful onsets, he at last succeeded in getting one\niron fast.  Meantime, Gabriel, ascending to the main-royal mast-head,\nwas tossing one arm in frantic gestures, and hurling forth prophecies\nof speedy doom to the sacrilegious assailants of his divinity.  Now,\nwhile Macey, the mate, was standing up in his boat's bow, and with\nall the reckless energy of his tribe was venting his wild\nexclamations upon the whale, and essaying to get a fair chance for\nhis poised lance, lo! a broad white shadow rose from the sea; by its\nquick, fanning motion, temporarily taking the breath out of the\nbodies of the oarsmen.  Next instant, the luckless mate, so full of\nfurious life, was smitten bodily into the air, and making a long arc\nin his descent, fell into the sea at the distance of about fifty\nyards.  Not a chip of the boat was harmed, nor a hair of any\noarsman's head; but the mate for ever sank.\n\nIt is well to parenthesize here, that of the fatal accidents in the\nSperm-Whale Fishery, this kind is perhaps almost as frequent as any.\nSometimes, nothing is injured but the man who is thus annihilated;\noftener the boat's bow is knocked off, or the thigh-board, in which\nthe headsman stands, is torn from its place and accompanies the body.\nBut strangest of all is the circumstance, that in more instances\nthan one, when the body has been recovered, not a single mark of\nviolence is discernible; the man being stark dead.\n\nThe whole calamity, with the falling form of Macey, was plainly\ndescried from the ship.  Raising a piercing shriek--\"The vial! the\nvial!\"  Gabriel called off the terror-stricken crew from the further\nhunting of the whale.  This terrible event clothed the archangel with\nadded influence; because his credulous disciples believed that he had\nspecifically fore-announced it, instead of only making a general\nprophecy, which any one might have done, and so have chanced to hit\none of many marks in the wide margin allowed.  He became a nameless\nterror to the ship.\n\nMayhew having concluded his narration, Ahab put such questions to\nhim, that the stranger captain could not forbear inquiring whether he\nintended to hunt the White Whale, if opportunity should offer.  To\nwhich Ahab answered--\"Aye.\"  Straightway, then, Gabriel once more\nstarted to his feet, glaring upon the old man, and vehemently\nexclaimed, with downward pointed finger--\"Think, think of the\nblasphemer--dead, and down there!--beware of the blasphemer's end!\"\n\nAhab stolidly turned aside; then said to Mayhew, \"Captain, I have\njust bethought me of my letter-bag; there is a letter for one of thy\nofficers, if I mistake not.  Starbuck, look over the bag.\"\n\nEvery whale-ship takes out a goodly number of letters for various\nships, whose delivery to the persons to whom they may be addressed,\ndepends upon the mere chance of encountering them in the four oceans.\nThus, most letters never reach their mark; and many are only\nreceived after attaining an age of two or three years or more.\n\nSoon Starbuck returned with a letter in his hand.  It was sorely\ntumbled, damp, and covered with a dull, spotted, green mould, in\nconsequence of being kept in a dark locker of the cabin.  Of such a\nletter, Death himself might well have been the post-boy.\n\n\"Can'st not read it?\" cried Ahab.  \"Give it me, man.  Aye, aye, it's\nbut a dim scrawl;--what's this?\"  As he was studying it out, Starbuck\ntook a long cutting-spade pole, and with his knife slightly split the\nend, to insert the letter there, and in that way, hand it to the\nboat, without its coming any closer to the ship.\n\nMeantime, Ahab holding the letter, muttered, \"Mr. Har--yes, Mr.\nHarry--(a woman's pinny hand,--the man's wife, I'll wager)--Aye--Mr.\nHarry Macey, Ship Jeroboam;--why it's Macey, and he's dead!\"\n\n\"Poor fellow! poor fellow! and from his wife,\" sighed Mayhew; \"but\nlet me have it.\"\n\n\"Nay, keep it thyself,\" cried Gabriel to Ahab; \"thou art soon going\nthat way.\"\n\n\"Curses throttle thee!\" yelled Ahab.  \"Captain Mayhew, stand by now\nto receive it\"; and taking the fatal missive from Starbuck's hands,\nhe caught it in the slit of the pole, and reached it over towards the\nboat.  But as he did so, the oarsmen expectantly desisted from\nrowing; the boat drifted a little towards the ship's stern; so that,\nas if by magic, the letter suddenly ranged along with Gabriel's eager\nhand.  He clutched it in an instant, seized the boat-knife, and\nimpaling the letter on it, sent it thus loaded back into the ship.\nIt fell at Ahab's feet.  Then Gabriel shrieked out to his comrades to\ngive way with their oars, and in that manner the mutinous boat\nrapidly shot away from the Pequod.\n\nAs, after this interlude, the seamen resumed their work upon the\njacket of the whale, many strange things were hinted in reference to\nthis wild affair.\n\n\n\nCHAPTER 72\n\nThe Monkey-Rope.\n\n\nIn the tumultuous business of cutting-in and attending to a whale,\nthere is much running backwards and forwards among the crew.  Now\nhands are wanted here, and then again hands are wanted there.  There\nis no staying in any one place; for at one and the same time\neverything has to be done everywhere.  It is much the same with him\nwho endeavors the description of the scene.  We must now retrace our\nway a little.  It was mentioned that upon first breaking ground in\nthe whale's back, the blubber-hook was inserted into the original\nhole there cut by the spades of the mates.  But how did so clumsy and\nweighty a mass as that same hook get fixed in that hole?  It was\ninserted there by my particular friend Queequeg, whose duty it was,\nas harpooneer, to descend upon the monster's back for the special\npurpose referred to.  But in very many cases, circumstances require\nthat the harpooneer shall remain on the whale till the whole tensing\nor stripping operation is concluded.  The whale, be it observed, lies\nalmost entirely submerged, excepting the immediate parts operated\nupon.  So down there, some ten feet below the level of the deck, the\npoor harpooneer flounders about, half on the whale and half in the\nwater, as the vast mass revolves like a tread-mill beneath him.  On\nthe occasion in question, Queequeg figured in the Highland costume--a\nshirt and socks--in which to my eyes, at least, he appeared to\nuncommon advantage; and no one had a better chance to observe him, as\nwill presently be seen.\n\nBeing the savage's bowsman, that is, the person who pulled the\nbow-oar in his boat (the second one from forward), it was my cheerful\nduty to attend upon him while taking that hard-scrabble scramble upon\nthe dead whale's back.  You have seen Italian organ-boys holding a\ndancing-ape by a long cord.  Just so, from the ship's steep side, did\nI hold Queequeg down there in the sea, by what is technically called\nin the fishery a monkey-rope, attached to a strong strip of canvas\nbelted round his waist.\n\nIt was a humorously perilous business for both of us.  For, before we\nproceed further, it must be said that the monkey-rope was fast at\nboth ends; fast to Queequeg's broad canvas belt, and fast to my\nnarrow leather one.  So that for better or for worse, we two, for the\ntime, were wedded; and should poor Queequeg sink to rise no more,\nthen both usage and honour demanded, that instead of cutting the cord,\nit should drag me down in his wake.  So, then, an elongated Siamese\nligature united us.  Queequeg was my own inseparable twin brother;\nnor could I any way get rid of the dangerous liabilities which the\nhempen bond entailed.\n\nSo strongly and metaphysically did I conceive of my situation then,\nthat while earnestly watching his motions, I seemed distinctly to\nperceive that my own individuality was now merged in a joint stock\ncompany of two; that my free will had received a mortal wound; and\nthat another's mistake or misfortune might plunge innocent me into\nunmerited disaster and death.  Therefore, I saw that here was a sort\nof interregnum in Providence; for its even-handed equity never could\nhave so gross an injustice.  And yet still further pondering--while I\njerked him now and then from between the whale and ship, which would\nthreaten to jam him--still further pondering, I say, I saw that this\nsituation of mine was the precise situation of every mortal that\nbreathes; only, in most cases, he, one way or other, has this Siamese\nconnexion with a plurality of other mortals.  If your banker breaks,\nyou snap; if your apothecary by mistake sends you poison in your\npills, you die.  True, you may say that, by exceeding caution, you\nmay possibly escape these and the multitudinous other evil chances of\nlife.  But handle Queequeg's monkey-rope heedfully as I would,\nsometimes he jerked it so, that I came very near sliding overboard.\nNor could I possibly forget that, do what I would, I only had the\nmanagement of one end of it.*\n\n\n*The monkey-rope is found in all whalers; but it was only in the\nPequod that the monkey and his holder were ever tied together.  This\nimprovement upon the original usage was introduced by no less a man\nthan Stubb, in order to afford the imperilled harpooneer the strongest\npossible guarantee for the faithfulness and vigilance of his\nmonkey-rope holder.\n\n\nI have hinted that I would often jerk poor Queequeg from between the\nwhale and the ship--where he would occasionally fall, from the\nincessant rolling and swaying of both.  But this was not the only\njamming jeopardy he was exposed to.  Unappalled by the massacre made\nupon them during the night, the sharks now freshly and more keenly\nallured by the before pent blood which began to flow from the\ncarcass--the rabid creatures swarmed round it like bees in a beehive.\n\nAnd right in among those sharks was Queequeg; who often pushed them\naside with his floundering feet.  A thing altogether incredible were\nit not that attracted by such prey as a dead whale, the otherwise\nmiscellaneously carnivorous shark will seldom touch a man.\n\nNevertheless, it may well be believed that since they have such a\nravenous finger in the pie, it is deemed but wise to look sharp to\nthem.  Accordingly, besides the monkey-rope, with which I now and\nthen jerked the poor fellow from too close a vicinity to the maw of\nwhat seemed a peculiarly ferocious shark--he was provided with still\nanother protection.  Suspended over the side in one of the stages,\nTashtego and Daggoo continually flourished over his head a couple of\nkeen whale-spades, wherewith they slaughtered as many sharks as they\ncould reach.  This procedure of theirs, to be sure, was very\ndisinterested and benevolent of them.  They meant Queequeg's best\nhappiness, I admit; but in their hasty zeal to befriend him, and from\nthe circumstance that both he and the sharks were at times half\nhidden by the blood-muddled water, those indiscreet spades of theirs\nwould come nearer amputating a leg than a tall.  But poor Queequeg, I\nsuppose, straining and gasping there with that great iron hook--poor\nQueequeg, I suppose, only prayed to his Yojo, and gave up his life\ninto the hands of his gods.\n\nWell, well, my dear comrade and twin-brother, thought I, as I drew in\nand then slacked off the rope to every swell of the sea--what matters\nit, after all?  Are you not the precious image of each and all of us\nmen in this whaling world?  That unsounded ocean you gasp in, is\nLife; those sharks, your foes; those spades, your friends; and what\nbetween sharks and spades you are in a sad pickle and peril, poor\nlad.\n\nBut courage! there is good cheer in store for you, Queequeg.  For\nnow, as with blue lips and blood-shot eyes the exhausted savage at\nlast climbs up the chains and stands all dripping and involuntarily\ntrembling over the side; the steward advances, and with a benevolent,\nconsolatory glance hands him--what?  Some hot Cognac?  No! hands him,\nye gods! hands him a cup of tepid ginger and water!\n\n\"Ginger?  Do I smell ginger?\" suspiciously asked Stubb, coming near.\n\"Yes, this must be ginger,\" peering into the as yet untasted cup.\nThen standing as if incredulous for a while, he calmly walked towards\nthe astonished steward slowly saying, \"Ginger? ginger? and will you\nhave the goodness to tell me, Mr. Dough-Boy, where lies the virtue of\nginger?  Ginger! is ginger the sort of fuel you use, Dough-boy, to\nkindle a fire in this shivering cannibal?  Ginger!--what the devil is\nginger?--sea-coal? firewood?--lucifer\nmatches?--tinder?--gunpowder?--what the devil is ginger, I say, that\nyou offer this cup to our poor Queequeg here.\"\n\n\"There is some sneaking Temperance Society movement about this\nbusiness,\" he suddenly added, now approaching Starbuck, who had just\ncome from forward.  \"Will you look at that kannakin, sir; smell of\nit, if you please.\"  Then watching the mate's countenance, he added,\n\"The steward, Mr. Starbuck, had the face to offer that calomel and\njalap to Queequeg, there, this instant off the whale.  Is the steward\nan apothecary, sir? and may I ask whether this is the sort of bitters\nby which he blows back the life into a half-drowned man?\"\n\n\"I trust not,\" said Starbuck, \"it is poor stuff enough.\"\n\n\"Aye, aye, steward,\" cried Stubb, \"we'll teach you to drug it\nharpooneer; none of your apothecary's medicine here; you want to\npoison us, do ye?  You have got out insurances on our lives and want\nto murder us all, and pocket the proceeds, do ye?\"\n\n\"It was not me,\" cried Dough-Boy, \"it was Aunt Charity that brought\nthe ginger on board; and bade me never give the harpooneers any\nspirits, but only this ginger-jub--so she called it.\"\n\n\"Ginger-jub! you gingerly rascal! take that! and run along with ye to\nthe lockers, and get something better.  I hope I do no wrong, Mr.\nStarbuck.  It is the captain's orders--grog for the harpooneer on a\nwhale.\"\n\n\"Enough,\" replied Starbuck, \"only don't hit him again, but--\"\n\n\"Oh, I never hurt when I hit, except when I hit a whale or something\nof that sort; and this fellow's a weazel.  What were you about\nsaying, sir?\"\n\n\"Only this: go down with him, and get what thou wantest thyself.\"\n\nWhen Stubb reappeared, he came with a dark flask in one hand, and a\nsort of tea-caddy in the other.  The first contained strong spirits,\nand was handed to Queequeg; the second was Aunt Charity's gift, and\nthat was freely given to the waves.\n\n\n\nCHAPTER 73\n\nStubb and Flask Kill a Right Whale; and Then Have a Talk Over Him.\n\n\nIt must be borne in mind that all this time we have a Sperm Whale's\nprodigious head hanging to the Pequod's side.  But we must let it\ncontinue hanging there a while till we can get a chance to attend to\nit.  For the present other matters press, and the best we can do now\nfor the head, is to pray heaven the tackles may hold.\n\nNow, during the past night and forenoon, the Pequod had gradually\ndrifted into a sea, which, by its occasional patches of yellow brit,\ngave unusual tokens of the vicinity of Right Whales, a species of the\nLeviathan that but few supposed to be at this particular time lurking\nanywhere near.  And though all hands commonly disdained the capture\nof those inferior creatures; and though the Pequod was not\ncommissioned to cruise for them at all, and though she had passed\nnumbers of them near the Crozetts without lowering a boat; yet now\nthat a Sperm Whale had been brought alongside and beheaded, to the\nsurprise of all, the announcement was made that a Right Whale should\nbe captured that day, if opportunity offered.\n\nNor was this long wanting.  Tall spouts were seen to leeward; and two\nboats, Stubb's and Flask's, were detached in pursuit.  Pulling\nfurther and further away, they at last became almost invisible to the\nmen at the mast-head.  But suddenly in the distance, they saw a great\nheap of tumultuous white water, and soon after news came from aloft\nthat one or both the boats must be fast.  An interval passed and the\nboats were in plain sight, in the act of being dragged right towards\nthe ship by the towing whale.  So close did the monster come to the\nhull, that at first it seemed as if he meant it malice; but suddenly\ngoing down in a maelstrom, within three rods of the planks, he wholly\ndisappeared from view, as if diving under the keel.  \"Cut, cut!\" was\nthe cry from the ship to the boats, which, for one instant, seemed on\nthe point of being brought with a deadly dash against the vessel's\nside.  But having plenty of line yet in the tubs, and the whale not\nsounding very rapidly, they paid out abundance of rope, and at the\nsame time pulled with all their might so as to get ahead of the ship.\nFor a few minutes the struggle was intensely critical; for while\nthey still slacked out the tightened line in one direction, and still\nplied their oars in another, the contending strain threatened to take\nthem under.  But it was only a few feet advance they sought to gain.\nAnd they stuck to it till they did gain it; when instantly, a swift\ntremor was felt running like lightning along the keel, as the\nstrained line, scraping beneath the ship, suddenly rose to view under\nher bows, snapping and quivering; and so flinging off its drippings,\nthat the drops fell like bits of broken glass on the water, while the\nwhale beyond also rose to sight, and once more the boats were free to\nfly.  But the fagged whale abated his speed, and blindly altering his\ncourse, went round the stern of the ship towing the two boats after\nhim, so that they performed a complete circuit.\n\nMeantime, they hauled more and more upon their lines, till close\nflanking him on both sides, Stubb answered Flask with lance for\nlance; and thus round and round the Pequod the battle went, while the\nmultitudes of sharks that had before swum round the Sperm Whale's\nbody, rushed to the fresh blood that was spilled, thirstily drinking\nat every new gash, as the eager Israelites did at the new bursting\nfountains that poured from the smitten rock.\n\nAt last his spout grew thick, and with a frightful roll and vomit, he\nturned upon his back a corpse.\n\nWhile the two headsmen were engaged in making fast cords to his\nflukes, and in other ways getting the mass in readiness for towing,\nsome conversation ensued between them.\n\n\"I wonder what the old man wants with this lump of foul lard,\" said\nStubb, not without some disgust at the thought of having to do with\nso ignoble a leviathan.\n\n\"Wants with it?\" said Flask, coiling some spare line in the boat's\nbow, \"did you never hear that the ship which but once has a Sperm\nWhale's head hoisted on her starboard side, and at the same time a\nRight Whale's on the larboard; did you never hear, Stubb, that that\nship can never afterwards capsize?\"\n\n\"Why not?\n\n\"I don't know, but I heard that gamboge ghost of a Fedallah saying\nso, and he seems to know all about ships' charms.  But I sometimes\nthink he'll charm the ship to no good at last.  I don't half like\nthat chap, Stubb.  Did you ever notice how that tusk of his is a sort\nof carved into a snake's head, Stubb?\"\n\n\"Sink him!  I never look at him at all; but if ever I get a chance of\na dark night, and he standing hard by the bulwarks, and no one by;\nlook down there, Flask\"--pointing into the sea with a peculiar motion\nof both hands--\"Aye, will I!  Flask, I take that Fedallah to be the\ndevil in disguise.  Do you believe that cock and bull story about his\nhaving been stowed away on board ship?  He's the devil, I say.  The\nreason why you don't see his tail, is because he tucks it up out of\nsight; he carries it coiled away in his pocket, I guess.  Blast him!\nnow that I think of it, he's always wanting oakum to stuff into the\ntoes of his boots.\"\n\n\"He sleeps in his boots, don't he?  He hasn't got any hammock; but\nI've seen him lay of nights in a coil of rigging.\"\n\n\"No doubt, and it's because of his cursed tail; he coils it down, do\nye see, in the eye of the rigging.\"\n\n\"What's the old man have so much to do with him for?\"\n\n\"Striking up a swap or a bargain, I suppose.\"\n\n\"Bargain?--about what?\"\n\n\"Why, do ye see, the old man is hard bent after that White Whale, and\nthe devil there is trying to come round him, and get him to swap away\nhis silver watch, or his soul, or something of that sort, and then\nhe'll surrender Moby Dick.\"\n\n\"Pooh!  Stubb, you are skylarking; how can Fedallah do that?\"\n\n\"I don't know, Flask, but the devil is a curious chap, and a wicked\none, I tell ye.  Why, they say as how he went a sauntering into the\nold flag-ship once, switching his tail about devilish easy and\ngentlemanlike, and inquiring if the old governor was at home.  Well,\nhe was at home, and asked the devil what he wanted.  The devil,\nswitching his hoofs, up and says, 'I want John.'  'What for?' says\nthe old governor.  'What business is that of yours,' says the devil,\ngetting mad,--'I want to use him.'  'Take him,' says the\ngovernor--and by the Lord, Flask, if the devil didn't give John the\nAsiatic cholera before he got through with him, I'll eat this whale\nin one mouthful.  But look sharp--ain't you all ready there?  Well,\nthen, pull ahead, and let's get the whale alongside.\"\n\n\"I think I remember some such story as you were telling,\" said Flask,\nwhen at last the two boats were slowly advancing with their burden\ntowards the ship, \"but I can't remember where.\"\n\n\"Three Spaniards?  Adventures of those three bloody-minded soladoes?\nDid ye read it there, Flask?  I guess ye did?\"\n\n\"No: never saw such a book; heard of it, though.  But now, tell me,\nStubb, do you suppose that that devil you was speaking of just now,\nwas the same you say is now on board the Pequod?\"\n\n\"Am I the same man that helped kill this whale?  Doesn't the devil\nlive for ever; who ever heard that the devil was dead?  Did you ever\nsee any parson a wearing mourning for the devil?  And if the devil\nhas a latch-key to get into the admiral's cabin, don't you suppose he\ncan crawl into a porthole?  Tell me that, Mr. Flask?\"\n\n\"How old do you suppose Fedallah is, Stubb?\"\n\n\"Do you see that mainmast there?\" pointing to the ship; \"well, that's\nthe figure one; now take all the hoops in the Pequod's hold, and\nstring along in a row with that mast, for oughts, do you see; well,\nthat wouldn't begin to be Fedallah's age.  Nor all the coopers in\ncreation couldn't show hoops enough to make oughts enough.\"\n\n\"But see here, Stubb, I thought you a little boasted just now, that\nyou meant to give Fedallah a sea-toss, if you got a good chance.\nNow, if he's so old as all those hoops of yours come to, and if he is\ngoing to live for ever, what good will it do to pitch him\noverboard--tell me that?\n\n\"Give him a good ducking, anyhow.\"\n\n\"But he'd crawl back.\"\n\n\"Duck him again; and keep ducking him.\"\n\n\"Suppose he should take it into his head to duck you, though--yes,\nand drown you--what then?\"\n\n\"I should like to see him try it; I'd give him such a pair of black\neyes that he wouldn't dare to show his face in the admiral's cabin\nagain for a long while, let alone down in the orlop there, where he\nlives, and hereabouts on the upper decks where he sneaks so much.\nDamn the devil, Flask; so you suppose I'm afraid of the devil?  Who's\nafraid of him, except the old governor who daresn't catch him and put\nhim in double-darbies, as he deserves, but lets him go about\nkidnapping people; aye, and signed a bond with him, that all the\npeople the devil kidnapped, he'd roast for him?  There's a governor!\"\n\n\"Do you suppose Fedallah wants to kidnap Captain Ahab?\"\n\n\"Do I suppose it?  You'll know it before long, Flask.  But I am going\nnow to keep a sharp look-out on him; and if I see anything very\nsuspicious going on, I'll just take him by the nape of his neck, and\nsay--Look here, Beelzebub, you don't do it; and if he makes any fuss,\nby the Lord I'll make a grab into his pocket for his tail, take it to\nthe capstan, and give him such a wrenching and heaving, that his tail\nwill come short off at the stump--do you see; and then, I rather\nguess when he finds himself docked in that queer fashion, he'll sneak\noff without the poor satisfaction of feeling his tail between his\nlegs.\"\n\n\"And what will you do with the tail, Stubb?\"\n\n\"Do with it?  Sell it for an ox whip when we get home;--what else?\"\n\n\"Now, do you mean what you say, and have been saying all along,\nStubb?\"\n\n\"Mean or not mean, here we are at the ship.\"\n\nThe boats were here hailed, to tow the whale on the larboard side,\nwhere fluke chains and other necessaries were already prepared for\nsecuring him.\n\n\"Didn't I tell you so?\" said Flask; \"yes, you'll soon see this right\nwhale's head hoisted up opposite that parmacetti's.\"\n\nIn good time, Flask's saying proved true.  As before, the Pequod\nsteeply leaned over towards the sperm whale's head, now, by the\ncounterpoise of both heads, she regained her even keel; though sorely\nstrained, you may well believe.  So, when on one side you hoist in\nLocke's head, you go over that way; but now, on the other side, hoist\nin Kant's and you come back again; but in very poor plight.  Thus,\nsome minds for ever keep trimming boat.  Oh, ye foolish! throw all\nthese thunder-heads overboard, and then you will float light and\nright.\n\nIn disposing of the body of a right whale, when brought alongside the\nship, the same preliminary proceedings commonly take place as in the\ncase of a sperm whale; only, in the latter instance, the head is cut\noff whole, but in the former the lips and tongue are separately\nremoved and hoisted on deck, with all the well known black bone\nattached to what is called the crown-piece.  But nothing like this,\nin the present case, had been done.  The carcases of both whales had\ndropped astern; and the head-laden ship not a little resembled a mule\ncarrying a pair of overburdening panniers.\n\nMeantime, Fedallah was calmly eyeing the right whale's head, and ever\nand anon glancing from the deep wrinkles there to the lines in his\nown hand.  And Ahab chanced so to stand, that the Parsee occupied his\nshadow; while, if the Parsee's shadow was there at all it seemed only\nto blend with, and lengthen Ahab's.  As the crew toiled on,\nLaplandish speculations were bandied among them, concerning all these\npassing things.\n\n\n\nCHAPTER 74\n\nThe Sperm Whale's Head--Contrasted View.\n\n\nHere, now, are two great whales, laying their heads together; let us\njoin them, and lay together our own.\n\nOf the grand order of folio leviathans, the Sperm Whale and the Right\nWhale are by far the most noteworthy.  They are the only whales\nregularly hunted by man.  To the Nantucketer, they present the two\nextremes of all the known varieties of the whale.  As the external\ndifference between them is mainly observable in their heads; and as a\nhead of each is this moment hanging from the Pequod's side; and as we\nmay freely go from one to the other, by merely stepping across the\ndeck:--where, I should like to know, will you obtain a better chance\nto study practical cetology than here?\n\nIn the first place, you are struck by the general contrast between\nthese heads.  Both are massive enough in all conscience; but there\nis a certain mathematical symmetry in the Sperm Whale's which the\nRight Whale's sadly lacks.  There is more character in the Sperm\nWhale's head.  As you behold it, you involuntarily yield the immense\nsuperiority to him, in point of pervading dignity.  In the present\ninstance, too, this dignity is heightened by the pepper and salt\ncolour of his head at the summit, giving token of advanced age and\nlarge experience.  In short, he is what the fishermen technically\ncall a \"grey-headed whale.\"\n\nLet us now note what is least dissimilar in these heads--namely, the\ntwo most important organs, the eye and the ear.  Far back on the side\nof the head, and low down, near the angle of either whale's jaw, if\nyou narrowly search, you will at last see a lashless eye, which you\nwould fancy to be a young colt's eye; so out of all proportion is it\nto the magnitude of the head.\n\nNow, from this peculiar sideway position of the whale's eyes, it is\nplain that he can never see an object which is exactly ahead, no more\nthan he can one exactly astern.  In a word, the position of the\nwhale's eyes corresponds to that of a man's ears; and you may fancy,\nfor yourself, how it would fare with you, did you sideways survey\nobjects through your ears.  You would find that you could only\ncommand some thirty degrees of vision in advance of the straight\nside-line of sight; and about thirty more behind it.  If your\nbitterest foe were walking straight towards you, with dagger uplifted\nin broad day, you would not be able to see him, any more than if he\nwere stealing upon you from behind.  In a word, you would have two\nbacks, so to speak; but, at the same time, also, two fronts (side\nfronts): for what is it that makes the front of a man--what, indeed,\nbut his eyes?\n\nMoreover, while in most other animals that I can now think of, the\neyes are so planted as imperceptibly to blend their visual power, so\nas to produce one picture and not two to the brain; the peculiar\nposition of the whale's eyes, effectually divided as they are by many\ncubic feet of solid head, which towers between them like a great\nmountain separating two lakes in valleys; this, of course, must\nwholly separate the impressions which each independent organ imparts.\nThe whale, therefore, must see one distinct picture on this side,\nand another distinct picture on that side; while all between must be\nprofound darkness and nothingness to him.  Man may, in effect, be\nsaid to look out on the world from a sentry-box with two joined\nsashes for his window.  But with the whale, these two sashes are\nseparately inserted, making two distinct windows, but sadly impairing\nthe view.  This peculiarity of the whale's eyes is a thing always to\nbe borne in mind in the fishery; and to be remembered by the reader\nin some subsequent scenes.\n\nA curious and most puzzling question might be started concerning this\nvisual matter as touching the Leviathan.  But I must be content with\na hint.  So long as a man's eyes are open in the light, the act of\nseeing is involuntary; that is, he cannot then help mechanically\nseeing whatever objects are before him.  Nevertheless, any one's\nexperience will teach him, that though he can take in an\nundiscriminating sweep of things at one glance, it is quite\nimpossible for him, attentively, and completely, to examine any two\nthings--however large or however small--at one and the same instant\nof time; never mind if they lie side by side and touch each other.\nBut if you now come to separate these two objects, and surround each\nby a circle of profound darkness; then, in order to see one of them,\nin such a manner as to bring your mind to bear on it, the other will\nbe utterly excluded from your contemporary consciousness.  How is it,\nthen, with the whale?  True, both his eyes, in themselves, must\nsimultaneously act; but is his brain so much more comprehensive,\ncombining, and subtle than man's, that he can at the same moment of\ntime attentively examine two distinct prospects, one on one side of\nhim, and the other in an exactly opposite direction?  If he can, then\nis it as marvellous a thing in him, as if a man were able\nsimultaneously to go through the demonstrations of two distinct\nproblems in Euclid.  Nor, strictly investigated, is there any\nincongruity in this comparison.\n\nIt may be but an idle whim, but it has always seemed to me, that the\nextraordinary vacillations of movement displayed by some whales when\nbeset by three or four boats; the timidity and liability to queer\nfrights, so common to such whales; I think that all this indirectly\nproceeds from the helpless perplexity of volition, in which their\ndivided and diametrically opposite powers of vision must involve\nthem.\n\nBut the ear of the whale is full as curious as the eye.  If you are\nan entire stranger to their race, you might hunt over these two heads\nfor hours, and never discover that organ.  The ear has no external\nleaf whatever; and into the hole itself you can hardly insert a\nquill, so wondrously minute is it.  It is lodged a little behind the\neye.  With respect to their ears, this important difference is to be\nobserved between the sperm whale and the right.  While the ear of\nthe former has an external opening, that of the latter is entirely\nand evenly covered over with a membrane, so as to be quite\nimperceptible from without.\n\nIs it not curious, that so vast a being as the whale should see the\nworld through so small an eye, and hear the thunder through an ear\nwhich is smaller than a hare's?  But if his eyes were broad as the\nlens of Herschel's great telescope; and his ears capacious as the\nporches of cathedrals; would that make him any longer of sight, or\nsharper of hearing?  Not at all.--Why then do you try to \"enlarge\"\nyour mind?  Subtilize it.\n\nLet us now with whatever levers and steam-engines we have at hand,\ncant over the sperm whale's head, that it may lie bottom up;\nthen, ascending by a ladder to the summit, have a peep down the\nmouth; and were it not that the body is now completely separated from\nit, with a lantern we might descend into the great Kentucky Mammoth\nCave of his stomach.  But let us hold on here by this tooth, and look\nabout us where we are.  What a really beautiful and chaste-looking\nmouth! from floor to ceiling, lined, or rather papered with a\nglistening white membrane, glossy as bridal satins.\n\nBut come out now, and look at this portentous lower jaw, which seems\nlike the long narrow lid of an immense snuff-box, with the hinge at\none end, instead of one side.  If you pry it up, so as to get it\noverhead, and expose its rows of teeth, it seems a terrific\nportcullis; and such, alas! it proves to many a poor wight in the\nfishery, upon whom these spikes fall with impaling force.  But far\nmore terrible is it to behold, when fathoms down in the sea, you see\nsome sulky whale, floating there suspended, with his prodigious jaw,\nsome fifteen feet long, hanging straight down at right-angles with\nhis body, for all the world like a ship's jib-boom.  This whale is\nnot dead; he is only dispirited; out of sorts, perhaps;\nhypochondriac; and so supine, that the hinges of his jaw have\nrelaxed, leaving him there in that ungainly sort of plight, a\nreproach to all his tribe, who must, no doubt, imprecate lock-jaws\nupon him.\n\nIn most cases this lower jaw--being easily unhinged by a practised\nartist--is disengaged and hoisted on deck for the purpose of\nextracting the ivory teeth, and furnishing a supply of that hard\nwhite whalebone with which the fishermen fashion all sorts of curious\narticles, including canes, umbrella-stocks, and handles to\nriding-whips.\n\nWith a long, weary hoist the jaw is dragged on board, as if it were\nan anchor; and when the proper time comes--some few days after the\nother work--Queequeg, Daggoo, and Tashtego, being all accomplished\ndentists, are set to drawing teeth.  With a keen cutting-spade,\nQueequeg lances the gums; then the jaw is lashed down to ringbolts,\nand a tackle being rigged from aloft, they drag out these teeth, as\nMichigan oxen drag stumps of old oaks out of wild wood lands.  There\nare generally forty-two teeth in all; in old whales, much worn down,\nbut undecayed; nor filled after our artificial fashion.  The jaw is\nafterwards sawn into slabs, and piled away like joists for building\nhouses.\n\n\n\nCHAPTER 75\n\nThe Right Whale's Head--Contrasted View.\n\n\nCrossing the deck, let us now have a good long look at the Right\nWhale's head.\n\nAs in general shape the noble Sperm Whale's head may be compared to a\nRoman war-chariot (especially in front, where it is so broadly\nrounded); so, at a broad view, the Right Whale's head bears a rather\ninelegant resemblance to a gigantic galliot-toed shoe.  Two hundred\nyears ago an old Dutch voyager likened its shape to that of a\nshoemaker's last.  And in this same last or shoe, that old woman of\nthe nursery tale, with the swarming brood, might very comfortably be\nlodged, she and all her progeny.\n\nBut as you come nearer to this great head it begins to assume\ndifferent aspects, according to your point of view.  If you stand on\nits summit and look at these two F-shaped spoutholes, you would take\nthe whole head for an enormous bass-viol, and these spiracles, the\napertures in its sounding-board.  Then, again, if you fix your eye\nupon this strange, crested, comb-like incrustation on the top of the\nmass--this green, barnacled thing, which the Greenlanders call the\n\"crown,\" and the Southern fishers the \"bonnet\" of the Right Whale;\nfixing your eyes solely on this, you would take the head for the\ntrunk of some huge oak, with a bird's nest in its crotch.  At any\nrate, when you watch those live crabs that nestle here on this\nbonnet, such an idea will be almost sure to occur to you; unless,\nindeed, your fancy has been fixed by the technical term \"crown\" also\nbestowed upon it; in which case you will take great interest in\nthinking how this mighty monster is actually a diademed king of the\nsea, whose green crown has been put together for him in this\nmarvellous manner.  But if this whale be a king, he is a very sulky\nlooking fellow to grace a diadem.  Look at that hanging lower lip!\nwhat a huge sulk and pout is there! a sulk and pout, by carpenter's\nmeasurement, about twenty feet long and five feet deep; a sulk and\npout that will yield you some 500 gallons of oil and more.\n\nA great pity, now, that this unfortunate whale should be hare-lipped.\nThe fissure is about a foot across.  Probably the mother during an\nimportant interval was sailing down the Peruvian coast, when\nearthquakes caused the beach to gape.  Over this lip, as over a\nslippery threshold, we now slide into the mouth.  Upon my word were I\nat Mackinaw, I should take this to be the inside of an Indian wigwam.\nGood Lord! is this the road that Jonah went?  The roof is about\ntwelve feet high, and runs to a pretty sharp angle, as if there were\na regular ridge-pole there; while these ribbed, arched, hairy sides,\npresent us with those wondrous, half vertical, scimetar-shaped slats\nof whalebone, say three hundred on a side, which depending from the\nupper part of the head or crown bone, form those Venetian blinds\nwhich have elsewhere been cursorily mentioned.  The edges of these\nbones are fringed with hairy fibres, through which the Right Whale\nstrains the water, and in whose intricacies he retains the small\nfish, when openmouthed he goes through the seas of brit in feeding\ntime.  In the central blinds of bone, as they stand in their natural\norder, there are certain curious marks, curves, hollows, and ridges,\nwhereby some whalemen calculate the creature's age, as the age of an\noak by its circular rings.  Though the certainty of this criterion is\nfar from demonstrable, yet it has the savor of analogical\nprobability.  At any rate, if we yield to it, we must grant a far\ngreater age to the Right Whale than at first glance will seem\nreasonable.\n\nIn old times, there seem to have prevailed the most curious fancies\nconcerning these blinds.  One voyager in Purchas calls them the\nwondrous \"whiskers\" inside of the whale's mouth;* another, \"hogs'\nbristles\"; a third old gentleman in Hackluyt uses the following\nelegant language: \"There are about two hundred and fifty fins growing\non each side of his upper CHOP, which arch over his tongue on each\nside of his mouth.\"\n\n\n*This reminds us that the Right Whale really has a sort of whisker,\nor rather a moustache, consisting of a few scattered white hairs on\nthe upper part of the outer end of the lower jaw.  Sometimes these\ntufts impart a rather brigandish expression to his otherwise solemn\ncountenance.\n\n\nAs every one knows, these same \"hogs' bristles,\" \"fins,\" \"whiskers,\"\n\"blinds,\" or whatever you please, furnish to the ladies their busks\nand other stiffening contrivances.  But in this particular, the\ndemand has long been on the decline.  It was in Queen Anne's time\nthat the bone was in its glory, the farthingale being then all the\nfashion.  And as those ancient dames moved about gaily, though in the\njaws of the whale, as you may say; even so, in a shower, with the\nlike thoughtlessness, do we nowadays fly under the same jaws for\nprotection; the umbrella being a tent spread over the same bone.\n\nBut now forget all about blinds and whiskers for a moment, and,\nstanding in the Right Whale's mouth, look around you afresh.  Seeing\nall these colonnades of bone so methodically ranged about, would you\nnot think you were inside of the great Haarlem organ, and gazing\nupon its thousand pipes?  For a carpet to the organ we have a rug of\nthe softest Turkey--the tongue, which is glued, as it were, to the\nfloor of the mouth.  It is very fat and tender, and apt to tear in\npieces in hoisting it on deck.  This particular tongue now before us;\nat a passing glance I should say it was a six-barreler; that is, it\nwill yield you about that amount of oil.\n\nEre this, you must have plainly seen the truth of what I started\nwith--that the Sperm Whale and the Right Whale have almost entirely\ndifferent heads.  To sum up, then: in the Right Whale's there is no\ngreat well of sperm; no ivory teeth at all; no long, slender mandible\nof a lower jaw, like the Sperm Whale's.  Nor in the Sperm Whale are\nthere any of those blinds of bone; no huge lower lip; and scarcely\nanything of a tongue.  Again, the Right Whale has two external\nspout-holes, the Sperm Whale only one.\n\nLook your last, now, on these venerable hooded heads, while they yet\nlie together; for one will soon sink, unrecorded, in the sea; the\nother will not be very long in following.\n\nCan you catch the expression of the Sperm Whale's there?  It is the\nsame he died with, only some of the longer wrinkles in the forehead\nseem now faded away.  I think his broad brow to be full of a\nprairie-like placidity, born of a speculative indifference as to\ndeath.  But mark the other head's expression.  See that amazing lower\nlip, pressed by accident against the vessel's side, so as firmly to\nembrace the jaw.  Does not this whole head seem to speak of an\nenormous practical resolution in facing death?  This Right Whale I\ntake to have been a Stoic; the Sperm Whale, a Platonian, who might\nhave taken up Spinoza in his latter years.\n\n\n\nCHAPTER 76\n\nThe Battering-Ram.\n\n\nEre quitting, for the nonce, the Sperm Whale's head, I would have\nyou, as a sensible physiologist, simply--particularly remark its\nfront aspect, in all its compacted collectedness.  I would have you\ninvestigate it now with the sole view of forming to yourself some\nunexaggerated, intelligent estimate of whatever battering-ram power\nmay be lodged there.  Here is a vital point; for you must either\nsatisfactorily settle this matter with yourself, or for ever remain\nan infidel as to one of the most appalling, but not the less true\nevents, perhaps anywhere to be found in all recorded history.\n\nYou observe that in the ordinary swimming position of the Sperm\nWhale, the front of his head presents an almost wholly vertical plane\nto the water; you observe that the lower part of that front slopes\nconsiderably backwards, so as to furnish more of a retreat for the\nlong socket which receives the boom-like lower jaw; you observe that\nthe mouth is entirely under the head, much in the same way, indeed,\nas though your own mouth were entirely under your chin.  Moreover you\nobserve that the whale has no external nose; and that what nose he\nhas--his spout hole--is on the top of his head; you observe that his\neyes and ears are at the sides of his head, nearly one third of his\nentire length from the front.  Wherefore, you must now have perceived\nthat the front of the Sperm Whale's head is a dead, blind wall,\nwithout a single organ or tender prominence of any sort whatsoever.\nFurthermore, you are now to consider that only in the extreme, lower,\nbackward sloping part of the front of the head, is there the\nslightest vestige of bone; and not till you get near twenty feet from\nthe forehead do you come to the full cranial development.  So that\nthis whole enormous boneless mass is as one wad.  Finally, though, as\nwill soon be revealed, its contents partly comprise the most delicate\noil; yet, you are now to be apprised of the nature of the substance\nwhich so impregnably invests all that apparent effeminacy.  In some\nprevious place I have described to you how the blubber wraps the body\nof the whale, as the rind wraps an orange.  Just so with the head;\nbut with this difference: about the head this envelope, though not so\nthick, is of a boneless toughness, inestimable by any man who has not\nhandled it.  The severest pointed harpoon, the sharpest lance darted\nby the strongest human arm, impotently rebounds from it.  It is as\nthough the forehead of the Sperm Whale were paved with horses' hoofs.\nI do not think that any sensation lurks in it.\n\nBethink yourself also of another thing.  When two large, loaded\nIndiamen chance to crowd and crush towards each other in the\ndocks, what do the sailors do?  They do not suspend between them, at\nthe point of coming contact, any merely hard substance, like iron or\nwood.  No, they hold there a large, round wad of tow and cork,\nenveloped in the thickest and toughest of ox-hide.  That bravely and\nuninjured takes the jam which would have snapped all their oaken\nhandspikes and iron crow-bars.  By itself this sufficiently\nillustrates the obvious fact I drive at.  But supplementary to this,\nit has hypothetically occurred to me, that as ordinary fish possess\nwhat is called a swimming bladder in them, capable, at will, of\ndistension or contraction; and as the Sperm Whale, as far as I know,\nhas no such provision in him; considering, too, the otherwise\ninexplicable manner in which he now depresses his head altogether\nbeneath the surface, and anon swims with it high elevated out of the\nwater; considering the unobstructed elasticity of its envelope;\nconsidering the unique interior of his head; it has hypothetically\noccurred to me, I say, that those mystical lung-celled honeycombs\nthere may possibly have some hitherto unknown and unsuspected\nconnexion with the outer air, so as to be susceptible to atmospheric\ndistension and contraction.  If this be so, fancy the\nirresistibleness of that might, to which the most impalpable and\ndestructive of all elements contributes.\n\nNow, mark.  Unerringly impelling this dead, impregnable, uninjurable\nwall, and this most buoyant thing within; there swims behind it all a\nmass of tremendous life, only to be adequately estimated as piled\nwood is--by the cord; and all obedient to one volition, as the\nsmallest insect.  So that when I shall hereafter detail to you all\nthe specialities and concentrations of potency everywhere lurking in\nthis expansive monster; when I shall show you some of his more\ninconsiderable braining feats; I trust you will have renounced all\nignorant incredulity, and be ready to abide by this; that though the\nSperm Whale stove a passage through the Isthmus of Darien, and mixed\nthe Atlantic with the Pacific, you would not elevate one hair of your\neye-brow.  For unless you own the whale, you are but a provincial and\nsentimentalist in Truth.  But clear Truth is a thing for salamander\ngiants only to encounter; how small the chances for the provincials\nthen?  What befell the weakling youth lifting the dread goddess's\nveil at Lais?\n\n\n\nCHAPTER 77\n\nThe Great Heidelburgh Tun.\n\n\nNow comes the Baling of the Case.  But to comprehend it aright, you\nmust know something of the curious internal structure of the thing\noperated upon.\n\nRegarding the Sperm Whale's head as a solid oblong, you may, on an\ninclined plane, sideways divide it into two quoins,* whereof the\nlower is the bony structure, forming the cranium and jaws, and the\nupper an unctuous mass wholly free from bones; its broad forward end\nforming the expanded vertical apparent forehead of the whale.  At the\nmiddle of the forehead horizontally subdivide this upper quoin, and\nthen you have two almost equal parts, which before were naturally\ndivided by an internal wall of a thick tendinous substance.\n\n\n*Quoin is not a Euclidean term.  It belongs to the pure nautical\nmathematics.  I know not that it has been defined before.  A quoin is\na solid which differs from a wedge in having its sharp end formed by\nthe steep inclination of one side, instead of the mutual tapering of\nboth sides.\n\n\nThe lower subdivided part, called the junk, is one immense honeycomb\nof oil, formed by the crossing and recrossing, into ten thousand\ninfiltrated cells, of tough elastic white fibres throughout its whole\nextent.  The upper part, known as the Case, may be regarded as the\ngreat Heidelburgh Tun of the Sperm Whale.  And as that famous great\ntierce is mystically carved in front, so the whale's vast plaited\nforehead forms innumerable strange devices for the emblematical\nadornment of his wondrous tun.  Moreover, as that of Heidelburgh was\nalways replenished with the most excellent of the wines of the\nRhenish valleys, so the tun of the whale contains by far the most\nprecious of all his oily vintages; namely, the highly-prized\nspermaceti, in its absolutely pure, limpid, and odoriferous state.\nNor is this precious substance found unalloyed in any other part of\nthe creature.  Though in life it remains perfectly fluid, yet, upon\nexposure to the air, after death, it soon begins to concrete; sending\nforth beautiful crystalline shoots, as when the first thin delicate\nice is just forming in water.  A large whale's case generally yields\nabout five hundred gallons of sperm, though from unavoidable\ncircumstances, considerable of it is spilled, leaks, and dribbles\naway, or is otherwise irrevocably lost in the ticklish business of\nsecuring what you can.\n\nI know not with what fine and costly material the Heidelburgh Tun was\ncoated within, but in superlative richness that coating could not\npossibly have compared with the silken pearl-coloured membrane, like\nthe lining of a fine pelisse, forming the inner surface of the Sperm\nWhale's case.\n\nIt will have been seen that the Heidelburgh Tun of the Sperm Whale\nembraces the entire length of the entire top of the head; and\nsince--as has been elsewhere set forth--the head embraces one third\nof the whole length of the creature, then setting that length down at\neighty feet for a good sized whale, you have more than twenty-six\nfeet for the depth of the tun, when it is lengthwise hoisted up and\ndown against a ship's side.\n\nAs in decapitating the whale, the operator's instrument is brought\nclose to the spot where an entrance is subsequently forced into the\nspermaceti magazine; he has, therefore, to be uncommonly heedful,\nlest a careless, untimely stroke should invade the sanctuary and\nwastingly let out its invaluable contents.  It is this decapitated\nend of the head, also, which is at last elevated out of the water,\nand retained in that position by the enormous cutting tackles, whose\nhempen combinations, on one side, make quite a wilderness of ropes in\nthat quarter.\n\nThus much being said, attend now, I pray you, to that marvellous\nand--in this particular instance--almost fatal operation whereby the\nSperm Whale's great Heidelburgh Tun is tapped.\n\n\n\nCHAPTER 78\n\nCistern and Buckets.\n\n\nNimble as a cat, Tashtego mounts aloft; and without altering his\nerect posture, runs straight out upon the overhanging mainyard-arm,\nto the part where it exactly projects over the hoisted Tun.  He has\ncarried with him a light tackle called a whip, consisting of only two\nparts, travelling through a single-sheaved block.  Securing this\nblock, so that it hangs down from the yard-arm, he swings one end of\nthe rope, till it is caught and firmly held by a hand on deck.\nThen, hand-over-hand, down the other part, the Indian drops through\nthe air, till dexterously he lands on the summit of the head.\nThere--still high elevated above the rest of the company, to whom he\nvivaciously cries--he seems some Turkish Muezzin calling the good\npeople to prayers from the top of a tower.  A short-handled sharp\nspade being sent up to him, he diligently searches for the proper\nplace to begin breaking into the Tun.  In this business he proceeds\nvery heedfully, like a treasure-hunter in some old house, sounding\nthe walls to find where the gold is masoned in.  By the time this\ncautious search is over, a stout iron-bound bucket, precisely like a\nwell-bucket, has been attached to one end of the whip; while the\nother end, being stretched across the deck, is there held by two or\nthree alert hands.  These last now hoist the bucket within grasp of\nthe Indian, to whom another person has reached up a very long pole.\nInserting this pole into the bucket, Tashtego downward guides the\nbucket into the Tun, till it entirely disappears; then giving the\nword to the seamen at the whip, up comes the bucket again, all\nbubbling like a dairy-maid's pail of new milk.  Carefully lowered\nfrom its height, the full-freighted vessel is caught by an appointed\nhand, and quickly emptied into a large tub.  Then remounting aloft,\nit again goes through the same round until the deep cistern will\nyield no more.  Towards the end, Tashtego has to ram his long pole\nharder and harder, and deeper and deeper into the Tun, until some\ntwenty feet of the pole have gone down.\n\nNow, the people of the Pequod had been baling some time in this way;\nseveral tubs had been filled with the fragrant sperm; when all at\nonce a queer accident happened.  Whether it was that Tashtego, that\nwild Indian, was so heedless and reckless as to let go for a moment\nhis one-handed hold on the great cabled tackles suspending the head;\nor whether the place where he stood was so treacherous and oozy; or\nwhether the Evil One himself would have it to fall out so, without\nstating his particular reasons; how it was exactly, there is no\ntelling now; but, on a sudden, as the eightieth or ninetieth bucket\ncame suckingly up--my God! poor Tashtego--like the twin reciprocating\nbucket in a veritable well, dropped head-foremost down into this\ngreat Tun of Heidelburgh, and with a horrible oily gurgling, went\nclean out of sight!\n\n\"Man overboard!\" cried Daggoo, who amid the general consternation\nfirst came to his senses.  \"Swing the bucket this way!\" and putting\none foot into it, so as the better to secure his slippery hand-hold\non the whip itself, the hoisters ran him high up to the top of the\nhead, almost before Tashtego could have reached its interior bottom.\nMeantime, there was a terrible tumult.  Looking over the side, they\nsaw the before lifeless head throbbing and heaving just below the\nsurface of the sea, as if that moment seized with some momentous\nidea; whereas it was only the poor Indian unconsciously revealing by\nthose struggles the perilous depth to which he had sunk.\n\nAt this instant, while Daggoo, on the summit of the head, was\nclearing the whip--which had somehow got foul of the great cutting\ntackles--a sharp cracking noise was heard; and to the unspeakable\nhorror of all, one of the two enormous hooks suspending the head tore\nout, and with a vast vibration the enormous mass sideways swung, till\nthe drunk ship reeled and shook as if smitten by an iceberg.  The one\nremaining hook, upon which the entire strain now depended, seemed\nevery instant to be on the point of giving way; an event still more\nlikely from the violent motions of the head.\n\n\"Come down, come down!\" yelled the seamen to Daggoo, but with one\nhand holding on to the heavy tackles, so that if the head should\ndrop, he would still remain suspended; the negro having cleared the\nfoul line, rammed down the bucket into the now collapsed well,\nmeaning that the buried harpooneer should grasp it, and so be hoisted\nout.\n\n\"In heaven's name, man,\" cried Stubb, \"are you ramming home a\ncartridge there?--Avast!  How will that help him; jamming that\niron-bound bucket on top of his head?  Avast, will ye!\"\n\n\"Stand clear of the tackle!\" cried a voice like the bursting of a\nrocket.\n\nAlmost in the same instant, with a thunder-boom, the enormous mass\ndropped into the sea, like Niagara's Table-Rock into the whirlpool;\nthe suddenly relieved hull rolled away from it, to far down her\nglittering copper; and all caught their breath, as half swinging--now\nover the sailors' heads, and now over the water--Daggoo, through a\nthick mist of spray, was dimly beheld clinging to the pendulous\ntackles, while poor, buried-alive Tashtego was sinking utterly down\nto the bottom of the sea!  But hardly had the blinding vapour cleared\naway, when a naked figure with a boarding-sword in his hand, was for\none swift moment seen hovering over the bulwarks.  The next, a loud\nsplash announced that my brave Queequeg had dived to the rescue.  One\npacked rush was made to the side, and every eye counted every ripple,\nas moment followed moment, and no sign of either the sinker or the\ndiver could be seen.  Some hands now jumped into a boat alongside,\nand pushed a little off from the ship.\n\n\"Ha! ha!\" cried Daggoo, all at once, from his now quiet, swinging\nperch overhead; and looking further off from the side, we saw an arm\nthrust upright from the blue waves; a sight strange to see, as an arm\nthrust forth from the grass over a grave.\n\n\"Both! both!--it is both!\"--cried Daggoo again with a joyful shout;\nand soon after, Queequeg was seen boldly striking out with one hand,\nand with the other clutching the long hair of the Indian.  Drawn into\nthe waiting boat, they were quickly brought to the deck; but Tashtego\nwas long in coming to, and Queequeg did not look very brisk.\n\nNow, how had this noble rescue been accomplished?  Why, diving after\nthe slowly descending head, Queequeg with his keen sword had made\nside lunges near its bottom, so as to scuttle a large hole there;\nthen dropping his sword, had thrust his long arm far inwards and\nupwards, and so hauled out poor Tash by the head.  He averred, that\nupon first thrusting in for him, a leg was presented; but well\nknowing that that was not as it ought to be, and might occasion great\ntrouble;--he had thrust back the leg, and by a dexterous heave and\ntoss, had wrought a somerset upon the Indian; so that with the next\ntrial, he came forth in the good old way--head foremost.  As for the\ngreat head itself, that was doing as well as could be expected.\n\nAnd thus, through the courage and great skill in obstetrics of\nQueequeg, the deliverance, or rather, delivery of Tashtego, was\nsuccessfully accomplished, in the teeth, too, of the most untoward\nand apparently hopeless impediments; which is a lesson by no means to\nbe forgotten.  Midwifery should be taught in the same course with\nfencing and boxing, riding and rowing.\n\nI know that this queer adventure of the Gay-Header's will be sure to\nseem incredible to some landsmen, though they themselves may have\neither seen or heard of some one's falling into a cistern ashore; an\naccident which not seldom happens, and with much less reason too than\nthe Indian's, considering the exceeding slipperiness of the curb of\nthe Sperm Whale's well.\n\nBut, peradventure, it may be sagaciously urged, how is this?  We\nthought the tissued, infiltrated head of the Sperm Whale, was the\nlightest and most corky part about him; and yet thou makest it sink\nin an element of a far greater specific gravity than itself.  We have\nthee there.  Not at all, but I have ye; for at the time poor Tash\nfell in, the case had been nearly emptied of its lighter contents,\nleaving little but the dense tendinous wall of the well--a double\nwelded, hammered substance, as I have before said, much heavier than\nthe sea water, and a lump of which sinks in it like lead almost.  But\nthe tendency to rapid sinking in this substance was in the present\ninstance materially counteracted by the other parts of the head\nremaining undetached from it, so that it sank very slowly and\ndeliberately indeed, affording Queequeg a fair chance for performing\nhis agile obstetrics on the run, as you may say.  Yes, it was a\nrunning delivery, so it was.\n\nNow, had Tashtego perished in that head, it had been a very precious\nperishing; smothered in the very whitest and daintiest of fragrant\nspermaceti; coffined, hearsed, and tombed in the secret inner chamber\nand sanctum sanctorum of the whale.  Only one sweeter end can readily\nbe recalled--the delicious death of an Ohio honey-hunter, who seeking\nhoney in the crotch of a hollow tree, found such exceeding store of\nit, that leaning too far over, it sucked him in, so that he died\nembalmed.  How many, think ye, have likewise fallen into Plato's\nhoney head, and sweetly perished there?\n\n\n\nCHAPTER 79\n\nThe Prairie.\n\n\nTo scan the lines of his face, or feel the bumps on the head of this\nLeviathan; this is a thing which no Physiognomist or Phrenologist has\nas yet undertaken.  Such an enterprise would seem almost as hopeful\nas for Lavater to have scrutinized the wrinkles on the Rock of\nGibraltar, or for Gall to have mounted a ladder and manipulated the\nDome of the Pantheon.  Still, in that famous work of his, Lavater\nnot only treats of the various faces of men, but also attentively\nstudies the faces of horses, birds, serpents, and fish; and dwells in\ndetail upon the modifications of expression discernible therein.  Nor\nhave Gall and his disciple Spurzheim failed to throw out some hints\ntouching the phrenological characteristics of other beings than man.\nTherefore, though I am but ill qualified for a pioneer, in the\napplication of these two semi-sciences to the whale, I will do my\nendeavor.  I try all things; I achieve what I can.\n\nPhysiognomically regarded, the Sperm Whale is an anomalous creature.\nHe has no proper nose.  And since the nose is the central and most\nconspicuous of the features; and since it perhaps most modifies and\nfinally controls their combined expression; hence it would seem that\nits entire absence, as an external appendage, must very largely\naffect the countenance of the whale.  For as in landscape gardening,\na spire, cupola, monument, or tower of some sort, is deemed almost\nindispensable to the completion of the scene; so no face can be\nphysiognomically in keeping without the elevated open-work belfry of\nthe nose.  Dash the nose from Phidias's marble Jove, and what a sorry\nremainder!  Nevertheless, Leviathan is of so mighty a magnitude, all\nhis proportions are so stately, that the same deficiency which in the\nsculptured Jove were hideous, in him is no blemish at all.  Nay, it\nis an added grandeur.  A nose to the whale would have been\nimpertinent.  As on your physiognomical voyage you sail round his\nvast head in your jolly-boat, your noble conceptions of him are never\ninsulted by the reflection that he has a nose to be pulled.  A\npestilent conceit, which so often will insist upon obtruding even\nwhen beholding the mightiest royal beadle on his throne.\n\nIn some particulars, perhaps the most imposing physiognomical view\nto be had of the Sperm Whale, is that of the full front of his head.\nThis aspect is sublime.\n\nIn thought, a fine human brow is like the East when troubled with\nthe morning.  In the repose of the pasture, the curled brow of the\nbull has a touch of the grand in it.  Pushing heavy cannon up\nmountain defiles, the elephant's brow is majestic.  Human or animal,\nthe mystical brow is as that great golden seal affixed by the German\nEmperors to their decrees.  It signifies--\"God: done this day by my\nhand.\"  But in most creatures, nay in man himself, very often the\nbrow is but a mere strip of alpine land lying along the snow line.\nFew are the foreheads which like Shakespeare's or Melancthon's rise\nso high, and descend so low, that the eyes themselves seem clear,\neternal, tideless mountain lakes; and all above them in the forehead's\nwrinkles, you seem to track the antlered thoughts descending there to\ndrink, as the Highland hunters track the snow prints of the deer.\nBut in the great Sperm Whale, this high and mighty god-like dignity\ninherent in the brow is so immensely amplified, that gazing on it, in\nthat full front view, you feel the Deity and the dread powers more\nforcibly than in beholding any other object in living nature.  For\nyou see no one point precisely; not one distinct feature is revealed;\nno nose, eyes, ears, or mouth; no face; he has none, proper; nothing\nbut that one broad firmament of a forehead, pleated with riddles;\ndumbly lowering with the doom of boats, and ships, and men.  Nor, in\nprofile, does this wondrous brow diminish; though that way viewed its\ngrandeur does not domineer upon you so.  In profile, you plainly\nperceive that horizontal, semi-crescentic depression in the\nforehead's middle, which, in man, is Lavater's mark of genius.\n\nBut how?  Genius in the Sperm Whale?  Has the Sperm Whale ever\nwritten a book, spoken a speech?  No, his great genius is declared in\nhis doing nothing particular to prove it.  It is moreover declared in\nhis pyramidical silence.  And this reminds me that had the great\nSperm Whale been known to the young Orient World, he would have been\ndeified by their child-magian thoughts.  They deified the crocodile\nof the Nile, because the crocodile is tongueless; and the Sperm Whale\nhas no tongue, or at least it is so exceedingly small, as to be\nincapable of protrusion.  If hereafter any highly cultured, poetical\nnation shall lure back to their birth-right, the merry May-day gods\nof old; and livingly enthrone them again in the now egotistical sky;\nin the now unhaunted hill; then be sure, exalted to Jove's high seat,\nthe great Sperm Whale shall lord it.\n\nChampollion deciphered the wrinkled granite hieroglyphics.  But there\nis no Champollion to decipher the Egypt of every man's and every\nbeing's face.  Physiognomy, like every other human science, is but a\npassing fable.  If then, Sir William Jones, who read in thirty\nlanguages, could not read the simplest peasant's face in its\nprofounder and more subtle meanings, how may unlettered Ishmael hope\nto read the awful Chaldee of the Sperm Whale's brow?  I but put that\nbrow before you.  Read it if you can.\n\n\n\nCHAPTER 80\n\nThe Nut.\n\n\nIf the Sperm Whale be physiognomically a Sphinx, to the phrenologist\nhis brain seems that geometrical circle which it is impossible to\nsquare.\n\nIn the full-grown creature the skull will measure at least twenty\nfeet in length.  Unhinge the lower jaw, and the side view of this\nskull is as the side of a moderately inclined plane resting\nthroughout on a level base.  But in life--as we have elsewhere\nseen--this inclined plane is angularly filled up, and almost squared\nby the enormous superincumbent mass of the junk and sperm.  At the\nhigh end the skull forms a crater to bed that part of the mass; while\nunder the long floor of this crater--in another cavity seldom\nexceeding ten inches in length and as many in depth--reposes the\nmere handful of this monster's brain.  The brain is at least twenty\nfeet from his apparent forehead in life; it is hidden away behind its\nvast outworks, like the innermost citadel within the amplified\nfortifications of Quebec.  So like a choice casket is it secreted in\nhim, that I have known some whalemen who peremptorily deny that the\nSperm Whale has any other brain than that palpable semblance of one\nformed by the cubic-yards of his sperm magazine.  Lying in strange\nfolds, courses, and convolutions, to their apprehensions, it seems\nmore in keeping with the idea of his general might to regard that\nmystic part of him as the seat of his intelligence.\n\nIt is plain, then, that phrenologically the head of this Leviathan,\nin the creature's living intact state, is an entire delusion.  As for\nhis true brain, you can then see no indications of it, nor feel any.\nThe whale, like all things that are mighty, wears a false brow to the\ncommon world.\n\nIf you unload his skull of its spermy heaps and then take a rear view\nof its rear end, which is the high end, you will be struck by its\nresemblance to the human skull, beheld in the same situation, and\nfrom the same point of view.  Indeed, place this reversed skull\n(scaled down to the human magnitude) among a plate of men's skulls,\nand you would involuntarily confound it with them; and remarking the\ndepressions on one part of its summit, in phrenological phrase you\nwould say--This man had no self-esteem, and no veneration.  And by\nthose negations, considered along with the affirmative fact of his\nprodigious bulk and power, you can best form to yourself the truest,\nthough not the most exhilarating conception of what the most exalted\npotency is.\n\nBut if from the comparative dimensions of the whale's proper brain,\nyou deem it incapable of being adequately charted, then I have\nanother idea for you.  If you attentively regard almost any\nquadruped's spine, you will be struck with the resemblance of its\nvertebrae to a strung necklace of dwarfed skulls, all bearing\nrudimental resemblance to the skull proper.  It is a German conceit,\nthat the vertebrae are absolutely undeveloped skulls.  But the\ncurious external resemblance, I take it the Germans were not the\nfirst men to perceive.  A foreign friend once pointed it out to me,\nin the skeleton of a foe he had slain, and with the vertebrae of\nwhich he was inlaying, in a sort of basso-relievo, the beaked prow\nof his canoe.  Now, I consider that the phrenologists have omitted an\nimportant thing in not pushing their investigations from the\ncerebellum through the spinal canal.  For I believe that much of a\nman's character will be found betokened in his backbone.  I would\nrather feel your spine than your skull, whoever you are.  A thin\njoist of a spine never yet upheld a full and noble soul.  I rejoice\nin my spine, as in the firm audacious staff of that flag which I\nfling half out to the world.\n\nApply this spinal branch of phrenology to the Sperm Whale.  His\ncranial cavity is continuous with the first neck-vertebra; and in\nthat vertebra the bottom of the spinal canal will measure ten inches\nacross, being eight in height, and of a triangular figure with the\nbase downwards.  As it passes through the remaining vertebrae the\ncanal tapers in size, but for a considerable distance remains of\nlarge capacity.  Now, of course, this canal is filled with much the\nsame strangely fibrous substance--the spinal cord--as the brain; and\ndirectly communicates with the brain.  And what is still more, for\nmany feet after emerging from the brain's cavity, the spinal cord\nremains of an undecreasing girth, almost equal to that of the brain.\nUnder all these circumstances, would it be unreasonable to survey and\nmap out the whale's spine phrenologically?  For, viewed in this\nlight, the wonderful comparative smallness of his brain proper is\nmore than compensated by the wonderful comparative magnitude of his\nspinal cord.\n\nBut leaving this hint to operate as it may with the phrenologists, I\nwould merely assume the spinal theory for a moment, in reference to\nthe Sperm Whale's hump.  This august hump, if I mistake not, rises\nover one of the larger vertebrae, and is, therefore, in some sort,\nthe outer convex mould of it.  From its relative situation then, I\nshould call this high hump the organ of firmness or indomitableness\nin the Sperm Whale.  And that the great monster is indomitable, you\nwill yet have reason to know.\n\n\n\nCHAPTER 81\n\nThe Pequod Meets The Virgin.\n\n\nThe predestinated day arrived, and we duly met the ship Jungfrau,\nDerick De Deer, master, of Bremen.\n\nAt one time the greatest whaling people in the world, the Dutch and\nGermans are now among the least; but here and there at very wide\nintervals of latitude and longitude, you still occasionally meet with\ntheir flag in the Pacific.\n\nFor some reason, the Jungfrau seemed quite eager to pay her respects.\nWhile yet some distance from the Pequod, she rounded to, and\ndropping a boat, her captain was impelled towards us, impatiently\nstanding in the bows instead of the stern.\n\n\"What has he in his hand there?\" cried Starbuck, pointing to\nsomething wavingly held by the German.  \"Impossible!--a lamp-feeder!\"\n\n\"Not that,\" said Stubb, \"no, no, it's a coffee-pot, Mr. Starbuck;\nhe's coming off to make us our coffee, is the Yarman; don't you see\nthat big tin can there alongside of him?--that's his boiling water.\nOh! he's all right, is the Yarman.\"\n\n\"Go along with you,\" cried Flask, \"it's a lamp-feeder and an oil-can.\nHe's out of oil, and has come a-begging.\"\n\nHowever curious it may seem for an oil-ship to be borrowing oil on\nthe whale-ground, and however much it may invertedly contradict the\nold proverb about carrying coals to Newcastle, yet sometimes such a\nthing really happens; and in the present case Captain Derick De Deer\ndid indubitably conduct a lamp-feeder as Flask did declare.\n\nAs he mounted the deck, Ahab abruptly accosted him, without at all\nheeding what he had in his hand; but in his broken lingo, the German\nsoon evinced his complete ignorance of the White Whale; immediately\nturning the conversation to his lamp-feeder and oil can, with some\nremarks touching his having to turn into his hammock at night in\nprofound darkness--his last drop of Bremen oil being gone, and not a\nsingle flying-fish yet captured to supply the deficiency; concluding\nby hinting that his ship was indeed what in the Fishery is\ntechnically called a CLEAN one (that is, an empty one), well\ndeserving the name of Jungfrau or the Virgin.\n\nHis necessities supplied, Derick departed; but he had not gained his\nship's side, when whales were almost simultaneously raised from the\nmast-heads of both vessels; and so eager for the chase was Derick,\nthat without pausing to put his oil-can and lamp-feeder aboard, he\nslewed round his boat and made after the leviathan lamp-feeders.\n\nNow, the game having risen to leeward, he and the other three German\nboats that soon followed him, had considerably the start of the\nPequod's keels.  There were eight whales, an average pod.  Aware of\ntheir danger, they were going all abreast with great speed straight\nbefore the wind, rubbing their flanks as closely as so many spans of\nhorses in harness.  They left a great, wide wake, as though\ncontinually unrolling a great wide parchment upon the sea.\n\nFull in this rapid wake, and many fathoms in the rear, swam a huge,\nhumped old bull, which by his comparatively slow progress, as well as\nby the unusual yellowish incrustations overgrowing him, seemed\nafflicted with the jaundice, or some other infirmity.  Whether this\nwhale belonged to the pod in advance, seemed questionable; for it is\nnot customary for such venerable leviathans to be at all social.\nNevertheless, he stuck to their wake, though indeed their back water\nmust have retarded him, because the white-bone or swell at his broad\nmuzzle was a dashed one, like the swell formed when two hostile\ncurrents meet.  His spout was short, slow, and laborious; coming\nforth with a choking sort of gush, and spending itself in torn\nshreds, followed by strange subterranean commotions in him, which\nseemed to have egress at his other buried extremity, causing the\nwaters behind him to upbubble.\n\n\"Who's got some paregoric?\" said Stubb, \"he has the stomach-ache, I'm\nafraid.  Lord, think of having half an acre of stomach-ache!  Adverse\nwinds are holding mad Christmas in him, boys.  It's the first foul\nwind I ever knew to blow from astern; but look, did ever whale yaw\nso before? it must be, he's lost his tiller.\"\n\nAs an overladen Indiaman bearing down the Hindostan coast with a deck\nload of frightened horses, careens, buries, rolls, and wallows on her\nway; so did this old whale heave his aged bulk, and now and then\npartly turning over on his cumbrous rib-ends, expose the cause of his\ndevious wake in the unnatural stump of his starboard fin.  Whether he\nhad lost that fin in battle, or had been born without it, it were\nhard to say.\n\n\"Only wait a bit, old chap, and I'll give ye a sling for that wounded\narm,\" cried cruel Flask, pointing to the whale-line near him.\n\n\"Mind he don't sling thee with it,\" cried Starbuck.  \"Give way, or\nthe German will have him.\"\n\nWith one intent all the combined rival boats were pointed for this\none fish, because not only was he the largest, and therefore the most\nvaluable whale, but he was nearest to them, and the other whales were\ngoing with such great velocity, moreover, as almost to defy pursuit\nfor the time.  At this juncture the Pequod's keels had shot by the\nthree German boats last lowered; but from the great start he had had,\nDerick's boat still led the chase, though every moment neared by his\nforeign rivals.  The only thing they feared, was, that from being\nalready so nigh to his mark, he would be enabled to dart his iron\nbefore they could completely overtake and pass him.  As for Derick,\nhe seemed quite confident that this would be the case, and\noccasionally with a deriding gesture shook his lamp-feeder at the\nother boats.\n\n\"The ungracious and ungrateful dog!\" cried Starbuck; \"he mocks and\ndares me with the very poor-box I filled for him not five minutes\nago!\"--then in his old intense whisper--\"Give way, greyhounds!  Dog\nto it!\"\n\n\"I tell ye what it is, men\"--cried Stubb to his crew--\"it's against\nmy religion to get mad; but I'd like to eat that villainous\nYarman--Pull--won't ye?  Are ye going to let that rascal beat ye?  Do\nye love brandy?  A hogshead of brandy, then, to the best man.  Come,\nwhy don't some of ye burst a blood-vessel?  Who's that been dropping\nan anchor overboard--we don't budge an inch--we're becalmed.  Halloo,\nhere's grass growing in the boat's bottom--and by the Lord, the mast\nthere's budding.  This won't do, boys.  Look at that Yarman!  The\nshort and long of it is, men, will ye spit fire or not?\"\n\n\"Oh! see the suds he makes!\" cried Flask, dancing up and down--\"What\na hump--Oh, DO pile on the beef--lays like a log!  Oh! my lads, DO\nspring--slap-jacks and quahogs for supper, you know, my lads--baked\nclams and muffins--oh, DO, DO, spring,--he's a hundred barreller--don't\nlose him now--don't oh, DON'T!--see that Yarman--Oh,\nwon't ye pull for your duff, my lads--such a sog! such a sogger!\nDon't ye love sperm?  There goes three thousand dollars, men!--a\nbank!--a whole bank!  The bank of England!--Oh, DO, DO, DO!--What's\nthat Yarman about now?\"\n\nAt this moment Derick was in the act of pitching his lamp-feeder at\nthe advancing boats, and also his oil-can; perhaps with the double\nview of retarding his rivals' way, and at the same time economically\naccelerating his own by the momentary impetus of the backward toss.\n\n\"The unmannerly Dutch dogger!\" cried Stubb.  \"Pull now, men, like\nfifty thousand line-of-battle-ship loads of red-haired devils.  What\nd'ye say, Tashtego; are you the man to snap your spine in\ntwo-and-twenty pieces for the honour of old Gayhead?  What d'ye say?\"\n\n\"I say, pull like god-dam,\"--cried the Indian.\n\nFiercely, but evenly incited by the taunts of the German, the\nPequod's three boats now began ranging almost abreast; and, so\ndisposed, momentarily neared him.  In that fine, loose, chivalrous\nattitude of the headsman when drawing near to his prey, the three\nmates stood up proudly, occasionally backing the after oarsman with\nan exhilarating cry of, \"There she slides, now!  Hurrah for the\nwhite-ash breeze!  Down with the Yarman!  Sail over him!\"\n\nBut so decided an original start had Derick had, that spite of all\ntheir gallantry, he would have proved the victor in this race, had\nnot a righteous judgment descended upon him in a crab which caught\nthe blade of his midship oarsman.  While this clumsy lubber was\nstriving to free his white-ash, and while, in consequence, Derick's\nboat was nigh to capsizing, and he thundering away at his men in a\nmighty rage;--that was a good time for Starbuck, Stubb, and Flask.\nWith a shout, they took a mortal start forwards, and slantingly\nranged up on the German's quarter.  An instant more, and all four\nboats were diagonically in the whale's immediate wake, while\nstretching from them, on both sides, was the foaming swell that he\nmade.\n\nIt was a terrific, most pitiable, and maddening sight.  The whale was\nnow going head out, and sending his spout before him in a continual\ntormented jet; while his one poor fin beat his side in an agony of\nfright.  Now to this hand, now to that, he yawed in his faltering\nflight, and still at every billow that he broke, he spasmodically\nsank in the sea, or sideways rolled towards the sky his one beating\nfin.  So have I seen a bird with clipped wing making affrighted\nbroken circles in the air, vainly striving to escape the piratical\nhawks.  But the bird has a voice, and with plaintive cries will make\nknown her fear; but the fear of this vast dumb brute of the sea, was\nchained up and enchanted in him; he had no voice, save that choking\nrespiration through his spiracle, and this made the sight of him\nunspeakably pitiable; while still, in his amazing bulk, portcullis\njaw, and omnipotent tail, there was enough to appal the stoutest man\nwho so pitied.\n\nSeeing now that but a very few moments more would give the Pequod's\nboats the advantage, and rather than be thus foiled of his game,\nDerick chose to hazard what to him must have seemed a most unusually\nlong dart, ere the last chance would for ever escape.\n\nBut no sooner did his harpooneer stand up for the stroke, than all\nthree tigers--Queequeg, Tashtego, Daggoo--instinctively sprang to\ntheir feet, and standing in a diagonal row, simultaneously pointed\ntheir barbs; and darted over the head of the German harpooneer, their\nthree Nantucket irons entered the whale.  Blinding vapours of foam and\nwhite-fire!  The three boats, in the first fury of the whale's\nheadlong rush, bumped the German's aside with such force, that both\nDerick and his baffled harpooneer were spilled out, and sailed over\nby the three flying keels.\n\n\"Don't be afraid, my butter-boxes,\" cried Stubb, casting a passing\nglance upon them as he shot by; \"ye'll be picked up presently--all\nright--I saw some sharks astern--St. Bernard's dogs, you\nknow--relieve distressed travellers.  Hurrah! this is the way to sail\nnow.  Every keel a sunbeam!  Hurrah!--Here we go like three tin\nkettles at the tail of a mad cougar!  This puts me in mind of\nfastening to an elephant in a tilbury on a plain--makes the\nwheel-spokes fly, boys, when you fasten to him that way; and there's\ndanger of being pitched out too, when you strike a hill.  Hurrah!\nthis is the way a fellow feels when he's going to Davy Jones--all a\nrush down an endless inclined plane!  Hurrah! this whale carries the\neverlasting mail!\"\n\nBut the monster's run was a brief one.  Giving a sudden gasp, he\ntumultuously sounded.  With a grating rush, the three lines flew\nround the loggerheads with such a force as to gouge deep grooves in\nthem; while so fearful were the harpooneers that this rapid sounding\nwould soon exhaust the lines, that using all their dexterous might,\nthey caught repeated smoking turns with the rope to hold on; till at\nlast--owing to the perpendicular strain from the lead-lined chocks of\nthe boats, whence the three ropes went straight down into the\nblue--the gunwales of the bows were almost even with the water, while\nthe three sterns tilted high in the air.  And the whale soon ceasing\nto sound, for some time they remained in that attitude, fearful of\nexpending more line, though the position was a little ticklish.  But\nthough boats have been taken down and lost in this way, yet it is\nthis \"holding on,\" as it is called; this hooking up by the sharp\nbarbs of his live flesh from the back; this it is that often torments\nthe Leviathan into soon rising again to meet the sharp lance of his\nfoes.  Yet not to speak of the peril of the thing, it is to be\ndoubted whether this course is always the best; for it is but\nreasonable to presume, that the longer the stricken whale stays under\nwater, the more he is exhausted.  Because, owing to the enormous\nsurface of him--in a full grown sperm whale something less than 2000\nsquare feet--the pressure of the water is immense.  We all know what\nan astonishing atmospheric weight we ourselves stand up under; even\nhere, above-ground, in the air; how vast, then, the burden of a\nwhale, bearing on his back a column of two hundred fathoms of ocean!\nIt must at least equal the weight of fifty atmospheres.  One whaleman\nhas estimated it at the weight of twenty line-of-battle ships, with\nall their guns, and stores, and men on board.\n\nAs the three boats lay there on that gently rolling sea, gazing down\ninto its eternal blue noon; and as not a single groan or cry of any\nsort, nay, not so much as a ripple or a bubble came up from its\ndepths; what landsman would have thought, that beneath all that\nsilence and placidity, the utmost monster of the seas was writhing\nand wrenching in agony!  Not eight inches of perpendicular rope were\nvisible at the bows.  Seems it credible that by three such thin\nthreads the great Leviathan was suspended like the big weight to an\neight day clock.  Suspended? and to what?  To three bits of board.\nIs this the creature of whom it was once so triumphantly said--\"Canst\nthou fill his skin with barbed irons? or his head with fish-spears?\nThe sword of him that layeth at him cannot hold, the spear, the dart,\nnor the habergeon: he esteemeth iron as straw; the arrow cannot make\nhim flee; darts are counted as stubble; he laugheth at the shaking of\na spear!\"  This the creature? this he?  Oh! that unfulfilments should\nfollow the prophets.  For with the strength of a thousand thighs in\nhis tail, Leviathan had run his head under the mountains of the sea,\nto hide him from the Pequod's fish-spears!\n\nIn that sloping afternoon sunlight, the shadows that the three boats\nsent down beneath the surface, must have been long enough and broad\nenough to shade half Xerxes' army.  Who can tell how appalling to the\nwounded whale must have been such huge phantoms flitting over his\nhead!\n\n\"Stand by, men; he stirs,\" cried Starbuck, as the three lines\nsuddenly vibrated in the water, distinctly conducting upwards to\nthem, as by magnetic wires, the life and death throbs of the whale,\nso that every oarsman felt them in his seat.  The next moment,\nrelieved in great part from the downward strain at the bows, the\nboats gave a sudden bounce upwards, as a small icefield will, when a\ndense herd of white bears are scared from it into the sea.\n\n\"Haul in!  Haul in!\" cried Starbuck again; \"he's rising.\"\n\nThe lines, of which, hardly an instant before, not one hand's breadth\ncould have been gained, were now in long quick coils flung back all\ndripping into the boats, and soon the whale broke water within two\nship's lengths of the hunters.\n\nHis motions plainly denoted his extreme exhaustion.  In most land\nanimals there are certain valves or flood-gates in many of their\nveins, whereby when wounded, the blood is in some degree at least\ninstantly shut off in certain directions.  Not so with the whale; one\nof whose peculiarities it is to have an entire non-valvular structure\nof the blood-vessels, so that when pierced even by so small a point\nas a harpoon, a deadly drain is at once begun upon his whole\narterial system; and when this is heightened by the extraordinary\npressure of water at a great distance below the surface, his life may\nbe said to pour from him in incessant streams.  Yet so vast is the\nquantity of blood in him, and so distant and numerous its interior\nfountains, that he will keep thus bleeding and bleeding for a\nconsiderable period; even as in a drought a river will flow, whose\nsource is in the well-springs of far-off and undiscernible hills.\nEven now, when the boats pulled upon this whale, and perilously drew\nover his swaying flukes, and the lances were darted into him, they\nwere followed by steady jets from the new made wound, which kept\ncontinually playing, while the natural spout-hole in his head was\nonly at intervals, however rapid, sending its affrighted moisture\ninto the air.  From this last vent no blood yet came, because no\nvital part of him had thus far been struck.  His life, as they\nsignificantly call it, was untouched.\n\nAs the boats now more closely surrounded him, the whole upper part of\nhis form, with much of it that is ordinarily submerged, was plainly\nrevealed.  His eyes, or rather the places where his eyes had been,\nwere beheld.  As strange misgrown masses gather in the knot-holes of\nthe noblest oaks when prostrate, so from the points which the whale's\neyes had once occupied, now protruded blind bulbs, horribly pitiable\nto see.  But pity there was none.  For all his old age, and his one\narm, and his blind eyes, he must die the death and be murdered, in\norder to light the gay bridals and other merry-makings of men, and\nalso to illuminate the solemn churches that preach unconditional\ninoffensiveness by all to all.  Still rolling in his blood, at last\nhe partially disclosed a strangely discoloured bunch or protuberance,\nthe size of a bushel, low down on the flank.\n\n\"A nice spot,\" cried Flask; \"just let me prick him there once.\"\n\n\"Avast!\" cried Starbuck, \"there's no need of that!\"\n\nBut humane Starbuck was too late.  At the instant of the dart an\nulcerous jet shot from this cruel wound, and goaded by it into more\nthan sufferable anguish, the whale now spouting thick blood, with\nswift fury blindly darted at the craft, bespattering them and their\nglorying crews all over with showers of gore, capsizing Flask's boat\nand marring the bows.  It was his death stroke.  For, by this time,\nso spent was he by loss of blood, that he helplessly rolled away from\nthe wreck he had made; lay panting on his side, impotently flapped\nwith his stumped fin, then over and over slowly revolved like a\nwaning world; turned up the white secrets of his belly; lay like a\nlog, and died.  It was most piteous, that last expiring spout.  As\nwhen by unseen hands the water is gradually drawn off from some\nmighty fountain, and with half-stifled melancholy gurglings the\nspray-column lowers and lowers to the ground--so the last long dying\nspout of the whale.\n\nSoon, while the crews were awaiting the arrival of the ship, the body\nshowed symptoms of sinking with all its treasures unrifled.\nImmediately, by Starbuck's orders, lines were secured to it at\ndifferent points, so that ere long every boat was a buoy; the sunken\nwhale being suspended a few inches beneath them by the cords.  By\nvery heedful management, when the ship drew nigh, the whale was\ntransferred to her side, and was strongly secured there by the\nstiffest fluke-chains, for it was plain that unless artificially\nupheld, the body would at once sink to the bottom.\n\nIt so chanced that almost upon first cutting into him with the\nspade, the entire length of a corroded harpoon was found imbedded in\nhis flesh, on the lower part of the bunch before described.  But as\nthe stumps of harpoons are frequently found in the dead bodies of\ncaptured whales, with the flesh perfectly healed around them, and no\nprominence of any kind to denote their place; therefore, there must\nneeds have been some other unknown reason in the present case fully\nto account for the ulceration alluded to.  But still more curious was\nthe fact of a lance-head of stone being found in him, not far from\nthe buried iron, the flesh perfectly firm about it.  Who had darted\nthat stone lance?  And when?  It might have been darted by some Nor'\nWest Indian long before America was discovered.\n\nWhat other marvels might have been rummaged out of this monstrous\ncabinet there is no telling.  But a sudden stop was put to further\ndiscoveries, by the ship's being unprecedentedly dragged over\nsideways to the sea, owing to the body's immensely increasing\ntendency to sink.  However, Starbuck, who had the ordering of\naffairs, hung on to it to the last; hung on to it so resolutely,\nindeed, that when at length the ship would have been capsized, if\nstill persisting in locking arms with the body; then, when the\ncommand was given to break clear from it, such was the immovable\nstrain upon the timber-heads to which the fluke-chains and cables\nwere fastened, that it was impossible to cast them off.  Meantime\neverything in the Pequod was aslant.  To cross to the other side of\nthe deck was like walking up the steep gabled roof of a house.  The\nship groaned and gasped.  Many of the ivory inlayings of her bulwarks\nand cabins were started from their places, by the unnatural\ndislocation.  In vain handspikes and crows were brought to bear upon\nthe immovable fluke-chains, to pry them adrift from the timberheads;\nand so low had the whale now settled that the submerged ends could\nnot be at all approached, while every moment whole tons of\nponderosity seemed added to the sinking bulk, and the ship seemed on\nthe point of going over.\n\n\"Hold on, hold on, won't ye?\" cried Stubb to the body, \"don't be in\nsuch a devil of a hurry to sink!  By thunder, men, we must do\nsomething or go for it.  No use prying there; avast, I say with your\nhandspikes, and run one of ye for a prayer book and a pen-knife, and\ncut the big chains.\"\n\n\"Knife?  Aye, aye,\" cried Queequeg, and seizing the carpenter's heavy\nhatchet, he leaned out of a porthole, and steel to iron, began\nslashing at the largest fluke-chains.  But a few strokes, full of\nsparks, were given, when the exceeding strain effected the rest.\nWith a terrific snap, every fastening went adrift; the ship righted,\nthe carcase sank.\n\nNow, this occasional inevitable sinking of the recently killed Sperm\nWhale is a very curious thing; nor has any fisherman yet adequately\naccounted for it.  Usually the dead Sperm Whale floats with great\nbuoyancy, with its side or belly considerably elevated above the\nsurface.  If the only whales that thus sank were old, meagre, and\nbroken-hearted creatures, their pads of lard diminished and all their\nbones heavy and rheumatic; then you might with some reason assert\nthat this sinking is caused by an uncommon specific gravity in the\nfish so sinking, consequent upon this absence of buoyant matter in\nhim.  But it is not so.  For young whales, in the highest health, and\nswelling with noble aspirations, prematurely cut off in the warm\nflush and May of life, with all their panting lard about them; even\nthese brawny, buoyant heroes do sometimes sink.\n\nBe it said, however, that the Sperm Whale is far less liable to this\naccident than any other species.  Where one of that sort go down,\ntwenty Right Whales do.  This difference in the species is no doubt\nimputable in no small degree to the greater quantity of bone in the\nRight Whale; his Venetian blinds alone sometimes weighing more than a\nton; from this incumbrance the Sperm Whale is wholly free.  But there\nare instances where, after the lapse of many hours or several days,\nthe sunken whale again rises, more buoyant than in life.  But the\nreason of this is obvious.  Gases are generated in him; he swells to\na prodigious magnitude; becomes a sort of animal balloon.  A\nline-of-battle ship could hardly keep him under then.  In the Shore\nWhaling, on soundings, among the Bays of New Zealand, when a Right\nWhale gives token of sinking, they fasten buoys to him, with plenty\nof rope; so that when the body has gone down, they know where to look\nfor it when it shall have ascended again.\n\nIt was not long after the sinking of the body that a cry was heard\nfrom the Pequod's mast-heads, announcing that the Jungfrau was again\nlowering her boats; though the only spout in sight was that of a\nFin-Back, belonging to the species of uncapturable whales, because of\nits incredible power of swimming.  Nevertheless, the Fin-Back's spout\nis so similar to the Sperm Whale's, that by unskilful fishermen it is\noften mistaken for it.  And consequently Derick and all his host were\nnow in valiant chase of this unnearable brute.  The Virgin crowding\nall sail, made after her four young keels, and thus they all\ndisappeared far to leeward, still in bold, hopeful chase.\n\nOh! many are the Fin-Backs, and many are the Dericks, my friend.\n\n\n\nCHAPTER 82\n\nThe Honour and Glory of Whaling.\n\n\nThere are some enterprises in which a careful disorderliness is the\ntrue method.\n\nThe more I dive into this matter of whaling, and push my researches\nup to the very spring-head of it so much the more am I impressed with\nits great honourableness and antiquity; and especially when I find so\nmany great demi-gods and heroes, prophets of all sorts, who one way\nor other have shed distinction upon it, I am transported with the\nreflection that I myself belong, though but subordinately, to so\nemblazoned a fraternity.\n\nThe gallant Perseus, a son of Jupiter, was the first whaleman; and to\nthe eternal honour of our calling be it said, that the first whale\nattacked by our brotherhood was not killed with any sordid intent.\nThose were the knightly days of our profession, when we only bore\narms to succor the distressed, and not to fill men's lamp-feeders.\nEvery one knows the fine story of Perseus and Andromeda; how the\nlovely Andromeda, the daughter of a king, was tied to a rock on the\nsea-coast, and as Leviathan was in the very act of carrying her off,\nPerseus, the prince of whalemen, intrepidly advancing, harpooned the\nmonster, and delivered and married the maid.  It was an admirable\nartistic exploit, rarely achieved by the best harpooneers of the\npresent day; inasmuch as this Leviathan was slain at the very first\ndart.  And let no man doubt this Arkite story; for in the ancient\nJoppa, now Jaffa, on the Syrian coast, in one of the Pagan temples,\nthere stood for many ages the vast skeleton of a whale, which the\ncity's legends and all the inhabitants asserted to be the identical\nbones of the monster that Perseus slew.  When the Romans took Joppa,\nthe same skeleton was carried to Italy in triumph.  What seems most\nsingular and suggestively important in this story, is this: it was\nfrom Joppa that Jonah set sail.\n\nAkin to the adventure of Perseus and Andromeda--indeed, by some\nsupposed to be indirectly derived from it--is that famous story of\nSt. George and the Dragon; which dragon I maintain to have been a\nwhale; for in many old chronicles whales and dragons are strangely\njumbled together, and often stand for each other.  \"Thou art as a\nlion of the waters, and as a dragon of the sea,\" saith Ezekiel;\nhereby, plainly meaning a whale; in truth, some versions of the Bible\nuse that word itself.  Besides, it would much subtract from the glory\nof the exploit had St. George but encountered a crawling reptile of\nthe land, instead of doing battle with the great monster of the deep.\nAny man may kill a snake, but only a Perseus, a St. George, a\nCoffin, have the heart in them to march boldly up to a whale.\n\nLet not the modern paintings of this scene mislead us; for though the\ncreature encountered by that valiant whaleman of old is vaguely\nrepresented of a griffin-like shape, and though the battle is\ndepicted on land and the saint on horseback, yet considering the\ngreat ignorance of those times, when the true form of the whale was\nunknown to artists; and considering that as in Perseus' case, St.\nGeorge's whale might have crawled up out of the sea on the beach; and\nconsidering that the animal ridden by St. George might have been only\na large seal, or sea-horse; bearing all this in mind, it will not\nappear altogether incompatible with the sacred legend and the\nancientest draughts of the scene, to hold this so-called dragon no\nother than the great Leviathan himself.  In fact, placed before the\nstrict and piercing truth, this whole story will fare like that fish,\nflesh, and fowl idol of the Philistines, Dagon by name; who being\nplanted before the ark of Israel, his horse's head and both the palms\nof his hands fell off from him, and only the stump or fishy part of\nhim remained.  Thus, then, one of our own noble stamp, even a\nwhaleman, is the tutelary guardian of England; and by good rights, we\nharpooneers of Nantucket should be enrolled in the most noble order\nof St. George.  And therefore, let not the knights of that honourable\ncompany (none of whom, I venture to say, have ever had to do with a\nwhale like their great patron), let them never eye a Nantucketer with\ndisdain, since even in our woollen frocks and tarred trowsers we are\nmuch better entitled to St. George's decoration than they.\n\nWhether to admit Hercules among us or not, concerning this I long\nremained dubious: for though according to the Greek mythologies, that\nantique Crockett and Kit Carson--that brawny doer of rejoicing good\ndeeds, was swallowed down and thrown up by a whale; still, whether\nthat strictly makes a whaleman of him, that might be mooted.  It\nnowhere appears that he ever actually harpooned his fish, unless,\nindeed, from the inside.  Nevertheless, he may be deemed a sort of\ninvoluntary whaleman; at any rate the whale caught him, if he did not\nthe whale.  I claim him for one of our clan.\n\nBut, by the best contradictory authorities, this Grecian story of\nHercules and the whale is considered to be derived from the still\nmore ancient Hebrew story of Jonah and the whale; and vice versa;\ncertainly they are very similar.  If I claim the demigod then, why\nnot the prophet?\n\nNor do heroes, saints, demigods, and prophets alone comprise the\nwhole roll of our order.  Our grand master is still to be named; for\nlike royal kings of old times, we find the head waters of our\nfraternity in nothing short of the great gods themselves.  That\nwondrous oriental story is now to be rehearsed from the Shaster,\nwhich gives us the dread Vishnoo, one of the three persons in the\ngodhead of the Hindoos; gives us this divine Vishnoo himself for our\nLord;--Vishnoo, who, by the first of his ten earthly incarnations,\nhas for ever set apart and sanctified the whale.  When Brahma, or the\nGod of Gods, saith the Shaster, resolved to recreate the world after\none of its periodical dissolutions, he gave birth to Vishnoo, to\npreside over the work; but the Vedas, or mystical books, whose\nperusal would seem to have been indispensable to Vishnoo before\nbeginning the creation, and which therefore must have contained\nsomething in the shape of practical hints to young architects, these\nVedas were lying at the bottom of the waters; so Vishnoo became\nincarnate in a whale, and sounding down in him to the uttermost\ndepths, rescued the sacred volumes.  Was not this Vishnoo a whaleman,\nthen? even as a man who rides a horse is called a horseman?\n\nPerseus, St. George, Hercules, Jonah, and Vishnoo! there's a\nmember-roll for you!  What club but the whaleman's can head off like\nthat?\n\n\n\nCHAPTER 83\n\nJonah Historically Regarded.\n\n\nReference was made to the historical story of Jonah and the whale in\nthe preceding chapter.  Now some Nantucketers rather distrust this\nhistorical story of Jonah and the whale.  But then there were some\nsceptical Greeks and Romans, who, standing out from the orthodox\npagans of their times, equally doubted the story of Hercules and the\nwhale, and Arion and the dolphin; and yet their doubting those\ntraditions did not make those traditions one whit the less facts, for\nall that.\n\nOne old Sag-Harbor whaleman's chief reason for questioning the Hebrew\nstory was this:--He had one of those quaint old-fashioned Bibles,\nembellished with curious, unscientific plates; one of which\nrepresented Jonah's whale with two spouts in his head--a peculiarity\nonly true with respect to a species of the Leviathan (the Right\nWhale, and the varieties of that order), concerning which the\nfishermen have this saying, \"A penny roll would choke him\"; his\nswallow is so very small.  But, to this, Bishop Jebb's anticipative\nanswer is ready.  It is not necessary, hints the Bishop, that we\nconsider Jonah as tombed in the whale's belly, but as temporarily\nlodged in some part of his mouth.  And this seems reasonable enough\nin the good Bishop.  For truly, the Right Whale's mouth would\naccommodate a couple of whist-tables, and comfortably seat all the\nplayers.  Possibly, too, Jonah might have ensconced himself in a\nhollow tooth; but, on second thoughts, the Right Whale is toothless.\n\nAnother reason which Sag-Harbor (he went by that name) urged for his\nwant of faith in this matter of the prophet, was something obscurely\nin reference to his incarcerated body and the whale's gastric juices.\nBut this objection likewise falls to the ground, because a German\nexegetist supposes that Jonah must have taken refuge in the floating\nbody of a DEAD whale--even as the French soldiers in the Russian\ncampaign turned their dead horses into tents, and crawled into them.\nBesides, it has been divined by other continental commentators, that\nwhen Jonah was thrown overboard from the Joppa ship, he straightway\neffected his escape to another vessel near by, some vessel with a\nwhale for a figure-head; and, I would add, possibly called \"The\nWhale,\" as some craft are nowadays christened the \"Shark,\" the\n\"Gull,\" the \"Eagle.\"  Nor have there been wanting learned exegetists\nwho have opined that the whale mentioned in the book of Jonah merely\nmeant a life-preserver--an inflated bag of wind--which the endangered\nprophet swam to, and so was saved from a watery doom.  Poor\nSag-Harbor, therefore, seems worsted all round.  But he had still\nanother reason for his want of faith.  It was this, if I remember\nright: Jonah was swallowed by the whale in the Mediterranean Sea, and\nafter three days he was vomited up somewhere within three days'\njourney of Nineveh, a city on the Tigris, very much more than three\ndays' journey across from the nearest point of the Mediterranean\ncoast.  How is that?\n\nBut was there no other way for the whale to land the prophet within\nthat short distance of Nineveh?  Yes.  He might have carried him\nround by the way of the Cape of Good Hope.  But not to speak of the\npassage through the whole length of the Mediterranean, and another\npassage up the Persian Gulf and Red Sea, such a supposition would\ninvolve the complete circumnavigation of all Africa in three days,\nnot to speak of the Tigris waters, near the site of Nineveh, being\ntoo shallow for any whale to swim in.  Besides, this idea of Jonah's\nweathering the Cape of Good Hope at so early a day would wrest the\nhonour of the discovery of that great headland from Bartholomew Diaz,\nits reputed discoverer, and so make modern history a liar.\n\nBut all these foolish arguments of old Sag-Harbor only evinced his\nfoolish pride of reason--a thing still more reprehensible in him,\nseeing that he had but little learning except what he had picked up\nfrom the sun and the sea.  I say it only shows his foolish, impious\npride, and abominable, devilish rebellion against the reverend\nclergy.  For by a Portuguese Catholic priest, this very idea of\nJonah's going to Nineveh via the Cape of Good Hope was advanced as a\nsignal magnification of the general miracle.  And so it was.\nBesides, to this day, the highly enlightened Turks devoutly believe\nin the historical story of Jonah.  And some three centuries ago, an\nEnglish traveller in old Harris's Voyages, speaks of a Turkish Mosque\nbuilt in honour of Jonah, in which Mosque was a miraculous lamp that\nburnt without any oil.\n\n\n\nCHAPTER 84\n\nPitchpoling.\n\n\nTo make them run easily and swiftly, the axles of carriages are\nanointed; and for much the same purpose, some whalers perform an\nanalogous operation upon their boat; they grease the bottom.  Nor is\nit to be doubted that as such a procedure can do no harm, it may\npossibly be of no contemptible advantage; considering that oil and\nwater are hostile; that oil is a sliding thing, and that the object\nin view is to make the boat slide bravely.  Queequeg believed\nstrongly in anointing his boat, and one morning not long after the\nGerman ship Jungfrau disappeared, took more than customary pains in\nthat occupation; crawling under its bottom, where it hung over the\nside, and rubbing in the unctuousness as though diligently seeking to\ninsure a crop of hair from the craft's bald keel.  He seemed to be\nworking in obedience to some particular presentiment.  Nor did it\nremain unwarranted by the event.\n\nTowards noon whales were raised; but so soon as the ship sailed down\nto them, they turned and fled with swift precipitancy; a disordered\nflight, as of Cleopatra's barges from Actium.\n\nNevertheless, the boats pursued, and Stubb's was foremost.  By great\nexertion, Tashtego at last succeeded in planting one iron; but the\nstricken whale, without at all sounding, still continued his\nhorizontal flight, with added fleetness.  Such unintermitted\nstrainings upon the planted iron must sooner or later inevitably\nextract it.  It became imperative to lance the flying whale, or be\ncontent to lose him.  But to haul the boat up to his flank was\nimpossible, he swam so fast and furious.  What then remained?\n\nOf all the wondrous devices and dexterities, the sleights of hand and\ncountless subtleties, to which the veteran whaleman is so often\nforced, none exceed that fine manoeuvre with the lance called\npitchpoling.  Small sword, or broad sword, in all its exercises\nboasts nothing like it.  It is only indispensable with an inveterate\nrunning whale; its grand fact and feature is the wonderful distance\nto which the long lance is accurately darted from a violently\nrocking, jerking boat, under extreme headway.  Steel and wood\nincluded, the entire spear is some ten or twelve feet in length; the\nstaff is much slighter than that of the harpoon, and also of a\nlighter material--pine.  It is furnished with a small rope called a\nwarp, of considerable length, by which it can be hauled back to the\nhand after darting.\n\nBut before going further, it is important to mention here, that\nthough the harpoon may be pitchpoled in the same way with the lance,\nyet it is seldom done; and when done, is still less frequently\nsuccessful, on account of the greater weight and inferior length of\nthe harpoon as compared with the lance, which in effect become\nserious drawbacks.  As a general thing, therefore, you must first\nget fast to a whale, before any pitchpoling comes into play.\n\nLook now at Stubb; a man who from his humorous, deliberate coolness\nand equanimity in the direst emergencies, was specially qualified to\nexcel in pitchpoling.  Look at him; he stands upright in the tossed\nbow of the flying boat; wrapt in fleecy foam, the towing whale is\nforty feet ahead.  Handling the long lance lightly, glancing twice or\nthrice along its length to see if it be exactly straight, Stubb\nwhistlingly gathers up the coil of the warp in one hand, so as to\nsecure its free end in his grasp, leaving the rest unobstructed.\nThen holding the lance full before his waistband's middle, he levels\nit at the whale; when, covering him with it, he steadily depresses\nthe butt-end in his hand, thereby elevating the point till the weapon\nstands fairly balanced upon his palm, fifteen feet in the air.  He\nminds you somewhat of a juggler, balancing a long staff on his chin.\nNext moment with a rapid, nameless impulse, in a superb lofty arch the\nbright steel spans the foaming distance, and quivers in the life spot\nof the whale.  Instead of sparkling water, he now spouts red blood.\n\n\"That drove the spigot out of him!\" cried Stubb.  \"'Tis July's\nimmortal Fourth; all fountains must run wine today!  Would now, it\nwere old Orleans whiskey, or old Ohio, or unspeakable old\nMonongahela!  Then, Tashtego, lad, I'd have ye hold a canakin to the\njet, and we'd drink round it!  Yea, verily, hearts alive, we'd brew\nchoice punch in the spread of his spout-hole there, and from that\nlive punch-bowl quaff the living stuff.\"\n\nAgain and again to such gamesome talk, the dexterous dart is\nrepeated, the spear returning to its master like a greyhound held in\nskilful leash.  The agonized whale goes into his flurry; the tow-line\nis slackened, and the pitchpoler dropping astern, folds his hands,\nand mutely watches the monster die.\n\n\n\nCHAPTER 85\n\nThe Fountain.\n\n\nThat for six thousand years--and no one knows how many millions of\nages before--the great whales should have been spouting all over the\nsea, and sprinkling and mistifying the gardens of the deep, as with\nso many sprinkling or mistifying pots; and that for some centuries\nback, thousands of hunters should have been close by the fountain of\nthe whale, watching these sprinklings and spoutings--that all this\nshould be, and yet, that down to this blessed minute (fifteen and a\nquarter minutes past one o'clock P.M. of this sixteenth day of\nDecember, A.D. 1851), it should still remain a problem, whether these\nspoutings are, after all, really water, or nothing but vapour--this is\nsurely a noteworthy thing.\n\nLet us, then, look at this matter, along with some interesting items\ncontingent.  Every one knows that by the peculiar cunning of their\ngills, the finny tribes in general breathe the air which at all times\nis combined with the element in which they swim; hence, a herring or\na cod might live a century, and never once raise its head above the\nsurface.  But owing to his marked internal structure which gives him\nregular lungs, like a human being's, the whale can only live by\ninhaling the disengaged air in the open atmosphere.  Wherefore the\nnecessity for his periodical visits to the upper world.  But he\ncannot in any degree breathe through his mouth, for, in his ordinary\nattitude, the Sperm Whale's mouth is buried at least eight feet\nbeneath the surface; and what is still more, his windpipe has no\nconnexion with his mouth.  No, he breathes through his spiracle\nalone; and this is on the top of his head.\n\nIf I say, that in any creature breathing is only a function\nindispensable to vitality, inasmuch as it withdraws from the air a\ncertain element, which being subsequently brought into contact with\nthe blood imparts to the blood its vivifying principle, I do not\nthink I shall err; though I may possibly use some superfluous\nscientific words.  Assume it, and it follows that if all the blood in\na man could be aerated with one breath, he might then seal up his\nnostrils and not fetch another for a considerable time.  That is to\nsay, he would then live without breathing.  Anomalous as it may seem,\nthis is precisely the case with the whale, who systematically lives,\nby intervals, his full hour and more (when at the bottom) without\ndrawing a single breath, or so much as in any way inhaling a particle\nof air; for, remember, he has no gills.  How is this?  Between his\nribs and on each side of his spine he is supplied with a remarkable\ninvolved Cretan labyrinth of vermicelli-like vessels, which vessels,\nwhen he quits the surface, are completely distended with oxygenated\nblood.  So that for an hour or more, a thousand fathoms in the sea,\nhe carries a surplus stock of vitality in him, just as the camel\ncrossing the waterless desert carries a surplus supply of drink for\nfuture use in its four supplementary stomachs.  The anatomical fact\nof this labyrinth is indisputable; and that the supposition founded\nupon it is reasonable and true, seems the more cogent to me, when I\nconsider the otherwise inexplicable obstinacy of that leviathan in\nHAVING HIS SPOUTINGS OUT, as the fishermen phrase it.  This is what I\nmean.  If unmolested, upon rising to the surface, the Sperm Whale\nwill continue there for a period of time exactly uniform with all his\nother unmolested risings.  Say he stays eleven minutes, and jets\nseventy times, that is, respires seventy breaths; then whenever he\nrises again, he will be sure to have his seventy breaths over again,\nto a minute.  Now, if after he fetches a few breaths you alarm him,\nso that he sounds, he will be always dodging up again to make good\nhis regular allowance of air.  And not till those seventy breaths are\ntold, will he finally go down to stay out his full term below.\nRemark, however, that in different individuals these rates are\ndifferent; but in any one they are alike.  Now, why should the whale\nthus insist upon having his spoutings out, unless it be to replenish\nhis reservoir of air, ere descending for good?  How obvious is it,\ntoo, that this necessity for the whale's rising exposes him to all\nthe fatal hazards of the chase.  For not by hook or by net could\nthis vast leviathan be caught, when sailing a thousand fathoms\nbeneath the sunlight.  Not so much thy skill, then, O hunter, as the\ngreat necessities that strike the victory to thee!\n\nIn man, breathing is incessantly going on--one breath only serving\nfor two or three pulsations; so that whatever other business he has\nto attend to, waking or sleeping, breathe he must, or die he will.\nBut the Sperm Whale only breathes about one seventh or Sunday of his\ntime.\n\nIt has been said that the whale only breathes through his spout-hole;\nif it could truthfully be added that his spouts are mixed with water,\nthen I opine we should be furnished with the reason why his sense of\nsmell seems obliterated in him; for the only thing about him that at\nall answers to his nose is that identical spout-hole; and being so\nclogged with two elements, it could not be expected to have the power\nof smelling.  But owing to the mystery of the spout--whether it be\nwater or whether it be vapour--no absolute certainty can as yet be\narrived at on this head.  Sure it is, nevertheless, that the Sperm\nWhale has no proper olfactories.  But what does he want of them?  No\nroses, no violets, no Cologne-water in the sea.\n\nFurthermore, as his windpipe solely opens into the tube of his\nspouting canal, and as that long canal--like the grand Erie Canal--is\nfurnished with a sort of locks (that open and shut) for the downward\nretention of air or the upward exclusion of water, therefore the\nwhale has no voice; unless you insult him by saying, that when he so\nstrangely rumbles, he talks through his nose.  But then again, what\nhas the whale to say?  Seldom have I known any profound being that\nhad anything to say to this world, unless forced to stammer out\nsomething by way of getting a living.  Oh! happy that the world is\nsuch an excellent listener!\n\nNow, the spouting canal of the Sperm Whale, chiefly intended as it is\nfor the conveyance of air, and for several feet laid along,\nhorizontally, just beneath the upper surface of his head, and a\nlittle to one side; this curious canal is very much like a gas-pipe\nlaid down in a city on one side of a street.  But the question\nreturns whether this gas-pipe is also a water-pipe; in other words,\nwhether the spout of the Sperm Whale is the mere vapour of the exhaled\nbreath, or whether that exhaled breath is mixed with water taken in\nat the mouth, and discharged through the spiracle.  It is certain\nthat the mouth indirectly communicates with the spouting canal; but\nit cannot be proved that this is for the purpose of discharging water\nthrough the spiracle.  Because the greatest necessity for so doing\nwould seem to be, when in feeding he accidentally takes in water.\nBut the Sperm Whale's food is far beneath the surface, and there he\ncannot spout even if he would.  Besides, if you regard him very\nclosely, and time him with your watch, you will find that when\nunmolested, there is an undeviating rhyme between the periods of his\njets and the ordinary periods of respiration.\n\nBut why pester one with all this reasoning on the subject?  Speak\nout!  You have seen him spout; then declare what the spout is; can\nyou not tell water from air?  My dear sir, in this world it is not so\neasy to settle these plain things.  I have ever found your plain\nthings the knottiest of all.  And as for this whale spout, you might\nalmost stand in it, and yet be undecided as to what it is precisely.\n\nThe central body of it is hidden in the snowy sparkling mist\nenveloping it; and how can you certainly tell whether any water falls\nfrom it, when, always, when you are close enough to a whale to get a\nclose view of his spout, he is in a prodigious commotion, the water\ncascading all around him.  And if at such times you should think that\nyou really perceived drops of moisture in the spout, how do you know\nthat they are not merely condensed from its vapour; or how do you know\nthat they are not those identical drops superficially lodged in the\nspout-hole fissure, which is countersunk into the summit of the\nwhale's head?  For even when tranquilly swimming through the mid-day\nsea in a calm, with his elevated hump sun-dried as a dromedary's in\nthe desert; even then, the whale always carries a small basin of\nwater on his head, as under a blazing sun you will sometimes see a\ncavity in a rock filled up with rain.\n\nNor is it at all prudent for the hunter to be over curious touching\nthe precise nature of the whale spout.  It will not do for him to be\npeering into it, and putting his face in it.  You cannot go with your\npitcher to this fountain and fill it, and bring it away.  For even\nwhen coming into slight contact with the outer, vapoury shreds of the\njet, which will often happen, your skin will feverishly smart, from\nthe acridness of the thing so touching it.  And I know one, who\ncoming into still closer contact with the spout, whether with some\nscientific object in view, or otherwise, I cannot say, the skin\npeeled off from his cheek and arm.  Wherefore, among whalemen, the\nspout is deemed poisonous; they try to evade it.  Another thing; I\nhave heard it said, and I do not much doubt it, that if the jet is\nfairly spouted into your eyes, it will blind you.  The wisest thing\nthe investigator can do then, it seems to me, is to let this deadly\nspout alone.\n\nStill, we can hypothesize, even if we cannot prove and establish.  My\nhypothesis is this: that the spout is nothing but mist.  And besides\nother reasons, to this conclusion I am impelled, by considerations\ntouching the great inherent dignity and sublimity of the Sperm Whale;\nI account him no common, shallow being, inasmuch as it is an\nundisputed fact that he is never found on soundings, or near shores;\nall other whales sometimes are.  He is both ponderous and profound.\nAnd I am convinced that from the heads of all ponderous profound\nbeings, such as Plato, Pyrrho, the Devil, Jupiter, Dante, and so on,\nthere always goes up a certain semi-visible steam, while in the act\nof thinking deep thoughts.  While composing a little treatise on\nEternity, I had the curiosity to place a mirror before me; and ere\nlong saw reflected there, a curious involved worming and undulation\nin the atmosphere over my head.  The invariable moisture of my hair,\nwhile plunged in deep thought, after six cups of hot tea in my thin\nshingled attic, of an August noon; this seems an additional argument\nfor the above supposition.\n\nAnd how nobly it raises our conceit of the mighty, misty monster, to\nbehold him solemnly sailing through a calm tropical sea; his vast,\nmild head overhung by a canopy of vapour, engendered by his\nincommunicable contemplations, and that vapour--as you will sometimes\nsee it--glorified by a rainbow, as if Heaven itself had put its seal\nupon his thoughts.  For, d'ye see, rainbows do not visit the clear\nair; they only irradiate vapour.  And so, through all the thick mists\nof the dim doubts in my mind, divine intuitions now and then shoot,\nenkindling my fog with a heavenly ray.  And for this I thank God; for\nall have doubts; many deny; but doubts or denials, few along with\nthem, have intuitions.  Doubts of all things earthly, and intuitions\nof some things heavenly; this combination makes neither believer nor\ninfidel, but makes a man who regards them both with equal eye.\n\n\n\nCHAPTER 86\n\nThe Tail.\n\n\nOther poets have warbled the praises of the soft eye of the antelope,\nand the lovely plumage of the bird that never alights; less\ncelestial, I celebrate a tail.\n\nReckoning the largest sized Sperm Whale's tail to begin at that point\nof the trunk where it tapers to about the girth of a man, it\ncomprises upon its upper surface alone, an area of at least fifty\nsquare feet.  The compact round body of its root expands into two\nbroad, firm, flat palms or flukes, gradually shoaling away to less\nthan an inch in thickness.  At the crotch or junction, these flukes\nslightly overlap, then sideways recede from each other like wings,\nleaving a wide vacancy between.  In no living thing are the lines of\nbeauty more exquisitely defined than in the crescentic borders of\nthese flukes.  At its utmost expansion in the full grown whale, the\ntail will considerably exceed twenty feet across.\n\nThe entire member seems a dense webbed bed of welded sinews; but cut\ninto it, and you find that three distinct strata compose it:--upper,\nmiddle, and lower.  The fibres in the upper and lower layers, are\nlong and horizontal; those of the middle one, very short, and running\ncrosswise between the outside layers.  This triune structure, as much\nas anything else, imparts power to the tail.  To the student of old\nRoman walls, the middle layer will furnish a curious parallel to the\nthin course of tiles always alternating with the stone in those\nwonderful relics of the antique, and which undoubtedly contribute so\nmuch to the great strength of the masonry.\n\nBut as if this vast local power in the tendinous tail were not\nenough, the whole bulk of the leviathan is knit over with a warp and\nwoof of muscular fibres and filaments, which passing on either side\nthe loins and running down into the flukes, insensibly blend with\nthem, and largely contribute to their might; so that in the tail the\nconfluent measureless force of the whole whale seems concentrated to\na point.  Could annihilation occur to matter, this were the thing to\ndo it.\n\nNor does this--its amazing strength, at all tend to cripple the\ngraceful flexion of its motions; where infantileness of ease\nundulates through a Titanism of power.  On the contrary, those\nmotions derive their most appalling beauty from it.  Real strength\nnever impairs beauty or harmony, but it often bestows it; and in\neverything imposingly beautiful, strength has much to do with the\nmagic.  Take away the tied tendons that all over seem bursting from\nthe marble in the carved Hercules, and its charm would be gone.  As\ndevout Eckerman lifted the linen sheet from the naked corpse of\nGoethe, he was overwhelmed with the massive chest of the man, that\nseemed as a Roman triumphal arch.  When Angelo paints even God the\nFather in human form, mark what robustness is there.  And whatever\nthey may reveal of the divine love in the Son, the soft, curled,\nhermaphroditical Italian pictures, in which his idea has been most\nsuccessfully embodied; these pictures, so destitute as they are of\nall brawniness, hint nothing of any power, but the mere negative,\nfeminine one of submission and endurance, which on all hands it is\nconceded, form the peculiar practical virtues of his teachings.\n\nSuch is the subtle elasticity of the organ I treat of, that whether\nwielded in sport, or in earnest, or in anger, whatever be the mood it\nbe in, its flexions are invariably marked by exceeding grace.\nTherein no fairy's arm can transcend it.\n\nFive great motions are peculiar to it.  First, when used as a fin for\nprogression; Second, when used as a mace in battle; Third, in\nsweeping; Fourth, in lobtailing; Fifth, in peaking flukes.\n\nFirst: Being horizontal in its position, the Leviathan's tail acts in\na different manner from the tails of all other sea creatures.  It\nnever wriggles.  In man or fish, wriggling is a sign of inferiority.\nTo the whale, his tail is the sole means of propulsion.  Scroll-wise\ncoiled forwards beneath the body, and then rapidly sprung backwards,\nit is this which gives that singular darting, leaping motion to the\nmonster when furiously swimming.  His side-fins only serve to steer\nby.\n\nSecond: It is a little significant, that while one sperm whale only\nfights another sperm whale with his head and jaw, nevertheless, in\nhis conflicts with man, he chiefly and contemptuously uses his tail.\nIn striking at a boat, he swiftly curves away his flukes from it, and\nthe blow is only inflicted by the recoil.  If it be made in the\nunobstructed air, especially if it descend to its mark, the stroke is\nthen simply irresistible.  No ribs of man or boat can withstand it.\nYour only salvation lies in eluding it; but if it comes sideways\nthrough the opposing water, then partly owing to the light buoyancy\nof the whale boat, and the elasticity of its materials, a cracked\nrib or a dashed plank or two, a sort of stitch in the side, is\ngenerally the most serious result.  These submerged side blows are so\noften received in the fishery, that they are accounted mere child's\nplay.  Some one strips off a frock, and the hole is stopped.\n\nThird: I cannot demonstrate it, but it seems to me, that in the whale\nthe sense of touch is concentrated in the tail; for in this respect\nthere is a delicacy in it only equalled by the daintiness of the\nelephant's trunk.  This delicacy is chiefly evinced in the action of\nsweeping, when in maidenly gentleness the whale with a certain soft\nslowness moves his immense flukes from side to side upon the surface of\nthe sea; and if he feel but a sailor's whisker, woe to that sailor,\nwhiskers and all.  What tenderness there is in that preliminary\ntouch!  Had this tail any prehensile power, I should straightway\nbethink me of Darmonodes' elephant that so frequented the\nflower-market, and with low salutations presented nosegays to\ndamsels, and then caressed their zones.  On more accounts than one, a\npity it is that the whale does not possess this prehensile virtue in\nhis tail; for I have heard of yet another elephant, that when wounded\nin the fight, curved round his trunk and extracted the dart.\n\nFourth: Stealing unawares upon the whale in the fancied security of\nthe middle of solitary seas, you find him unbent from the vast\ncorpulence of his dignity, and kitten-like, he plays on the ocean as\nif it were a hearth.  But still you see his power in his play.  The\nbroad palms of his tail are flirted high into the air; then smiting\nthe surface, the thunderous concussion resounds for miles.  You would\nalmost think a great gun had been discharged; and if you noticed the\nlight wreath of vapour from the spiracle at his other extremity, you\nwould think that that was the smoke from the touch-hole.\n\nFifth: As in the ordinary floating posture of the leviathan the\nflukes lie considerably below the level of his back, they are then\ncompletely out of sight beneath the surface; but when he is about to\nplunge into the deeps, his entire flukes with at least thirty feet of\nhis body are tossed erect in the air, and so remain vibrating a\nmoment, till they downwards shoot out of view.  Excepting the sublime\nBREACH--somewhere else to be described--this peaking of the whale's\nflukes is perhaps the grandest sight to be seen in all animated\nnature.  Out of the bottomless profundities the gigantic tail seems\nspasmodically snatching at the highest heaven.  So in dreams, have I\nseen majestic Satan thrusting forth his tormented colossal claw from\nthe flame Baltic of Hell.  But in gazing at such scenes, it is all in\nall what mood you are in; if in the Dantean, the devils will occur to\nyou; if in that of Isaiah, the archangels.  Standing at the mast-head\nof my ship during a sunrise that crimsoned sky and sea, I once saw a\nlarge herd of whales in the east, all heading towards the sun, and\nfor a moment vibrating in concert with peaked flukes.  As it seemed\nto me at the time, such a grand embodiment of adoration of the gods\nwas never beheld, even in Persia, the home of the fire worshippers.\nAs Ptolemy Philopater testified of the African elephant, I then\ntestified of the whale, pronouncing him the most devout of all\nbeings.  For according to King Juba, the military elephants of\nantiquity often hailed the morning with their trunks uplifted in the\nprofoundest silence.\n\nThe chance comparison in this chapter, between the whale and the\nelephant, so far as some aspects of the tail of the one and the trunk\nof the other are concerned, should not tend to place those two\nopposite organs on an equality, much less the creatures to which they\nrespectively belong.  For as the mightiest elephant is but a terrier\nto Leviathan, so, compared with Leviathan's tail, his trunk is but\nthe stalk of a lily.  The most direful blow from the elephant's trunk\nwere as the playful tap of a fan, compared with the measureless crush\nand crash of the sperm whale's ponderous flukes, which in repeated\ninstances have one after the other hurled entire boats with all their\noars and crews into the air, very much as an Indian juggler tosses\nhis balls.*\n\n\n*Though all comparison in the way of general bulk between the whale\nand the elephant is preposterous, inasmuch as in that particular the\nelephant stands in much the same respect to the whale that a dog does\nto the elephant; nevertheless, there are not wanting some points of\ncurious similitude; among these is the spout.  It is well known that\nthe elephant will often draw up water or dust in his trunk, and then\nelevating it, jet it forth in a stream.\n\n\nThe more I consider this mighty tail, the more do I deplore my\ninability to express it.  At times there are gestures in it, which,\nthough they would well grace the hand of man, remain wholly\ninexplicable.  In an extensive herd, so remarkable, occasionally, are\nthese mystic gestures, that I have heard hunters who have declared\nthem akin to Free-Mason signs and symbols; that the whale, indeed, by\nthese methods intelligently conversed with the world.  Nor are there\nwanting other motions of the whale in his general body, full of\nstrangeness, and unaccountable to his most experienced assailant.\nDissect him how I may, then, I but go skin deep; I know him not,\nand never will.  But if I know not even the tail of this whale, how\nunderstand his head? much more, how comprehend his face, when face he\nhas none?  Thou shalt see my back parts, my tail, he seems to say,\nbut my face shall not be seen.  But I cannot completely make out his\nback parts; and hint what he will about his face, I say again he has\nno face.\n\n\n\nCHAPTER 87\n\nThe Grand Armada.\n\n\nThe long and narrow peninsula of Malacca, extending south-eastward\nfrom the territories of Birmah, forms the most southerly point of all\nAsia.  In a continuous line from that peninsula stretch the long\nislands of Sumatra, Java, Bally, and Timor; which, with many others,\nform a vast mole, or rampart, lengthwise connecting Asia with\nAustralia, and dividing the long unbroken Indian ocean from the\nthickly studded oriental archipelagoes.  This rampart is pierced by\nseveral sally-ports for the convenience of ships and whales;\nconspicuous among which are the straits of Sunda and Malacca.  By the\nstraits of Sunda, chiefly, vessels bound to China from the west,\nemerge into the China seas.\n\nThose narrow straits of Sunda divide Sumatra from Java; and standing\nmidway in that vast rampart of islands, buttressed by that bold green\npromontory, known to seamen as Java Head; they not a little\ncorrespond to the central gateway opening into some vast walled\nempire: and considering the inexhaustible wealth of spices, and\nsilks, and jewels, and gold, and ivory, with which the thousand\nislands of that oriental sea are enriched, it seems a significant\nprovision of nature, that such treasures, by the very formation of\nthe land, should at least bear the appearance, however ineffectual,\nof being guarded from the all-grasping western world.  The shores of\nthe Straits of Sunda are unsupplied with those domineering fortresses\nwhich guard the entrances to the Mediterranean, the Baltic, and the\nPropontis.  Unlike the Danes, these Orientals do not demand the\nobsequious homage of lowered top-sails from the endless procession of\nships before the wind, which for centuries past, by night and by day,\nhave passed between the islands of Sumatra and Java, freighted with\nthe costliest cargoes of the east.  But while they freely waive a\nceremonial like this, they do by no means renounce their claim to\nmore solid tribute.\n\nTime out of mind the piratical proas of the Malays, lurking among the\nlow shaded coves and islets of Sumatra, have sallied out upon the\nvessels sailing through the straits, fiercely demanding tribute at\nthe point of their spears.  Though by the repeated bloody\nchastisements they have received at the hands of European cruisers,\nthe audacity of these corsairs has of late been somewhat repressed;\nyet, even at the present day, we occasionally hear of English and\nAmerican vessels, which, in those waters, have been remorselessly\nboarded and pillaged.\n\nWith a fair, fresh wind, the Pequod was now drawing nigh to these\nstraits; Ahab purposing to pass through them into the Javan sea, and\nthence, cruising northwards, over waters known to be frequented here\nand there by the Sperm Whale, sweep inshore by the Philippine\nIslands, and gain the far coast of Japan, in time for the great\nwhaling season there.  By these means, the circumnavigating Pequod\nwould sweep almost all the known Sperm Whale cruising grounds of the\nworld, previous to descending upon the Line in the Pacific; where\nAhab, though everywhere else foiled in his pursuit, firmly counted\nupon giving battle to Moby Dick, in the sea he was most known to\nfrequent; and at a season when he might most reasonably be presumed\nto be haunting it.\n\nBut how now? in this zoned quest, does Ahab touch no land? does his\ncrew drink air?  Surely, he will stop for water.  Nay.  For a long\ntime, now, the circus-running sun has raced within his fiery ring,\nand needs no sustenance but what's in himself.  So Ahab.  Mark this,\ntoo, in the whaler.  While other hulls are loaded down with alien\nstuff, to be transferred to foreign wharves; the world-wandering\nwhale-ship carries no cargo but herself and crew, their weapons and\ntheir wants.  She has a whole lake's contents bottled in her ample\nhold.  She is ballasted with utilities; not altogether with unusable\npig-lead and kentledge.  She carries years' water in her.  Clear old\nprime Nantucket water; which, when three years afloat, the\nNantucketer, in the Pacific, prefers to drink before the brackish\nfluid, but yesterday rafted off in casks, from the Peruvian or Indian\nstreams.  Hence it is, that, while other ships may have gone to China\nfrom New York, and back again, touching at a score of ports, the\nwhale-ship, in all that interval, may not have sighted one grain of\nsoil; her crew having seen no man but floating seamen like\nthemselves.  So that did you carry them the news that another flood\nhad come; they would only answer--\"Well, boys, here's the ark!\"\n\nNow, as many Sperm Whales had been captured off the western coast of\nJava, in the near vicinity of the Straits of Sunda; indeed, as most\nof the ground, roundabout, was generally recognised by the fishermen\nas an excellent spot for cruising; therefore, as the Pequod gained\nmore and more upon Java Head, the look-outs were repeatedly hailed,\nand admonished to keep wide awake.  But though the green palmy cliffs\nof the land soon loomed on the starboard bow, and with delighted\nnostrils the fresh cinnamon was snuffed in the air, yet not a single\njet was descried.  Almost renouncing all thought of falling in with\nany game hereabouts, the ship had well nigh entered the straits, when\nthe customary cheering cry was heard from aloft, and ere long a\nspectacle of singular magnificence saluted us.\n\nBut here be it premised, that owing to the unwearied activity with\nwhich of late they have been hunted over all four oceans, the Sperm\nWhales, instead of almost invariably sailing in small detached\ncompanies, as in former times, are now frequently met with in\nextensive herds, sometimes embracing so great a multitude, that it\nwould almost seem as if numerous nations of them had sworn solemn\nleague and covenant for mutual assistance and protection.  To this\naggregation of the Sperm Whale into such immense caravans, may be\nimputed the circumstance that even in the best cruising grounds, you\nmay now sometimes sail for weeks and months together, without being\ngreeted by a single spout; and then be suddenly saluted by what\nsometimes seems thousands on thousands.\n\nBroad on both bows, at the distance of some two or three miles, and\nforming a great semicircle, embracing one half of the level horizon,\na continuous chain of whale-jets were up-playing and sparkling in the\nnoon-day air.  Unlike the straight perpendicular twin-jets of the\nRight Whale, which, dividing at top, fall over in two branches, like\nthe cleft drooping boughs of a willow, the single forward-slanting\nspout of the Sperm Whale presents a thick curled bush of white mist,\ncontinually rising and falling away to leeward.\n\nSeen from the Pequod's deck, then, as she would rise on a high hill\nof the sea, this host of vapoury spouts, individually curling up into\nthe air, and beheld through a blending atmosphere of bluish haze,\nshowed like the thousand cheerful chimneys of some dense metropolis,\ndescried of a balmy autumnal morning, by some horseman on a height.\n\nAs marching armies approaching an unfriendly defile in the mountains,\naccelerate their march, all eagerness to place that perilous passage\nin their rear, and once more expand in comparative security upon the\nplain; even so did this vast fleet of whales now seem hurrying\nforward through the straits; gradually contracting the wings of their\nsemicircle, and swimming on, in one solid, but still crescentic\ncentre.\n\nCrowding all sail the Pequod pressed after them; the harpooneers\nhandling their weapons, and loudly cheering from the heads of their\nyet suspended boats.  If the wind only held, little doubt had they,\nthat chased through these Straits of Sunda, the vast host would only\ndeploy into the Oriental seas to witness the capture of not a few of\ntheir number.  And who could tell whether, in that congregated\ncaravan, Moby Dick himself might not temporarily be swimming, like\nthe worshipped white-elephant in the coronation procession of the\nSiamese!  So with stun-sail piled on stun-sail, we sailed along,\ndriving these leviathans before us; when, of a sudden, the voice of\nTashtego was heard, loudly directing attention to something in our\nwake.\n\nCorresponding to the crescent in our van, we beheld another in our\nrear.  It seemed formed of detached white vapours, rising and falling\nsomething like the spouts of the whales; only they did not so\ncompletely come and go; for they constantly hovered, without finally\ndisappearing.  Levelling his glass at this sight, Ahab quickly\nrevolved in his pivot-hole, crying, \"Aloft there, and rig whips and\nbuckets to wet the sails;--Malays, sir, and after us!\"\n\nAs if too long lurking behind the headlands, till the Pequod should\nfairly have entered the straits, these rascally Asiatics were now in\nhot pursuit, to make up for their over-cautious delay.  But when the\nswift Pequod, with a fresh leading wind, was herself in hot chase;\nhow very kind of these tawny philanthropists to assist in speeding\nher on to her own chosen pursuit,--mere riding-whips and rowels to\nher, that they were.  As with glass under arm, Ahab to-and-fro paced\nthe deck; in his forward turn beholding the monsters he chased, and\nin the after one the bloodthirsty pirates chasing him; some such\nfancy as the above seemed his.  And when he glanced upon the green\nwalls of the watery defile in which the ship was then sailing, and\nbethought him that through that gate lay the route to his vengeance,\nand beheld, how that through that same gate he was now both chasing\nand being chased to his deadly end; and not only that, but a herd of\nremorseless wild pirates and inhuman atheistical devils were\ninfernally cheering him on with their curses;--when all these\nconceits had passed through his brain, Ahab's brow was left gaunt and\nribbed, like the black sand beach after some stormy tide has been\ngnawing it, without being able to drag the firm thing from its place.\n\nBut thoughts like these troubled very few of the reckless crew; and\nwhen, after steadily dropping and dropping the pirates astern, the\nPequod at last shot by the vivid green Cockatoo Point on the Sumatra\nside, emerging at last upon the broad waters beyond; then, the\nharpooneers seemed more to grieve that the swift whales had been\ngaining upon the ship, than to rejoice that the ship had so\nvictoriously gained upon the Malays.  But still driving on in the\nwake of the whales, at length they seemed abating their speed;\ngradually the ship neared them; and the wind now dying away, word was\npassed to spring to the boats.  But no sooner did the herd, by some\npresumed wonderful instinct of the Sperm Whale, become notified of\nthe three keels that were after them,--though as yet a mile in their\nrear,--than they rallied again, and forming in close ranks and\nbattalions, so that their spouts all looked like flashing lines of\nstacked bayonets, moved on with redoubled velocity.\n\nStripped to our shirts and drawers, we sprang to the white-ash, and\nafter several hours' pulling were almost disposed to renounce the\nchase, when a general pausing commotion among the whales gave\nanimating token that they were now at last under the influence of\nthat strange perplexity of inert irresolution, which, when the\nfishermen perceive it in the whale, they say he is gallied.  The\ncompact martial columns in which they had been hitherto rapidly and\nsteadily swimming, were now broken up in one measureless rout; and\nlike King Porus' elephants in the Indian battle with Alexander, they\nseemed going mad with consternation.  In all directions expanding in\nvast irregular circles, and aimlessly swimming hither and thither, by\ntheir short thick spoutings, they plainly betrayed their distraction\nof panic.  This was still more strangely evinced by those of their\nnumber, who, completely paralysed as it were, helplessly floated like\nwater-logged dismantled ships on the sea.  Had these Leviathans been\nbut a flock of simple sheep, pursued over the pasture by three fierce\nwolves, they could not possibly have evinced such excessive dismay.\nBut this occasional timidity is characteristic of almost all herding\ncreatures.  Though banding together in tens of thousands, the\nlion-maned buffaloes of the West have fled before a solitary\nhorseman.  Witness, too, all human beings, how when herded together\nin the sheepfold of a theatre's pit, they will, at the slightest\nalarm of fire, rush helter-skelter for the outlets, crowding,\ntrampling, jamming, and remorselessly dashing each other to death.\nBest, therefore, withhold any amazement at the strangely gallied\nwhales before us, for there is no folly of the beasts of the earth\nwhich is not infinitely outdone by the madness of men.\n\nThough many of the whales, as has been said, were in violent motion,\nyet it is to be observed that as a whole the herd neither advanced\nnor retreated, but collectively remained in one place.  As is\ncustomary in those cases, the boats at once separated, each making\nfor some one lone whale on the outskirts of the shoal.  In about\nthree minutes' time, Queequeg's harpoon was flung; the stricken fish\ndarted blinding spray in our faces, and then running away with us like\nlight, steered straight for the heart of the herd.  Though such a\nmovement on the part of the whale struck under such circumstances, is\nin no wise unprecedented; and indeed is almost always more or less\nanticipated; yet does it present one of the more perilous\nvicissitudes of the fishery.  For as the swift monster drags you\ndeeper and deeper into the frantic shoal, you bid adieu to\ncircumspect life and only exist in a delirious throb.\n\nAs, blind and deaf, the whale plunged forward, as if by sheer power\nof speed to rid himself of the iron leech that had fastened to him;\nas we thus tore a white gash in the sea, on all sides menaced as we\nflew, by the crazed creatures to and fro rushing about us; our beset\nboat was like a ship mobbed by ice-isles in a tempest, and striving\nto steer through their complicated channels and straits, knowing not at\nwhat moment it may be locked in and crushed.\n\nBut not a bit daunted, Queequeg steered us manfully; now sheering off\nfrom this monster directly across our route in advance; now edging\naway from that, whose colossal flukes were suspended overhead, while\nall the time, Starbuck stood up in the bows, lance in hand, pricking\nout of our way whatever whales he could reach by short darts, for\nthere was no time to make long ones.  Nor were the oarsmen quite\nidle, though their wonted duty was now altogether dispensed with.\nThey chiefly attended to the shouting part of the business.  \"Out of\nthe way, Commodore!\" cried one, to a great dromedary that of a sudden\nrose bodily to the surface, and for an instant threatened to swamp\nus.  \"Hard down with your tail, there!\" cried a second to another,\nwhich, close to our gunwale, seemed calmly cooling himself with his\nown fan-like extremity.\n\nAll whaleboats carry certain curious contrivances, originally\ninvented by the Nantucket Indians, called druggs.  Two thick squares\nof wood of equal size are stoutly clenched together, so that they\ncross each other's grain at right angles; a line of considerable\nlength is then attached to the middle of this block, and the other\nend of the line being looped, it can in a moment be fastened to a\nharpoon.  It is chiefly among gallied whales that this drugg is used.\nFor then, more whales are close round you than you can possibly\nchase at one time.  But sperm whales are not every day encountered;\nwhile you may, then, you must kill all you can.  And if you cannot\nkill them all at once, you must wing them, so that they can be\nafterwards killed at your leisure.  Hence it is, that at times like\nthese the drugg, comes into requisition.  Our boat was furnished with\nthree of them.  The first and second were successfully darted, and we\nsaw the whales staggeringly running off, fettered by the enormous\nsidelong resistance of the towing drugg.  They were cramped like\nmalefactors with the chain and ball.  But upon flinging the third, in\nthe act of tossing overboard the clumsy wooden block, it caught under\none of the seats of the boat, and in an instant tore it out and\ncarried it away, dropping the oarsman in the boat's bottom as the\nseat slid from under him.  On both sides the sea came in at the\nwounded planks, but we stuffed two or three drawers and shirts in,\nand so stopped the leaks for the time.\n\nIt had been next to impossible to dart these drugged-harpoons, were\nit not that as we advanced into the herd, our whale's way greatly\ndiminished; moreover, that as we went still further and further from\nthe circumference of commotion, the direful disorders seemed waning.\nSo that when at last the jerking harpoon drew out, and the towing\nwhale sideways vanished; then, with the tapering force of his parting\nmomentum, we glided between two whales into the innermost heart of\nthe shoal, as if from some mountain torrent we had slid into a serene\nvalley lake.  Here the storms in the roaring glens between the\noutermost whales, were heard but not felt.  In this central expanse\nthe sea presented that smooth satin-like surface, called a sleek,\nproduced by the subtle moisture thrown off by the whale in his more\nquiet moods.  Yes, we were now in that enchanted calm which they say\nlurks at the heart of every commotion.  And still in the distracted\ndistance we beheld the tumults of the outer concentric circles, and\nsaw successive pods of whales, eight or ten in each, swiftly going\nround and round, like multiplied spans of horses in a ring; and so\nclosely shoulder to shoulder, that a Titanic circus-rider might\neasily have over-arched the middle ones, and so have gone round on\ntheir backs.  Owing to the density of the crowd of reposing whales,\nmore immediately surrounding the embayed axis of the herd, no\npossible chance of escape was at present afforded us.  We must watch\nfor a breach in the living wall that hemmed us in; the wall that had\nonly admitted us in order to shut us up.  Keeping at the centre of\nthe lake, we were occasionally visited by small tame cows and calves;\nthe women and children of this routed host.\n\nNow, inclusive of the occasional wide intervals between the revolving\nouter circles, and inclusive of the spaces between the various pods\nin any one of those circles, the entire area at this juncture,\nembraced by the whole multitude, must have contained at least two or\nthree square miles.  At any rate--though indeed such a test at such a\ntime might be deceptive--spoutings might be discovered from our low\nboat that seemed playing up almost from the rim of the horizon.  I\nmention this circumstance, because, as if the cows and calves had\nbeen purposely locked up in this innermost fold; and as if the wide\nextent of the herd had hitherto prevented them from learning the\nprecise cause of its stopping; or, possibly, being so young,\nunsophisticated, and every way innocent and inexperienced; however it\nmay have been, these smaller whales--now and then visiting our\nbecalmed boat from the margin of the lake--evinced a wondrous\nfearlessness and confidence, or else a still becharmed panic which it\nwas impossible not to marvel at.  Like household dogs they came\nsnuffling round us, right up to our gunwales, and touching them; till\nit almost seemed that some spell had suddenly domesticated them.\nQueequeg patted their foreheads; Starbuck scratched their backs with\nhis lance; but fearful of the consequences, for the time refrained\nfrom darting it.\n\nBut far beneath this wondrous world upon the surface, another and\nstill stranger world met our eyes as we gazed over the side.  For,\nsuspended in those watery vaults, floated the forms of the nursing\nmothers of the whales, and those that by their enormous girth seemed\nshortly to become mothers.  The lake, as I have hinted, was to a\nconsiderable depth exceedingly transparent; and as human infants\nwhile suckling will calmly and fixedly gaze away from the breast, as\nif leading two different lives at the time; and while yet drawing\nmortal nourishment, be still spiritually feasting upon some unearthly\nreminiscence;--even so did the young of these whales seem looking up\ntowards us, but not at us, as if we were but a bit of Gulfweed in\ntheir new-born sight.  Floating on their sides, the mothers also\nseemed quietly eyeing us.  One of these little infants, that from\ncertain queer tokens seemed hardly a day old, might have measured\nsome fourteen feet in length, and some six feet in girth.  He was a\nlittle frisky; though as yet his body seemed scarce yet recovered\nfrom that irksome position it had so lately occupied in the maternal\nreticule; where, tail to head, and all ready for the final spring,\nthe unborn whale lies bent like a Tartar's bow.  The delicate\nside-fins, and the palms of his flukes, still freshly retained the\nplaited crumpled appearance of a baby's ears newly arrived from\nforeign parts.\n\n\"Line! line!\" cried Queequeg, looking over the gunwale; \"him fast!\nhim fast!--Who line him!  Who struck?--Two whale; one big, one\nlittle!\"\n\n\"What ails ye, man?\" cried Starbuck.\n\n\"Look-e here,\" said Queequeg, pointing down.\n\nAs when the stricken whale, that from the tub has reeled out hundreds\nof fathoms of rope; as, after deep sounding, he floats up again, and\nshows the slackened curling line buoyantly rising and spiralling\ntowards the air; so now, Starbuck saw long coils of the umbilical\ncord of Madame Leviathan, by which the young cub seemed still\ntethered to its dam.  Not seldom in the rapid vicissitudes of the\nchase, this natural line, with the maternal end loose, becomes\nentangled with the hempen one, so that the cub is thereby trapped.\nSome of the subtlest secrets of the seas seemed divulged to us in\nthis enchanted pond.  We saw young Leviathan amours in the deep.*\n\n\n*The sperm whale, as with all other species of the Leviathan, but\nunlike most other fish, breeds indifferently at all seasons; after a\ngestation which may probably be set down at nine months, producing\nbut one at a time; though in some few known instances giving birth to\nan Esau and Jacob:--a contingency provided for in suckling by two\nteats, curiously situated, one on each side of the anus; but the\nbreasts themselves extend upwards from that.  When by chance these\nprecious parts in a nursing whale are cut by the hunter's lance, the\nmother's pouring milk and blood rivallingly discolour the sea for\nrods.  The milk is very sweet and rich; it has been tasted by man; it\nmight do well with strawberries.  When overflowing with mutual\nesteem, the whales salute MORE HOMINUM.\n\n\nAnd thus, though surrounded by circle upon circle of consternations\nand affrights, did these inscrutable creatures at the centre freely\nand fearlessly indulge in all peaceful concernments; yea, serenely\nrevelled in dalliance and delight.  But even so, amid the tornadoed\nAtlantic of my being, do I myself still for ever centrally disport in\nmute calm; and while ponderous planets of unwaning woe revolve round\nme, deep down and deep inland there I still bathe me in eternal\nmildness of joy.\n\nMeanwhile, as we thus lay entranced, the occasional sudden frantic\nspectacles in the distance evinced the activity of the other boats,\nstill engaged in drugging the whales on the frontier of the host; or\npossibly carrying on the war within the first circle, where abundance\nof room and some convenient retreats were afforded them.  But the\nsight of the enraged drugged whales now and then blindly darting to\nand fro across the circles, was nothing to what at last met our eyes.\nIt is sometimes the custom when fast to a whale more than commonly\npowerful and alert, to seek to hamstring him, as it were, by\nsundering or maiming his gigantic tail-tendon.  It is done by darting\na short-handled cutting-spade, to which is attached a rope for\nhauling it back again.  A whale wounded (as we afterwards learned) in\nthis part, but not effectually, as it seemed, had broken away from\nthe boat, carrying along with him half of the harpoon line; and in\nthe extraordinary agony of the wound, he was now dashing among the\nrevolving circles like the lone mounted desperado Arnold, at the\nbattle of Saratoga, carrying dismay wherever he went.\n\nBut agonizing as was the wound of this whale, and an appalling\nspectacle enough, any way; yet the peculiar horror with which he\nseemed to inspire the rest of the herd, was owing to a cause which at\nfirst the intervening distance obscured from us.  But at length we\nperceived that by one of the unimaginable accidents of the fishery,\nthis whale had become entangled in the harpoon-line that he towed; he\nhad also run away with the cutting-spade in him; and while the free\nend of the rope attached to that weapon, had permanently caught in\nthe coils of the harpoon-line round his tail, the cutting-spade\nitself had worked loose from his flesh.  So that tormented to\nmadness, he was now churning through the water, violently flailing\nwith his flexible tail, and tossing the keen spade about him,\nwounding and murdering his own comrades.\n\nThis terrific object seemed to recall the whole herd from their\nstationary fright.  First, the whales forming the margin of our lake\nbegan to crowd a little, and tumble against each other, as if lifted\nby half spent billows from afar; then the lake itself began faintly\nto heave and swell; the submarine bridal-chambers and nurseries\nvanished; in more and more contracting orbits the whales in the more\ncentral circles began to swim in thickening clusters.  Yes, the long\ncalm was departing.  A low advancing hum was soon heard; and then\nlike to the tumultuous masses of block-ice when the great river\nHudson breaks up in Spring, the entire host of whales came tumbling\nupon their inner centre, as if to pile themselves up in one common\nmountain.  Instantly Starbuck and Queequeg changed places; Starbuck\ntaking the stern.\n\n\"Oars!  Oars!\" he intensely whispered, seizing the helm--\"gripe your\noars, and clutch your souls, now!  My God, men, stand by!  Shove him\noff, you Queequeg--the whale there!--prick him!--hit him!  Stand\nup--stand up, and stay so!  Spring, men--pull, men; never mind their\nbacks--scrape them!--scrape away!\"\n\nThe boat was now all but jammed between two vast black bulks, leaving\na narrow Dardanelles between their long lengths.  But by desperate\nendeavor we at last shot into a temporary opening; then giving way\nrapidly, and at the same time earnestly watching for another outlet.\nAfter many similar hair-breadth escapes, we at last swiftly glided\ninto what had just been one of the outer circles, but now crossed by\nrandom whales, all violently making for one centre.  This lucky\nsalvation was cheaply purchased by the loss of Queequeg's hat, who,\nwhile standing in the bows to prick the fugitive whales, had his hat\ntaken clean from his head by the air-eddy made by the sudden tossing\nof a pair of broad flukes close by.\n\nRiotous and disordered as the universal commotion now was, it soon\nresolved itself into what seemed a systematic movement; for having\nclumped together at last in one dense body, they then renewed their\nonward flight with augmented fleetness.  Further pursuit was useless;\nbut the boats still lingered in their wake to pick up what drugged\nwhales might be dropped astern, and likewise to secure one which\nFlask had killed and waifed.  The waif is a pennoned pole, two or\nthree of which are carried by every boat; and which, when additional\ngame is at hand, are inserted upright into the floating body of a\ndead whale, both to mark its place on the sea, and also as token of\nprior possession, should the boats of any other ship draw near.\n\nThe result of this lowering was somewhat illustrative of that\nsagacious saying in the Fishery,--the more whales the less fish.  Of\nall the drugged whales only one was captured.  The rest contrived to\nescape for the time, but only to be taken, as will hereafter be seen,\nby some other craft than the Pequod.\n\n\n\nCHAPTER 88\n\nSchools and Schoolmasters.\n\n\nThe previous chapter gave account of an immense body or herd of Sperm\nWhales, and there was also then given the probable cause inducing\nthose vast aggregations.\n\nNow, though such great bodies are at times encountered, yet, as must\nhave been seen, even at the present day, small detached bands are\noccasionally observed, embracing from twenty to fifty individuals\neach.  Such bands are known as schools.  They generally are of two\nsorts; those composed almost entirely of females, and those mustering\nnone but young vigorous males, or bulls, as they are familiarly\ndesignated.\n\nIn cavalier attendance upon the school of females, you invariably see\na male of full grown magnitude, but not old; who, upon any alarm,\nevinces his gallantry by falling in the rear and covering the flight\nof his ladies.  In truth, this gentleman is a luxurious Ottoman,\nswimming about over the watery world, surroundingly accompanied by\nall the solaces and endearments of the harem.  The contrast between\nthis Ottoman and his concubines is striking; because, while he is\nalways of the largest leviathanic proportions, the ladies, even at\nfull growth, are not more than one-third of the bulk of an\naverage-sized male.  They are comparatively delicate, indeed; I dare\nsay, not to exceed half a dozen yards round the waist.  Nevertheless,\nit cannot be denied, that upon the whole they are hereditarily\nentitled to EMBONPOINT.\n\nIt is very curious to watch this harem and its lord in their indolent\nramblings.  Like fashionables, they are for ever on the move in\nleisurely search of variety.  You meet them on the Line in time for\nthe full flower of the Equatorial feeding season, having just\nreturned, perhaps, from spending the summer in the Northern seas, and\nso cheating summer of all unpleasant weariness and warmth.  By the\ntime they have lounged up and down the promenade of the Equator\nawhile, they start for the Oriental waters in anticipation of the\ncool season there, and so evade the other excessive temperature of\nthe year.\n\nWhen serenely advancing on one of these journeys, if any strange\nsuspicious sights are seen, my lord whale keeps a wary eye on his\ninteresting family.  Should any unwarrantably pert young Leviathan\ncoming that way, presume to draw confidentially close to one of the\nladies, with what prodigious fury the Bashaw assails him, and chases\nhim away!  High times, indeed, if unprincipled young rakes like him\nare to be permitted to invade the sanctity of domestic bliss; though\ndo what the Bashaw will, he cannot keep the most notorious Lothario\nout of his bed; for, alas! all fish bed in common.  As ashore, the\nladies often cause the most terrible duels among their rival\nadmirers; just so with the whales, who sometimes come to deadly\nbattle, and all for love.  They fence with their long lower jaws,\nsometimes locking them together, and so striving for the supremacy\nlike elks that warringly interweave their antlers.  Not a few are\ncaptured having the deep scars of these encounters,--furrowed heads,\nbroken teeth, scolloped fins; and in some instances, wrenched and\ndislocated mouths.\n\nBut supposing the invader of domestic bliss to betake himself away at\nthe first rush of the harem's lord, then is it very diverting to\nwatch that lord.  Gently he insinuates his vast bulk among them again\nand revels there awhile, still in tantalizing vicinity to young\nLothario, like pious Solomon devoutly worshipping among his thousand\nconcubines.  Granting other whales to be in sight, the fishermen\nwill seldom give chase to one of these Grand Turks; for these Grand\nTurks are too lavish of their strength, and hence their unctuousness\nis small.  As for the sons and the daughters they beget, why, those sons\nand daughters must take care of themselves; at least, with only the\nmaternal help.  For like certain other omnivorous roving lovers that\nmight be named, my Lord Whale has no taste for the nursery, however\nmuch for the bower; and so, being a great traveller, he leaves his\nanonymous babies all over the world; every baby an exotic.  In good\ntime, nevertheless, as the ardour of youth declines; as years and\ndumps increase; as reflection lends her solemn pauses; in short, as a\ngeneral lassitude overtakes the sated Turk; then a love of ease and\nvirtue supplants the love for maidens; our Ottoman enters upon the\nimpotent, repentant, admonitory stage of life, forswears, disbands\nthe harem, and grown to an exemplary, sulky old soul, goes about all\nalone among the meridians and parallels saying his prayers, and\nwarning each young Leviathan from his amorous errors.\n\nNow, as the harem of whales is called by the fishermen a school, so\nis the lord and master of that school technically known as the\nschoolmaster.  It is therefore not in strict character, however\nadmirably satirical, that after going to school himself, he should\nthen go abroad inculcating not what he learned there, but the folly\nof it.  His title, schoolmaster, would very naturally seem derived\nfrom the name bestowed upon the harem itself, but some have surmised\nthat the man who first thus entitled this sort of Ottoman whale, must\nhave read the memoirs of Vidocq, and informed himself what sort of a\ncountry-schoolmaster that famous Frenchman was in his younger days,\nand what was the nature of those occult lessons he inculcated into\nsome of his pupils.\n\nThe same secludedness and isolation to which the schoolmaster whale\nbetakes himself in his advancing years, is true of all aged Sperm\nWhales.  Almost universally, a lone whale--as a solitary Leviathan is\ncalled--proves an ancient one.  Like venerable moss-bearded Daniel\nBoone, he will have no one near him but Nature herself; and her he\ntakes to wife in the wilderness of waters, and the best of wives she\nis, though she keeps so many moody secrets.\n\nThe schools composing none but young and vigorous males, previously\nmentioned, offer a strong contrast to the harem schools.  For while\nthose female whales are characteristically timid, the young males, or\nforty-barrel-bulls, as they call them, are by far the most pugnacious\nof all Leviathans, and proverbially the most dangerous to encounter;\nexcepting those wondrous grey-headed, grizzled whales, sometimes met,\nand these will fight you like grim fiends exasperated by a penal\ngout.\n\nThe Forty-barrel-bull schools are larger than the harem schools.\nLike a mob of young collegians, they are full of fight, fun, and\nwickedness, tumbling round the world at such a reckless, rollicking\nrate, that no prudent underwriter would insure them any more than he\nwould a riotous lad at Yale or Harvard.  They soon relinquish this\nturbulence though, and when about three-fourths grown, break up, and\nseparately go about in quest of settlements, that is, harems.\n\nAnother point of difference between the male and female schools is\nstill more characteristic of the sexes.  Say you strike a\nForty-barrel-bull--poor devil! all his comrades quit him.  But strike\na member of the harem school, and her companions swim around her with\nevery token of concern, sometimes lingering so near her and so long,\nas themselves to fall a prey.\n\n\n\nCHAPTER 89\n\nFast-Fish and Loose-Fish.\n\n\nThe allusion to the waif and waif-poles in the last chapter but one,\nnecessitates some account of the laws and regulations of the whale\nfishery, of which the waif may be deemed the grand symbol and badge.\n\nIt frequently happens that when several ships are cruising in\ncompany, a whale may be struck by one vessel, then escape, and be\nfinally killed and captured by another vessel; and herein are\nindirectly comprised many minor contingencies, all partaking of this\none grand feature.  For example,--after a weary and perilous chase\nand capture of a whale, the body may get loose from the ship by\nreason of a violent storm; and drifting far away to leeward, be\nretaken by a second whaler, who, in a calm, snugly tows it alongside,\nwithout risk of life or line.  Thus the most vexatious and violent\ndisputes would often arise between the fishermen, were there not some\nwritten or unwritten, universal, undisputed law applicable to all\ncases.\n\nPerhaps the only formal whaling code authorized by legislative\nenactment, was that of Holland.  It was decreed by the States-General\nin A.D. 1695.  But though no other nation has ever had any written\nwhaling law, yet the American fishermen have been their own\nlegislators and lawyers in this matter.  They have provided a system\nwhich for terse comprehensiveness surpasses Justinian's Pandects and\nthe By-laws of the Chinese Society for the Suppression of Meddling\nwith other People's Business.  Yes; these laws might be engraven on a\nQueen Anne's forthing, or the barb of a harpoon, and worn round the\nneck, so small are they.\n\nI.  A Fast-Fish belongs to the party fast to it.\n\nII.  A Loose-Fish is fair game for anybody who can soonest catch it.\n\nBut what plays the mischief with this masterly code is the admirable\nbrevity of it, which necessitates a vast volume of commentaries to\nexpound it.\n\nFirst: What is a Fast-Fish?  Alive or dead a fish is technically\nfast, when it is connected with an occupied ship or boat, by any\nmedium at all controllable by the occupant or occupants,--a mast, an\noar, a nine-inch cable, a telegraph wire, or a strand of cobweb, it\nis all the same.  Likewise a fish is technically fast when it bears a\nwaif, or any other recognised symbol of possession; so long as the\nparty waifing it plainly evince their ability at any time to take it\nalongside, as well as their intention so to do.\n\nThese are scientific commentaries; but the commentaries of the\nwhalemen themselves sometimes consist in hard words and harder\nknocks--the Coke-upon-Littleton of the fist.  True, among the more\nupright and honourable whalemen allowances are always made for\npeculiar cases, where it would be an outrageous moral injustice for\none party to claim possession of a whale previously chased or killed\nby another party.  But others are by no means so scrupulous.\n\nSome fifty years ago there was a curious case of whale-trover\nlitigated in England, wherein the plaintiffs set forth that after a\nhard chase of a whale in the Northern seas; and when indeed they (the\nplaintiffs) had succeeded in harpooning the fish; they were at last,\nthrough peril of their lives, obliged to forsake not only their\nlines, but their boat itself.  Ultimately the defendants (the crew of\nanother ship) came up with the whale, struck, killed, seized, and\nfinally appropriated it before the very eyes of the plaintiffs.  And\nwhen those defendants were remonstrated with, their captain snapped\nhis fingers in the plaintiffs' teeth, and assured them that by way of\ndoxology to the deed he had done, he would now retain their line,\nharpoons, and boat, which had remained attached to the whale at the\ntime of the seizure.  Wherefore the plaintiffs now sued for the\nrecovery of the value of their whale, line, harpoons, and boat.\n\nMr. Erskine was counsel for the defendants; Lord Ellenborough was the\njudge.  In the course of the defence, the witty Erskine went on to\nillustrate his position, by alluding to a recent crim. con. case,\nwherein a gentleman, after in vain trying to bridle his wife's\nviciousness, had at last abandoned her upon the seas of life; but in\nthe course of years, repenting of that step, he instituted an action\nto recover possession of her.  Erskine was on the other side; and he\nthen supported it by saying, that though the gentleman had originally\nharpooned the lady, and had once had her fast, and only by reason of\nthe great stress of her plunging viciousness, had at last abandoned\nher; yet abandon her he did, so that she became a loose-fish; and\ntherefore when a subsequent gentleman re-harpooned her, the lady then\nbecame that subsequent gentleman's property, along with whatever\nharpoon might have been found sticking in her.\n\nNow in the present case Erskine contended that the examples of the\nwhale and the lady were reciprocally illustrative of each other.\n\nThese pleadings, and the counter pleadings, being duly heard, the\nvery learned Judge in set terms decided, to wit,--That as for the\nboat, he awarded it to the plaintiffs, because they had merely\nabandoned it to save their lives; but that with regard to the\ncontroverted whale, harpoons, and line, they belonged to the\ndefendants; the whale, because it was a Loose-Fish at the time of the\nfinal capture; and the harpoons and line because when the fish made\noff with them, it (the fish) acquired a property in those articles;\nand hence anybody who afterwards took the fish had a right to them.\nNow the defendants afterwards took the fish; ergo, the aforesaid\narticles were theirs.\n\nA common man looking at this decision of the very learned Judge,\nmight possibly object to it.  But ploughed up to the primary rock of\nthe matter, the two great principles laid down in the twin whaling\nlaws previously quoted, and applied and elucidated by Lord\nEllenborough in the above cited case; these two laws touching\nFast-Fish and Loose-Fish, I say, will, on reflection, be found the\nfundamentals of all human jurisprudence; for notwithstanding its\ncomplicated tracery of sculpture, the Temple of the Law, like the\nTemple of the Philistines, has but two props to stand on.\n\nIs it not a saying in every one's mouth, Possession is half of the\nlaw: that is, regardless of how the thing came into possession?  But\noften possession is the whole of the law.  What are the sinews and\nsouls of Russian serfs and Republican slaves but Fast-Fish, whereof\npossession is the whole of the law?  What to the rapacious landlord\nis the widow's last mite but a Fast-Fish?  What is yonder undetected\nvillain's marble mansion with a door-plate for a waif; what is that\nbut a Fast-Fish?  What is the ruinous discount which Mordecai, the\nbroker, gets from poor Woebegone, the bankrupt, on a loan to\nkeep Woebegone's family from starvation; what is that ruinous\ndiscount but a Fast-Fish?  What is the Archbishop of Savesoul's\nincome of L100,000 seized from the scant bread and cheese of\nhundreds of thousands of broken-backed laborers (all sure of heaven\nwithout any of Savesoul's help) what is that globular L100,000 but a\nFast-Fish?  What are the Duke of Dunder's hereditary towns and\nhamlets but Fast-Fish?  What to that redoubted harpooneer, John Bull,\nis poor Ireland, but a Fast-Fish?  What to that apostolic lancer,\nBrother Jonathan, is Texas but a Fast-Fish?  And concerning all\nthese, is not Possession the whole of the law?\n\nBut if the doctrine of Fast-Fish be pretty generally applicable, the\nkindred doctrine of Loose-Fish is still more widely so.  That is\ninternationally and universally applicable.\n\nWhat was America in 1492 but a Loose-Fish, in which Columbus struck\nthe Spanish standard by way of waifing it for his royal master and\nmistress?  What was Poland to the Czar?  What Greece to the Turk?\nWhat India to England?  What at last will Mexico be to the United\nStates?  All Loose-Fish.\n\nWhat are the Rights of Man and the Liberties of the World but\nLoose-Fish?  What all men's minds and opinions but Loose-Fish?  What\nis the principle of religious belief in them but a Loose-Fish?  What\nto the ostentatious smuggling verbalists are the thoughts of thinkers\nbut Loose-Fish?  What is the great globe itself but a Loose-Fish?\nAnd what are you, reader, but a Loose-Fish and a Fast-Fish, too?\n\n\n\nCHAPTER 90\n\nHeads or Tails.\n\n\n\"De balena vero sufficit, si rex habeat caput, et regina caudam.\"\nBRACTON, L. 3, C. 3.\n\n\nLatin from the books of the Laws of England, which taken along with\nthe context, means, that of all whales captured by anybody on the\ncoast of that land, the King, as Honourary Grand Harpooneer, must have\nthe head, and the Queen be respectfully presented with the tail.  A\ndivision which, in the whale, is much like halving an apple; there is\nno intermediate remainder.  Now as this law, under a modified form,\nis to this day in force in England; and as it offers in various\nrespects a strange anomaly touching the general law of Fast and\nLoose-Fish, it is here treated of in a separate chapter, on the same\ncourteous principle that prompts the English railways to be at the\nexpense of a separate car, specially reserved for the accommodation\nof royalty.  In the first place, in curious proof of the fact that\nthe above-mentioned law is still in force, I proceed to lay before\nyou a circumstance that happened within the last two years.\n\nIt seems that some honest mariners of Dover, or Sandwich, or some one\nof the Cinque Ports, had after a hard chase succeeded in killing and\nbeaching a fine whale which they had originally descried afar off\nfrom the shore.  Now the Cinque Ports are partially or somehow under\nthe jurisdiction of a sort of policeman or beadle, called a Lord\nWarden.  Holding the office directly from the crown, I believe, all\nthe royal emoluments incident to the Cinque Port territories become\nby assignment his.  By some writers this office is called a sinecure.\nBut not so.  Because the Lord Warden is busily employed at times in\nfobbing his perquisites; which are his chiefly by virtue of that same\nfobbing of them.\n\nNow when these poor sun-burnt mariners, bare-footed, and with their\ntrowsers rolled high up on their eely legs, had wearily hauled their\nfat fish high and dry, promising themselves a good L150 from the\nprecious oil and bone; and in fantasy sipping rare tea with their\nwives, and good ale with their cronies, upon the strength of their\nrespective shares; up steps a very learned and most Christian and\ncharitable gentleman, with a copy of Blackstone under his arm; and\nlaying it upon the whale's head, he says--\"Hands off! this fish, my\nmasters, is a Fast-Fish.  I seize it as the Lord Warden's.\"  Upon\nthis the poor mariners in their respectful consternation--so truly\nEnglish--knowing not what to say, fall to vigorously scratching their\nheads all round; meanwhile ruefully glancing from the whale to the\nstranger.  But that did in nowise mend the matter, or at all soften\nthe hard heart of the learned gentleman with the copy of Blackstone.\nAt length one of them, after long scratching about for his ideas,\nmade bold to speak,\n\n\"Please, sir, who is the Lord Warden?\"\n\n\"The Duke.\"\n\n\"But the duke had nothing to do with taking this fish?\"\n\n\"It is his.\"\n\n\"We have been at great trouble, and peril, and some expense, and is\nall that to go to the Duke's benefit; we getting nothing at all for\nour pains but our blisters?\"\n\n\"It is his.\"\n\n\"Is the Duke so very poor as to be forced to this desperate mode of\ngetting a livelihood?\"\n\n\"It is his.\"\n\n\"I thought to relieve my old bed-ridden mother by part of my share of\nthis whale.\"\n\n\"It is his.\"\n\n\"Won't the Duke be content with a quarter or a half?\"\n\n\"It is his.\"\n\nIn a word, the whale was seized and sold, and his Grace the Duke of\nWellington received the money.  Thinking that viewed in some\nparticular lights, the case might by a bare possibility in some small\ndegree be deemed, under the circumstances, a rather hard one, an\nhonest clergyman of the town respectfully addressed a note to his\nGrace, begging him to take the case of those unfortunate mariners\ninto full consideration.  To which my Lord Duke in substance replied\n(both letters were published) that he had already done so, and\nreceived the money, and would be obliged to the reverend gentleman if\nfor the future he (the reverend gentleman) would decline meddling\nwith other people's business.  Is this the still militant old man,\nstanding at the corners of the three kingdoms, on all hands coercing\nalms of beggars?\n\nIt will readily be seen that in this case the alleged right of the\nDuke to the whale was a delegated one from the Sovereign.  We must\nneeds inquire then on what principle the Sovereign is originally\ninvested with that right.  The law itself has already been set forth.\nBut Plowdon gives us the reason for it.  Says Plowdon, the whale so\ncaught belongs to the King and Queen, \"because of its superior\nexcellence.\"  And by the soundest commentators this has ever been\nheld a cogent argument in such matters.\n\nBut why should the King have the head, and the Queen the tail?  A\nreason for that, ye lawyers!\n\nIn his treatise on \"Queen-Gold,\" or Queen-pinmoney, an old King's\nBench author, one William Prynne, thus discourseth: \"Ye tail is ye\nQueen's, that ye Queen's wardrobe may be supplied with ye whalebone.\"\nNow this was written at a time when the black limber bone of the\nGreenland or Right whale was largely used in ladies' bodices.  But\nthis same bone is not in the tail; it is in the head, which is a sad\nmistake for a sagacious lawyer like Prynne.  But is the Queen a\nmermaid, to be presented with a tail?  An allegorical meaning may\nlurk here.\n\nThere are two royal fish so styled by the English law writers--the\nwhale and the sturgeon; both royal property under certain\nlimitations, and nominally supplying the tenth branch of the crown's\nordinary revenue.  I know not that any other author has hinted of the\nmatter; but by inference it seems to me that the sturgeon must be\ndivided in the same way as the whale, the King receiving the highly\ndense and elastic head peculiar to that fish, which, symbolically\nregarded, may possibly be humorously grounded upon some presumed\ncongeniality.  And thus there seems a reason in all things, even in\nlaw.\n\n\n\nCHAPTER 91\n\nThe Pequod Meets The Rose-Bud.\n\n\n\"In vain it was to rake for Ambergriese in the paunch of this\nLeviathan, insufferable fetor denying not inquiry.\"\nSIR T. BROWNE, V.E.\n\n\nIt was a week or two after the last whaling scene recounted, and when\nwe were slowly sailing over a sleepy, vapoury, mid-day sea, that the\nmany noses on the Pequod's deck proved more vigilant discoverers than\nthe three pairs of eyes aloft.  A peculiar and not very pleasant\nsmell was smelt in the sea.\n\n\"I will bet something now,\" said Stubb, \"that somewhere hereabouts\nare some of those drugged whales we tickled the other day.  I thought\nthey would keel up before long.\"\n\nPresently, the vapours in advance slid aside; and there in the\ndistance lay a ship, whose furled sails betokened that some sort of\nwhale must be alongside.  As we glided nearer, the stranger showed\nFrench colours from his peak; and by the eddying cloud of vulture\nsea-fowl that circled, and hovered, and swooped around him, it was\nplain that the whale alongside must be what the fishermen call a\nblasted whale, that is, a whale that has died unmolested on the sea,\nand so floated an unappropriated corpse.  It may well be conceived,\nwhat an unsavory odor such a mass must exhale; worse than an Assyrian\ncity in the plague, when the living are incompetent to bury the\ndeparted.  So intolerable indeed is it regarded by some, that no\ncupidity could persuade them to moor alongside of it.  Yet are there\nthose who will still do it; notwithstanding the fact that the oil\nobtained from such subjects is of a very inferior quality, and by no\nmeans of the nature of attar-of-rose.\n\nComing still nearer with the expiring breeze, we saw that the\nFrenchman had a second whale alongside; and this second whale seemed\neven more of a nosegay than the first.  In truth, it turned out to be\none of those problematical whales that seem to dry up and die with a\nsort of prodigious dyspepsia, or indigestion; leaving their defunct\nbodies almost entirely bankrupt of anything like oil.  Nevertheless,\nin the proper place we shall see that no knowing fisherman will ever\nturn up his nose at such a whale as this, however much he may shun\nblasted whales in general.\n\nThe Pequod had now swept so nigh to the stranger, that Stubb vowed he\nrecognised his cutting spade-pole entangled in the lines that were\nknotted round the tail of one of these whales.\n\n\"There's a pretty fellow, now,\" he banteringly laughed, standing in\nthe ship's bows, \"there's a jackal for ye!  I well know that these\nCrappoes of Frenchmen are but poor devils in the fishery; sometimes\nlowering their boats for breakers, mistaking them for Sperm Whale\nspouts; yes, and sometimes sailing from their port with their hold\nfull of boxes of tallow candles, and cases of snuffers, foreseeing\nthat all the oil they will get won't be enough to dip the Captain's\nwick into; aye, we all know these things; but look ye, here's a\nCrappo that is content with our leavings, the drugged whale there, I\nmean; aye, and is content too with scraping the dry bones of that\nother precious fish he has there.  Poor devil!  I say, pass round a\nhat, some one, and let's make him a present of a little oil for dear\ncharity's sake.  For what oil he'll get from that drugged whale\nthere, wouldn't be fit to burn in a jail; no, not in a condemned\ncell.  And as for the other whale, why, I'll agree to get more oil by\nchopping up and trying out these three masts of ours, than he'll get\nfrom that bundle of bones; though, now that I think of it, it may\ncontain something worth a good deal more than oil; yes, ambergris.  I\nwonder now if our old man has thought of that.  It's worth trying.\nYes, I'm for it;\" and so saying he started for the quarter-deck.\n\nBy this time the faint air had become a complete calm; so that\nwhether or no, the Pequod was now fairly entrapped in the smell, with\nno hope of escaping except by its breezing up again.  Issuing from\nthe cabin, Stubb now called his boat's crew, and pulled off for the\nstranger.  Drawing across her bow, he perceived that in accordance\nwith the fanciful French taste, the upper part of her stem-piece was\ncarved in the likeness of a huge drooping stalk, was painted green,\nand for thorns had copper spikes projecting from it here and there;\nthe whole terminating in a symmetrical folded bulb of a bright red\ncolour.  Upon her head boards, in large gilt letters, he read \"Bouton\nde Rose,\"--Rose-button, or Rose-bud; and this was the romantic name\nof this aromatic ship.\n\nThough Stubb did not understand the BOUTON part of the inscription,\nyet the word ROSE, and the bulbous figure-head put together,\nsufficiently explained the whole to him.\n\n\"A wooden rose-bud, eh?\" he cried with his hand to his nose, \"that\nwill do very well; but how like all creation it smells!\"\n\nNow in order to hold direct communication with the people on deck, he\nhad to pull round the bows to the starboard side, and thus come close\nto the blasted whale; and so talk over it.\n\nArrived then at this spot, with one hand still to his nose, he\nbawled--\"Bouton-de-Rose, ahoy! are there any of you Bouton-de-Roses\nthat speak English?\"\n\n\"Yes,\" rejoined a Guernsey-man from the bulwarks, who turned out to\nbe the chief-mate.\n\n\"Well, then, my Bouton-de-Rose-bud, have you seen the White Whale?\"\n\n\"WHAT whale?\"\n\n\"The WHITE Whale--a Sperm Whale--Moby Dick, have ye seen him?\n\n\"Never heard of such a whale.  Cachalot Blanche!  White Whale--no.\"\n\n\"Very good, then; good bye now, and I'll call again in a minute.\"\n\nThen rapidly pulling back towards the Pequod, and seeing Ahab leaning\nover the quarter-deck rail awaiting his report, he moulded his two\nhands into a trumpet and shouted--\"No, Sir!  No!\"  Upon which Ahab\nretired, and Stubb returned to the Frenchman.\n\nHe now perceived that the Guernsey-man, who had just got into the\nchains, and was using a cutting-spade, had slung his nose in a sort\nof bag.\n\n\"What's the matter with your nose, there?\" said Stubb.  \"Broke it?\"\n\n\"I wish it was broken, or that I didn't have any nose at all!\"\nanswered the Guernsey-man, who did not seem to relish the job he was\nat very much.  \"But what are you holding YOURS for?\"\n\n\"Oh, nothing!  It's a wax nose; I have to hold it on.  Fine day,\nain't it?  Air rather gardenny, I should say; throw us a bunch of\nposies, will ye, Bouton-de-Rose?\"\n\n\"What in the devil's name do you want here?\" roared the Guernseyman,\nflying into a sudden passion.\n\n\"Oh! keep cool--cool? yes, that's the word! why don't you pack those\nwhales in ice while you're working at 'em?  But joking aside, though;\ndo you know, Rose-bud, that it's all nonsense trying to get any oil\nout of such whales?  As for that dried up one, there, he hasn't a\ngill in his whole carcase.\"\n\n\"I know that well enough; but, d'ye see, the Captain here won't\nbelieve it; this is his first voyage; he was a Cologne manufacturer\nbefore.  But come aboard, and mayhap he'll believe you, if he won't\nme; and so I'll get out of this dirty scrape.\"\n\n\"Anything to oblige ye, my sweet and pleasant fellow,\" rejoined\nStubb, and with that he soon mounted to the deck.  There a queer\nscene presented itself.  The sailors, in tasselled caps of red\nworsted, were getting the heavy tackles in readiness for the whales.\nBut they worked rather slow and talked very fast, and seemed in\nanything but a good humor.  All their noses upwardly projected from\ntheir faces like so many jib-booms.  Now and then pairs of them would\ndrop their work, and run up to the mast-head to get some fresh air.\nSome thinking they would catch the plague, dipped oakum in coal-tar,\nand at intervals held it to their nostrils.  Others having broken the\nstems of their pipes almost short off at the bowl, were vigorously\npuffing tobacco-smoke, so that it constantly filled their\nolfactories.\n\nStubb was struck by a shower of outcries and anathemas proceeding\nfrom the Captain's round-house abaft; and looking in that direction\nsaw a fiery face thrust from behind the door, which was held ajar\nfrom within.  This was the tormented surgeon, who, after in vain\nremonstrating against the proceedings of the day, had betaken himself\nto the Captain's round-house (CABINET he called it) to avoid the\npest; but still, could not help yelling out his entreaties and\nindignations at times.\n\nMarking all this, Stubb argued well for his scheme, and turning to\nthe Guernsey-man had a little chat with him, during which the\nstranger mate expressed his detestation of his Captain as a conceited\nignoramus, who had brought them all into so unsavory and unprofitable\na pickle.  Sounding him carefully, Stubb further perceived that the\nGuernsey-man had not the slightest suspicion concerning the\nambergris.  He therefore held his peace on that head, but otherwise\nwas quite frank and confidential with him, so that the two quickly\nconcocted a little plan for both circumventing and satirizing the\nCaptain, without his at all dreaming of distrusting their sincerity.\nAccording to this little plan of theirs, the Guernsey-man, under\ncover of an interpreter's office, was to tell the Captain what he\npleased, but as coming from Stubb; and as for Stubb, he was to utter\nany nonsense that should come uppermost in him during the interview.\n\nBy this time their destined victim appeared from his cabin.  He was a\nsmall and dark, but rather delicate looking man for a sea-captain,\nwith large whiskers and moustache, however; and wore a red cotton\nvelvet vest with watch-seals at his side.  To this gentleman, Stubb\nwas now politely introduced by the Guernsey-man, who at once\nostentatiously put on the aspect of interpreting between them.\n\n\"What shall I say to him first?\" said he.\n\n\"Why,\" said Stubb, eyeing the velvet vest and the watch and seals,\n\"you may as well begin by telling him that he looks a sort of babyish\nto me, though I don't pretend to be a judge.\"\n\n\"He says, Monsieur,\" said the Guernsey-man, in French, turning to his\ncaptain, \"that only yesterday his ship spoke a vessel, whose captain\nand chief-mate, with six sailors, had all died of a fever caught from\na blasted whale they had brought alongside.\"\n\nUpon this the captain started, and eagerly desired to know more.\n\n\"What now?\" said the Guernsey-man to Stubb.\n\n\"Why, since he takes it so easy, tell him that now I have eyed him\ncarefully, I'm quite certain that he's no more fit to command a\nwhale-ship than a St. Jago monkey.  In fact, tell him from me he's a\nbaboon.\"\n\n\"He vows and declares, Monsieur, that the other whale, the dried one,\nis far more deadly than the blasted one; in fine, Monsieur, he\nconjures us, as we value our lives, to cut loose from these fish.\"\n\nInstantly the captain ran forward, and in a loud voice commanded his\ncrew to desist from hoisting the cutting-tackles, and at once cast\nloose the cables and chains confining the whales to the ship.\n\n\"What now?\" said the Guernsey-man, when the Captain had returned to\nthem.\n\n\"Why, let me see; yes, you may as well tell him now that--that--in\nfact, tell him I've diddled him, and (aside to himself) perhaps\nsomebody else.\"\n\n\"He says, Monsieur, that he's very happy to have been of any service\nto us.\"\n\nHearing this, the captain vowed that they were the grateful parties\n(meaning himself and mate) and concluded by inviting Stubb down\ninto his cabin to drink a bottle of Bordeaux.\n\n\"He wants you to take a glass of wine with him,\" said the\ninterpreter.\n\n\"Thank him heartily; but tell him it's against my principles to drink\nwith the man I've diddled.  In fact, tell him I must go.\"\n\n\"He says, Monsieur, that his principles won't admit of his drinking;\nbut that if Monsieur wants to live another day to drink, then\nMonsieur had best drop all four boats, and pull the ship away from\nthese whales, for it's so calm they won't drift.\"\n\nBy this time Stubb was over the side, and getting into his boat,\nhailed the Guernsey-man to this effect,--that having a long tow-line\nin his boat, he would do what he could to help them, by pulling out\nthe lighter whale of the two from the ship's side.  While the\nFrenchman's boats, then, were engaged in towing the ship one way,\nStubb benevolently towed away at his whale the other way,\nostentatiously slacking out a most unusually long tow-line.\n\nPresently a breeze sprang up; Stubb feigned to cast off from the\nwhale; hoisting his boats, the Frenchman soon increased his distance,\nwhile the Pequod slid in between him and Stubb's whale.  Whereupon\nStubb quickly pulled to the floating body, and hailing the Pequod to\ngive notice of his intentions, at once proceeded to reap the fruit of\nhis unrighteous cunning.  Seizing his sharp boat-spade, he commenced\nan excavation in the body, a little behind the side fin.  You would\nalmost have thought he was digging a cellar there in the sea; and\nwhen at length his spade struck against the gaunt ribs, it was like\nturning up old Roman tiles and pottery buried in fat English loam.\nHis boat's crew were all in high excitement, eagerly helping their\nchief, and looking as anxious as gold-hunters.\n\nAnd all the time numberless fowls were diving, and ducking, and\nscreaming, and yelling, and fighting around them.  Stubb was\nbeginning to look disappointed, especially as the horrible nosegay\nincreased, when suddenly from out the very heart of this plague,\nthere stole a faint stream of perfume, which flowed through the tide\nof bad smells without being absorbed by it, as one river will flow\ninto and then along with another, without at all blending with it for\na time.\n\n\"I have it, I have it,\" cried Stubb, with delight, striking something\nin the subterranean regions, \"a purse! a purse!\"\n\nDropping his spade, he thrust both hands in, and drew out handfuls of\nsomething that looked like ripe Windsor soap, or rich mottled old\ncheese; very unctuous and savory withal.  You might easily dent it\nwith your thumb; it is of a hue between yellow and ash colour.  And\nthis, good friends, is ambergris, worth a gold guinea an ounce to any\ndruggist.  Some six handfuls were obtained; but more was unavoidably\nlost in the sea, and still more, perhaps, might have been secured\nwere it not for impatient Ahab's loud command to Stubb to desist, and\ncome on board, else the ship would bid them good bye.\n\n\n\nCHAPTER 92\n\nAmbergris.\n\n\nNow this ambergris is a very curious substance, and so important as\nan article of commerce, that in 1791 a certain Nantucket-born Captain\nCoffin was examined at the bar of the English House of Commons on\nthat subject.  For at that time, and indeed until a comparatively\nlate day, the precise origin of ambergris remained, like amber\nitself, a problem to the learned.  Though the word ambergris is but\nthe French compound for grey amber, yet the two substances are quite\ndistinct.  For amber, though at times found on the sea-coast, is also\ndug up in some far inland soils, whereas ambergris is never found\nexcept upon the sea.  Besides, amber is a hard, transparent, brittle,\nodorless substance, used for mouth-pieces to pipes, for beads and\nornaments; but ambergris is soft, waxy, and so highly fragrant and\nspicy, that it is largely used in perfumery, in pastiles, precious\ncandles, hair-powders, and pomatum.  The Turks use it in cooking, and\nalso carry it to Mecca, for the same purpose that frankincense is\ncarried to St. Peter's in Rome.  Some wine merchants drop a few\ngrains into claret, to flavor it.\n\nWho would think, then, that such fine ladies and gentlemen should\nregale themselves with an essence found in the inglorious bowels of a\nsick whale!  Yet so it is.  By some, ambergris is supposed to be the\ncause, and by others the effect, of the dyspepsia in the whale.  How\nto cure such a dyspepsia it were hard to say, unless by administering\nthree or four boat loads of Brandreth's pills, and then running out\nof harm's way, as laborers do in blasting rocks.\n\nI have forgotten to say that there were found in this ambergris,\ncertain hard, round, bony plates, which at first Stubb thought might\nbe sailors' trowsers buttons; but it afterwards turned out that they\nwere nothing more than pieces of small squid bones embalmed in that\nmanner.\n\nNow that the incorruption of this most fragrant ambergris should be\nfound in the heart of such decay; is this nothing?  Bethink thee of\nthat saying of St. Paul in Corinthians, about corruption and\nincorruption; how that we are sown in dishonour, but raised in glory.\nAnd likewise call to mind that saying of Paracelsus about what it is\nthat maketh the best musk.  Also forget not the strange fact that of\nall things of ill-savor, Cologne-water, in its rudimental\nmanufacturing stages, is the worst.\n\nI should like to conclude the chapter with the above appeal, but\ncannot, owing to my anxiety to repel a charge often made against\nwhalemen, and which, in the estimation of some already biased minds,\nmight be considered as indirectly substantiated by what has been said\nof the Frenchman's two whales.  Elsewhere in this volume the\nslanderous aspersion has been disproved, that the vocation of whaling\nis throughout a slatternly, untidy business.  But there is another\nthing to rebut.  They hint that all whales always smell bad.  Now how\ndid this odious stigma originate?\n\nI opine, that it is plainly traceable to the first arrival of the\nGreenland whaling ships in London, more than two centuries ago.\nBecause those whalemen did not then, and do not now, try out their\noil at sea as the Southern ships have always done; but cutting up the\nfresh blubber in small bits, thrust it through the bung holes of\nlarge casks, and carry it home in that manner; the shortness of the\nseason in those Icy Seas, and the sudden and violent storms to which\nthey are exposed, forbidding any other course.  The consequence is,\nthat upon breaking into the hold, and unloading one of these whale\ncemeteries, in the Greenland dock, a savor is given forth somewhat\nsimilar to that arising from excavating an old city grave-yard, for\nthe foundations of a Lying-in-Hospital.\n\nI partly surmise also, that this wicked charge against whalers may be\nlikewise imputed to the existence on the coast of Greenland, in\nformer times, of a Dutch village called Schmerenburgh or Smeerenberg,\nwhich latter name is the one used by the learned Fogo Von Slack, in\nhis great work on Smells, a text-book on that subject.  As its name\nimports (smeer, fat; berg, to put up), this village was founded in\norder to afford a place for the blubber of the Dutch whale fleet to\nbe tried out, without being taken home to Holland for that purpose.\nIt was a collection of furnaces, fat-kettles, and oil sheds; and when\nthe works were in full operation certainly gave forth no very\npleasant savor.  But all this is quite different with a South Sea\nSperm Whaler; which in a voyage of four years perhaps, after\ncompletely filling her hold with oil, does not, perhaps, consume\nfifty days in the business of boiling out; and in the state that it\nis casked, the oil is nearly scentless.  The truth is, that living or\ndead, if but decently treated, whales as a species are by no means\ncreatures of ill odor; nor can whalemen be recognised, as the people\nof the middle ages affected to detect a Jew in the company, by the\nnose.  Nor indeed can the whale possibly be otherwise than fragrant,\nwhen, as a general thing, he enjoys such high health; taking\nabundance of exercise; always out of doors; though, it is true,\nseldom in the open air.  I say, that the motion of a Sperm Whale's\nflukes above water dispenses a perfume, as when a musk-scented lady\nrustles her dress in a warm parlor.  What then shall I liken the\nSperm Whale to for fragrance, considering his magnitude?  Must it not\nbe to that famous elephant, with jewelled tusks, and redolent with\nmyrrh, which was led out of an Indian town to do honour to Alexander\nthe Great?\n\n\n\nCHAPTER 93\n\nThe Castaway.\n\n\nIt was but some few days after encountering the Frenchman, that a\nmost significant event befell the most insignificant of the Pequod's\ncrew; an event most lamentable; and which ended in providing the\nsometimes madly merry and predestinated craft with a living and ever\naccompanying prophecy of whatever shattered sequel might prove her\nown.\n\nNow, in the whale ship, it is not every one that goes in the boats.\nSome few hands are reserved called ship-keepers, whose province it is\nto work the vessel while the boats are pursuing the whale.  As a\ngeneral thing, these ship-keepers are as hardy fellows as the men\ncomprising the boats' crews.  But if there happen to be an unduly\nslender, clumsy, or timorous wight in the ship, that wight is certain\nto be made a ship-keeper.  It was so in the Pequod with the little\nnegro Pippin by nick-name, Pip by abbreviation.  Poor Pip! ye have\nheard of him before; ye must remember his tambourine on that dramatic\nmidnight, so gloomy-jolly.\n\nIn outer aspect, Pip and Dough-Boy made a match, like a black pony\nand a white one, of equal developments, though of dissimilar colour,\ndriven in one eccentric span.  But while hapless Dough-Boy was by\nnature dull and torpid in his intellects, Pip, though over\ntender-hearted, was at bottom very bright, with that pleasant,\ngenial, jolly brightness peculiar to his tribe; a tribe, which ever\nenjoy all holidays and festivities with finer, freer relish than any\nother race.  For blacks, the year's calendar should show naught but\nthree hundred and sixty-five Fourth of Julys and New Year's Days.\nNor smile so, while I write that this little black was brilliant, for\neven blackness has its brilliancy; behold yon lustrous ebony,\npanelled in king's cabinets.  But Pip loved life, and all life's\npeaceable securities; so that the panic-striking business in which he\nhad somehow unaccountably become entrapped, had most sadly blurred\nhis brightness; though, as ere long will be seen, what was thus\ntemporarily subdued in him, in the end was destined to be luridly\nillumined by strange wild fires, that fictitiously showed him off to\nten times the natural lustre with which in his native Tolland County\nin Connecticut, he had once enlivened many a fiddler's frolic on the\ngreen; and at melodious even-tide, with his gay ha-ha! had turned the\nround horizon into one star-belled tambourine.  So, though in the\nclear air of day, suspended against a blue-veined neck, the\npure-watered diamond drop will healthful glow; yet, when the cunning\njeweller would show you the diamond in its most impressive lustre, he\nlays it against a gloomy ground, and then lights it up, not by the\nsun, but by some unnatural gases.  Then come out those fiery\neffulgences, infernally superb; then the evil-blazing diamond, once\nthe divinest symbol of the crystal skies, looks like some crown-jewel\nstolen from the King of Hell.  But let us to the story.\n\nIt came to pass, that in the ambergris affair Stubb's after-oarsman\nchanced so to sprain his hand, as for a time to become quite maimed;\nand, temporarily, Pip was put into his place.\n\nThe first time Stubb lowered with him, Pip evinced much nervousness;\nbut happily, for that time, escaped close contact with the whale; and\ntherefore came off not altogether discreditably; though Stubb\nobserving him, took care, afterwards, to exhort him to cherish his\ncourageousness to the utmost, for he might often find it needful.\n\nNow upon the second lowering, the boat paddled upon the whale; and as\nthe fish received the darted iron, it gave its customary rap, which\nhappened, in this instance, to be right under poor Pip's seat.  The\ninvoluntary consternation of the moment caused him to leap, paddle in\nhand, out of the boat; and in such a way, that part of the slack\nwhale line coming against his chest, he breasted it overboard with\nhim, so as to become entangled in it, when at last plumping into the\nwater.  That instant the stricken whale started on a fierce run, the\nline swiftly straightened; and presto! poor Pip came all foaming up\nto the chocks of the boat, remorselessly dragged there by the line,\nwhich had taken several turns around his chest and neck.\n\nTashtego stood in the bows.  He was full of the fire of the hunt.  He\nhated Pip for a poltroon.  Snatching the boat-knife from its sheath,\nhe suspended its sharp edge over the line, and turning towards Stubb,\nexclaimed interrogatively, \"Cut?\"  Meantime Pip's blue, choked face\nplainly looked, Do, for God's sake!  All passed in a flash.  In less\nthan half a minute, this entire thing happened.\n\n\"Damn him, cut!\" roared Stubb; and so the whale was lost and Pip was\nsaved.\n\nSo soon as he recovered himself, the poor little negro was assailed\nby yells and execrations from the crew.  Tranquilly permitting these\nirregular cursings to evaporate, Stubb then in a plain,\nbusiness-like, but still half humorous manner, cursed Pip officially;\nand that done, unofficially gave him much wholesome advice.  The\nsubstance was, Never jump from a boat, Pip, except--but all the rest\nwas indefinite, as the soundest advice ever is.  Now, in general,\nSTICK TO THE BOAT, is your true motto in whaling; but cases will\nsometimes happen when LEAP FROM THE BOAT, is still better.  Moreover,\nas if perceiving at last that if he should give undiluted\nconscientious advice to Pip, he would be leaving him too wide a\nmargin to jump in for the future; Stubb suddenly dropped all advice,\nand concluded with a peremptory command, \"Stick to the boat, Pip, or\nby the Lord, I won't pick you up if you jump; mind that.  We can't\nafford to lose whales by the likes of you; a whale would sell for\nthirty times what you would, Pip, in Alabama.  Bear that in mind, and\ndon't jump any more.\"  Hereby perhaps Stubb indirectly hinted, that\nthough man loved his fellow, yet man is a money-making animal, which\npropensity too often interferes with his benevolence.\n\nBut we are all in the hands of the Gods; and Pip jumped again.  It\nwas under very similar circumstances to the first performance; but\nthis time he did not breast out the line; and hence, when the whale\nstarted to run, Pip was left behind on the sea, like a hurried\ntraveller's trunk.  Alas!  Stubb was but too true to his word.  It\nwas a beautiful, bounteous, blue day; the spangled sea calm and\ncool, and flatly stretching away, all round, to the horizon, like\ngold-beater's skin hammered out to the extremest.  Bobbing up and\ndown in that sea, Pip's ebon head showed like a head of cloves.  No\nboat-knife was lifted when he fell so rapidly astern.  Stubb's\ninexorable back was turned upon him; and the whale was winged.  In\nthree minutes, a whole mile of shoreless ocean was between Pip and\nStubb.  Out from the centre of the sea, poor Pip turned his crisp,\ncurling, black head to the sun, another lonely castaway, though the\nloftiest and the brightest.\n\nNow, in calm weather, to swim in the open ocean is as easy to the\npractised swimmer as to ride in a spring-carriage ashore.  But the\nawful lonesomeness is intolerable.  The intense concentration of self\nin the middle of such a heartless immensity, my God! who can tell it?\nMark, how when sailors in a dead calm bathe in the open sea--mark\nhow closely they hug their ship and only coast along her sides.\n\nBut had Stubb really abandoned the poor little negro to his fate?\nNo; he did not mean to, at least.  Because there were two boats in\nhis wake, and he supposed, no doubt, that they would of course come\nup to Pip very quickly, and pick him up; though, indeed, such\nconsiderations towards oarsmen jeopardized through their own\ntimidity, is not always manifested by the hunters in all similar\ninstances; and such instances not unfrequently occur; almost\ninvariably in the fishery, a coward, so called, is marked with the\nsame ruthless detestation peculiar to military navies and armies.\n\nBut it so happened, that those boats, without seeing Pip, suddenly\nspying whales close to them on one side, turned, and gave chase; and\nStubb's boat was now so far away, and he and all his crew so intent\nupon his fish, that Pip's ringed horizon began to expand around him\nmiserably.  By the merest chance the ship itself at last rescued him;\nbut from that hour the little negro went about the deck an idiot;\nsuch, at least, they said he was.  The sea had jeeringly kept his\nfinite body up, but drowned the infinite of his soul.  Not drowned\nentirely, though.  Rather carried down alive to wondrous depths,\nwhere strange shapes of the unwarped primal world glided to and fro\nbefore his passive eyes; and the miser-merman, Wisdom, revealed his\nhoarded heaps; and among the joyous, heartless, ever-juvenile\neternities, Pip saw the multitudinous, God-omnipresent, coral\ninsects, that out of the firmament of waters heaved the colossal\norbs.  He saw God's foot upon the treadle of the loom, and spoke it;\nand therefore his shipmates called him mad.  So man's insanity is\nheaven's sense; and wandering from all mortal reason, man comes at\nlast to that celestial thought, which, to reason, is absurd and\nfrantic; and weal or woe, feels then uncompromised, indifferent as\nhis God.\n\nFor the rest, blame not Stubb too hardly.  The thing is common in\nthat fishery; and in the sequel of the narrative, it will then be\nseen what like abandonment befell myself.\n\n\n\nCHAPTER 94\n\nA Squeeze of the Hand.\n\n\nThat whale of Stubb's, so dearly purchased, was duly brought to the\nPequod's side, where all those cutting and hoisting operations\npreviously detailed, were regularly gone through, even to the baling\nof the Heidelburgh Tun, or Case.\n\nWhile some were occupied with this latter duty, others were employed\nin dragging away the larger tubs, so soon as filled with the sperm;\nand when the proper time arrived, this same sperm was carefully\nmanipulated ere going to the try-works, of which anon.\n\nIt had cooled and crystallized to such a degree, that when, with\nseveral others, I sat down before a large Constantine's bath of it, I\nfound it strangely concreted into lumps, here and there rolling about\nin the liquid part.  It was our business to squeeze these lumps back\ninto fluid.  A sweet and unctuous duty!  No wonder that in old times\nthis sperm was such a favourite cosmetic.  Such a clearer! such a\nsweetener! such a softener! such a delicious molifier!  After\nhaving my hands in it for only a few minutes, my fingers felt like\neels, and began, as it were, to serpentine and spiralise.\n\nAs I sat there at my ease, cross-legged on the deck; after the bitter\nexertion at the windlass; under a blue tranquil sky; the ship under\nindolent sail, and gliding so serenely along; as I bathed my hands\namong those soft, gentle globules of infiltrated tissues, woven\nalmost within the hour; as they richly broke to my fingers, and\ndischarged all their opulence, like fully ripe grapes their wine; as\nI snuffed up that uncontaminated aroma,--literally and truly, like\nthe smell of spring violets; I declare to you, that for the time I\nlived as in a musky meadow; I forgot all about our horrible oath; in\nthat inexpressible sperm, I washed my hands and my heart of it; I\nalmost began to credit the old Paracelsan superstition that sperm is\nof rare virtue in allaying the heat of anger; while bathing in that\nbath, I felt divinely free from all ill-will, or petulance, or\nmalice, of any sort whatsoever.\n\nSqueeze! squeeze! squeeze! all the morning long; I squeezed that\nsperm till I myself almost melted into it; I squeezed that sperm till\na strange sort of insanity came over me; and I found myself\nunwittingly squeezing my co-laborers' hands in it, mistaking their\nhands for the gentle globules.  Such an abounding, affectionate,\nfriendly, loving feeling did this avocation beget; that at last I was\ncontinually squeezing their hands, and looking up into their eyes\nsentimentally; as much as to say,--Oh! my dear fellow beings, why\nshould we longer cherish any social acerbities, or know the slightest\nill-humor or envy!  Come; let us squeeze hands all round; nay, let us\nall squeeze ourselves into each other; let us squeeze ourselves\nuniversally into the very milk and sperm of kindness.\n\nWould that I could keep squeezing that sperm for ever!  For now,\nsince by many prolonged, repeated experiences, I have perceived that\nin all cases man must eventually lower, or at least shift, his\nconceit of attainable felicity; not placing it anywhere in the\nintellect or the fancy; but in the wife, the heart, the bed, the\ntable, the saddle, the fireside, the country; now that I have\nperceived all this, I am ready to squeeze case eternally.  In\nthoughts of the visions of the night, I saw long rows of angels in\nparadise, each with his hands in a jar of spermaceti.\n\nNow, while discoursing of sperm, it behooves to speak of other things\nakin to it, in the business of preparing the sperm whale for the\ntry-works.\n\nFirst comes white-horse, so called, which is obtained from the\ntapering part of the fish, and also from the thicker portions of his\nflukes.  It is tough with congealed tendons--a wad of muscle--but\nstill contains some oil.  After being severed from the whale, the\nwhite-horse is first cut into portable oblongs ere going to the\nmincer.  They look much like blocks of Berkshire marble.\n\nPlum-pudding is the term bestowed upon certain fragmentary parts of\nthe whale's flesh, here and there adhering to the blanket of blubber,\nand often participating to a considerable degree in its unctuousness.\nIt is a most refreshing, convivial, beautiful object to behold.  As\nits name imports, it is of an exceedingly rich, mottled tint, with a\nbestreaked snowy and golden ground, dotted with spots of the deepest\ncrimson and purple.  It is plums of rubies, in pictures of citron.\nSpite of reason, it is hard to keep yourself from eating it.  I\nconfess, that once I stole behind the foremast to try it.  It tasted\nsomething as I should conceive a royal cutlet from the thigh of Louis\nle Gros might have tasted, supposing him to have been killed the\nfirst day after the venison season, and that particular venison\nseason contemporary with an unusually fine vintage of the vineyards\nof Champagne.\n\nThere is another substance, and a very singular one, which turns up\nin the course of this business, but which I feel it to be very\npuzzling adequately to describe.  It is called slobgollion; an\nappellation original with the whalemen, and even so is the nature of\nthe substance.  It is an ineffably oozy, stringy affair, most\nfrequently found in the tubs of sperm, after a prolonged squeezing,\nand subsequent decanting.  I hold it to be the wondrously thin,\nruptured membranes of the case, coalescing.\n\nGurry, so called, is a term properly belonging to right whalemen, but\nsometimes incidentally used by the sperm fishermen.  It designates\nthe dark, glutinous substance which is scraped off the back of the\nGreenland or right whale, and much of which covers the decks of those\ninferior souls who hunt that ignoble Leviathan.\n\nNippers.  Strictly this word is not indigenous to the whale's\nvocabulary.  But as applied by whalemen, it becomes so.  A whaleman's\nnipper is a short firm strip of tendinous stuff cut from the tapering\npart of Leviathan's tail: it averages an inch in thickness, and for\nthe rest, is about the size of the iron part of a hoe.  Edgewise\nmoved along the oily deck, it operates like a leathern squilgee; and\nby nameless blandishments, as of magic, allures along with it all\nimpurities.\n\nBut to learn all about these recondite matters, your best way is at\nonce to descend into the blubber-room, and have a long talk with its\ninmates.  This place has previously been mentioned as the receptacle\nfor the blanket-pieces, when stript and hoisted from the whale.  When\nthe proper time arrives for cutting up its contents, this apartment\nis a scene of terror to all tyros, especially by night.  On one side,\nlit by a dull lantern, a space has been left clear for the workmen.\nThey generally go in pairs,--a pike-and-gaffman and a spade-man.\nThe whaling-pike is similar to a frigate's boarding-weapon of the\nsame name.  The gaff is something like a boat-hook.  With his gaff,\nthe gaffman hooks on to a sheet of blubber, and strives to hold it\nfrom slipping, as the ship pitches and lurches about.  Meanwhile, the\nspade-man stands on the sheet itself, perpendicularly chopping it\ninto the portable horse-pieces.  This spade is sharp as hone can make\nit; the spademan's feet are shoeless; the thing he stands on will\nsometimes irresistibly slide away from him, like a sledge.  If he\ncuts off one of his own toes, or one of his assistants', would you be\nvery much astonished?  Toes are scarce among veteran blubber-room\nmen.\n\n\n\nCHAPTER 95\n\nThe Cassock.\n\n\nHad you stepped on board the Pequod at a certain juncture of this\npost-mortemizing of the whale; and had you strolled forward nigh the\nwindlass, pretty sure am I that you would have scanned with no small\ncuriosity a very strange, enigmatical object, which you would have\nseen there, lying along lengthwise in the lee scuppers.  Not the\nwondrous cistern in the whale's huge head; not the prodigy of his\nunhinged lower jaw; not the miracle of his symmetrical tail; none of\nthese would so surprise you, as half a glimpse of that unaccountable\ncone,--longer than a Kentuckian is tall, nigh a foot in diameter at\nthe base, and jet-black as Yojo, the ebony idol of Queequeg.  And an\nidol, indeed, it is; or, rather, in old times, its likeness was.\nSuch an idol as that found in the secret groves of Queen Maachah in\nJudea; and for worshipping which, King Asa, her son, did depose her,\nand destroyed the idol, and burnt it for an abomination at the brook\nKedron, as darkly set forth in the 15th chapter of the First Book of\nKings.\n\nLook at the sailor, called the mincer, who now comes along, and\nassisted by two allies, heavily backs the grandissimus, as the\nmariners call it, and with bowed shoulders, staggers off with it as\nif he were a grenadier carrying a dead comrade from the field.\nExtending it upon the forecastle deck, he now proceeds cylindrically\nto remove its dark pelt, as an African hunter the pelt of a boa.\nThis done he turns the pelt inside out, like a pantaloon leg; gives\nit a good stretching, so as almost to double its diameter; and at\nlast hangs it, well spread, in the rigging, to dry.  Ere long, it is\ntaken down; when removing some three feet of it, towards the pointed\nextremity, and then cutting two slits for arm-holes at the other end,\nhe lengthwise slips himself bodily into it.  The mincer now stands\nbefore you invested in the full canonicals of his calling.\nImmemorial to all his order, this investiture alone will adequately\nprotect him, while employed in the peculiar functions of his office.\n\nThat office consists in mincing the horse-pieces of blubber for the\npots; an operation which is conducted at a curious wooden horse,\nplanted endwise against the bulwarks, and with a capacious tub\nbeneath it, into which the minced pieces drop, fast as the sheets\nfrom a rapt orator's desk.  Arrayed in decent black; occupying a\nconspicuous pulpit; intent on bible leaves; what a candidate for an\narchbishopric, what a lad for a Pope were this mincer!*\n\n\n*Bible leaves!  Bible leaves!  This is the invariable cry from the\nmates to the mincer.  It enjoins him to be careful, and cut his work\ninto as thin slices as possible, inasmuch as by so doing the business\nof boiling out the oil is much accelerated, and its quantity\nconsiderably increased, besides perhaps improving it in quality.\n\n\n\nCHAPTER 96\n\nThe Try-Works.\n\n\nBesides her hoisted boats, an American whaler is outwardly\ndistinguished by her try-works.  She presents the curious anomaly of\nthe most solid masonry joining with oak and hemp in constituting the\ncompleted ship.  It is as if from the open field a brick-kiln were\ntransported to her planks.\n\nThe try-works are planted between the foremast and mainmast, the\nmost roomy part of the deck.  The timbers beneath are of a peculiar\nstrength, fitted to sustain the weight of an almost solid mass of\nbrick and mortar, some ten feet by eight square, and five in height.\nThe foundation does not penetrate the deck, but the masonry is firmly\nsecured to the surface by ponderous knees of iron bracing it on all\nsides, and screwing it down to the timbers.  On the flanks it is\ncased with wood, and at top completely covered by a large, sloping,\nbattened hatchway.  Removing this hatch we expose the great try-pots,\ntwo in number, and each of several barrels' capacity.  When not in\nuse, they are kept remarkably clean.  Sometimes they are polished\nwith soapstone and sand, till they shine within like silver\npunch-bowls.  During the night-watches some cynical old sailors will\ncrawl into them and coil themselves away there for a nap.  While\nemployed in polishing them--one man in each pot, side by side--many\nconfidential communications are carried on, over the iron lips.  It\nis a place also for profound mathematical meditation.  It was in the\nleft hand try-pot of the Pequod, with the soapstone diligently\ncircling round me, that I was first indirectly struck by the\nremarkable fact, that in geometry all bodies gliding along the\ncycloid, my soapstone for example, will descend from any point in\nprecisely the same time.\n\nRemoving the fire-board from the front of the try-works, the bare\nmasonry of that side is exposed, penetrated by the two iron mouths of\nthe furnaces, directly underneath the pots.  These mouths are fitted\nwith heavy doors of iron.  The intense heat of the fire is prevented\nfrom communicating itself to the deck, by means of a shallow\nreservoir extending under the entire inclosed surface of the works.\nBy a tunnel inserted at the rear, this reservoir is kept replenished\nwith water as fast as it evaporates.  There are no external chimneys;\nthey open direct from the rear wall.  And here let us go back for a\nmoment.\n\nIt was about nine o'clock at night that the Pequod's try-works were\nfirst started on this present voyage.  It belonged to Stubb to\noversee the business.\n\n\"All ready there?  Off hatch, then, and start her.  You cook, fire\nthe works.\"  This was an easy thing, for the carpenter had been\nthrusting his shavings into the furnace throughout the passage.  Here\nbe it said that in a whaling voyage the first fire in the try-works has\nto be fed for a time with wood.  After that no wood is used, except\nas a means of quick ignition to the staple fuel.  In a word, after\nbeing tried out, the crisp, shrivelled blubber, now called scraps or\nfritters, still contains considerable of its unctuous properties.\nThese fritters feed the flames.  Like a plethoric burning martyr, or\na self-consuming misanthrope, once ignited, the whale supplies his\nown fuel and burns by his own body.  Would that he consumed his own\nsmoke! for his smoke is horrible to inhale, and inhale it you must,\nand not only that, but you must live in it for the time.  It has an\nunspeakable, wild, Hindoo odor about it, such as may lurk in the\nvicinity of funereal pyres.  It smells like the left wing of the day\nof judgment; it is an argument for the pit.\n\nBy midnight the works were in full operation.  We were clear from the\ncarcase; sail had been made; the wind was freshening; the wild ocean\ndarkness was intense.  But that darkness was licked up by the fierce\nflames, which at intervals forked forth from the sooty flues, and\nilluminated every lofty rope in the rigging, as with the famed Greek\nfire.  The burning ship drove on, as if remorselessly commissioned to\nsome vengeful deed.  So the pitch and sulphur-freighted brigs of the\nbold Hydriote, Canaris, issuing from their midnight harbors, with\nbroad sheets of flame for sails, bore down upon the Turkish frigates,\nand folded them in conflagrations.\n\nThe hatch, removed from the top of the works, now afforded a wide\nhearth in front of them.  Standing on this were the Tartarean shapes\nof the pagan harpooneers, always the whale-ship's stokers.  With huge\npronged poles they pitched hissing masses of blubber into the\nscalding pots, or stirred up the fires beneath, till the snaky flames\ndarted, curling, out of the doors to catch them by the feet.  The\nsmoke rolled away in sullen heaps.  To every pitch of the ship there\nwas a pitch of the boiling oil, which seemed all eagerness to leap\ninto their faces.  Opposite the mouth of the works, on the further\nside of the wide wooden hearth, was the windlass.  This served for a\nsea-sofa.  Here lounged the watch, when not otherwise employed,\nlooking into the red heat of the fire, till their eyes felt scorched\nin their heads.  Their tawny features, now all begrimed with smoke\nand sweat, their matted beards, and the contrasting barbaric\nbrilliancy of their teeth, all these were strangely revealed in the\ncapricious emblazonings of the works.  As they narrated to each other\ntheir unholy adventures, their tales of terror told in words of\nmirth; as their uncivilized laughter forked upwards out of them, like\nthe flames from the furnace; as to and fro, in their front, the\nharpooneers wildly gesticulated with their huge pronged forks and\ndippers; as the wind howled on, and the sea leaped, and the ship\ngroaned and dived, and yet steadfastly shot her red hell further and\nfurther into the blackness of the sea and the night, and scornfully\nchamped the white bone in her mouth, and viciously spat round her on\nall sides; then the rushing Pequod, freighted with savages, and laden\nwith fire, and burning a corpse, and plunging into that blackness of\ndarkness, seemed the material counterpart of her monomaniac\ncommander's soul.\n\nSo seemed it to me, as I stood at her helm, and for long hours\nsilently guided the way of this fire-ship on the sea.  Wrapped, for\nthat interval, in darkness myself, I but the better saw the redness,\nthe madness, the ghastliness of others.  The continual sight of the\nfiend shapes before me, capering half in smoke and half in fire,\nthese at last begat kindred visions in my soul, so soon as I began to\nyield to that unaccountable drowsiness which ever would come over me\nat a midnight helm.\n\nBut that night, in particular, a strange (and ever since\ninexplicable) thing occurred to me.  Starting from a brief standing\nsleep, I was horribly conscious of something fatally wrong.  The\njaw-bone tiller smote my side, which leaned against it; in my ears\nwas the low hum of sails, just beginning to shake in the wind; I\nthought my eyes were open; I was half conscious of putting my fingers\nto the lids and mechanically stretching them still further apart.\nBut, spite of all this, I could see no compass before me to steer by;\nthough it seemed but a minute since I had been watching the card, by\nthe steady binnacle lamp illuminating it.  Nothing seemed before me\nbut a jet gloom, now and then made ghastly by flashes of redness.\nUppermost was the impression, that whatever swift, rushing thing I\nstood on was not so much bound to any haven ahead as rushing from all\nhavens astern.  A stark, bewildered feeling, as of death, came over\nme.  Convulsively my hands grasped the tiller, but with the crazy\nconceit that the tiller was, somehow, in some enchanted way,\ninverted.  My God! what is the matter with me? thought I.  Lo! in my\nbrief sleep I had turned myself about, and was fronting the ship's\nstern, with my back to her prow and the compass.  In an instant I\nfaced back, just in time to prevent the vessel from flying up into\nthe wind, and very probably capsizing her.  How glad and how grateful\nthe relief from this unnatural hallucination of the night, and the\nfatal contingency of being brought by the lee!\n\nLook not too long in the face of the fire, O man!  Never dream with\nthy hand on the helm!  Turn not thy back to the compass; accept the\nfirst hint of the hitching tiller; believe not the artificial fire,\nwhen its redness makes all things look ghastly.  To-morrow, in the\nnatural sun, the skies will be bright; those who glared like devils\nin the forking flames, the morn will show in far other, at least\ngentler, relief; the glorious, golden, glad sun, the only true\nlamp--all others but liars!\n\nNevertheless the sun hides not Virginia's Dismal Swamp, nor Rome's\naccursed Campagna, nor wide Sahara, nor all the millions of miles of\ndeserts and of griefs beneath the moon.  The sun hides not the ocean,\nwhich is the dark side of this earth, and which is two thirds of this\nearth.  So, therefore, that mortal man who hath more of joy than\nsorrow in him, that mortal man cannot be true--not true, or\nundeveloped.  With books the same.  The truest of all men was the Man\nof Sorrows, and the truest of all books is Solomon's, and\nEcclesiastes is the fine hammered steel of woe.  \"All is vanity.\"\nALL.  This wilful world hath not got hold of unchristian Solomon's\nwisdom yet.  But he who dodges hospitals and jails, and walks fast\ncrossing graveyards, and would rather talk of operas than hell;\ncalls Cowper, Young, Pascal, Rousseau, poor devils all of sick men;\nand throughout a care-free lifetime swears by Rabelais as passing\nwise, and therefore jolly;--not that man is fitted to sit down on\ntomb-stones, and break the green damp mould with unfathomably\nwondrous Solomon.\n\nBut even Solomon, he says, \"the man that wandereth out of the way of\nunderstanding shall remain\" (I.E., even while living) \"in the\ncongregation of the dead.\"  Give not thyself up, then, to fire, lest\nit invert thee, deaden thee; as for the time it did me.  There is a\nwisdom that is woe; but there is a woe that is madness.  And there is\na Catskill eagle in some souls that can alike dive down into the\nblackest gorges, and soar out of them again and become invisible in\nthe sunny spaces.  And even if he for ever flies within the gorge,\nthat gorge is in the mountains; so that even in his lowest swoop the\nmountain eagle is still higher than other birds upon the plain, even\nthough they soar.\n\n\n\nCHAPTER 97\n\nThe Lamp.\n\n\nHad you descended from the Pequod's try-works to the Pequod's\nforecastle, where the off duty watch were sleeping, for one single\nmoment you would have almost thought you were standing in some\nilluminated shrine of canonized kings and counsellors.  There they\nlay in their triangular oaken vaults, each mariner a chiselled\nmuteness; a score of lamps flashing upon his hooded eyes.\n\nIn merchantmen, oil for the sailor is more scarce than the milk of\nqueens.  To dress in the dark, and eat in the dark, and stumble in\ndarkness to his pallet, this is his usual lot.  But the whaleman, as\nhe seeks the food of light, so he lives in light.  He makes his berth\nan Aladdin's lamp, and lays him down in it; so that in the pitchiest\nnight the ship's black hull still houses an illumination.\n\nSee with what entire freedom the whaleman takes his handful of\nlamps--often but old bottles and vials, though--to the copper cooler\nat the try-works, and replenishes them there, as mugs of ale at a\nvat.  He burns, too, the purest of oil, in its unmanufactured, and,\ntherefore, unvitiated state; a fluid unknown to solar, lunar, or\nastral contrivances ashore.  It is sweet as early grass butter in\nApril.  He goes and hunts for his oil, so as to be sure of its\nfreshness and genuineness, even as the traveller on the prairie hunts\nup his own supper of game.\n\n\n\nCHAPTER 98\n\nStowing Down and Clearing Up.\n\n\nAlready has it been related how the great leviathan is afar off\ndescried from the mast-head; how he is chased over the watery moors,\nand slaughtered in the valleys of the deep; how he is then towed\nalongside and beheaded; and how (on the principle which entitled the\nheadsman of old to the garments in which the beheaded was killed) his\ngreat padded surtout becomes the property of his executioner; how, in\ndue time, he is condemned to the pots, and, like Shadrach, Meshach,\nand Abednego, his spermaceti, oil, and bone pass unscathed through\nthe fire;--but now it remains to conclude the last chapter of this\npart of the description by rehearsing--singing, if I may--the\nromantic proceeding of decanting off his oil into the casks and\nstriking them down into the hold, where once again leviathan returns\nto his native profundities, sliding along beneath the surface as\nbefore; but, alas! never more to rise and blow.\n\nWhile still warm, the oil, like hot punch, is received into the\nsix-barrel casks; and while, perhaps, the ship is pitching and\nrolling this way and that in the midnight sea, the enormous casks are\nslewed round and headed over, end for end, and sometimes perilously\nscoot across the slippery deck, like so many land slides, till at\nlast man-handled and stayed in their course; and all round the hoops,\nrap, rap, go as many hammers as can play upon them, for now, EX\nOFFICIO, every sailor is a cooper.\n\nAt length, when the last pint is casked, and all is cool, then the\ngreat hatchways are unsealed, the bowels of the ship are thrown open,\nand down go the casks to their final rest in the sea.  This done, the\nhatches are replaced, and hermetically closed, like a closet walled\nup.\n\nIn the sperm fishery, this is perhaps one of the most remarkable\nincidents in all the business of whaling.  One day the planks stream\nwith freshets of blood and oil; on the sacred quarter-deck enormous\nmasses of the whale's head are profanely piled; great rusty casks lie\nabout, as in a brewery yard; the smoke from the try-works has\nbesooted all the bulwarks; the mariners go about suffused with\nunctuousness; the entire ship seems great leviathan himself; while on\nall hands the din is deafening.\n\nBut a day or two after, you look about you, and prick your ears in\nthis self-same ship; and were it not for the tell-tale boats and\ntry-works, you would all but swear you trod some silent merchant\nvessel, with a most scrupulously neat commander.  The unmanufactured\nsperm oil possesses a singularly cleansing virtue.  This is the\nreason why the decks never look so white as just after what they call\nan affair of oil.  Besides, from the ashes of the burned scraps of\nthe whale, a potent lye is readily made; and whenever any\nadhesiveness from the back of the whale remains clinging to the side,\nthat lye quickly exterminates it.  Hands go diligently along the\nbulwarks, and with buckets of water and rags restore them to their\nfull tidiness.  The soot is brushed from the lower rigging.  All the\nnumerous implements which have been in use are likewise faithfully\ncleansed and put away.  The great hatch is scrubbed and placed upon\nthe try-works, completely hiding the pots; every cask is out of\nsight; all tackles are coiled in unseen nooks; and when by the\ncombined and simultaneous industry of almost the entire ship's\ncompany, the whole of this conscientious duty is at last concluded,\nthen the crew themselves proceed to their own ablutions; shift\nthemselves from top to toe; and finally issue to the immaculate deck,\nfresh and all aglow, as bridegrooms new-leaped from out the daintiest\nHolland.\n\nNow, with elated step, they pace the planks in twos and threes, and\nhumorously discourse of parlors, sofas, carpets, and fine cambrics;\npropose to mat the deck; think of having hanging to the top; object\nnot to taking tea by moonlight on the piazza of the forecastle.  To\nhint to such musked mariners of oil, and bone, and blubber, were\nlittle short of audacity.  They know not the thing you distantly\nallude to.  Away, and bring us napkins!\n\nBut mark: aloft there, at the three mast heads, stand three men\nintent on spying out more whales, which, if caught, infallibly will\nagain soil the old oaken furniture, and drop at least one small\ngrease-spot somewhere.  Yes; and many is the time, when, after the\nseverest uninterrupted labors, which know no night; continuing\nstraight through for ninety-six hours; when from the boat, where they\nhave swelled their wrists with all day rowing on the Line,--they only\nstep to the deck to carry vast chains, and heave the heavy windlass,\nand cut and slash, yea, and in their very sweatings to be smoked and\nburned anew by the combined fires of the equatorial sun and the\nequatorial try-works; when, on the heel of all this, they have\nfinally bestirred themselves to cleanse the ship, and make a spotless\ndairy room of it; many is the time the poor fellows, just buttoning\nthe necks of their clean frocks, are startled by the cry of \"There\nshe blows!\" and away they fly to fight another whale, and go through\nthe whole weary thing again.  Oh! my friends, but this is\nman-killing!  Yet this is life.  For hardly have we mortals by long\ntoilings extracted from this world's vast bulk its small but\nvaluable sperm; and then, with weary patience, cleansed ourselves\nfrom its defilements, and learned to live here in clean tabernacles\nof the soul; hardly is this done, when--THERE SHE BLOWS!--the ghost\nis spouted up, and away we sail to fight some other world, and go\nthrough young life's old routine again.\n\nOh! the metempsychosis!  Oh!  Pythagoras, that in bright Greece, two\nthousand years ago, did die, so good, so wise, so mild; I sailed with\nthee along the Peruvian coast last voyage--and, foolish as I am,\ntaught thee, a green simple boy, how to splice a rope!\n\n\n\nCHAPTER 99\n\nThe Doubloon.\n\n\nEre now it has been related how Ahab was wont to pace his\nquarter-deck, taking regular turns at either limit, the binnacle and\nmainmast; but in the multiplicity of other things requiring narration\nit has not been added how that sometimes in these walks, when most\nplunged in his mood, he was wont to pause in turn at each spot, and\nstand there strangely eyeing the particular object before him.  When\nhe halted before the binnacle, with his glance fastened on the\npointed needle in the compass, that glance shot like a javelin with\nthe pointed intensity of his purpose; and when resuming his walk he\nagain paused before the mainmast, then, as the same riveted glance\nfastened upon the riveted gold coin there, he still wore the same\naspect of nailed firmness, only dashed with a certain wild longing,\nif not hopefulness.\n\nBut one morning, turning to pass the doubloon, he seemed to be newly\nattracted by the strange figures and inscriptions stamped on it, as\nthough now for the first time beginning to interpret for himself in\nsome monomaniac way whatever significance might lurk in them.  And\nsome certain significance lurks in all things, else all things are\nlittle worth, and the round world itself but an empty cipher, except\nto sell by the cartload, as they do hills about Boston, to fill up\nsome morass in the Milky Way.\n\nNow this doubloon was of purest, virgin gold, raked somewhere out of\nthe heart of gorgeous hills, whence, east and west, over golden\nsands, the head-waters of many a Pactolus flows.  And though now\nnailed amidst all the rustiness of iron bolts and the verdigris of\ncopper spikes, yet, untouchable and immaculate to any foulness, it\nstill preserved its Quito glow.  Nor, though placed amongst a\nruthless crew and every hour passed by ruthless hands, and through\nthe livelong nights shrouded with thick darkness which might cover\nany pilfering approach, nevertheless every sunrise found the doubloon\nwhere the sunset left it last.  For it was set apart and sanctified\nto one awe-striking end; and however wanton in their sailor ways, one\nand all, the mariners revered it as the white whale's talisman.\nSometimes they talked it over in the weary watch by night, wondering\nwhose it was to be at last, and whether he would ever live to spend\nit.\n\nNow those noble golden coins of South America are as medals of the\nsun and tropic token-pieces.  Here palms, alpacas, and volcanoes;\nsun's disks and stars; ecliptics, horns-of-plenty, and rich banners\nwaving, are in luxuriant profusion stamped; so that the precious gold\nseems almost to derive an added preciousness and enhancing glories,\nby passing through those fancy mints, so Spanishly poetic.\n\nIt so chanced that the doubloon of the Pequod was a most wealthy\nexample of these things.  On its round border it bore the letters,\nREPUBLICA DEL ECUADOR: QUITO.  So this bright coin came from a\ncountry planted in the middle of the world, and beneath the great\nequator, and named after it; and it had been cast midway up the\nAndes, in the unwaning clime that knows no autumn.  Zoned by those\nletters you saw the likeness of three Andes' summits; from one a\nflame; a tower on another; on the third a crowing cock; while arching\nover all was a segment of the partitioned zodiac, the signs all\nmarked with their usual cabalistics, and the keystone sun entering\nthe equinoctial point at Libra.\n\nBefore this equatorial coin, Ahab, not unobserved by others, was now\npausing.\n\n\"There's something ever egotistical in mountain-tops and towers, and\nall other grand and lofty things; look here,--three peaks as proud as\nLucifer.  The firm tower, that is Ahab; the volcano, that is Ahab;\nthe courageous, the undaunted, and victorious fowl, that, too, is\nAhab; all are Ahab; and this round gold is but the image of the\nrounder globe, which, like a magician's glass, to each and every man\nin turn but mirrors back his own mysterious self.  Great pains, small\ngains for those who ask the world to solve them; it cannot solve\nitself.  Methinks now this coined sun wears a ruddy face; but see!\naye, he enters the sign of storms, the equinox! and but six months\nbefore he wheeled out of a former equinox at Aries!  From storm to\nstorm!  So be it, then.  Born in throes, 't is fit that man should\nlive in pains and die in pangs!  So be it, then!  Here's stout stuff\nfor woe to work on.  So be it, then.\"\n\n\"No fairy fingers can have pressed the gold, but devil's claws must have\nleft their mouldings there since yesterday,\" murmured Starbuck to\nhimself, leaning against the bulwarks.  \"The old man seems to read\nBelshazzar's awful writing.  I have never marked the coin\ninspectingly.  He goes below; let me read.  A dark valley between\nthree mighty, heaven-abiding peaks, that almost seem the Trinity, in\nsome faint earthly symbol.  So in this vale of Death, God girds us\nround; and over all our gloom, the sun of Righteousness still shines\na beacon and a hope.  If we bend down our eyes, the dark vale shows\nher mouldy soil; but if we lift them, the bright sun meets our glance\nhalf way, to cheer.  Yet, oh, the great sun is no fixture; and if, at\nmidnight, we would fain snatch some sweet solace from him, we gaze\nfor him in vain!  This coin speaks wisely, mildly, truly, but still\nsadly to me.  I will quit it, lest Truth shake me falsely.\"\n\n\"There now's the old Mogul,\" soliloquized Stubb by the try-works,\n\"he's been twigging it; and there goes Starbuck from the same, and\nboth with faces which I should say might be somewhere within nine\nfathoms long.  And all from looking at a piece of gold, which did I\nhave it now on Negro Hill or in Corlaer's Hook, I'd not look at it\nvery long ere spending it.  Humph! in my poor, insignificant opinion,\nI regard this as queer.  I have seen doubloons before now in my\nvoyagings; your doubloons of old Spain, your doubloons of Peru, your\ndoubloons of Chili, your doubloons of Bolivia, your doubloons of\nPopayan; with plenty of gold moidores and pistoles, and joes, and\nhalf joes, and quarter joes.  What then should there be in this\ndoubloon of the Equator that is so killing wonderful?  By Golconda!\nlet me read it once.  Halloa! here's signs and wonders truly!  That,\nnow, is what old Bowditch in his Epitome calls the zodiac, and what\nmy almanac below calls ditto.  I'll get the almanac and as I have\nheard devils can be raised with Daboll's arithmetic, I'll try my hand\nat raising a meaning out of these queer curvicues here with the\nMassachusetts calendar.  Here's the book.  Let's see now.  Signs and\nwonders; and the sun, he's always among 'em.  Hem, hem, hem; here\nthey are--here they go--all alive:--Aries, or the Ram; Taurus, or the\nBull and Jimimi! here's Gemini himself, or the Twins.  Well; the sun\nhe wheels among 'em.  Aye, here on the coin he's just crossing the\nthreshold between two of twelve sitting-rooms all in a ring.  Book!\nyou lie there; the fact is, you books must know your places.  You'll\ndo to give us the bare words and facts, but we come in to supply the\nthoughts.  That's my small experience, so far as the Massachusetts\ncalendar, and Bowditch's navigator, and Daboll's arithmetic go.\nSigns and wonders, eh?  Pity if there is nothing wonderful in signs,\nand significant in wonders!  There's a clue somewhere; wait a bit;\nhist--hark!  By Jove, I have it!  Look you, Doubloon, your zodiac\nhere is the life of man in one round chapter; and now I'll read it\noff, straight out of the book.  Come, Almanack!  To begin: there's\nAries, or the Ram--lecherous dog, he begets us; then, Taurus, or the\nBull--he bumps us the first thing; then Gemini, or the Twins--that\nis, Virtue and Vice; we try to reach Virtue, when lo! comes Cancer\nthe Crab, and drags us back; and here, going from Virtue, Leo, a\nroaring Lion, lies in the path--he gives a few fierce bites and surly\ndabs with his paw; we escape, and hail Virgo, the Virgin! that's our\nfirst love; we marry and think to be happy for aye, when pop comes\nLibra, or the Scales--happiness weighed and found wanting; and while\nwe are very sad about that, Lord! how we suddenly jump, as Scorpio,\nor the Scorpion, stings us in the rear; we are curing the wound, when\nwhang come the arrows all round; Sagittarius, or the Archer, is\namusing himself.  As we pluck out the shafts, stand aside! here's\nthe battering-ram, Capricornus, or the Goat; full tilt, he comes\nrushing, and headlong we are tossed; when Aquarius, or the\nWater-bearer, pours out his whole deluge and drowns us; and to wind\nup with Pisces, or the Fishes, we sleep.  There's a sermon now, writ\nin high heaven, and the sun goes through it every year, and yet comes\nout of it all alive and hearty.  Jollily he, aloft there, wheels\nthrough toil and trouble; and so, alow here, does jolly Stubb.  Oh,\njolly's the word for aye!  Adieu, Doubloon!  But stop; here comes\nlittle King-Post; dodge round the try-works, now, and let's hear what\nhe'll have to say.  There; he's before it; he'll out with something\npresently.  So, so; he's beginning.\"\n\n\"I see nothing here, but a round thing made of gold, and whoever\nraises a certain whale, this round thing belongs to him.  So, what's\nall this staring been about?  It is worth sixteen dollars, that's\ntrue; and at two cents the cigar, that's nine hundred and sixty\ncigars.  I won't smoke dirty pipes like Stubb, but I like cigars, and\nhere's nine hundred and sixty of them; so here goes Flask aloft to\nspy 'em out.\"\n\n\"Shall I call that wise or foolish, now; if it be really wise it has\na foolish look to it; yet, if it be really foolish, then has it a\nsort of wiseish look to it.  But, avast; here comes our old\nManxman--the old hearse-driver, he must have been, that is, before he\ntook to the sea.  He luffs up before the doubloon; halloa, and goes\nround on the other side of the mast; why, there's a horse-shoe nailed\non that side; and now he's back again; what does that mean?  Hark!\nhe's muttering--voice like an old worn-out coffee-mill.  Prick ears,\nand listen!\"\n\n\"If the White Whale be raised, it must be in a month and a day, when\nthe sun stands in some one of these signs.  I've studied signs, and\nknow their marks; they were taught me two score years ago, by the old\nwitch in Copenhagen.  Now, in what sign will the sun then be?  The\nhorse-shoe sign; for there it is, right opposite the gold.  And\nwhat's the horse-shoe sign?  The lion is the horse-shoe sign--the\nroaring and devouring lion.  Ship, old ship! my old head shakes to\nthink of thee.\"\n\n\"There's another rendering now; but still one text.  All sorts of men\nin one kind of world, you see.  Dodge again! here comes Queequeg--all\ntattooing--looks like the signs of the Zodiac himself.  What says the\nCannibal?  As I live he's comparing notes; looking at his thigh bone;\nthinks the sun is in the thigh, or in the calf, or in the bowels, I\nsuppose, as the old women talk Surgeon's Astronomy in the back\ncountry.  And by Jove, he's found something there in the vicinity of\nhis thigh--I guess it's Sagittarius, or the Archer.  No: he don't\nknow what to make of the doubloon; he takes it for an old button off\nsome king's trowsers.  But, aside again! here comes that ghost-devil,\nFedallah; tail coiled out of sight as usual, oakum in the toes of his\npumps as usual.  What does he say, with that look of his?  Ah, only\nmakes a sign to the sign and bows himself; there is a sun on the\ncoin--fire worshipper, depend upon it.  Ho! more and more.  This way\ncomes Pip--poor boy! would he had died, or I; he's half horrible to\nme.  He too has been watching all of these interpreters--myself\nincluded--and look now, he comes to read, with that unearthly idiot\nface.  Stand away again and hear him.  Hark!\"\n\n\"I look, you look, he looks; we look, ye look, they look.\"\n\n\"Upon my soul, he's been studying Murray's Grammar!  Improving his\nmind, poor fellow!  But what's that he says now--hist!\"\n\n\"I look, you look, he looks; we look, ye look, they look.\"\n\n\"Why, he's getting it by heart--hist! again.\"\n\n\"I look, you look, he looks; we look, ye look, they look.\"\n\n\"Well, that's funny.\"\n\n\"And I, you, and he; and we, ye, and they, are all bats; and I'm a\ncrow, especially when I stand a'top of this pine tree here.  Caw!\ncaw! caw! caw! caw! caw!  Ain't I a crow?  And where's the\nscare-crow?  There he stands; two bones stuck into a pair of old\ntrowsers, and two more poked into the sleeves of an old jacket.\"\n\n\"Wonder if he means me?--complimentary!--poor lad!--I could go hang\nmyself.  Any way, for the present, I'll quit Pip's vicinity.  I can\nstand the rest, for they have plain wits; but he's too crazy-witty\nfor my sanity.  So, so, I leave him muttering.\"\n\n\"Here's the ship's navel, this doubloon here, and they are all on\nfire to unscrew it.  But, unscrew your navel, and what's the\nconsequence?  Then again, if it stays here, that is ugly, too, for\nwhen aught's nailed to the mast it's a sign that things grow\ndesperate.  Ha, ha! old Ahab! the White Whale; he'll nail ye!  This\nis a pine tree.  My father, in old Tolland county, cut down a pine\ntree once, and found a silver ring grown over in it; some old\ndarkey's wedding ring.  How did it get there?  And so they'll say in\nthe resurrection, when they come to fish up this old mast, and find a\ndoubloon lodged in it, with bedded oysters for the shaggy bark.  Oh,\nthe gold! the precious, precious, gold! the green miser'll hoard ye\nsoon!  Hish! hish!  God goes 'mong the worlds blackberrying.  Cook!\nho, cook! and cook us!  Jenny! hey, hey, hey, hey, hey, Jenny, Jenny!\nand get your hoe-cake done!\"\n\n\n\nCHAPTER 100\n\nLeg and Arm.\n\nThe Pequod, of Nantucket, Meets the Samuel Enderby, of London.\n\n\n\"Ship, ahoy!  Hast seen the White Whale?\"\n\nSo cried Ahab, once more hailing a ship showing English colours,\nbearing down under the stern.  Trumpet to mouth, the old man was\nstanding in his hoisted quarter-boat, his ivory leg plainly revealed\nto the stranger captain, who was carelessly reclining in his own\nboat's bow.  He was a darkly-tanned, burly, good-natured,\nfine-looking man, of sixty or thereabouts, dressed in a spacious\nroundabout, that hung round him in festoons of blue pilot-cloth; and\none empty arm of this jacket streamed behind him like the broidered\narm of a hussar's surcoat.\n\n\"Hast seen the White Whale!\"\n\n\"See you this?\" and withdrawing it from the folds that had hidden\nit, he held up a white arm of sperm whale bone, terminating in a\nwooden head like a mallet.\n\n\"Man my boat!\" cried Ahab, impetuously, and tossing about the oars\nnear him--\"Stand by to lower!\"\n\nIn less than a minute, without quitting his little craft, he and his\ncrew were dropped to the water, and were soon alongside of the\nstranger.  But here a curious difficulty presented itself.  In the\nexcitement of the moment, Ahab had forgotten that since the loss of\nhis leg he had never once stepped on board of any vessel at sea but\nhis own, and then it was always by an ingenious and very handy\nmechanical contrivance peculiar to the Pequod, and a thing not to be\nrigged and shipped in any other vessel at a moment's warning.  Now,\nit is no very easy matter for anybody--except those who are almost\nhourly used to it, like whalemen--to clamber up a ship's side from a\nboat on the open sea; for the great swells now lift the boat high up\ntowards the bulwarks, and then instantaneously drop it half way down\nto the kelson.  So, deprived of one leg, and the strange ship of\ncourse being altogether unsupplied with the kindly invention, Ahab\nnow found himself abjectly reduced to a clumsy landsman again;\nhopelessly eyeing the uncertain changeful height he could hardly hope\nto attain.\n\nIt has before been hinted, perhaps, that every little untoward\ncircumstance that befell him, and which indirectly sprang from his\nluckless mishap, almost invariably irritated or exasperated Ahab.\nAnd in the present instance, all this was heightened by the sight of\nthe two officers of the strange ship, leaning over the side, by the\nperpendicular ladder of nailed cleets there, and swinging towards him\na pair of tastefully-ornamented man-ropes; for at first they did not\nseem to bethink them that a one-legged man must be too much of a\ncripple to use their sea bannisters.  But this awkwardness only\nlasted a minute, because the strange captain, observing at a glance\nhow affairs stood, cried out, \"I see, I see!--avast heaving there!\nJump, boys, and swing over the cutting-tackle.\"\n\nAs good luck would have it, they had had a whale alongside a day or\ntwo previous, and the great tackles were still aloft, and the massive\ncurved blubber-hook, now clean and dry, was still attached to the\nend.  This was quickly lowered to Ahab, who at once comprehending it\nall, slid his solitary thigh into the curve of the hook (it was like\nsitting in the fluke of an anchor, or the crotch of an apple tree),\nand then giving the word, held himself fast, and at the same time\nalso helped to hoist his own weight, by pulling hand-over-hand upon\none of the running parts of the tackle.  Soon he was carefully swung\ninside the high bulwarks, and gently landed upon the capstan head.\nWith his ivory arm frankly thrust forth in welcome, the other captain\nadvanced, and Ahab, putting out his ivory leg, and crossing the ivory\narm (like two sword-fish blades) cried out in his walrus way, \"Aye,\naye, hearty! let us shake bones together!--an arm and a leg!--an arm\nthat never can shrink, d'ye see; and a leg that never can run.  Where\ndid'st thou see the White Whale?--how long ago?\"\n\n\"The White Whale,\" said the Englishman, pointing his ivory arm\ntowards the East, and taking a rueful sight along it, as if it had\nbeen a telescope; \"there I saw him, on the Line, last season.\"\n\n\"And he took that arm off, did he?\" asked Ahab, now sliding down from\nthe capstan, and resting on the Englishman's shoulder, as he did so.\n\n\"Aye, he was the cause of it, at least; and that leg, too?\"\n\n\"Spin me the yarn,\" said Ahab; \"how was it?\"\n\n\"It was the first time in my life that I ever cruised on the Line,\"\nbegan the Englishman.  \"I was ignorant of the White Whale at that\ntime.  Well, one day we lowered for a pod of four or five whales, and\nmy boat fastened to one of them; a regular circus horse he was, too,\nthat went milling and milling round so, that my boat's crew could\nonly trim dish, by sitting all their sterns on the outer gunwale.\nPresently up breaches from the bottom of the sea a bouncing great\nwhale, with a milky-white head and hump, all crows' feet and\nwrinkles.\"\n\n\"It was he, it was he!\" cried Ahab, suddenly letting out his\nsuspended breath.\n\n\"And harpoons sticking in near his starboard fin.\"\n\n\"Aye, aye--they were mine--MY irons,\" cried Ahab, exultingly--\"but\non!\"\n\n\"Give me a chance, then,\" said the Englishman, good-humoredly.\n\"Well, this old great-grandfather, with the white head and hump, runs\nall afoam into the pod, and goes to snapping furiously at my\nfast-line!\n\n\"Aye, I see!--wanted to part it; free the fast-fish--an old trick--I\nknow him.\"\n\n\"How it was exactly,\" continued the one-armed commander, \"I do not\nknow; but in biting the line, it got foul of his teeth, caught there\nsomehow; but we didn't know it then; so that when we afterwards\npulled on the line, bounce we came plump on to his hump! instead of\nthe other whale's; that went off to windward, all fluking.  Seeing\nhow matters stood, and what a noble great whale it was--the noblest\nand biggest I ever saw, sir, in my life--I resolved to capture him,\nspite of the boiling rage he seemed to be in.  And thinking the\nhap-hazard line would get loose, or the tooth it was tangled to\nmight draw (for I have a devil of a boat's crew for a pull on a\nwhale-line); seeing all this, I say, I jumped into my first mate's\nboat--Mr. Mounttop's here (by the way, Captain--Mounttop;\nMounttop--the captain);--as I was saying, I jumped into Mounttop's\nboat, which, d'ye see, was gunwale and gunwale with mine, then; and\nsnatching the first harpoon, let this old great-grandfather have it.\nBut, Lord, look you, sir--hearts and souls alive, man--the next\ninstant, in a jiff, I was blind as a bat--both eyes out--all befogged\nand bedeadened with black foam--the whale's tail looming straight up\nout of it, perpendicular in the air, like a marble steeple.  No use\nsterning all, then; but as I was groping at midday, with a blinding\nsun, all crown-jewels; as I was groping, I say, after the second\niron, to toss it overboard--down comes the tail like a Lima tower,\ncutting my boat in two, leaving each half in splinters; and, flukes\nfirst, the white hump backed through the wreck, as though it was all\nchips.  We all struck out.  To escape his terrible flailings, I\nseized hold of my harpoon-pole sticking in him, and for a moment\nclung to that like a sucking fish.  But a combing sea dashed me off,\nand at the same instant, the fish, taking one good dart forwards,\nwent down like a flash; and the barb of that cursed second iron\ntowing along near me caught me here\" (clapping his hand just below\nhis shoulder); \"yes, caught me just here, I say, and bore me down to\nHell's flames, I was thinking; when, when, all of a sudden, thank the\ngood God, the barb ript its way along the flesh--clear along the\nwhole length of my arm--came out nigh my wrist, and up I\nfloated;--and that gentleman there will tell you the rest (by the\nway, captain--Dr. Bunger, ship's surgeon: Bunger, my lad,--the\ncaptain).  Now, Bunger boy, spin your part of the yarn.\"\n\nThe professional gentleman thus familiarly pointed out, had been all\nthe time standing near them, with nothing specific visible, to denote\nhis gentlemanly rank on board.  His face was an exceedingly round but\nsober one; he was dressed in a faded blue woollen frock or shirt, and\npatched trowsers; and had thus far been dividing his attention\nbetween a marlingspike he held in one hand, and a pill-box held in\nthe other, occasionally casting a critical glance at the ivory limbs\nof the two crippled captains.  But, at his superior's introduction of\nhim to Ahab, he politely bowed, and straightway went on to do his\ncaptain's bidding.\n\n\"It was a shocking bad wound,\" began the whale-surgeon; \"and, taking\nmy advice, Captain Boomer here, stood our old Sammy--\"\n\n\"Samuel Enderby is the name of my ship,\" interrupted the one-armed\ncaptain, addressing Ahab; \"go on, boy.\"\n\n\"Stood our old Sammy off to the northward, to get out of the blazing\nhot weather there on the Line.  But it was no use--I did all I could;\nsat up with him nights; was very severe with him in the matter of\ndiet--\"\n\n\"Oh, very severe!\" chimed in the patient himself; then suddenly\naltering his voice, \"Drinking hot rum toddies with me every night,\ntill he couldn't see to put on the bandages; and sending me to bed,\nhalf seas over, about three o'clock in the morning.  Oh, ye stars! he\nsat up with me indeed, and was very severe in my diet.  Oh! a great\nwatcher, and very dietetically severe, is Dr. Bunger. (Bunger, you\ndog, laugh out! why don't ye?  You know you're a precious jolly\nrascal.) But, heave ahead, boy, I'd rather be killed by you than kept\nalive by any other man.\"\n\n\"My captain, you must have ere this perceived, respected sir\"--said\nthe imperturbable godly-looking Bunger, slightly bowing to Ahab--\"is\napt to be facetious at times; he spins us many clever things of that\nsort.  But I may as well say--en passant, as the French remark--that\nI myself--that is to say, Jack Bunger, late of the reverend\nclergy--am a strict total abstinence man; I never drink--\"\n\n\"Water!\" cried the captain; \"he never drinks it; it's a sort of fits\nto him; fresh water throws him into the hydrophobia; but go on--go on\nwith the arm story.\"\n\n\"Yes, I may as well,\" said the surgeon, coolly.  \"I was about\nobserving, sir, before Captain Boomer's facetious interruption, that\nspite of my best and severest endeavors, the wound kept getting worse\nand worse; the truth was, sir, it was as ugly gaping wound as surgeon\never saw; more than two feet and several inches long.  I measured it\nwith the lead line.  In short, it grew black; I knew what was\nthreatened, and off it came.  But I had no hand in shipping that\nivory arm there; that thing is against all rule\"--pointing at it with\nthe marlingspike--\"that is the captain's work, not mine; he ordered\nthe carpenter to make it; he had that club-hammer there put to the\nend, to knock some one's brains out with, I suppose, as he tried mine\nonce.  He flies into diabolical passions sometimes.  Do ye see this\ndent, sir\"--removing his hat, and brushing aside his hair, and\nexposing a bowl-like cavity in his skull, but which bore not the\nslightest scarry trace, or any token of ever having been a\nwound--\"Well, the captain there will tell you how that came here;\nhe knows.\"\n\n\"No, I don't,\" said the captain, \"but his mother did; he was born\nwith it.  Oh, you solemn rogue, you--you Bunger! was there ever such\nanother Bunger in the watery world?  Bunger, when you die, you ought\nto die in pickle, you dog; you should be preserved to future ages,\nyou rascal.\"\n\n\"What became of the White Whale?\" now cried Ahab, who thus far had\nbeen impatiently listening to this by-play between the two\nEnglishmen.\n\n\"Oh!\" cried the one-armed captain, \"oh, yes!  Well; after he sounded,\nwe didn't see him again for some time; in fact, as I before hinted, I\ndidn't then know what whale it was that had served me such a trick,\ntill some time afterwards, when coming back to the Line, we heard\nabout Moby Dick--as some call him--and then I knew it was he.\"\n\n\"Did'st thou cross his wake again?\"\n\n\"Twice.\"\n\n\"But could not fasten?\"\n\n\"Didn't want to try to: ain't one limb enough?  What should I do\nwithout this other arm?  And I'm thinking Moby Dick doesn't bite so\nmuch as he swallows.\"\n\n\"Well, then,\" interrupted Bunger, \"give him your left arm for bait to\nget the right.  Do you know, gentlemen\"--very gravely and\nmathematically bowing to each Captain in succession--\"Do you know,\ngentlemen, that the digestive organs of the whale are so inscrutably\nconstructed by Divine Providence, that it is quite impossible for him\nto completely digest even a man's arm?  And he knows it too.  So that\nwhat you take for the White Whale's malice is only his awkwardness.\nFor he never means to swallow a single limb; he only thinks to\nterrify by feints.  But sometimes he is like the old juggling fellow,\nformerly a patient of mine in Ceylon, that making believe swallow\njack-knives, once upon a time let one drop into him in good earnest,\nand there it stayed for a twelvemonth or more; when I gave him an\nemetic, and he heaved it up in small tacks, d'ye see.  No possible\nway for him to digest that jack-knife, and fully incorporate it into\nhis general bodily system.  Yes, Captain Boomer, if you are quick\nenough about it, and have a mind to pawn one arm for the sake of the\nprivilege of giving decent burial to the other, why in that case\nthe arm is yours; only let the whale have another chance at you\nshortly, that's all.\"\n\n\"No, thank ye, Bunger,\" said the English Captain, \"he's welcome to\nthe arm he has, since I can't help it, and didn't know him then; but\nnot to another one.  No more White Whales for me; I've lowered for\nhim once, and that has satisfied me.  There would be great glory in\nkilling him, I know that; and there is a ship-load of precious sperm\nin him, but, hark ye, he's best let alone; don't you think so,\nCaptain?\"--glancing at the ivory leg.\n\n\"He is.  But he will still be hunted, for all that.  What is best let\nalone, that accursed thing is not always what least allures.  He's\nall a magnet!  How long since thou saw'st him last?  Which way\nheading?\"\n\n\"Bless my soul, and curse the foul fiend's,\" cried Bunger, stoopingly\nwalking round Ahab, and like a dog, strangely snuffing; \"this man's\nblood--bring the thermometer!--it's at the boiling point!--his pulse\nmakes these planks beat!--sir!\"--taking a lancet from his pocket, and\ndrawing near to Ahab's arm.\n\n\"Avast!\" roared Ahab, dashing him against the bulwarks--\"Man the\nboat!  Which way heading?\"\n\n\"Good God!\" cried the English Captain, to whom the question was put.\n\"What's the matter?  He was heading east, I think.--Is your Captain\ncrazy?\" whispering Fedallah.\n\nBut Fedallah, putting a finger on his lip, slid over the bulwarks to\ntake the boat's steering oar, and Ahab, swinging the cutting-tackle\ntowards him, commanded the ship's sailors to stand by to lower.\n\nIn a moment he was standing in the boat's stern, and the Manilla men\nwere springing to their oars.  In vain the English Captain hailed\nhim.  With back to the stranger ship, and face set like a flint to\nhis own, Ahab stood upright till alongside of the Pequod.\n\n\n\nCHAPTER 101\n\nThe Decanter.\n\n\nEre the English ship fades from sight, be it set down here, that she\nhailed from London, and was named after the late Samuel Enderby,\nmerchant of that city, the original of the famous whaling house of\nEnderby & Sons; a house which in my poor whaleman's opinion, comes\nnot far behind the united royal houses of the Tudors and Bourbons, in\npoint of real historical interest.  How long, prior to the year of\nour Lord 1775, this great whaling house was in existence, my numerous\nfish-documents do not make plain; but in that year (1775) it fitted\nout the first English ships that ever regularly hunted the Sperm\nWhale; though for some score of years previous (ever since 1726) our\nvaliant Coffins and Maceys of Nantucket and the Vineyard had in large\nfleets pursued that Leviathan, but only in the North and South\nAtlantic: not elsewhere.  Be it distinctly recorded here, that the\nNantucketers were the first among mankind to harpoon with civilized\nsteel the great Sperm Whale; and that for half a century they were\nthe only people of the whole globe who so harpooned him.\n\nIn 1778, a fine ship, the Amelia, fitted out for the express purpose,\nand at the sole charge of the vigorous Enderbys, boldly rounded Cape\nHorn, and was the first among the nations to lower a whale-boat of\nany sort in the great South Sea.  The voyage was a skilful and lucky\none; and returning to her berth with her hold full of the precious\nsperm, the Amelia's example was soon followed by other ships, English\nand American, and thus the vast Sperm Whale grounds of the Pacific\nwere thrown open.  But not content with this good deed, the\nindefatigable house again bestirred itself: Samuel and all his\nSons--how many, their mother only knows--and under their immediate\nauspices, and partly, I think, at their expense, the British\ngovernment was induced to send the sloop-of-war Rattler on a whaling\nvoyage of discovery into the South Sea.  Commanded by a naval\nPost-Captain, the Rattler made a rattling voyage of it, and did some\nservice; how much does not appear.  But this is not all.  In 1819,\nthe same house fitted out a discovery whale ship of their own, to go\non a tasting cruise to the remote waters of Japan.  That ship--well\ncalled the \"Syren\"--made a noble experimental cruise; and it was thus\nthat the great Japanese Whaling Ground first became generally known.\nThe Syren in this famous voyage was commanded by a Captain Coffin, a\nNantucketer.\n\nAll honour to the Enderbies, therefore, whose house, I think, exists\nto the present day; though doubtless the original Samuel must long\nago have slipped his cable for the great South Sea of the other\nworld.\n\nThe ship named after him was worthy of the honour, being a very fast\nsailer and a noble craft every way.  I boarded her once at midnight\nsomewhere off the Patagonian coast, and drank good flip down in the\nforecastle.  It was a fine gam we had, and they were all\ntrumps--every soul on board.  A short life to them, and a jolly\ndeath.  And that fine gam I had--long, very long after old Ahab\ntouched her planks with his ivory heel--it minds me of the noble,\nsolid, Saxon hospitality of that ship; and may my parson forget me,\nand the devil remember me, if I ever lose sight of it.  Flip?  Did I\nsay we had flip?  Yes, and we flipped it at the rate of ten gallons\nthe hour; and when the squall came (for it's squally off there by\nPatagonia), and all hands--visitors and all--were called to reef\ntopsails, we were so top-heavy that we had to swing each other aloft\nin bowlines; and we ignorantly furled the skirts of our jackets into\nthe sails, so that we hung there, reefed fast in the howling gale, a\nwarning example to all drunken tars.  However, the masts did not go\noverboard; and by and by we scrambled down, so sober, that we had to\npass the flip again, though the savage salt spray bursting down the\nforecastle scuttle, rather too much diluted and pickled it to my\ntaste.\n\nThe beef was fine--tough, but with body in it.  They said it was\nbull-beef; others, that it was dromedary beef; but I do not know, for\ncertain, how that was.  They had dumplings too; small, but\nsubstantial, symmetrically globular, and indestructible dumplings.  I\nfancied that you could feel them, and roll them about in you after\nthey were swallowed.  If you stooped over too far forward, you risked\ntheir pitching out of you like billiard-balls.  The bread--but that\ncouldn't be helped; besides, it was an anti-scorbutic; in short, the\nbread contained the only fresh fare they had.  But the forecastle was\nnot very light, and it was very easy to step over into a dark corner\nwhen you ate it.  But all in all, taking her from truck to helm,\nconsidering the dimensions of the cook's boilers, including his own\nlive parchment boilers; fore and aft, I say, the Samuel Enderby was a\njolly ship; of good fare and plenty; fine flip and strong; crack\nfellows all, and capital from boot heels to hat-band.\n\nBut why was it, think ye, that the Samuel Enderby, and some other\nEnglish whalers I know of--not all though--were such famous,\nhospitable ships; that passed round the beef, and the bread, and the\ncan, and the joke; and were not soon weary of eating, and drinking,\nand laughing?  I will tell you.  The abounding good cheer of these\nEnglish whalers is matter for historical research.  Nor have I been\nat all sparing of historical whale research, when it has seemed\nneeded.\n\nThe English were preceded in the whale fishery by the Hollanders,\nZealanders, and Danes; from whom they derived many terms still extant\nin the fishery; and what is yet more, their fat old fashions,\ntouching plenty to eat and drink.  For, as a general thing, the\nEnglish merchant-ship scrimps her crew; but not so the English\nwhaler.  Hence, in the English, this thing of whaling good cheer is\nnot normal and natural, but incidental and particular; and,\ntherefore, must have some special origin, which is here pointed out,\nand will be still further elucidated.\n\nDuring my researches in the Leviathanic histories, I stumbled upon an\nancient Dutch volume, which, by the musty whaling smell of it, I knew\nmust be about whalers.  The title was, \"Dan Coopman,\" wherefore I\nconcluded that this must be the invaluable memoirs of some Amsterdam\ncooper in the fishery, as every whale ship must carry its cooper.  I\nwas reinforced in this opinion by seeing that it was the production\nof one \"Fitz Swackhammer.\"  But my friend Dr. Snodhead, a very\nlearned man, professor of Low Dutch and High German in the college of\nSanta Claus and St. Pott's, to whom I handed the work for\ntranslation, giving him a box of sperm candles for his trouble--this\nsame Dr. Snodhead, so soon as he spied the book, assured me that \"Dan\nCoopman\" did not mean \"The Cooper,\" but \"The Merchant.\"  In short,\nthis ancient and learned Low Dutch book treated of the commerce of\nHolland; and, among other subjects, contained a very interesting\naccount of its whale fishery.  And in this chapter it was, headed,\n\"Smeer,\" or \"Fat,\" that I found a long detailed list of the outfits\nfor the larders and cellars of 180 sail of Dutch whalemen; from which\nlist, as translated by Dr. Snodhead, I transcribe the following:\n\n400,000 lbs. of beef.\n60,000 lbs. Friesland pork.\n150,000 lbs. of stock fish.\n550,000 lbs. of biscuit.\n72,000 lbs. of soft bread.\n2,800 firkins of butter.\n20,000 lbs. Texel & Leyden cheese.\n144,000 lbs. cheese (probably an inferior article).\n550 ankers of Geneva.\n10,800 barrels of beer.\n\nMost statistical tables are parchingly dry in the reading; not so in\nthe present case, however, where the reader is flooded with whole\npipes, barrels, quarts, and gills of good gin and good cheer.\n\nAt the time, I devoted three days to the studious digesting of all\nthis beer, beef, and bread, during which many profound thoughts were\nincidentally suggested to me, capable of a transcendental and\nPlatonic application; and, furthermore, I compiled supplementary\ntables of my own, touching the probable quantity of stock-fish, etc.,\nconsumed by every Low Dutch harpooneer in that ancient Greenland and\nSpitzbergen whale fishery.  In the first place, the amount of butter,\nand Texel and Leyden cheese consumed, seems amazing.  I impute it,\nthough, to their naturally unctuous natures, being rendered still\nmore unctuous by the nature of their vocation, and especially by\ntheir pursuing their game in those frigid Polar Seas, on the very\ncoasts of that Esquimaux country where the convivial natives pledge\neach other in bumpers of train oil.\n\nThe quantity of beer, too, is very large, 10,800 barrels.  Now,\nas those polar fisheries could only be prosecuted in the short summer\nof that climate, so that the whole cruise of one of these Dutch\nwhalemen, including the short voyage to and from the Spitzbergen sea,\ndid not much exceed three months, say, and reckoning 30 men to each\nof their fleet of 180 sail, we have 5,400 Low Dutch seamen in all;\ntherefore, I say, we have precisely two barrels of beer per man, for\na twelve weeks' allowance, exclusive of his fair proportion of that\n550 ankers of gin.  Now, whether these gin and beer harpooneers, so\nfuddled as one might fancy them to have been, were the right sort of\nmen to stand up in a boat's head, and take good aim at flying whales;\nthis would seem somewhat improbable.  Yet they did aim at them, and\nhit them too.  But this was very far North, be it remembered, where\nbeer agrees well with the constitution; upon the Equator, in our\nsouthern fishery, beer would be apt to make the harpooneer sleepy at\nthe mast-head and boozy in his boat; and grievous loss might ensue to\nNantucket and New Bedford.\n\nBut no more; enough has been said to show that the old Dutch whalers\nof two or three centuries ago were high livers; and that the English\nwhalers have not neglected so excellent an example.  For, say they,\nwhen cruising in an empty ship, if you can get nothing better out of\nthe world, get a good dinner out of it, at least.  And this empties\nthe decanter.\n\n\n\nCHAPTER 102\n\nA Bower in the Arsacides.\n\n\nHitherto, in descriptively treating of the Sperm Whale, I have\nchiefly dwelt upon the marvels of his outer aspect; or separately and\nin detail upon some few interior structural features.  But to a large\nand thorough sweeping comprehension of him, it behooves me now to\nunbutton him still further, and untagging the points of his hose,\nunbuckling his garters, and casting loose the hooks and the eyes of\nthe joints of his innermost bones, set him before you in his\nultimatum; that is to say, in his unconditional skeleton.\n\nBut how now, Ishmael?  How is it, that you, a mere oarsman in the\nfishery, pretend to know aught about the subterranean parts of the\nwhale?  Did erudite Stubb, mounted upon your capstan, deliver\nlectures on the anatomy of the Cetacea; and by help of the windlass,\nhold up a specimen rib for exhibition?  Explain thyself, Ishmael.\nCan you land a full-grown whale on your deck for examination, as a\ncook dishes a roast-pig?  Surely not.  A veritable witness have you\nhitherto been, Ishmael; but have a care how you seize the privilege\nof Jonah alone; the privilege of discoursing upon the joists and\nbeams; the rafters, ridge-pole, sleepers, and under-pinnings, making\nup the frame-work of leviathan; and belike of the tallow-vats,\ndairy-rooms, butteries, and cheeseries in his bowels.\n\nI confess, that since Jonah, few whalemen have penetrated very far\nbeneath the skin of the adult whale; nevertheless, I have been\nblessed with an opportunity to dissect him in miniature.  In a ship I\nbelonged to, a small cub Sperm Whale was once bodily hoisted to the\ndeck for his poke or bag, to make sheaths for the barbs of the\nharpoons, and for the heads of the lances.  Think you I let that\nchance go, without using my boat-hatchet and jack-knife, and breaking\nthe seal and reading all the contents of that young cub?\n\nAnd as for my exact knowledge of the bones of the leviathan in their\ngigantic, full grown development, for that rare knowledge I am\nindebted to my late royal friend Tranquo, king of Tranque, one of\nthe Arsacides.  For being at Tranque, years ago, when attached to the\ntrading-ship Dey of Algiers, I was invited to spend part of the\nArsacidean holidays with the lord of Tranque, at his retired palm\nvilla at Pupella; a sea-side glen not very far distant from what our\nsailors called Bamboo-Town, his capital.\n\nAmong many other fine qualities, my royal friend Tranquo, being\ngifted with a devout love for all matters of barbaric vertu, had\nbrought together in Pupella whatever rare things the more ingenious\nof his people could invent; chiefly carved woods of wonderful\ndevices, chiselled shells, inlaid spears, costly paddles, aromatic\ncanoes; and all these distributed among whatever natural wonders, the\nwonder-freighted, tribute-rendering waves had cast upon his shores.\n\nChief among these latter was a great Sperm Whale, which, after an\nunusually long raging gale, had been found dead and stranded, with\nhis head against a cocoa-nut tree, whose plumage-like, tufted\ndroopings seemed his verdant jet.  When the vast body had at last\nbeen stripped of its fathom-deep enfoldings, and the bones become\ndust dry in the sun, then the skeleton was carefully transported up\nthe Pupella glen, where a grand temple of lordly palms now sheltered\nit.\n\nThe ribs were hung with trophies; the vertebrae were carved with\nArsacidean annals, in strange hieroglyphics; in the skull, the\npriests kept up an unextinguished aromatic flame, so that the mystic\nhead again sent forth its vapoury spout; while, suspended from a\nbough, the terrific lower jaw vibrated over all the devotees, like\nthe hair-hung sword that so affrighted Damocles.\n\nIt was a wondrous sight.  The wood was green as mosses of the Icy\nGlen; the trees stood high and haughty, feeling their living sap; the\nindustrious earth beneath was as a weaver's loom, with a gorgeous\ncarpet on it, whereof the ground-vine tendrils formed the warp and\nwoof, and the living flowers the figures.  All the trees, with all\ntheir laden branches; all the shrubs, and ferns, and grasses; the\nmessage-carrying air; all these unceasingly were active.  Through the\nlacings of the leaves, the great sun seemed a flying shuttle weaving\nthe unwearied verdure.  Oh, busy weaver! unseen weaver!--pause!--one\nword!--whither flows the fabric? what palace may it deck? wherefore\nall these ceaseless toilings?  Speak, weaver!--stay thy hand!--but\none single word with thee!  Nay--the shuttle flies--the figures float\nfrom forth the loom; the freshet-rushing carpet for ever slides\naway.  The weaver-god, he weaves; and by that weaving is he deafened,\nthat he hears no mortal voice; and by that humming, we, too, who look\non the loom are deafened; and only when we escape it shall we hear\nthe thousand voices that speak through it.  For even so it is in all\nmaterial factories.  The spoken words that are inaudible among the\nflying spindles; those same words are plainly heard without the\nwalls, bursting from the opened casements.  Thereby have villainies\nbeen detected.  Ah, mortal! then, be heedful; for so, in all this din\nof the great world's loom, thy subtlest thinkings may be overheard\nafar.\n\nNow, amid the green, life-restless loom of that Arsacidean wood, the\ngreat, white, worshipped skeleton lay lounging--a gigantic idler!\nYet, as the ever-woven verdant warp and woof intermixed and hummed\naround him, the mighty idler seemed the cunning weaver; himself all\nwoven over with the vines; every month assuming greener, fresher\nverdure; but himself a skeleton.  Life folded Death; Death trellised\nLife; the grim god wived with youthful Life, and begat him\ncurly-headed glories.\n\nNow, when with royal Tranquo I visited this wondrous whale, and saw\nthe skull an altar, and the artificial smoke ascending from where the\nreal jet had issued, I marvelled that the king should regard a chapel\nas an object of vertu.  He laughed.  But more I marvelled that the\npriests should swear that smoky jet of his was genuine.  To and fro I\npaced before this skeleton--brushed the vines aside--broke through\nthe ribs--and with a ball of Arsacidean twine, wandered, eddied long\namid its many winding, shaded colonnades and arbours.  But soon my\nline was out; and following it back, I emerged from the opening where I\nentered.  I saw no living thing within; naught was there but bones.\n\nCutting me a green measuring-rod, I once more dived within the\nskeleton.  From their arrow-slit in the skull, the priests perceived\nme taking the altitude of the final rib, \"How now!\" they shouted;\n\"Dar'st thou measure this our god!  That's for us.\"  \"Aye,\npriests--well, how long do ye make him, then?\"  But hereupon a fierce\ncontest rose among them, concerning feet and inches; they cracked\neach other's sconces with their yard-sticks--the great skull\nechoed--and seizing that lucky chance, I quickly concluded my own\nadmeasurements.\n\nThese admeasurements I now propose to set before you.  But first, be\nit recorded, that, in this matter, I am not free to utter any fancied\nmeasurement I please.  Because there are skeleton authorities you\ncan refer to, to test my accuracy.  There is a Leviathanic Museum,\nthey tell me, in Hull, England, one of the whaling ports of that\ncountry, where they have some fine specimens of fin-backs and other\nwhales.  Likewise, I have heard that in the museum of Manchester, in\nNew Hampshire, they have what the proprietors call \"the only perfect\nspecimen of a Greenland or River Whale in the United States.\"\nMoreover, at a place in Yorkshire, England, Burton Constable by name,\na certain Sir Clifford Constable has in his possession the skeleton\nof a Sperm Whale, but of moderate size, by no means of the full-grown\nmagnitude of my friend King Tranquo's.\n\nIn both cases, the stranded whales to which these two skeletons\nbelonged, were originally claimed by their proprietors upon similar\ngrounds.  King Tranquo seizing his because he wanted it; and Sir\nClifford, because he was lord of the seignories of those parts.  Sir\nClifford's whale has been articulated throughout; so that, like a\ngreat chest of drawers, you can open and shut him, in all his bony\ncavities--spread out his ribs like a gigantic fan--and swing all day\nupon his lower jaw.  Locks are to be put upon some of his trap-doors\nand shutters; and a footman will show round future visitors with a\nbunch of keys at his side.  Sir Clifford thinks of charging twopence\nfor a peep at the whispering gallery in the spinal column; threepence\nto hear the echo in the hollow of his cerebellum; and sixpence for\nthe unrivalled view from his forehead.\n\nThe skeleton dimensions I shall now proceed to set down are copied\nverbatim from my right arm, where I had them tattooed; as in my wild\nwanderings at that period, there was no other secure way of\npreserving such valuable statistics.  But as I was crowded for space,\nand wished the other parts of my body to remain a blank page for a\npoem I was then composing--at least, what untattooed parts might\nremain--I did not trouble myself with the odd inches; nor, indeed,\nshould inches at all enter into a congenial admeasurement of the\nwhale.\n\n\n\nCHAPTER 103\n\nMeasurement of The Whale's Skeleton.\n\n\nIn the first place, I wish to lay before you a particular, plain\nstatement, touching the living bulk of this leviathan, whose skeleton\nwe are briefly to exhibit.  Such a statement may prove useful here.\n\nAccording to a careful calculation I have made, and which I partly\nbase upon Captain Scoresby's estimate, of seventy tons for the\nlargest sized Greenland whale of sixty feet in length; according to\nmy careful calculation, I say, a Sperm Whale of the largest\nmagnitude, between eighty-five and ninety feet in length, and\nsomething less than forty feet in its fullest circumference, such a\nwhale will weigh at least ninety tons; so that, reckoning thirteen\nmen to a ton, he would considerably outweigh the combined population\nof a whole village of one thousand one hundred inhabitants.\n\nThink you not then that brains, like yoked cattle, should be put to\nthis leviathan, to make him at all budge to any landsman's\nimagination?\n\nHaving already in various ways put before you his skull, spout-hole,\njaw, teeth, tail, forehead, fins, and divers other parts, I shall now\nsimply point out what is most interesting in the general bulk of his\nunobstructed bones.  But as the colossal skull embraces so very large\na proportion of the entire extent of the skeleton; as it is by far\nthe most complicated part; and as nothing is to be repeated\nconcerning it in this chapter, you must not fail to carry it in your\nmind, or under your arm, as we proceed, otherwise you will not gain a\ncomplete notion of the general structure we are about to view.\n\nIn length, the Sperm Whale's skeleton at Tranque measured seventy-two\nFeet; so that when fully invested and extended in life, he must have\nbeen ninety feet long; for in the whale, the skeleton loses about one\nfifth in length compared with the living body.  Of this seventy-two\nfeet, his skull and jaw comprised some twenty feet, leaving some\nfifty feet of plain back-bone.  Attached to this back-bone, for\nsomething less than a third of its length, was the mighty circular\nbasket of ribs which once enclosed his vitals.\n\nTo me this vast ivory-ribbed chest, with the long, unrelieved spine,\nextending far away from it in a straight line, not a little resembled\nthe hull of a great ship new-laid upon the stocks, when only some\ntwenty of her naked bow-ribs are inserted, and the keel is otherwise,\nfor the time, but a long, disconnected timber.\n\nThe ribs were ten on a side.  The first, to begin from the neck, was\nnearly six feet long; the second, third, and fourth were each\nsuccessively longer, till you came to the climax of the fifth, or one\nof the middle ribs, which measured eight feet and some inches.  From\nthat part, the remaining ribs diminished, till the tenth and last\nonly spanned five feet and some inches.  In general thickness, they\nall bore a seemly correspondence to their length.  The middle ribs\nwere the most arched.  In some of the Arsacides they are used for\nbeams whereon to lay footpath bridges over small streams.\n\nIn considering these ribs, I could not but be struck anew with the\ncircumstance, so variously repeated in this book, that the skeleton\nof the whale is by no means the mould of his invested form.  The\nlargest of the Tranque ribs, one of the middle ones, occupied that\npart of the fish which, in life, is greatest in depth.  Now, the\ngreatest depth of the invested body of this particular whale must\nhave been at least sixteen feet; whereas, the corresponding rib\nmeasured but little more than eight feet.  So that this rib only\nconveyed half of the true notion of the living magnitude of that\npart.  Besides, for some way, where I now saw but a naked spine, all\nthat had been once wrapped round with tons of added bulk in flesh,\nmuscle, blood, and bowels.  Still more, for the ample fins, I here\nsaw but a few disordered joints; and in place of the weighty and\nmajestic, but boneless flukes, an utter blank!\n\nHow vain and foolish, then, thought I, for timid untravelled man to\ntry to comprehend aright this wondrous whale, by merely poring over\nhis dead attenuated skeleton, stretched in this peaceful wood.  No.\nOnly in the heart of quickest perils; only when within the eddyings\nof his angry flukes; only on the profound unbounded sea, can the\nfully invested whale be truly and livingly found out.\n\nBut the spine.  For that, the best way we can consider it is, with a\ncrane, to pile its bones high up on end.  No speedy enterprise.  But\nnow it's done, it looks much like Pompey's Pillar.\n\nThere are forty and odd vertebrae in all, which in the skeleton are\nnot locked together.  They mostly lie like the great knobbed blocks\non a Gothic spire, forming solid courses of heavy masonry.  The\nlargest, a middle one, is in width something less than three feet,\nand in depth more than four.  The smallest, where the spine tapers\naway into the tail, is only two inches in width, and looks something\nlike a white billiard-ball.  I was told that there were still smaller\nones, but they had been lost by some little cannibal urchins, the\npriest's children, who had stolen them to play marbles with.  Thus we\nsee how that the spine of even the hugest of living things tapers off\nat last into simple child's play.\n\n\n\nCHAPTER 104\n\nThe Fossil Whale.\n\n\nFrom his mighty bulk the whale affords a most congenial theme whereon\nto enlarge, amplify, and generally expatiate.  Would you, you could\nnot compress him.  By good rights he should only be treated of in\nimperial folio.  Not to tell over again his furlongs from spiracle to\ntail, and the yards he measures about the waist; only think of the\ngigantic involutions of his intestines, where they lie in him like\ngreat cables and hawsers coiled away in the subterranean orlop-deck\nof a line-of-battle-ship.\n\nSince I have undertaken to manhandle this Leviathan, it behooves me\nto approve myself omnisciently exhaustive in the enterprise; not\noverlooking the minutest seminal germs of his blood, and spinning him\nout to the uttermost coil of his bowels.  Having already described\nhim in most of his present habitatory and anatomical peculiarities,\nit now remains to magnify him in an archaeological, fossiliferous,\nand antediluvian point of view.  Applied to any other creature than\nthe Leviathan--to an ant or a flea--such portly terms might justly be\ndeemed unwarrantably grandiloquent.  But when Leviathan is the text,\nthe case is altered.  Fain am I to stagger to this emprise under\nthe weightiest words of the dictionary.  And here be it said, that\nwhenever it has been convenient to consult one in the course of these\ndissertations, I have invariably used a huge quarto edition of\nJohnson, expressly purchased for that purpose; because that famous\nlexicographer's uncommon personal bulk more fitted him to compile a\nlexicon to be used by a whale author like me.\n\nOne often hears of writers that rise and swell with their subject,\nthough it may seem but an ordinary one.  How, then, with me, writing\nof this Leviathan?  Unconsciously my chirography expands into placard\ncapitals.  Give me a condor's quill!  Give me Vesuvius' crater for an\ninkstand!  Friends, hold my arms!  For in the mere act of penning my\nthoughts of this Leviathan, they weary me, and make me faint with\ntheir outreaching comprehensiveness of sweep, as if to include the\nwhole circle of the sciences, and all the generations of whales, and\nmen, and mastodons, past, present, and to come, with all the\nrevolving panoramas of empire on earth, and throughout the whole\nuniverse, not excluding its suburbs.  Such, and so magnifying, is the\nvirtue of a large and liberal theme!  We expand to its bulk.  To\nproduce a mighty book, you must choose a mighty theme.  No great and\nenduring volume can ever be written on the flea, though many there be\nwho have tried it.\n\nEre entering upon the subject of Fossil Whales, I present my\ncredentials as a geologist, by stating that in my miscellaneous time\nI have been a stone-mason, and also a great digger of ditches,\ncanals and wells, wine-vaults, cellars, and cisterns of all sorts.\nLikewise, by way of preliminary, I desire to remind the reader, that\nwhile in the earlier geological strata there are found the fossils of\nmonsters now almost completely extinct; the subsequent relics\ndiscovered in what are called the Tertiary formations seem the\nconnecting, or at any rate intercepted links, between the\nantichronical creatures, and those whose remote posterity are said to\nhave entered the Ark; all the Fossil Whales hitherto discovered\nbelong to the Tertiary period, which is the last preceding the\nsuperficial formations.  And though none of them precisely answer to\nany known species of the present time, they are yet sufficiently akin\nto them in general respects, to justify their taking rank as\nCetacean fossils.\n\nDetached broken fossils of pre-adamite whales, fragments of their\nbones and skeletons, have within thirty years past, at various\nintervals, been found at the base of the Alps, in Lombardy, in\nFrance, in England, in Scotland, and in the States of Louisiana,\nMississippi, and Alabama.  Among the more curious of such remains is\npart of a skull, which in the year 1779 was disinterred in the Rue\nDauphine in Paris, a short street opening almost directly upon the\npalace of the Tuileries; and bones disinterred in excavating the\ngreat docks of Antwerp, in Napoleon's time.  Cuvier pronounced these\nfragments to have belonged to some utterly unknown Leviathanic\nspecies.\n\nBut by far the most wonderful of all Cetacean relics was the almost\ncomplete vast skeleton of an extinct monster, found in the year 1842,\non the plantation of Judge Creagh, in Alabama.  The awe-stricken\ncredulous slaves in the vicinity took it for the bones of one of the\nfallen angels.  The Alabama doctors declared it a huge reptile, and\nbestowed upon it the name of Basilosaurus.  But some specimen bones\nof it being taken across the sea to Owen, the English Anatomist, it\nturned out that this alleged reptile was a whale, though of a\ndeparted species.  A significant illustration of the fact, again and\nagain repeated in this book, that the skeleton of the whale furnishes\nbut little clue to the shape of his fully invested body.  So Owen\nrechristened the monster Zeuglodon; and in his paper read before the\nLondon Geological Society, pronounced it, in substance, one of the\nmost extraordinary creatures which the mutations of the globe have\nblotted out of existence.\n\nWhen I stand among these mighty Leviathan skeletons, skulls, tusks,\njaws, ribs, and vertebrae, all characterized by partial resemblances\nto the existing breeds of sea-monsters; but at the same time bearing\non the other hand similar affinities to the annihilated antichronical\nLeviathans, their incalculable seniors; I am, by a flood, borne back\nto that wondrous period, ere time itself can be said to have begun;\nfor time began with man.  Here Saturn's grey chaos rolls over me, and\nI obtain dim, shuddering glimpses into those Polar eternities; when\nwedged bastions of ice pressed hard upon what are now the Tropics;\nand in all the 25,000 miles of this world's circumference, not an\ninhabitable hand's breadth of land was visible.  Then the whole world\nwas the whale's; and, king of creation, he left his wake along the\npresent lines of the Andes and the Himmalehs.  Who can show a\npedigree like Leviathan?  Ahab's harpoon had shed older blood than\nthe Pharaoh's.  Methuselah seems a school-boy.  I look round to shake\nhands with Shem.  I am horror-struck at this antemosaic, unsourced\nexistence of the unspeakable terrors of the whale, which, having been\nbefore all time, must needs exist after all humane ages are over.\n\nBut not alone has this Leviathan left his pre-adamite traces in the\nstereotype plates of nature, and in limestone and marl bequeathed his\nancient bust; but upon Egyptian tablets, whose antiquity seems to\nclaim for them an almost fossiliferous character, we find the\nunmistakable print of his fin.  In an apartment of the great temple\nof Denderah, some fifty years ago, there was discovered upon the\ngranite ceiling a sculptured and painted planisphere, abounding in\ncentaurs, griffins, and dolphins, similar to the grotesque figures\non the celestial globe of the moderns.  Gliding among them, old\nLeviathan swam as of yore; was there swimming in that planisphere,\ncenturies before Solomon was cradled.\n\nNor must there be omitted another strange attestation of the\nantiquity of the whale, in his own osseous post-diluvian reality, as\nset down by the venerable John Leo, the old Barbary traveller.\n\n\"Not far from the Sea-side, they have a Temple, the Rafters and Beams\nof which are made of Whale-Bones; for Whales of a monstrous size are\noftentimes cast up dead upon that shore.  The Common People imagine,\nthat by a secret Power bestowed by God upon the temple, no Whale can\npass it without immediate death.  But the truth of the Matter is,\nthat on either side of the Temple, there are Rocks that shoot two\nMiles into the Sea, and wound the Whales when they light upon 'em.\nThey keep a Whale's Rib of an incredible length for a Miracle, which\nlying upon the Ground with its convex part uppermost, makes an Arch,\nthe Head of which cannot be reached by a Man upon a Camel's Back.\nThis Rib (says John Leo) is said to have layn there a hundred Years\nbefore I saw it.  Their Historians affirm, that a Prophet who\nprophesy'd of Mahomet, came from this Temple, and some do not stand\nto assert, that the Prophet Jonas was cast forth by the Whale at the\nBase of the Temple.\"\n\nIn this Afric Temple of the Whale I leave you, reader, and if you be\na Nantucketer, and a whaleman, you will silently worship there.\n\n\n\nCHAPTER 105\n\nDoes the Whale's Magnitude Diminish?--Will He Perish?\n\n\nInasmuch, then, as this Leviathan comes floundering down upon us from\nthe head-waters of the Eternities, it may be fitly inquired, whether,\nin the long course of his generations, he has not degenerated from\nthe original bulk of his sires.\n\nBut upon investigation we find, that not only are the whales of the\npresent day superior in magnitude to those whose fossil remains are\nfound in the Tertiary system (embracing a distinct geological period\nprior to man), but of the whales found in that Tertiary system, those\nbelonging to its latter formations exceed in size those of its\nearlier ones.\n\nOf all the pre-adamite whales yet exhumed, by far the largest is the\nAlabama one mentioned in the last chapter, and that was less than\nseventy feet in length in the skeleton.  Whereas, we have already\nseen, that the tape-measure gives seventy-two feet for the skeleton\nof a large sized modern whale.  And I have heard, on whalemen's\nauthority, that Sperm Whales have been captured near a hundred feet\nlong at the time of capture.\n\nBut may it not be, that while the whales of the present hour are an\nadvance in magnitude upon those of all previous geological periods;\nmay it not be, that since Adam's time they have degenerated?\n\nAssuredly, we must conclude so, if we are to credit the accounts of\nsuch gentlemen as Pliny, and the ancient naturalists generally.  For\nPliny tells us of Whales that embraced acres of living bulk, and\nAldrovandus of others which measured eight hundred feet in\nlength--Rope Walks and Thames Tunnels of Whales!  And even in the\ndays of Banks and Solander, Cooke's naturalists, we find a Danish\nmember of the Academy of Sciences setting down certain Iceland Whales\n(reydan-siskur, or Wrinkled Bellies) at one hundred and twenty yards;\nthat is, three hundred and sixty feet.  And Lacepede, the French\nnaturalist, in his elaborate history of whales, in the very beginning\nof his work (page 3), sets down the Right Whale at one hundred\nmetres, three hundred and twenty-eight feet.  And this work was\npublished so late as A.D. 1825.\n\nBut will any whaleman believe these stories?  No.  The whale of\nto-day is as big as his ancestors in Pliny's time.  And if ever I go\nwhere Pliny is, I, a whaleman (more than he was), will make bold to\ntell him so.  Because I cannot understand how it is, that while the\nEgyptian mummies that were buried thousands of years before even\nPliny was born, do not measure so much in their coffins as a modern\nKentuckian in his socks; and while the cattle and other animals\nsculptured on the oldest Egyptian and Nineveh tablets, by the\nrelative proportions in which they are drawn, just as plainly prove\nthat the high-bred, stall-fed, prize cattle of Smithfield, not only\nequal, but far exceed in magnitude the fattest of Pharaoh's fat kine;\nin the face of all this, I will not admit that of all animals the\nwhale alone should have degenerated.\n\nBut still another inquiry remains; one often agitated by the more\nrecondite Nantucketers.  Whether owing to the almost omniscient\nlook-outs at the mast-heads of the whaleships, now penetrating even\nthrough Behring's straits, and into the remotest secret drawers and\nlockers of the world; and the thousand harpoons and lances darted\nalong all continental coasts; the moot point is, whether Leviathan\ncan long endure so wide a chase, and so remorseless a havoc; whether\nhe must not at last be exterminated from the waters, and the last\nwhale, like the last man, smoke his last pipe, and then himself\nevaporate in the final puff.\n\nComparing the humped herds of whales with the humped herds of\nbuffalo, which, not forty years ago, overspread by tens of thousands\nthe prairies of Illinois and Missouri, and shook their iron manes and\nscowled with their thunder-clotted brows upon the sites of populous\nriver-capitals, where now the polite broker sells you land at a\ndollar an inch; in such a comparison an irresistible argument would\nseem furnished, to show that the hunted whale cannot now escape\nspeedy extinction.\n\nBut you must look at this matter in every light.  Though so short a\nperiod ago--not a good lifetime--the census of the buffalo in\nIllinois exceeded the census of men now in London, and though at the\npresent day not one horn or hoof of them remains in all that region;\nand though the cause of this wondrous extermination was the spear of\nman; yet the far different nature of the whale-hunt peremptorily\nforbids so inglorious an end to the Leviathan.  Forty men in one ship\nhunting the Sperm Whales for forty-eight months think they have done\nextremely well, and thank God, if at last they carry home the oil of\nforty fish.  Whereas, in the days of the old Canadian and Indian\nhunters and trappers of the West, when the far west (in whose sunset\nsuns still rise) was a wilderness and a virgin, the same number of\nmoccasined men, for the same number of months, mounted on horse\ninstead of sailing in ships, would have slain not forty, but forty\nthousand and more buffaloes; a fact that, if need were, could be\nstatistically stated.\n\nNor, considered aright, does it seem any argument in favour of the\ngradual extinction of the Sperm Whale, for example, that in former\nyears (the latter part of the last century, say) these Leviathans, in\nsmall pods, were encountered much oftener than at present, and, in\nconsequence, the voyages were not so prolonged, and were also much\nmore remunerative.  Because, as has been elsewhere noticed, those\nwhales, influenced by some views to safety, now swim the seas in\nimmense caravans, so that to a large degree the scattered solitaries,\nyokes, and pods, and schools of other days are now aggregated into\nvast but widely separated, unfrequent armies.  That is all.  And\nequally fallacious seems the conceit, that because the so-called\nwhale-bone whales no longer haunt many grounds in former years\nabounding with them, hence that species also is declining.  For they\nare only being driven from promontory to cape; and if one coast is no\nlonger enlivened with their jets, then, be sure, some other and\nremoter strand has been very recently startled by the unfamiliar\nspectacle.\n\nFurthermore: concerning these last mentioned Leviathans, they have\ntwo firm fortresses, which, in all human probability, will for ever\nremain impregnable.  And as upon the invasion of their valleys, the\nfrosty Swiss have retreated to their mountains; so, hunted from the\nsavannas and glades of the middle seas, the whale-bone whales can at\nlast resort to their Polar citadels, and diving under the ultimate\nglassy barriers and walls there, come up among icy fields and floes;\nand in a charmed circle of everlasting December, bid defiance to all\npursuit from man.\n\nBut as perhaps fifty of these whale-bone whales are harpooned for one\ncachalot, some philosophers of the forecastle have concluded that\nthis positive havoc has already very seriously diminished their\nbattalions.  But though for some time past a number of these whales,\nnot less than 13,000, have been annually slain on the nor'-west\ncoast by the Americans alone; yet there are considerations which\nrender even this circumstance of little or no account as an opposing\nargument in this matter.\n\nNatural as it is to be somewhat incredulous concerning the\npopulousness of the more enormous creatures of the globe, yet what\nshall we say to Harto, the historian of Goa, when he tells us that at\none hunting the King of Siam took 4,000 elephants; that in those\nregions elephants are numerous as droves of cattle in the temperate\nclimes.  And there seems no reason to doubt that if these elephants,\nwhich have now been hunted for thousands of years, by Semiramis, by\nPorus, by Hannibal, and by all the successive monarchs of the\nEast--if they still survive there in great numbers, much more may the\ngreat whale outlast all hunting, since he has a pasture to expatiate\nin, which is precisely twice as large as all Asia, both Americas,\nEurope and Africa, New Holland, and all the Isles of the sea\ncombined.\n\nMoreover: we are to consider, that from the presumed great longevity\nof whales, their probably attaining the age of a century and more,\ntherefore at any one period of time, several distinct adult\ngenerations must be contemporary.  And what that is, we may soon\ngain some idea of, by imagining all the grave-yards, cemeteries, and\nfamily vaults of creation yielding up the live bodies of all the men,\nwomen, and children who were alive seventy-five years ago; and adding\nthis countless host to the present human population of the globe.\n\nWherefore, for all these things, we account the whale immortal in his\nspecies, however perishable in his individuality.  He swam the seas\nbefore the continents broke water; he once swam over the site of the\nTuileries, and Windsor Castle, and the Kremlin.  In Noah's flood he\ndespised Noah's Ark; and if ever the world is to be again flooded,\nlike the Netherlands, to kill off its rats, then the eternal whale\nwill still survive, and rearing upon the topmost crest of the\nequatorial flood, spout his frothed defiance to the skies.\n\n\n\nCHAPTER 106\n\nAhab's Leg.\n\n\nThe precipitating manner in which Captain Ahab had quitted the Samuel\nEnderby of London, had not been unattended with some small violence\nto his own person.  He had lighted with such energy upon a thwart of\nhis boat that his ivory leg had received a half-splintering shock.\nAnd when after gaining his own deck, and his own pivot-hole there, he\nso vehemently wheeled round with an urgent command to the steersman\n(it was, as ever, something about his not steering inflexibly\nenough); then, the already shaken ivory received such an additional\ntwist and wrench, that though it still remained entire, and to all\nappearances lusty, yet Ahab did not deem it entirely trustworthy.\n\nAnd, indeed, it seemed small matter for wonder, that for all his\npervading, mad recklessness, Ahab did at times give careful heed to\nthe condition of that dead bone upon which he partly stood.  For it\nhad not been very long prior to the Pequod's sailing from Nantucket,\nthat he had been found one night lying prone upon the ground, and\ninsensible; by some unknown, and seemingly inexplicable, unimaginable\ncasualty, his ivory limb having been so violently displaced, that it\nhad stake-wise smitten, and all but pierced his groin; nor was it\nwithout extreme difficulty that the agonizing wound was entirely\ncured.\n\nNor, at the time, had it failed to enter his monomaniac mind, that\nall the anguish of that then present suffering was but the direct\nissue of a former woe; and he too plainly seemed to see, that as the\nmost poisonous reptile of the marsh perpetuates his kind as\ninevitably as the sweetest songster of the grove; so, equally with\nevery felicity, all miserable events do naturally beget their like.\nYea, more than equally, thought Ahab; since both the ancestry and\nposterity of Grief go further than the ancestry and posterity of Joy.\nFor, not to hint of this: that it is an inference from certain\ncanonic teachings, that while some natural enjoyments here shall have\nno children born to them for the other world, but, on the contrary,\nshall be followed by the joy-childlessness of all hell's despair;\nwhereas, some guilty mortal miseries shall still fertilely beget to\nthemselves an eternally progressive progeny of griefs beyond the\ngrave; not at all to hint of this, there still seems an inequality in\nthe deeper analysis of the thing.  For, thought Ahab, while even the\nhighest earthly felicities ever have a certain unsignifying pettiness\nlurking in them, but, at bottom, all heartwoes, a mystic\nsignificance, and, in some men, an archangelic grandeur; so do their\ndiligent tracings-out not belie the obvious deduction.  To trail the\ngenealogies of these high mortal miseries, carries us at last among\nthe sourceless primogenitures of the gods; so that, in the face of\nall the glad, hay-making suns, and soft cymballing, round\nharvest-moons, we must needs give in to this: that the gods\nthemselves are not for ever glad.  The ineffaceable, sad birth-mark\nin the brow of man, is but the stamp of sorrow in the signers.\n\nUnwittingly here a secret has been divulged, which perhaps might more\nproperly, in set way, have been disclosed before.  With many other\nparticulars concerning Ahab, always had it remained a mystery to\nsome, why it was, that for a certain period, both before and after\nthe sailing of the Pequod, he had hidden himself away with such\nGrand-Lama-like exclusiveness; and, for that one interval, sought\nspeechless refuge, as it were, among the marble senate of the dead.\nCaptain Peleg's bruited reason for this thing appeared by no means\nadequate; though, indeed, as touching all Ahab's deeper part, every\nrevelation partook more of significant darkness than of explanatory\nlight.  But, in the end, it all came out; this one matter did, at\nleast.  That direful mishap was at the bottom of his temporary\nrecluseness.  And not only this, but to that ever-contracting,\ndropping circle ashore, who, for any reason, possessed the privilege\nof a less banned approach to him; to that timid circle the above\nhinted casualty--remaining, as it did, moodily unaccounted for by\nAhab--invested itself with terrors, not entirely underived from the\nland of spirits and of wails.  So that, through their zeal for him,\nthey had all conspired, so far as in them lay, to muffle up the\nknowledge of this thing from others; and hence it was, that not till\na considerable interval had elapsed, did it transpire upon the\nPequod's decks.\n\nBut be all this as it may; let the unseen, ambiguous synod in the\nair, or the vindictive princes and potentates of fire, have to do or\nnot with earthly Ahab, yet, in this present matter of his leg, he\ntook plain practical procedures;--he called the carpenter.\n\nAnd when that functionary appeared before him, he bade him without\ndelay set about making a new leg, and directed the mates to see him\nsupplied with all the studs and joists of jaw-ivory (Sperm Whale)\nwhich had thus far been accumulated on the voyage, in order that a\ncareful selection of the stoutest, clearest-grained stuff might be\nsecured.  This done, the carpenter received orders to have the leg\ncompleted that night; and to provide all the fittings for it,\nindependent of those pertaining to the distrusted one in use.\nMoreover, the ship's forge was ordered to be hoisted out of its\ntemporary idleness in the hold; and, to accelerate the affair, the\nblacksmith was commanded to proceed at once to the forging of\nwhatever iron contrivances might be needed.\n\n\n\nCHAPTER 107\n\nThe Carpenter.\n\n\nSeat thyself sultanically among the moons of Saturn, and take high\nabstracted man alone; and he seems a wonder, a grandeur, and a woe.\nBut from the same point, take mankind in mass, and for the most part,\nthey seem a mob of unnecessary duplicates, both contemporary and\nhereditary.  But most humble though he was, and far from furnishing\nan example of the high, humane abstraction; the Pequod's carpenter\nwas no duplicate; hence, he now comes in person on this stage.\n\nLike all sea-going ship carpenters, and more especially those\nbelonging to whaling vessels, he was, to a certain off-handed,\npractical extent, alike experienced in numerous trades and callings\ncollateral to his own; the carpenter's pursuit being the ancient and\noutbranching trunk of all those numerous handicrafts which more or\nless have to do with wood as an auxiliary material.  But, besides the\napplication to him of the generic remark above, this carpenter of the\nPequod was singularly efficient in those thousand nameless mechanical\nemergencies continually recurring in a large ship, upon a three or\nfour years' voyage, in uncivilized and far-distant seas.  For not to\nspeak of his readiness in ordinary duties:--repairing stove boats,\nsprung spars, reforming the shape of clumsy-bladed oars, inserting\nbull's eyes in the deck, or new tree-nails in the side planks, and\nother miscellaneous matters more directly pertaining to his special\nbusiness; he was moreover unhesitatingly expert in all manner of\nconflicting aptitudes, both useful and capricious.\n\nThe one grand stage where he enacted all his various parts so\nmanifold, was his vice-bench; a long rude ponderous table furnished\nwith several vices, of different sizes, and both of iron and of wood.\nAt all times except when whales were alongside, this bench was\nsecurely lashed athwartships against the rear of the Try-works.\n\nA belaying pin is found too large to be easily inserted into its\nhole: the carpenter claps it into one of his ever-ready vices, and\nstraightway files it smaller.  A lost land-bird of strange plumage\nstrays on board, and is made a captive: out of clean shaved rods of\nright-whale bone, and cross-beams of sperm whale ivory, the carpenter\nmakes a pagoda-looking cage for it.  An oarsman sprains his wrist:\nthe carpenter concocts a soothing lotion.  Stubb longed for\nvermillion stars to be painted upon the blade of his every oar;\nscrewing each oar in his big vice of wood, the carpenter\nsymmetrically supplies the constellation.  A sailor takes a fancy to\nwear shark-bone ear-rings: the carpenter drills his ears.  Another\nhas the toothache: the carpenter out pincers, and clapping one hand\nupon his bench bids him be seated there; but the poor fellow\nunmanageably winces under the unconcluded operation; whirling round\nthe handle of his wooden vice, the carpenter signs him to clap his\njaw in that, if he would have him draw the tooth.\n\nThus, this carpenter was prepared at all points, and alike\nindifferent and without respect in all.  Teeth he accounted bits of\nivory; heads he deemed but top-blocks; men themselves he lightly held\nfor capstans.  But while now upon so wide a field thus variously\naccomplished and with such liveliness of expertness in him, too; all\nthis would seem to argue some uncommon vivacity of intelligence.  But\nnot precisely so.  For nothing was this man more remarkable, than for\na certain impersonal stolidity as it were; impersonal, I say; for it\nso shaded off into the surrounding infinite of things, that it seemed\none with the general stolidity discernible in the whole visible\nworld; which while pauselessly active in uncounted modes, still\neternally holds its peace, and ignores you, though you dig\nfoundations for cathedrals.  Yet was this half-horrible stolidity in\nhim, involving, too, as it appeared, an all-ramifying\nheartlessness;--yet was it oddly dashed at times, with an old,\ncrutch-like, antediluvian, wheezing humorousness, not unstreaked now\nand then with a certain grizzled wittiness; such as might have served\nto pass the time during the midnight watch on the bearded forecastle\nof Noah's ark.  Was it that this old carpenter had been a life-long\nwanderer, whose much rolling, to and fro, not only had gathered no\nmoss; but what is more, had rubbed off whatever small outward\nclingings might have originally pertained to him?  He was a stript\nabstract; an unfractioned integral; uncompromised as a new-born babe;\nliving without premeditated reference to this world or the next.  You\nmight almost say, that this strange uncompromisedness in him involved\na sort of unintelligence; for in his numerous trades, he did not seem\nto work so much by reason or by instinct, or simply because he had\nbeen tutored to it, or by any intermixture of all these, even or\nuneven; but merely by a kind of deaf and dumb, spontaneous literal\nprocess.  He was a pure manipulator; his brain, if he had ever had\none, must have early oozed along into the muscles of his fingers.  He\nwas like one of those unreasoning but still highly useful, MULTUM IN\nPARVO, Sheffield contrivances, assuming the exterior--though a little\nswelled--of a common pocket knife; but containing, not only blades of\nvarious sizes, but also screw-drivers, cork-screws, tweezers, awls,\npens, rulers, nail-filers, countersinkers.  So, if his superiors\nwanted to use the carpenter for a screw-driver, all they had to do\nwas to open that part of him, and the screw was fast: or if for\ntweezers, take him up by the legs, and there they were.\n\nYet, as previously hinted, this omnitooled, open-and-shut carpenter,\nwas, after all, no mere machine of an automaton.  If he did not have\na common soul in him, he had a subtle something that somehow\nanomalously did its duty.  What that was, whether essence of\nquicksilver, or a few drops of hartshorn, there is no telling.  But\nthere it was; and there it had abided for now some sixty years or\nmore.  And this it was, this same unaccountable, cunning\nlife-principle in him; this it was, that kept him a great part of the\ntime soliloquizing; but only like an unreasoning wheel, which also\nhummingly soliloquizes; or rather, his body was a sentry-box and this\nsoliloquizer on guard there, and talking all the time to keep himself\nawake.\n\n\n\nCHAPTER 108\n\nAhab and the Carpenter.\n\nThe Deck--First Night Watch.\n\n\n(CARPENTER STANDING BEFORE HIS VICE-BENCH, AND BY THE LIGHT OF TWO\nLANTERNS BUSILY FILING THE IVORY JOIST FOR THE LEG, WHICH JOIST IS\nFIRMLY FIXED IN THE VICE.  SLABS OF IVORY, LEATHER STRAPS, PADS,\nSCREWS, AND VARIOUS TOOLS OF ALL SORTS LYING ABOUT THE BENCH.\nFORWARD, THE RED FLAME OF THE FORGE IS SEEN, WHERE THE BLACKSMITH IS\nAT WORK.)\n\n\nDrat the file, and drat the bone!  That is hard which should be soft,\nand that is soft which should be hard.  So we go, who file old jaws\nand shinbones.  Let's try another.  Aye, now, this works better\n(SNEEZES).  Halloa, this bone dust is (SNEEZES)--why it's\n(SNEEZES)--yes it's (SNEEZES)--bless my soul, it won't let me speak!\nThis is what an old fellow gets now for working in dead lumber.  Saw\na live tree, and you don't get this dust; amputate a live bone, and\nyou don't get it (SNEEZES).  Come, come, you old Smut, there, bear a\nhand, and let's have that ferule and buckle-screw; I'll be ready\nfor them presently.  Lucky now (SNEEZES) there's no knee-joint to\nmake; that might puzzle a little; but a mere shinbone--why it's\neasy as making hop-poles; only I should like to put a good finish on.\nTime, time; if I but only had the time, I could turn him out as neat\na leg now as ever (SNEEZES) scraped to a lady in a parlor.  Those\nbuckskin legs and calves of legs I've seen in shop windows wouldn't\ncompare at all.  They soak water, they do; and of course get\nrheumatic, and have to be doctored (SNEEZES) with washes and lotions,\njust like live legs.  There; before I saw it off, now, I must call his\nold Mogulship, and see whether the length will be all right; too\nshort, if anything, I guess.  Ha! that's the heel; we are in luck;\nhere he comes, or it's somebody else, that's certain.\n\nAHAB (ADVANCING)\n\n(DURING THE ENSUING SCENE, THE CARPENTER CONTINUES SNEEZING AT TIMES)\n\n\nWell, manmaker!\n\nJust in time, sir.  If the captain pleases, I will now mark the\nlength.  Let me measure, sir.\n\nMeasured for a leg! good.  Well, it's not the first time.  About it!\nThere; keep thy finger on it.  This is a cogent vice thou hast here,\ncarpenter; let me feel its grip once.  So, so; it does pinch some.\n\nOh, sir, it will break bones--beware, beware!\n\nNo fear; I like a good grip; I like to feel something in this\nslippery world that can hold, man.  What's Prometheus about\nthere?--the blacksmith, I mean--what's he about?\n\nHe must be forging the buckle-screw, sir, now.\n\nRight.  It's a partnership; he supplies the muscle part.  He makes a\nfierce red flame there!\n\nAye, sir; he must have the white heat for this kind of fine work.\n\nUm-m.  So he must.  I do deem it now a most meaning thing, that that\nold Greek, Prometheus, who made men, they say, should have been a\nblacksmith, and animated them with fire; for what's made in fire must\nproperly belong to fire; and so hell's probable.  How the soot flies!\nThis must be the remainder the Greek made the Africans of.\nCarpenter, when he's through with that buckle, tell him to forge a\npair of steel shoulder-blades; there's a pedlar aboard with a\ncrushing pack.\n\nSir?\n\nHold; while Prometheus is about it, I'll order a complete man after a\ndesirable pattern.  Imprimis, fifty feet high in his socks; then,\nchest modelled after the Thames Tunnel; then, legs with roots to 'em,\nto stay in one place; then, arms three feet through the wrist; no\nheart at all, brass forehead, and about a quarter of an acre of fine\nbrains; and let me see--shall I order eyes to see outwards?  No, but\nput a sky-light on top of his head to illuminate inwards.  There,\ntake the order, and away.\n\nNow, what's he speaking about, and who's he speaking to, I should\nlike to know?  Shall I keep standing here? (ASIDE).\n\n'Tis but indifferent architecture to make a blind dome; here's one.\nNo, no, no; I must have a lantern.\n\nHo, ho!  That's it, hey?  Here are two, sir; one will serve my turn.\n\nWhat art thou thrusting that thief-catcher into my face for, man?\nThrusted light is worse than presented pistols.\n\nI thought, sir, that you spoke to carpenter.\n\n\nCarpenter? why that's--but no;--a very tidy, and, I may say, an\nextremely gentlemanlike sort of business thou art in here,\ncarpenter;--or would'st thou rather work in clay?\n\nSir?--Clay? clay, sir?  That's mud; we leave clay to ditchers, sir.\n\nThe fellow's impious!  What art thou sneezing about?\n\nBone is rather dusty, sir.\n\nTake the hint, then; and when thou art dead, never bury thyself under\nliving people's noses.\n\nSir?--oh! ah!--I guess so;--yes--dear!\n\nLook ye, carpenter, I dare say thou callest thyself a right good\nworkmanlike workman, eh?  Well, then, will it speak thoroughly well\nfor thy work, if, when I come to mount this leg thou makest, I shall\nnevertheless feel another leg in the same identical place with it;\nthat is, carpenter, my old lost leg; the flesh and blood one, I mean.\nCanst thou not drive that old Adam away?\n\nTruly, sir, I begin to understand somewhat now.  Yes, I have heard\nsomething curious on that score, sir; how that a dismasted man never\nentirely loses the feeling of his old spar, but it will be still\npricking him at times.  May I humbly ask if it be really so, sir?\n\nIt is, man.  Look, put thy live leg here in the place where mine once\nwas; so, now, here is only one distinct leg to the eye, yet two to\nthe soul.  Where thou feelest tingling life; there, exactly there,\nthere to a hair, do I.  Is't a riddle?\n\nI should humbly call it a poser, sir.\n\nHist, then.  How dost thou know that some entire, living, thinking\nthing may not be invisibly and uninterpenetratingly standing\nprecisely where thou now standest; aye, and standing there in thy\nspite?  In thy most solitary hours, then, dost thou not fear\neavesdroppers?  Hold, don't speak!  And if I still feel the smart of\nmy crushed leg, though it be now so long dissolved; then, why mayst\nnot thou, carpenter, feel the fiery pains of hell for ever, and\nwithout a body?  Hah!\n\nGood Lord!  Truly, sir, if it comes to that, I must calculate over\nagain; I think I didn't carry a small figure, sir.\n\nLook ye, pudding-heads should never grant premises.--How long before\nthe leg is done?\n\nPerhaps an hour, sir.\n\nBungle away at it then, and bring it to me (TURNS TO GO).  Oh, Life!\nHere I am, proud as Greek god, and yet standing debtor to this\nblockhead for a bone to stand on!  Cursed be that mortal\ninter-indebtedness which will not do away with ledgers.  I would be\nfree as air; and I'm down in the whole world's books.  I am so rich,\nI could have given bid for bid with the wealthiest Praetorians at the\nauction of the Roman empire (which was the world's); and yet I owe\nfor the flesh in the tongue I brag with.  By heavens!  I'll get a\ncrucible, and into it, and dissolve myself down to one small,\ncompendious vertebra.  So.\n\nCARPENTER (RESUMING HIS WORK).\n\n\nWell, well, well!  Stubb knows him best of all, and Stubb always says\nhe's queer; says nothing but that one sufficient little word queer;\nhe's queer, says Stubb; he's queer--queer, queer; and keeps dinning\nit into Mr. Starbuck all the time--queer--sir--queer, queer, very\nqueer.  And here's his leg!  Yes, now that I think of it, here's his\nbedfellow! has a stick of whale's jaw-bone for a wife!  And this is\nhis leg; he'll stand on this.  What was that now about one leg\nstanding in three places, and all three places standing in one\nhell--how was that?  Oh!  I don't wonder he looked so scornful at me!\nI'm a sort of strange-thoughted sometimes, they say; but that's only\nhaphazard-like.  Then, a short, little old body like me, should never\nundertake to wade out into deep waters with tall, heron-built\ncaptains; the water chucks you under the chin pretty quick, and\nthere's a great cry for life-boats.  And here's the heron's leg! long\nand slim, sure enough!  Now, for most folks one pair of legs lasts a\nlifetime, and that must be because they use them mercifully, as a\ntender-hearted old lady uses her roly-poly old coach-horses.  But\nAhab; oh he's a hard driver.  Look, driven one leg to death, and\nspavined the other for life, and now wears out bone legs by the cord.\nHalloa, there, you Smut! bear a hand there with those screws, and\nlet's finish it before the resurrection fellow comes a-calling with\nhis horn for all legs, true or false, as brewery-men go round\ncollecting old beer barrels, to fill 'em up again.  What a leg this\nis!  It looks like a real live leg, filed down to nothing but the\ncore; he'll be standing on this to-morrow; he'll be taking altitudes\non it.  Halloa!  I almost forgot the little oval slate, smoothed\nivory, where he figures up the latitude.  So, so; chisel, file, and\nsand-paper, now!\n\n\n\nCHAPTER 109\n\nAhab and Starbuck in the Cabin.\n\n\nAccording to usage they were pumping the ship next morning; and lo!\nno inconsiderable oil came up with the water; the casks below must\nhave sprung a bad leak.  Much concern was shown; and Starbuck went\ndown into the cabin to report this unfavourable affair.*\n\n\n*In Sperm-whalemen with any considerable quantity of oil on board, it\nis a regular semiweekly duty to conduct a hose into the hold, and\ndrench the casks with sea-water; which afterwards, at varying\nintervals, is removed by the ship's pumps.  Hereby the casks are\nsought to be kept damply tight; while by the changed character of the\nwithdrawn water, the mariners readily detect any serious leakage in\nthe precious cargo.\n\n\nNow, from the South and West the Pequod was drawing nigh to Formosa\nand the Bashee Isles, between which lies one of the tropical outlets\nfrom the China waters into the Pacific.  And so Starbuck found Ahab\nwith a general chart of the oriental archipelagoes spread before him;\nand another separate one representing the long eastern coasts of the\nJapanese islands--Niphon, Matsmai, and Sikoke.  With his snow-white\nnew ivory leg braced against the screwed leg of his table, and with a\nlong pruning-hook of a jack-knife in his hand, the wondrous old man,\nwith his back to the gangway door, was wrinkling his brow, and\ntracing his old courses again.\n\n\"Who's there?\" hearing the footstep at the door, but not turning\nround to it.  \"On deck!  Begone!\"\n\n\"Captain Ahab mistakes; it is I.  The oil in the hold is leaking,\nsir.  We must up Burtons and break out.\"\n\n\"Up Burtons and break out?  Now that we are nearing Japan; heave-to\nhere for a week to tinker a parcel of old hoops?\"\n\n\"Either do that, sir, or waste in one day more oil than we may make\ngood in a year.  What we come twenty thousand miles to get is worth\nsaving, sir.\"\n\n\"So it is, so it is; if we get it.\"\n\n\"I was speaking of the oil in the hold, sir.\"\n\n\"And I was not speaking or thinking of that at all.  Begone!  Let it\nleak!  I'm all aleak myself.  Aye! leaks in leaks! not only full of\nleaky casks, but those leaky casks are in a leaky ship; and that's a\nfar worse plight than the Pequod's, man.  Yet I don't stop to plug my\nleak; for who can find it in the deep-loaded hull; or how hope to\nplug it, even if found, in this life's howling gale?  Starbuck!\nI'll not have the Burtons hoisted.\"\n\n\"What will the owners say, sir?\"\n\n\"Let the owners stand on Nantucket beach and outyell the Typhoons.\nWhat cares Ahab?  Owners, owners?  Thou art always prating to me,\nStarbuck, about those miserly owners, as if the owners were my\nconscience.  But look ye, the only real owner of anything is its\ncommander; and hark ye, my conscience is in this ship's keel.--On\ndeck!\"\n\n\"Captain Ahab,\" said the reddening mate, moving further into the\ncabin, with a daring so strangely respectful and cautious that it\nalmost seemed not only every way seeking to avoid the slightest\noutward manifestation of itself, but within also seemed more than\nhalf distrustful of itself; \"A better man than I might well pass over\nin thee what he would quickly enough resent in a younger man; aye,\nand in a happier, Captain Ahab.\"\n\n\"Devils!  Dost thou then so much as dare to critically think of\nme?--On deck!\"\n\n\"Nay, sir, not yet; I do entreat.  And I do dare, sir--to be\nforbearing!  Shall we not understand each other better than hitherto,\nCaptain Ahab?\"\n\nAhab seized a loaded musket from the rack (forming part of most\nSouth-Sea-men's cabin furniture), and pointing it towards Starbuck,\nexclaimed: \"There is one God that is Lord over the earth, and one\nCaptain that is lord over the Pequod.--On deck!\"\n\nFor an instant in the flashing eyes of the mate, and his fiery\ncheeks, you would have almost thought that he had really received the\nblaze of the levelled tube.  But, mastering his emotion, he half\ncalmly rose, and as he quitted the cabin, paused for an instant and\nsaid: \"Thou hast outraged, not insulted me, sir; but for that I ask\nthee not to beware of Starbuck; thou wouldst but laugh; but let Ahab\nbeware of Ahab; beware of thyself, old man.\"\n\n\"He waxes brave, but nevertheless obeys; most careful bravery that!\"\nmurmured Ahab, as Starbuck disappeared.  \"What's that he said--Ahab\nbeware of Ahab--there's something there!\"  Then unconsciously using\nthe musket for a staff, with an iron brow he paced to and fro in the\nlittle cabin; but presently the thick plaits of his forehead relaxed,\nand returning the gun to the rack, he went to the deck.\n\n\"Thou art but too good a fellow, Starbuck,\" he said lowly to the\nmate; then raising his voice to the crew: \"Furl the t'gallant-sails,\nand close-reef the top-sails, fore and aft; back the main-yard; up\nBurton, and break out in the main-hold.\"\n\nIt were perhaps vain to surmise exactly why it was, that as\nrespecting Starbuck, Ahab thus acted.  It may have been a flash of\nhonesty in him; or mere prudential policy which, under the\ncircumstance, imperiously forbade the slightest symptom of open\ndisaffection, however transient, in the important chief officer of\nhis ship.  However it was, his orders were executed; and the Burtons\nwere hoisted.\n\n\n\nCHAPTER 110\n\nQueequeg in His Coffin.\n\n\nUpon searching, it was found that the casks last struck into the hold\nwere perfectly sound, and that the leak must be further off.  So, it\nbeing calm weather, they broke out deeper and deeper, disturbing the\nslumbers of the huge ground-tier butts; and from that black midnight\nsending those gigantic moles into the daylight above.  So deep did\nthey go; and so ancient, and corroded, and weedy the aspect of the\nlowermost puncheons, that you almost looked next for some mouldy\ncorner-stone cask containing coins of Captain Noah, with copies of\nthe posted placards, vainly warning the infatuated old world from the\nflood.  Tierce after tierce, too, of water, and bread, and beef, and\nshooks of staves, and iron bundles of hoops, were hoisted out, till\nat last the piled decks were hard to get about; and the hollow hull\nechoed under foot, as if you were treading over empty catacombs, and\nreeled and rolled in the sea like an air-freighted demijohn.\nTop-heavy was the ship as a dinnerless student with all Aristotle in\nhis head.  Well was it that the Typhoons did not visit them then.\n\nNow, at this time it was that my poor pagan companion, and fast\nbosom-friend, Queequeg, was seized with a fever, which brought him\nnigh to his endless end.\n\nBe it said, that in this vocation of whaling, sinecures are unknown;\ndignity and danger go hand in hand; till you get to be Captain, the\nhigher you rise the harder you toil.  So with poor Queequeg, who, as\nharpooneer, must not only face all the rage of the living whale,\nbut--as we have elsewhere seen--mount his dead back in a rolling sea;\nand finally descend into the gloom of the hold, and bitterly sweating\nall day in that subterraneous confinement, resolutely manhandle the\nclumsiest casks and see to their stowage.  To be short, among\nwhalemen, the harpooneers are the holders, so called.\n\nPoor Queequeg! when the ship was about half disembowelled, you should\nhave stooped over the hatchway, and peered down upon him there;\nwhere, stripped to his woollen drawers, the tattooed savage was\ncrawling about amid that dampness and slime, like a green spotted\nlizard at the bottom of a well.  And a well, or an ice-house, it\nsomehow proved to him, poor pagan; where, strange to say, for all the\nheat of his sweatings, he caught a terrible chill which lapsed into a\nfever; and at last, after some days' suffering, laid him in his\nhammock, close to the very sill of the door of death.  How he wasted\nand wasted away in those few long-lingering days, till there seemed\nbut little left of him but his frame and tattooing.  But as all else\nin him thinned, and his cheek-bones grew sharper, his eyes,\nnevertheless, seemed growing fuller and fuller; they became of a\nstrange softness of lustre; and mildly but deeply looked out at you\nthere from his sickness, a wondrous testimony to that immortal health\nin him which could not die, or be weakened.  And like circles on the\nwater, which, as they grow fainter, expand; so his eyes seemed\nrounding and rounding, like the rings of Eternity.  An awe that\ncannot be named would steal over you as you sat by the side of this\nwaning savage, and saw as strange things in his face, as any beheld\nwho were bystanders when Zoroaster died.  For whatever is truly\nwondrous and fearful in man, never yet was put into words or books.\nAnd the drawing near of Death, which alike levels all, alike\nimpresses all with a last revelation, which only an author from the\ndead could adequately tell.  So that--let us say it again--no dying\nChaldee or Greek had higher and holier thoughts than those, whose\nmysterious shades you saw creeping over the face of poor Queequeg, as\nhe quietly lay in his swaying hammock, and the rolling sea seemed\ngently rocking him to his final rest, and the ocean's invisible\nflood-tide lifted him higher and higher towards his destined heaven.\n\nNot a man of the crew but gave him up; and, as for Queequeg himself,\nwhat he thought of his case was forcibly shown by a curious favour he\nasked.  He called one to him in the grey morning watch, when the day\nwas just breaking, and taking his hand, said that while in Nantucket\nhe had chanced to see certain little canoes of dark wood, like the\nrich war-wood of his native isle; and upon inquiry, he had learned\nthat all whalemen who died in Nantucket, were laid in those same dark\ncanoes, and that the fancy of being so laid had much pleased him; for\nit was not unlike the custom of his own race, who, after embalming a\ndead warrior, stretched him out in his canoe, and so left him to be\nfloated away to the starry archipelagoes; for not only do they\nbelieve that the stars are isles, but that far beyond all visible\nhorizons, their own mild, uncontinented seas, interflow with the blue\nheavens; and so form the white breakers of the milky way.  He added,\nthat he shuddered at the thought of being buried in his hammock,\naccording to the usual sea-custom, tossed like something vile to the\ndeath-devouring sharks.  No: he desired a canoe like those of\nNantucket, all the more congenial to him, being a whaleman, that like\na whale-boat these coffin-canoes were without a keel; though that\ninvolved but uncertain steering, and much lee-way adown the dim ages.\n\nNow, when this strange circumstance was made known aft, the carpenter\nwas at once commanded to do Queequeg's bidding, whatever it might\ninclude.  There was some heathenish, coffin-coloured old lumber\naboard, which, upon a long previous voyage, had been cut from the\naboriginal groves of the Lackaday islands, and from these dark planks\nthe coffin was recommended to be made.  No sooner was the carpenter\napprised of the order, than taking his rule, he forthwith with all\nthe indifferent promptitude of his character, proceeded into the\nforecastle and took Queequeg's measure with great accuracy, regularly\nchalking Queequeg's person as he shifted the rule.\n\n\"Ah! poor fellow! he'll have to die now,\" ejaculated the Long Island\nsailor.\n\nGoing to his vice-bench, the carpenter for convenience sake and\ngeneral reference, now transferringly measured on it the exact length\nthe coffin was to be, and then made the transfer permanent by cutting\ntwo notches at its extremities.  This done, he marshalled the planks\nand his tools, and to work.\n\nWhen the last nail was driven, and the lid duly planed and fitted, he\nlightly shouldered the coffin and went forward with it, inquiring\nwhether they were ready for it yet in that direction.\n\nOverhearing the indignant but half-humorous cries with which the\npeople on deck began to drive the coffin away, Queequeg, to every\none's consternation, commanded that the thing should be instantly\nbrought to him, nor was there any denying him; seeing that, of all\nmortals, some dying men are the most tyrannical; and certainly, since\nthey will shortly trouble us so little for evermore, the poor fellows\nought to be indulged.\n\nLeaning over in his hammock, Queequeg long regarded the coffin with\nan attentive eye.  He then called for his harpoon, had the wooden\nstock drawn from it, and then had the iron part placed in the coffin\nalong with one of the paddles of his boat.  All by his own request,\nalso, biscuits were then ranged round the sides within: a flask of\nfresh water was placed at the head, and a small bag of woody earth\nscraped up in the hold at the foot; and a piece of sail-cloth being\nrolled up for a pillow, Queequeg now entreated to be lifted into his\nfinal bed, that he might make trial of its comforts, if any it had.\nHe lay without moving a few minutes, then told one to go to his bag\nand bring out his little god, Yojo.  Then crossing his arms on his\nbreast with Yojo between, he called for the coffin lid (hatch he\ncalled it) to be placed over him.  The head part turned over with a\nleather hinge, and there lay Queequeg in his coffin with little but\nhis composed countenance in view.  \"Rarmai\" (it will do; it is easy),\nhe murmured at last, and signed to be replaced in his hammock.\n\nBut ere this was done, Pip, who had been slily hovering near by all\nthis while, drew nigh to him where he lay, and with soft sobbings,\ntook him by the hand; in the other, holding his tambourine.\n\n\"Poor rover! will ye never have done with all this weary roving?\nwhere go ye now?  But if the currents carry ye to those sweet\nAntilles where the beaches are only beat with water-lilies, will ye\ndo one little errand for me?  Seek out one Pip, who's now been\nmissing long: I think he's in those far Antilles.  If ye find him,\nthen comfort him; for he must be very sad; for look! he's left his\ntambourine behind;--I found it.  Rig-a-dig, dig, dig!  Now, Queequeg,\ndie; and I'll beat ye your dying march.\"\n\n\"I have heard,\" murmured Starbuck, gazing down the scuttle, \"that in\nviolent fevers, men, all ignorance, have talked in ancient tongues;\nand that when the mystery is probed, it turns out always that in\ntheir wholly forgotten childhood those ancient tongues had been\nreally spoken in their hearing by some lofty scholars.  So, to my\nfond faith, poor Pip, in this strange sweetness of his lunacy, brings\nheavenly vouchers of all our heavenly homes.  Where learned he that,\nbut there?--Hark! he speaks again: but more wildly now.\"\n\n\"Form two and two!  Let's make a General of him!  Ho, where's his\nharpoon?  Lay it across here.--Rig-a-dig, dig, dig! huzza!  Oh for a\ngame cock now to sit upon his head and crow!  Queequeg dies\ngame!--mind ye that; Queequeg dies game!--take ye good heed of that;\nQueequeg dies game!  I say; game, game, game! but base little Pip, he\ndied a coward; died all a'shiver;--out upon Pip!  Hark ye; if ye find\nPip, tell all the Antilles he's a runaway; a coward, a coward, a\ncoward!  Tell them he jumped from a whale-boat!  I'd never beat my\ntambourine over base Pip, and hail him General, if he were once more\ndying here.  No, no! shame upon all cowards--shame upon them!  Let 'em\ngo drown like Pip, that jumped from a whale-boat.  Shame! shame!\"\n\nDuring all this, Queequeg lay with closed eyes, as if in a dream.\nPip was led away, and the sick man was replaced in his hammock.\n\nBut now that he had apparently made every preparation for death; now\nthat his coffin was proved a good fit, Queequeg suddenly rallied;\nsoon there seemed no need of the carpenter's box: and thereupon,\nwhen some expressed their delighted surprise, he, in substance, said,\nthat the cause of his sudden convalescence was this;--at a critical\nmoment, he had just recalled a little duty ashore, which he was\nleaving undone; and therefore had changed his mind about dying: he\ncould not die yet, he averred.  They asked him, then, whether to live\nor die was a matter of his own sovereign will and pleasure.  He\nanswered, certainly.  In a word, it was Queequeg's conceit, that if a\nman made up his mind to live, mere sickness could not kill him:\nnothing but a whale, or a gale, or some violent, ungovernable,\nunintelligent destroyer of that sort.\n\nNow, there is this noteworthy difference between savage and\ncivilized; that while a sick, civilized man may be six months\nconvalescing, generally speaking, a sick savage is almost half-well\nagain in a day.  So, in good time my Queequeg gained strength; and at\nlength after sitting on the windlass for a few indolent days (but\neating with a vigorous appetite) he suddenly leaped to his feet,\nthrew out his arms and legs, gave himself a good stretching, yawned\na little bit, and then springing into the head of his hoisted boat,\nand poising a harpoon, pronounced himself fit for a fight.\n\nWith a wild whimsiness, he now used his coffin for a sea-chest; and\nemptying into it his canvas bag of clothes, set them in order there.\nMany spare hours he spent, in carving the lid with all manner of\ngrotesque figures and drawings; and it seemed that hereby he was\nstriving, in his rude way, to copy parts of the twisted tattooing on\nhis body.  And this tattooing had been the work of a departed\nprophet and seer of his island, who, by those hieroglyphic marks, had\nwritten out on his body a complete theory of the heavens and the\nearth, and a mystical treatise on the art of attaining truth; so that\nQueequeg in his own proper person was a riddle to unfold; a wondrous\nwork in one volume; but whose mysteries not even himself could read,\nthough his own live heart beat against them; and these mysteries were\ntherefore destined in the end to moulder away with the living\nparchment whereon they were inscribed, and so be unsolved to the\nlast.  And this thought it must have been which suggested to Ahab\nthat wild exclamation of his, when one morning turning away from\nsurveying poor Queequeg--\"Oh, devilish tantalization of the gods!\"\n\n\n\nCHAPTER 111\n\nThe Pacific.\n\n\nWhen gliding by the Bashee isles we emerged at last upon the great\nSouth Sea; were it not for other things, I could have greeted my dear\nPacific with uncounted thanks, for now the long supplication of my\nyouth was answered; that serene ocean rolled eastwards from me a\nthousand leagues of blue.\n\nThere is, one knows not what sweet mystery about this sea, whose\ngently awful stirrings seem to speak of some hidden soul beneath;\nlike those fabled undulations of the Ephesian sod over the buried\nEvangelist St. John.  And meet it is, that over these sea-pastures,\nwide-rolling watery prairies and Potters' Fields of all four\ncontinents, the waves should rise and fall, and ebb and flow\nunceasingly; for here, millions of mixed shades and shadows, drowned\ndreams, somnambulisms, reveries; all that we call lives and souls,\nlie dreaming, dreaming, still; tossing like slumberers in their beds;\nthe ever-rolling waves but made so by their restlessness.\n\nTo any meditative Magian rover, this serene Pacific, once beheld,\nmust ever after be the sea of his adoption.  It rolls the midmost\nwaters of the world, the Indian ocean and Atlantic being but its\narms.  The same waves wash the moles of the new-built Californian\ntowns, but yesterday planted by the recentest race of men, and lave\nthe faded but still gorgeous skirts of Asiatic lands, older than\nAbraham; while all between float milky-ways of coral isles, and\nlow-lying, endless, unknown Archipelagoes, and impenetrable Japans.\nThus this mysterious, divine Pacific zones the world's whole bulk\nabout; makes all coasts one bay to it; seems the tide-beating heart\nof earth.  Lifted by those eternal swells, you needs must own the\nseductive god, bowing your head to Pan.\n\nBut few thoughts of Pan stirred Ahab's brain, as standing like an\niron statue at his accustomed place beside the mizen rigging, with\none nostril he unthinkingly snuffed the sugary musk from the Bashee\nisles (in whose sweet woods mild lovers must be walking), and with\nthe other consciously inhaled the salt breath of the new found sea;\nthat sea in which the hated White Whale must even then be swimming.\nLaunched at length upon these almost final waters, and gliding\ntowards the Japanese cruising-ground, the old man's purpose\nintensified itself.  His firm lips met like the lips of a vice; the\nDelta of his forehead's veins swelled like overladen brooks; in his\nvery sleep, his ringing cry ran through the vaulted hull, \"Stern all!\nthe White Whale spouts thick blood!\"\n\n\n\nCHAPTER 112\n\nThe Blacksmith.\n\n\nAvailing himself of the mild, summer-cool weather that now reigned\nin these latitudes, and in preparation for the peculiarly active\npursuits shortly to be anticipated, Perth, the begrimed, blistered\nold blacksmith, had not removed his portable forge to the hold again,\nafter concluding his contributory work for Ahab's leg, but still\nretained it on deck, fast lashed to ringbolts by the foremast; being\nnow almost incessantly invoked by the headsmen, and harpooneers, and\nbowsmen to do some little job for them; altering, or repairing, or\nnew shaping their various weapons and boat furniture.  Often he would\nbe surrounded by an eager circle, all waiting to be served; holding\nboat-spades, pike-heads, harpoons, and lances, and jealously watching\nhis every sooty movement, as he toiled.  Nevertheless, this old man's\nwas a patient hammer wielded by a patient arm.  No murmur, no\nimpatience, no petulance did come from him.  Silent, slow, and\nsolemn; bowing over still further his chronically broken back, he\ntoiled away, as if toil were life itself, and the heavy beating of\nhis hammer the heavy beating of his heart.  And so it was.--Most\nmiserable!\n\nA peculiar walk in this old man, a certain slight but painful\nappearing yawing in his gait, had at an early period of the voyage\nexcited the curiosity of the mariners.  And to the importunity of\ntheir persisted questionings he had finally given in; and so it came\nto pass that every one now knew the shameful story of his wretched\nfate.\n\nBelated, and not innocently, one bitter winter's midnight, on the\nroad running between two country towns, the blacksmith half-stupidly\nfelt the deadly numbness stealing over him, and sought refuge in a\nleaning, dilapidated barn.  The issue was, the loss of the\nextremities of both feet.  Out of this revelation, part by part, at\nlast came out the four acts of the gladness, and the one long, and as\nyet uncatastrophied fifth act of the grief of his life's drama.\n\nHe was an old man, who, at the age of nearly sixty, had postponedly\nencountered that thing in sorrow's technicals called ruin.  He had\nbeen an artisan of famed excellence, and with plenty to do; owned a\nhouse and garden; embraced a youthful, daughter-like, loving wife,\nand three blithe, ruddy children; every Sunday went to a\ncheerful-looking church, planted in a grove.  But one night, under\ncover of darkness, and further concealed in a most cunning\ndisguisement, a desperate burglar slid into his happy home, and\nrobbed them all of everything.  And darker yet to tell, the\nblacksmith himself did ignorantly conduct this burglar into his\nfamily's heart.  It was the Bottle Conjuror!  Upon the opening of\nthat fatal cork, forth flew the fiend, and shrivelled up his home.\nNow, for prudent, most wise, and economic reasons, the blacksmith's\nshop was in the basement of his dwelling, but with a separate\nentrance to it; so that always had the young and loving healthy wife\nlistened with no unhappy nervousness, but with vigorous pleasure, to\nthe stout ringing of her young-armed old husband's hammer; whose\nreverberations, muffled by passing through the floors and walls, came\nup to her, not unsweetly, in her nursery; and so, to stout Labor's\niron lullaby, the blacksmith's infants were rocked to slumber.\n\nOh, woe on woe!  Oh, Death, why canst thou not sometimes be timely?\nHadst thou taken this old blacksmith to thyself ere his full ruin\ncame upon him, then had the young widow had a delicious grief, and\nher orphans a truly venerable, legendary sire to dream of in their\nafter years; and all of them a care-killing competency.  But Death\nplucked down some virtuous elder brother, on whose whistling daily\ntoil solely hung the responsibilities of some other family, and left\nthe worse than useless old man standing, till the hideous rot of life\nshould make him easier to harvest.\n\nWhy tell the whole?  The blows of the basement hammer every day grew\nmore and more between; and each blow every day grew fainter than the\nlast; the wife sat frozen at the window, with tearless eyes,\nglitteringly gazing into the weeping faces of her children; the\nbellows fell; the forge choked up with cinders; the house was sold;\nthe mother dived down into the long church-yard grass; her children\ntwice followed her thither; and the houseless, familyless old man\nstaggered off a vagabond in crape; his every woe unreverenced; his\ngrey head a scorn to flaxen curls!\n\nDeath seems the only desirable sequel for a career like this; but\nDeath is only a launching into the region of the strange Untried; it\nis but the first salutation to the possibilities of the immense\nRemote, the Wild, the Watery, the Unshored; therefore, to the\ndeath-longing eyes of such men, who still have left in them some\ninterior compunctions against suicide, does the all-contributed and\nall-receptive ocean alluringly spread forth his whole plain of\nunimaginable, taking terrors, and wonderful, new-life adventures; and\nfrom the hearts of infinite Pacifics, the thousand mermaids sing to\nthem--\"Come hither, broken-hearted; here is another life without the\nguilt of intermediate death; here are wonders supernatural, without\ndying for them.  Come hither! bury thyself in a life which, to your\nnow equally abhorred and abhorring, landed world, is more oblivious\nthan death.  Come hither! put up THY gravestone, too, within the\nchurchyard, and come hither, till we marry thee!\"\n\nHearkening to these voices, East and West, by early sunrise, and by\nfall of eve, the blacksmith's soul responded, Aye, I come!  And so\nPerth went a-whaling.\n\n\n\nCHAPTER 113\n\nThe Forge.\n\n\nWith matted beard, and swathed in a bristling shark-skin apron, about\nmid-day, Perth was standing between his forge and anvil, the latter\nplaced upon an iron-wood log, with one hand holding a pike-head in\nthe coals, and with the other at his forge's lungs, when Captain Ahab\ncame along, carrying in his hand a small rusty-looking leathern bag.\nWhile yet a little distance from the forge, moody Ahab paused; till\nat last, Perth, withdrawing his iron from the fire, began hammering\nit upon the anvil--the red mass sending off the sparks in thick\nhovering flights, some of which flew close to Ahab.\n\n\"Are these thy Mother Carey's chickens, Perth? they are always flying\nin thy wake; birds of good omen, too, but not to all;--look here,\nthey burn; but thou--thou liv'st among them without a scorch.\"\n\n\"Because I am scorched all over, Captain Ahab,\" answered Perth,\nresting for a moment on his hammer; \"I am past scorching; not easily\ncan'st thou scorch a scar.\"\n\n\"Well, well; no more.  Thy shrunk voice sounds too calmly, sanely\nwoeful to me.  In no Paradise myself, I am impatient of all misery in\nothers that is not mad.  Thou should'st go mad, blacksmith; say, why\ndost thou not go mad?  How can'st thou endure without being mad?  Do\nthe heavens yet hate thee, that thou can'st not go mad?--What wert\nthou making there?\"\n\n\"Welding an old pike-head, sir; there were seams and dents in it.\"\n\n\"And can'st thou make it all smooth again, blacksmith, after such\nhard usage as it had?\"\n\n\"I think so, sir.\"\n\n\"And I suppose thou can'st smoothe almost any seams and dents; never\nmind how hard the metal, blacksmith?\"\n\n\"Aye, sir, I think I can; all seams and dents but one.\"\n\n\"Look ye here, then,\" cried Ahab, passionately advancing, and leaning\nwith both hands on Perth's shoulders; \"look ye here--HERE--can ye\nsmoothe out a seam like this, blacksmith,\" sweeping one hand across\nhis ribbed brow; \"if thou could'st, blacksmith, glad enough would I\nlay my head upon thy anvil, and feel thy heaviest hammer between my\neyes.  Answer!  Can'st thou smoothe this seam?\"\n\n\"Oh! that is the one, sir!  Said I not all seams and dents but one?\"\n\n\"Aye, blacksmith, it is the one; aye, man, it is unsmoothable; for\nthough thou only see'st it here in my flesh, it has worked down into\nthe bone of my skull--THAT is all wrinkles!  But, away with child's\nplay; no more gaffs and pikes to-day.  Look ye here!\" jingling the\nleathern bag, as if it were full of gold coins.  \"I, too, want a\nharpoon made; one that a thousand yoke of fiends could not part,\nPerth; something that will stick in a whale like his own fin-bone.\nThere's the stuff,\" flinging the pouch upon the anvil.  \"Look ye,\nblacksmith, these are the gathered nail-stubbs of the steel shoes of\nracing horses.\"\n\n\"Horse-shoe stubbs, sir?  Why, Captain Ahab, thou hast here, then,\nthe best and stubbornest stuff we blacksmiths ever work.\"\n\n\"I know it, old man; these stubbs will weld together like glue from\nthe melted bones of murderers.  Quick! forge me the harpoon.  And\nforge me first, twelve rods for its shank; then wind, and twist, and\nhammer these twelve together like the yarns and strands of a\ntow-line.  Quick!  I'll blow the fire.\"\n\nWhen at last the twelve rods were made, Ahab tried them, one by one,\nby spiralling them, with his own hand, round a long, heavy iron bolt.\n\"A flaw!\" rejecting the last one.  \"Work that over again, Perth.\"\n\nThis done, Perth was about to begin welding the twelve into one, when\nAhab stayed his hand, and said he would weld his own iron.  As, then,\nwith regular, gasping hems, he hammered on the anvil, Perth passing\nto him the glowing rods, one after the other, and the hard pressed\nforge shooting up its intense straight flame, the Parsee passed\nsilently, and bowing over his head towards the fire, seemed invoking\nsome curse or some blessing on the toil.  But, as Ahab looked up, he\nslid aside.\n\n\"What's that bunch of lucifers dodging about there for?\" muttered\nStubb, looking on from the forecastle.  \"That Parsee smells fire like\na fusee; and smells of it himself, like a hot musket's powder-pan.\"\n\nAt last the shank, in one complete rod, received its final heat; and\nas Perth, to temper it, plunged it all hissing into the cask of water\nnear by, the scalding steam shot up into Ahab's bent face.\n\n\"Would'st thou brand me, Perth?\" wincing for a moment with the pain;\n\"have I been but forging my own branding-iron, then?\"\n\n\"Pray God, not that; yet I fear something, Captain Ahab.  Is not this\nharpoon for the White Whale?\"\n\n\"For the white fiend!  But now for the barbs; thou must make them\nthyself, man.  Here are my razors--the best of steel; here, and make\nthe barbs sharp as the needle-sleet of the Icy Sea.\"\n\nFor a moment, the old blacksmith eyed the razors as though he would\nfain not use them.\n\n\"Take them, man, I have no need for them; for I now neither shave,\nsup, nor pray till--but here--to work!\"\n\nFashioned at last into an arrowy shape, and welded by Perth to the\nshank, the steel soon pointed the end of the iron; and as the\nblacksmith was about giving the barbs their final heat, prior to\ntempering them, he cried to Ahab to place the water-cask near.\n\n\"No, no--no water for that; I want it of the true death-temper.\nAhoy, there!  Tashtego, Queequeg, Daggoo!  What say ye, pagans!  Will\nye give me as much blood as will cover this barb?\" holding it high\nup.  A cluster of dark nods replied, Yes.  Three punctures were made\nin the heathen flesh, and the White Whale's barbs were then tempered.\n\n\"Ego non baptizo te in nomine patris, sed in nomine diaboli!\"\ndeliriously howled Ahab, as the malignant iron scorchingly devoured\nthe baptismal blood.\n\nNow, mustering the spare poles from below, and selecting one of\nhickory, with the bark still investing it, Ahab fitted the end to the\nsocket of the iron.  A coil of new tow-line was then unwound, and\nsome fathoms of it taken to the windlass, and stretched to a great\ntension.  Pressing his foot upon it, till the rope hummed like a\nharp-string, then eagerly bending over it, and seeing no strandings,\nAhab exclaimed, \"Good! and now for the seizings.\"\n\nAt one extremity the rope was unstranded, and the separate spread\nyarns were all braided and woven round the socket of the harpoon; the\npole was then driven hard up into the socket; from the lower end the\nrope was traced half-way along the pole's length, and firmly secured\nso, with intertwistings of twine.  This done, pole, iron, and\nrope--like the Three Fates--remained inseparable, and Ahab moodily\nstalked away with the weapon; the sound of his ivory leg, and the\nsound of the hickory pole, both hollowly ringing along every plank.\nBut ere he entered his cabin, light, unnatural, half-bantering, yet\nmost piteous sound was heard.  Oh, Pip! thy wretched laugh, thy\nidle but unresting eye; all thy strange mummeries not unmeaningly\nblended with the black tragedy of the melancholy ship, and mocked it!\n\n\n\nCHAPTER 114\n\nThe Gilder.\n\n\nPenetrating further and further into the heart of the Japanese\ncruising ground, the Pequod was soon all astir in the fishery.\nOften, in mild, pleasant weather, for twelve, fifteen, eighteen, and\ntwenty hours on the stretch, they were engaged in the boats, steadily\npulling, or sailing, or paddling after the whales, or for an\ninterlude of sixty or seventy minutes calmly awaiting their uprising;\nthough with but small success for their pains.\n\nAt such times, under an abated sun; afloat all day upon smooth, slow\nheaving swells; seated in his boat, light as a birch canoe; and so\nsociably mixing with the soft waves themselves, that like\nhearth-stone cats they purr against the gunwale; these are the times\nof dreamy quietude, when beholding the tranquil beauty and brilliancy\nof the ocean's skin, one forgets the tiger heart that pants beneath\nit; and would not willingly remember, that this velvet paw but\nconceals a remorseless fang.\n\nThese are the times, when in his whale-boat the rover softly feels a\ncertain filial, confident, land-like feeling towards the sea; that he\nregards it as so much flowery earth; and the distant ship revealing\nonly the tops of her masts, seems struggling forward, not through\nhigh rolling waves, but through the tall grass of a rolling prairie:\nas when the western emigrants' horses only show their erected ears,\nwhile their hidden bodies widely wade through the amazing verdure.\n\nThe long-drawn virgin vales; the mild blue hill-sides; as over these\nthere steals the hush, the hum; you almost swear that play-wearied\nchildren lie sleeping in these solitudes, in some glad May-time, when\nthe flowers of the woods are plucked.  And all this mixes with your\nmost mystic mood; so that fact and fancy, half-way meeting,\ninterpenetrate, and form one seamless whole.\n\nNor did such soothing scenes, however temporary, fail of at least as\ntemporary an effect on Ahab.  But if these secret golden keys did\nseem to open in him his own secret golden treasuries, yet did his\nbreath upon them prove but tarnishing.\n\nOh, grassy glades! oh, ever vernal endless landscapes in the soul; in\nye,--though long parched by the dead drought of the earthy\nlife,--in ye, men yet may roll, like young horses in new morning\nclover; and for some few fleeting moments, feel the cool dew of the\nlife immortal on them.  Would to God these blessed calms would last.\nBut the mingled, mingling threads of life are woven by warp and woof:\ncalms crossed by storms, a storm for every calm.  There is no steady\nunretracing progress in this life; we do not advance through fixed\ngradations, and at the last one pause:--through infancy's unconscious\nspell, boyhood's thoughtless faith, adolescence' doubt (the common\ndoom), then scepticism, then disbelief, resting at last in manhood's\npondering repose of If.  But once gone through, we trace the round\nagain; and are infants, boys, and men, and Ifs eternally.  Where lies\nthe final harbor, whence we unmoor no more?  In what rapt ether sails\nthe world, of which the weariest will never weary?  Where is the\nfoundling's father hidden?  Our souls are like those orphans whose\nunwedded mothers die in bearing them: the secret of our paternity\nlies in their grave, and we must there to learn it.\n\nAnd that same day, too, gazing far down from his boat's side into\nthat same golden sea, Starbuck lowly murmured:--\n\n\"Loveliness unfathomable, as ever lover saw in his young bride's\neye!--Tell me not of thy teeth-tiered sharks, and thy kidnapping\ncannibal ways.  Let faith oust fact; let fancy oust memory; I look\ndeep down and do believe.\"\n\nAnd Stubb, fish-like, with sparkling scales, leaped up in that same\ngolden light:--\n\n\"I am Stubb, and Stubb has his history; but here Stubb takes oaths\nthat he has always been jolly!\"\n\n\n\nCHAPTER 115\n\nThe Pequod Meets The Bachelor.\n\n\nAnd jolly enough were the sights and the sounds that came bearing\ndown before the wind, some few weeks after Ahab's harpoon had been\nwelded.\n\nIt was a Nantucket ship, the Bachelor, which had just wedged in her\nlast cask of oil, and bolted down her bursting hatches; and now, in\nglad holiday apparel, was joyously, though somewhat vain-gloriously,\nsailing round among the widely-separated ships on the ground,\nprevious to pointing her prow for home.\n\nThe three men at her mast-head wore long streamers of narrow red\nbunting at their hats; from the stern, a whale-boat was suspended,\nbottom down; and hanging captive from the bowsprit was seen the long\nlower jaw of the last whale they had slain.  Signals, ensigns, and\njacks of all colours were flying from her rigging, on every side.\nSideways lashed in each of her three basketed tops were two barrels\nof sperm; above which, in her top-mast cross-trees, you saw slender\nbreakers of the same precious fluid; and nailed to her main truck was\na brazen lamp.\n\nAs was afterwards learned, the Bachelor had met with the most\nsurprising success; all the more wonderful, for that while cruising\nin the same seas numerous other vessels had gone entire months\nwithout securing a single fish.  Not only had barrels of beef and\nbread been given away to make room for the far more valuable sperm,\nbut additional supplemental casks had been bartered for, from the\nships she had met; and these were stowed along the deck, and in the\ncaptain's and officers' state-rooms.  Even the cabin table itself\nhad been knocked into kindling-wood; and the cabin mess dined off the\nbroad head of an oil-butt, lashed down to the floor for a\ncentrepiece.  In the forecastle, the sailors had actually caulked\nand pitched their chests, and filled them; it was humorously added,\nthat the cook had clapped a head on his largest boiler, and filled\nit; that the steward had plugged his spare coffee-pot and filled it;\nthat the harpooneers had headed the sockets of their irons and filled\nthem; that indeed everything was filled with sperm, except the\ncaptain's pantaloons pockets, and those he reserved to thrust his\nhands into, in self-complacent testimony of his entire satisfaction.\n\nAs this glad ship of good luck bore down upon the moody Pequod, the\nbarbarian sound of enormous drums came from her forecastle; and\ndrawing still nearer, a crowd of her men were seen standing round her\nhuge try-pots, which, covered with the parchment-like POKE or stomach\nskin of the black fish, gave forth a loud roar to every stroke of the\nclenched hands of the crew.  On the quarter-deck, the mates and\nharpooneers were dancing with the olive-hued girls who had eloped\nwith them from the Polynesian Isles; while suspended in an\nornamented boat, firmly secured aloft between the foremast and\nmainmast, three Long Island negroes, with glittering fiddle-bows of\nwhale ivory, were presiding over the hilarious jig.  Meanwhile,\nothers of the ship's company were tumultuously busy at the masonry of\nthe try-works, from which the huge pots had been removed.  You would\nhave almost thought they were pulling down the cursed Bastille, such\nwild cries they raised, as the now useless brick and mortar were\nbeing hurled into the sea.\n\nLord and master over all this scene, the captain stood erect on the\nship's elevated quarter-deck, so that the whole rejoicing drama was\nfull before him, and seemed merely contrived for his own individual\ndiversion.\n\nAnd Ahab, he too was standing on his quarter-deck, shaggy and black,\nwith a stubborn gloom; and as the two ships crossed each other's\nwakes--one all jubilations for things passed, the other all\nforebodings as to things to come--their two captains in themselves\nimpersonated the whole striking contrast of the scene.\n\n\"Come aboard, come aboard!\" cried the gay Bachelor's commander,\nlifting a glass and a bottle in the air.\n\n\"Hast seen the White Whale?\" gritted Ahab in reply.\n\n\"No; only heard of him; but don't believe in him at all,\" said the\nother good-humoredly.  \"Come aboard!\"\n\n\"Thou art too damned jolly.  Sail on.  Hast lost any men?\"\n\n\"Not enough to speak of--two islanders, that's all;--but come aboard,\nold hearty, come along.  I'll soon take that black from your brow.\nCome along, will ye (merry's the play); a full ship and\nhomeward-bound.\"\n\n\"How wondrous familiar is a fool!\" muttered Ahab; then aloud, \"Thou\nart a full ship and homeward bound, thou sayst; well, then, call me\nan empty ship, and outward-bound.  So go thy ways, and I will mine.\nForward there!  Set all sail, and keep her to the wind!\"\n\nAnd thus, while the one ship went cheerily before the breeze, the\nother stubbornly fought against it; and so the two vessels parted;\nthe crew of the Pequod looking with grave, lingering glances towards\nthe receding Bachelor; but the Bachelor's men never heeding their\ngaze for the lively revelry they were in.  And as Ahab, leaning over\nthe taffrail, eyed the homewardbound craft, he took from his pocket a\nsmall vial of sand, and then looking from the ship to the vial,\nseemed thereby bringing two remote associations together, for that\nvial was filled with Nantucket soundings.\n\n\n\nCHAPTER 116\n\nThe Dying Whale.\n\n\nNot seldom in this life, when, on the right side, fortune's favourites\nsail close by us, we, though all adroop before, catch somewhat of the\nrushing breeze, and joyfully feel our bagging sails fill out.  So\nseemed it with the Pequod.  For next day after encountering the gay\nBachelor, whales were seen and four were slain; and one of them by\nAhab.\n\nIt was far down the afternoon; and when all the spearings of the\ncrimson fight were done: and floating in the lovely sunset sea and\nsky, sun and whale both stilly died together; then, such a sweetness\nand such plaintiveness, such inwreathing orisons curled up in that\nrosy air, that it almost seemed as if far over from the deep green\nconvent valleys of the Manilla isles, the Spanish land-breeze,\nwantonly turned sailor, had gone to sea, freighted with these vesper\nhymns.\n\nSoothed again, but only soothed to deeper gloom, Ahab, who had\nsterned off from the whale, sat intently watching his final wanings\nfrom the now tranquil boat.  For that strange spectacle observable in\nall sperm whales dying--the turning sunwards of the head, and so\nexpiring--that strange spectacle, beheld of such a placid evening,\nsomehow to Ahab conveyed a wondrousness unknown before.\n\n\"He turns and turns him to it,--how slowly, but how steadfastly, his\nhomage-rendering and invoking brow, with his last dying motions.  He\ntoo worships fire; most faithful, broad, baronial vassal of the\nsun!--Oh that these too-favouring eyes should see these too-favouring\nsights.  Look! here, far water-locked; beyond all hum of human weal\nor woe; in these most candid and impartial seas; where to traditions\nno rocks furnish tablets; where for long Chinese ages, the billows\nhave still rolled on speechless and unspoken to, as stars that shine\nupon the Niger's unknown source; here, too, life dies sunwards full\nof faith; but see! no sooner dead, than death whirls round the\ncorpse, and it heads some other way.\n\n\"Oh, thou dark Hindoo half of nature, who of drowned bones hast\nbuilded thy separate throne somewhere in the heart of these\nunverdured seas; thou art an infidel, thou queen, and too truly\nspeakest to me in the wide-slaughtering Typhoon, and the hushed\nburial of its after calm.  Nor has this thy whale sunwards turned his\ndying head, and then gone round again, without a lesson to me.\n\n\"Oh, trebly hooped and welded hip of power!  Oh, high aspiring,\nrainbowed jet!--that one strivest, this one jettest all in vain!  In\nvain, oh whale, dost thou seek intercedings with yon all-quickening\nsun, that only calls forth life, but gives it not again.  Yet dost\nthou, darker half, rock me with a prouder, if a darker faith.  All\nthy unnamable imminglings float beneath me here; I am buoyed by\nbreaths of once living things, exhaled as air, but water now.\n\n\"Then hail, for ever hail, O sea, in whose eternal tossings the wild\nfowl finds his only rest.  Born of earth, yet suckled by the sea;\nthough hill and valley mothered me, ye billows are my\nfoster-brothers!\"\n\n\n\nCHAPTER 117\n\nThe Whale Watch.\n\n\nThe four whales slain that evening had died wide apart; one, far to\nwindward; one, less distant, to leeward; one ahead; one astern.\nThese last three were brought alongside ere nightfall; but the\nwindward one could not be reached till morning; and the boat that had\nkilled it lay by its side all night; and that boat was Ahab's.\n\nThe waif-pole was thrust upright into the dead whale's spout-hole;\nand the lantern hanging from its top, cast a troubled flickering\nglare upon the black, glossy back, and far out upon the midnight\nwaves, which gently chafed the whale's broad flank, like soft surf\nupon a beach.\n\nAhab and all his boat's crew seemed asleep but the Parsee; who\ncrouching in the bow, sat watching the sharks, that spectrally played\nround the whale, and tapped the light cedar planks with their tails.\nA sound like the moaning in squadrons over Asphaltites of unforgiven\nghosts of Gomorrah, ran shuddering through the air.\n\nStarted from his slumbers, Ahab, face to face, saw the Parsee; and\nhooped round by the gloom of the night they seemed the last men in a\nflooded world.  \"I have dreamed it again,\" said he.\n\n\"Of the hearses?  Have I not said, old man, that neither hearse nor\ncoffin can be thine?\"\n\n\"And who are hearsed that die on the sea?\"\n\n\"But I said, old man, that ere thou couldst die on this voyage, two\nhearses must verily be seen by thee on the sea; the first not made by\nmortal hands; and the visible wood of the last one must be grown in\nAmerica.\"\n\n\"Aye, aye! a strange sight that, Parsee:--a hearse and its plumes\nfloating over the ocean with the waves for the pall-bearers.  Ha!\nSuch a sight we shall not soon see.\"\n\n\"Believe it or not, thou canst not die till it be seen, old man.\"\n\n\"And what was that saying about thyself?\"\n\n\"Though it come to the last, I shall still go before thee thy pilot.\"\n\n\"And when thou art so gone before--if that ever befall--then ere I\ncan follow, thou must still appear to me, to pilot me still?--Was it\nnot so?  Well, then, did I believe all ye say, oh my pilot!  I have\nhere two pledges that I shall yet slay Moby Dick and survive it.\"\n\n\"Take another pledge, old man,\" said the Parsee, as his eyes lighted\nup like fire-flies in the gloom--\"Hemp only can kill thee.\"\n\n\"The gallows, ye mean.--I am immortal then, on land and on sea,\"\ncried Ahab, with a laugh of derision;--\"Immortal on land and on sea!\"\n\nBoth were silent again, as one man.  The grey dawn came on, and the\nslumbering crew arose from the boat's bottom, and ere noon the dead\nwhale was brought to the ship.\n\n\n\nCHAPTER 118\n\nThe Quadrant.\n\n\nThe season for the Line at length drew near; and every day when Ahab,\ncoming from his cabin, cast his eyes aloft, the vigilant helmsman\nwould ostentatiously handle his spokes, and the eager mariners\nquickly run to the braces, and would stand there with all their eyes\ncentrally fixed on the nailed doubloon; impatient for the order to\npoint the ship's prow for the equator.  In good time the order came.\nIt was hard upon high noon; and Ahab, seated in the bows of his\nhigh-hoisted boat, was about taking his wonted daily observation of\nthe sun to determine his latitude.\n\nNow, in that Japanese sea, the days in summer are as freshets of\neffulgences.  That unblinkingly vivid Japanese sun seems the blazing\nfocus of the glassy ocean's immeasurable burning-glass.  The sky\nlooks lacquered; clouds there are none; the horizon floats; and this\nnakedness of unrelieved radiance is as the insufferable splendors of\nGod's throne.  Well that Ahab's quadrant was furnished with coloured\nglasses, through which to take sight of that solar fire.  So,\nswinging his seated form to the roll of the ship, and with his\nastrological-looking instrument placed to his eye, he remained in\nthat posture for some moments to catch the precise instant when the\nsun should gain its precise meridian.  Meantime while his whole\nattention was absorbed, the Parsee was kneeling beneath him on the\nship's deck, and with face thrown up like Ahab's, was eyeing the same\nsun with him; only the lids of his eyes half hooded their orbs, and\nhis wild face was subdued to an earthly passionlessness.  At length\nthe desired observation was taken; and with his pencil upon his ivory\nleg, Ahab soon calculated what his latitude must be at that precise\ninstant.  Then falling into a moment's revery, he again looked up\ntowards the sun and murmured to himself: \"Thou sea-mark! thou high\nand mighty Pilot! thou tellest me truly where I AM--but canst thou\ncast the least hint where I SHALL be?  Or canst thou tell where some\nother thing besides me is this moment living?  Where is Moby Dick?\nThis instant thou must be eyeing him.  These eyes of mine look into\nthe very eye that is even now beholding him; aye, and into the eye\nthat is even now equally beholding the objects on the unknown,\nthither side of thee, thou sun!\"\n\nThen gazing at his quadrant, and handling, one after the other, its\nnumerous cabalistical contrivances, he pondered again, and muttered:\n\"Foolish toy! babies' plaything of haughty Admirals, and Commodores,\nand Captains; the world brags of thee, of thy cunning and might; but\nwhat after all canst thou do, but tell the poor, pitiful point, where\nthou thyself happenest to be on this wide planet, and the hand that\nholds thee: no! not one jot more!  Thou canst not tell where one drop\nof water or one grain of sand will be to-morrow noon; and yet with\nthy impotence thou insultest the sun!  Science!  Curse thee, thou\nvain toy; and cursed be all the things that cast man's eyes aloft to\nthat heaven, whose live vividness but scorches him, as these old eyes\nare even now scorched with thy light, O sun!  Level by nature to this\nearth's horizon are the glances of man's eyes; not shot from the\ncrown of his head, as if God had meant him to gaze on his firmament.\nCurse thee, thou quadrant!\" dashing it to the deck, \"no longer will I\nguide my earthly way by thee; the level ship's compass, and the level\ndeadreckoning, by log and by line; THESE shall conduct me, and show\nme my place on the sea.  Aye,\" lighting from the boat to the deck,\n\"thus I trample on thee, thou paltry thing that feebly pointest on\nhigh; thus I split and destroy thee!\"\n\nAs the frantic old man thus spoke and thus trampled with his live and\ndead feet, a sneering triumph that seemed meant for Ahab, and a\nfatalistic despair that seemed meant for himself--these passed over\nthe mute, motionless Parsee's face.  Unobserved he rose and glided\naway; while, awestruck by the aspect of their commander, the seamen\nclustered together on the forecastle, till Ahab, troubledly pacing\nthe deck, shouted out--\"To the braces!  Up helm!--square in!\"\n\nIn an instant the yards swung round; and as the ship half-wheeled\nupon her heel, her three firm-seated graceful masts erectly poised\nupon her long, ribbed hull, seemed as the three Horatii pirouetting\non one sufficient steed.\n\nStanding between the knight-heads, Starbuck watched the Pequod's\ntumultuous way, and Ahab's also, as he went lurching along the deck.\n\n\"I have sat before the dense coal fire and watched it all aglow, full\nof its tormented flaming life; and I have seen it wane at last, down,\ndown, to dumbest dust.  Old man of oceans! of all this fiery life of\nthine, what will at length remain but one little heap of ashes!\"\n\n\"Aye,\" cried Stubb, \"but sea-coal ashes--mind ye that, Mr.\nStarbuck--sea-coal, not your common charcoal.  Well, well; I heard\nAhab mutter, 'Here some one thrusts these cards into these old hands\nof mine; swears that I must play them, and no others.'  And damn me,\nAhab, but thou actest right; live in the game, and die in it!\"\n\n\n\nCHAPTER 119\n\nThe Candles.\n\n\nWarmest climes but nurse the cruellest fangs: the tiger of Bengal\ncrouches in spiced groves of ceaseless verdure.  Skies the most\neffulgent but basket the deadliest thunders: gorgeous Cuba knows\ntornadoes that never swept tame northern lands.  So, too, it is, that\nin these resplendent Japanese seas the mariner encounters the direst\nof all storms, the Typhoon.  It will sometimes burst from out that\ncloudless sky, like an exploding bomb upon a dazed and sleepy town.\n\nTowards evening of that day, the Pequod was torn of her canvas, and\nbare-poled was left to fight a Typhoon which had struck her directly\nahead.  When darkness came on, sky and sea roared and split with the\nthunder, and blazed with the lightning, that showed the disabled\nmasts fluttering here and there with the rags which the first fury of\nthe tempest had left for its after sport.\n\nHolding by a shroud, Starbuck was standing on the quarter-deck; at\nevery flash of the lightning glancing aloft, to see what additional\ndisaster might have befallen the intricate hamper there; while Stubb\nand Flask were directing the men in the higher hoisting and firmer\nlashing of the boats.  But all their pains seemed naught.  Though\nlifted to the very top of the cranes, the windward quarter boat\n(Ahab's) did not escape.  A great rolling sea, dashing high up\nagainst the reeling ship's high teetering side, stove in the boat's\nbottom at the stern, and left it again, all dripping through like a\nsieve.\n\n\"Bad work, bad work!  Mr. Starbuck,\" said Stubb, regarding the wreck,\n\"but the sea will have its way.  Stubb, for one, can't fight it.  You\nsee, Mr. Starbuck, a wave has such a great long start before it\nleaps, all round the world it runs, and then comes the spring!  But\nas for me, all the start I have to meet it, is just across the deck\nhere.  But never mind; it's all in fun: so the old song\nsays;\"--(SINGS.)\n\nOh! jolly is the gale,\nAnd a joker is the whale,\nA' flourishin' his tail,--\nSuch a funny, sporty, gamy, jesty, joky, hoky-poky lad, is the Ocean, oh!\n\nThe scud all a flyin',\nThat's his flip only foamin';\nWhen he stirs in the spicin',--\nSuch a funny, sporty, gamy, jesty, joky, hoky-poky lad, is the Ocean, oh!\n\nThunder splits the ships,\nBut he only smacks his lips,\nA tastin' of this flip,--\nSuch a funny, sporty, gamy, jesty, joky, hoky-poky lad, is the Ocean, oh!\n\n\n\"Avast Stubb,\" cried Starbuck, \"let the Typhoon sing, and strike his\nharp here in our rigging; but if thou art a brave man thou wilt hold\nthy peace.\"\n\n\"But I am not a brave man; never said I was a brave man; I am a\ncoward; and I sing to keep up my spirits.  And I tell you what it is,\nMr. Starbuck, there's no way to stop my singing in this world but to\ncut my throat.  And when that's done, ten to one I sing ye the\ndoxology for a wind-up.\"\n\n\"Madman! look through my eyes if thou hast none of thine own.\"\n\n\"What! how can you see better of a dark night than anybody else,\nnever mind how foolish?\"\n\n\"Here!\" cried Starbuck, seizing Stubb by the shoulder, and pointing\nhis hand towards the weather bow, \"markest thou not that the gale\ncomes from the eastward, the very course Ahab is to run for Moby\nDick? the very course he swung to this day noon? now mark his boat\nthere; where is that stove?  In the stern-sheets, man; where he is\nwont to stand--his stand-point is stove, man!  Now jump overboard,\nand sing away, if thou must!\n\n\"I don't half understand ye: what's in the wind?\"\n\n\"Yes, yes, round the Cape of Good Hope is the shortest way to\nNantucket,\" soliloquized Starbuck suddenly, heedless of Stubb's\nquestion.  \"The gale that now hammers at us to stave us, we can turn\nit into a fair wind that will drive us towards home.  Yonder, to\nwindward, all is blackness of doom; but to leeward, homeward--I see\nit lightens up there; but not with the lightning.\"\n\nAt that moment in one of the intervals of profound darkness,\nfollowing the flashes, a voice was heard at his side; and almost at\nthe same instant a volley of thunder peals rolled overhead.\n\n\"Who's there?\"\n\n\"Old Thunder!\" said Ahab, groping his way along the bulwarks to his\npivot-hole; but suddenly finding his path made plain to him by\nelbowed lances of fire.\n\nNow, as the lightning rod to a spire on shore is intended to carry\noff the perilous fluid into the soil; so the kindred rod which at sea\nsome ships carry to each mast, is intended to conduct it into the\nwater.  But as this conductor must descend to considerable depth,\nthat its end may avoid all contact with the hull; and as moreover, if\nkept constantly towing there, it would be liable to many mishaps,\nbesides interfering not a little with some of the rigging, and more\nor less impeding the vessel's way in the water; because of all this,\nthe lower parts of a ship's lightning-rods are not always overboard;\nbut are generally made in long slender links, so as to be the more\nreadily hauled up into the chains outside, or thrown down into the\nsea, as occasion may require.\n\n\"The rods! the rods!\" cried Starbuck to the crew, suddenly admonished\nto vigilance by the vivid lightning that had just been darting\nflambeaux, to light Ahab to his post.  \"Are they overboard? drop them\nover, fore and aft.  Quick!\"\n\n\"Avast!\" cried Ahab; \"let's have fair play here, though we be the\nweaker side.  Yet I'll contribute to raise rods on the Himmalehs and\nAndes, that all the world may be secured; but out on privileges!  Let\nthem be, sir.\"\n\n\"Look aloft!\" cried Starbuck.  \"The corpusants! the corpusants!\n\nAll the yard-arms were tipped with a pallid fire; and touched at each\ntri-pointed lightning-rod-end with three tapering white flames, each\nof the three tall masts was silently burning in that sulphurous air,\nlike three gigantic wax tapers before an altar.\n\n\"Blast the boat! let it go!\" cried Stubb at this instant, as a\nswashing sea heaved up under his own little craft, so that its\ngunwale violently jammed his hand, as he was passing a lashing.\n\"Blast it!\"--but slipping backward on the deck, his uplifted eyes\ncaught the flames; and immediately shifting his tone he cried--\"The\ncorpusants have mercy on us all!\"\n\nTo sailors, oaths are household words; they will swear in the trance\nof the calm, and in the teeth of the tempest; they will imprecate\ncurses from the topsail-yard-arms, when most they teeter over to a\nseething sea; but in all my voyagings, seldom have I heard a common\noath when God's burning finger has been laid on the ship; when His\n\"Mene, Mene, Tekel Upharsin\" has been woven into the shrouds and the\ncordage.\n\nWhile this pallidness was burning aloft, few words were heard from\nthe enchanted crew; who in one thick cluster stood on the forecastle,\nall their eyes gleaming in that pale phosphorescence, like a far away\nconstellation of stars.  Relieved against the ghostly light, the\ngigantic jet negro, Daggoo, loomed up to thrice his real stature, and\nseemed the black cloud from which the thunder had come.  The parted\nmouth of Tashtego revealed his shark-white teeth, which strangely\ngleamed as if they too had been tipped by corpusants; while lit up by\nthe preternatural light, Queequeg's tattooing burned like Satanic\nblue flames on his body.\n\nThe tableau all waned at last with the pallidness aloft; and once\nmore the Pequod and every soul on her decks were wrapped in a pall.\nA moment or two passed, when Starbuck, going forward, pushed against\nsome one.  It was Stubb.  \"What thinkest thou now, man; I heard thy\ncry; it was not the same in the song.\"\n\n\"No, no, it wasn't; I said the corpusants have mercy on us all; and I\nhope they will, still.  But do they only have mercy on long\nfaces?--have they no bowels for a laugh?  And look ye, Mr.\nStarbuck--but it's too dark to look.  Hear me, then: I take that\nmast-head flame we saw for a sign of good luck; for those masts are\nrooted in a hold that is going to be chock a' block with sperm-oil,\nd'ye see; and so, all that sperm will work up into the masts, like\nsap in a tree.  Yes, our three masts will yet be as three spermaceti\ncandles--that's the good promise we saw.\"\n\nAt that moment Starbuck caught sight of Stubb's face slowly beginning\nto glimmer into sight.  Glancing upwards, he cried: \"See! see!\" and\nonce more the high tapering flames were beheld with what seemed\nredoubled supernaturalness in their pallor.\n\n\"The corpusants have mercy on us all,\" cried Stubb, again.\n\nAt the base of the mainmast, full beneath the doubloon and the\nflame, the Parsee was kneeling in Ahab's front, but with his head\nbowed away from him; while near by, from the arched and overhanging\nrigging, where they had just been engaged securing a spar, a number\nof the seamen, arrested by the glare, now cohered together, and hung\npendulous, like a knot of numbed wasps from a drooping, orchard twig.\nIn various enchanted attitudes, like the standing, or stepping, or\nrunning skeletons in Herculaneum, others remained rooted to the deck;\nbut all their eyes upcast.\n\n\"Aye, aye, men!\" cried Ahab.  \"Look up at it; mark it well; the white\nflame but lights the way to the White Whale!  Hand me those mainmast\nlinks there; I would fain feel this pulse, and let mine beat against\nit; blood against fire!  So.\"\n\nThen turning--the last link held fast in his left hand, he put his\nfoot upon the Parsee; and with fixed upward eye, and high-flung right\narm, he stood erect before the lofty tri-pointed trinity of flames.\n\n\"Oh! thou clear spirit of clear fire, whom on these seas I as Persian\nonce did worship, till in the sacramental act so burned by thee, that\nto this hour I bear the scar; I now know thee, thou clear spirit, and\nI now know that thy right worship is defiance.  To neither love nor\nreverence wilt thou be kind; and e'en for hate thou canst but kill;\nand all are killed.  No fearless fool now fronts thee.  I own thy\nspeechless, placeless power; but to the last gasp of my earthquake\nlife will dispute its unconditional, unintegral mastery in me.  In the\nmidst of the personified impersonal, a personality stands here.\nThough but a point at best; whencesoe'er I came; wheresoe'er I go;\nyet while I earthly live, the queenly personality lives in me, and\nfeels her royal rights.  But war is pain, and hate is woe.  Come in\nthy lowest form of love, and I will kneel and kiss thee; but at thy\nhighest, come as mere supernal power; and though thou launchest\nnavies of full-freighted worlds, there's that in here that still\nremains indifferent.  Oh, thou clear spirit, of thy fire thou madest\nme, and like a true child of fire, I breathe it back to thee.\"\n\n[SUDDEN, REPEATED FLASHES OF LIGHTNING; THE NINE FLAMES LEAP\nLENGTHWISE TO THRICE THEIR PREVIOUS HEIGHT; AHAB, WITH THE REST,\nCLOSES HIS EYES, HIS RIGHT HAND PRESSED HARD UPON THEM.]\n\n\"I own thy speechless, placeless power; said I not so?  Nor was it\nwrung from me; nor do I now drop these links.  Thou canst blind; but\nI can then grope.  Thou canst consume; but I can then be ashes.  Take\nthe homage of these poor eyes, and shutter-hands.  I would not take\nit.  The lightning flashes through my skull; mine eye-balls ache and\nache; my whole beaten brain seems as beheaded, and rolling on some\nstunning ground.  Oh, oh!  Yet blindfold, yet will I talk to thee.\nLight though thou be, thou leapest out of darkness; but I am darkness\nleaping out of light, leaping out of thee!  The javelins cease; open\neyes; see, or not?  There burn the flames!  Oh, thou magnanimous! now\nI do glory in my genealogy.  But thou art but my fiery father; my\nsweet mother, I know not.  Oh, cruel! what hast thou done with her?\nThere lies my puzzle; but thine is greater.  Thou knowest not how\ncame ye, hence callest thyself unbegotten; certainly knowest not thy\nbeginning, hence callest thyself unbegun.  I know that of me, which\nthou knowest not of thyself, oh, thou omnipotent.  There is some\nunsuffusing thing beyond thee, thou clear spirit, to whom all thy\neternity is but time, all thy creativeness mechanical.  Through thee,\nthy flaming self, my scorched eyes do dimly see it.  Oh, thou\nfoundling fire, thou hermit immemorial, thou too hast thy\nincommunicable riddle, thy unparticipated grief.  Here again with\nhaughty agony, I read my sire.  Leap! leap up, and lick the sky!  I\nleap with thee; I burn with thee; would fain be welded with thee;\ndefyingly I worship thee!\"\n\n\"The boat! the boat!\" cried Starbuck, \"look at thy boat, old man!\"\n\nAhab's harpoon, the one forged at Perth's fire, remained firmly\nlashed in its conspicuous crotch, so that it projected beyond his\nwhale-boat's bow; but the sea that had stove its bottom had caused\nthe loose leather sheath to drop off; and from the keen steel barb\nthere now came a levelled flame of pale, forked fire.  As the silent\nharpoon burned there like a serpent's tongue, Starbuck grasped Ahab\nby the arm--\"God, God is against thee, old man; forbear! 'tis an\nill voyage! ill begun, ill continued; let me square the yards, while\nwe may, old man, and make a fair wind of it homewards, to go on a\nbetter voyage than this.\"\n\nOverhearing Starbuck, the panic-stricken crew instantly ran to the\nbraces--though not a sail was left aloft.  For the moment all the\naghast mate's thoughts seemed theirs; they raised a half mutinous\ncry.  But dashing the rattling lightning links to the deck, and\nsnatching the burning harpoon, Ahab waved it like a torch among them;\nswearing to transfix with it the first sailor that but cast loose a\nrope's end.  Petrified by his aspect, and still more shrinking from\nthe fiery dart that he held, the men fell back in dismay, and Ahab\nagain spoke:--\n\n\"All your oaths to hunt the White Whale are as binding as mine; and\nheart, soul, and body, lungs and life, old Ahab is bound.  And that\nye may know to what tune this heart beats; look ye here; thus I blow\nout the last fear!\"  And with one blast of his breath he extinguished\nthe flame.\n\nAs in the hurricane that sweeps the plain, men fly the neighborhood\nof some lone, gigantic elm, whose very height and strength but render\nit so much the more unsafe, because so much the more a mark for\nthunderbolts; so at those last words of Ahab's many of the mariners\ndid run from him in a terror of dismay.\n\n\n\nCHAPTER 120\n\nThe Deck Towards the End of the First Night Watch.\n\nAHAB STANDING BY THE HELM.  STARBUCK APPROACHING HIM.\n\n\nWe must send down the main-top-sail yard, sir.  The band is working\nloose and the lee lift is half-stranded.  Shall I strike it, sir?\"\n\n\"Strike nothing; lash it.  If I had sky-sail poles, I'd sway them up\nnow.\"\n\n\"Sir!--in God's name!--sir?\"\n\n\"Well.\"\n\n\"The anchors are working, sir.  Shall I get them inboard?\"\n\n\"Strike nothing, and stir nothing, but lash everything.  The wind\nrises, but it has not got up to my table-lands yet.  Quick, and see\nto it.--By masts and keels! he takes me for the hunch-backed skipper\nof some coasting smack.  Send down my main-top-sail yard!  Ho,\ngluepots!  Loftiest trucks were made for wildest winds, and this\nbrain-truck of mine now sails amid the cloud-scud.  Shall I strike\nthat?  Oh, none but cowards send down their brain-trucks in tempest\ntime.  What a hooroosh aloft there!  I would e'en take it for\nsublime, did I not know that the colic is a noisy malady.  Oh, take\nmedicine, take medicine!\"\n\n\n\nCHAPTER 121\n\nMidnight.--The Forecastle Bulwarks.\n\n\nSTUBB AND FLASK MOUNTED ON THEM, AND PASSING ADDITIONAL LASHINGS OVER\nTHE ANCHORS THERE HANGING.\n\n\nNo, Stubb; you may pound that knot there as much as you please, but\nyou will never pound into me what you were just now saying.  And how\nlong ago is it since you said the very contrary?  Didn't you once say\nthat whatever ship Ahab sails in, that ship should pay something\nextra on its insurance policy, just as though it were loaded with\npowder barrels aft and boxes of lucifers forward?  Stop, now; didn't\nyou say so?\"\n\n\"Well, suppose I did?  What then?  I've part changed my flesh since\nthat time, why not my mind?  Besides, supposing we ARE loaded with\npowder barrels aft and lucifers forward; how the devil could the\nlucifers get afire in this drenching spray here?  Why, my little man,\nyou have pretty red hair, but you couldn't get afire now.  Shake\nyourself; you're Aquarius, or the water-bearer, Flask; might fill\npitchers at your coat collar.  Don't you see, then, that for these\nextra risks the Marine Insurance companies have extra guarantees?\nHere are hydrants, Flask.  But hark, again, and I'll answer ye the\nother thing.  First take your leg off from the crown of the anchor\nhere, though, so I can pass the rope; now listen.  What's the mighty\ndifference between holding a mast's lightning-rod in the storm, and\nstanding close by a mast that hasn't got any lightning-rod at all in\na storm?  Don't you see, you timber-head, that no harm can come to\nthe holder of the rod, unless the mast is first struck?  What are you\ntalking about, then?  Not one ship in a hundred carries rods, and\nAhab,--aye, man, and all of us,--were in no more danger then, in my\npoor opinion, than all the crews in ten thousand ships now sailing\nthe seas.  Why, you King-Post, you, I suppose you would have every\nman in the world go about with a small lightning-rod running up the\ncorner of his hat, like a militia officer's skewered feather, and\ntrailing behind like his sash.  Why don't ye be sensible, Flask? it's\neasy to be sensible; why don't ye, then? any man with half an eye can\nbe sensible.\"\n\n\"I don't know that, Stubb.  You sometimes find it rather hard.\"\n\n\"Yes, when a fellow's soaked through, it's hard to be sensible,\nthat's a fact.  And I am about drenched with this spray.  Never mind;\ncatch the turn there, and pass it.  Seems to me we are lashing down\nthese anchors now as if they were never going to be used again.\nTying these two anchors here, Flask, seems like tying a man's hands\nbehind him.  And what big generous hands they are, to be sure.  These\nare your iron fists, hey?  What a hold they have, too!  I wonder,\nFlask, whether the world is anchored anywhere; if she is, she swings\nwith an uncommon long cable, though.  There, hammer that knot down,\nand we've done.  So; next to touching land, lighting on deck is the\nmost satisfactory.  I say, just wring out my jacket skirts, will ye?\nThank ye.  They laugh at long-togs so, Flask; but seems to me, a\nLong tailed coat ought always to be worn in all storms afloat.  The\ntails tapering down that way, serve to carry off the water, d'ye see.\nSame with cocked hats; the cocks form gable-end eave-troughs, Flask.\nNo more monkey-jackets and tarpaulins for me; I must mount a\nswallow-tail, and drive down a beaver; so.  Halloa! whew! there goes\nmy tarpaulin overboard; Lord, Lord, that the winds that come from\nheaven should be so unmannerly!  This is a nasty night, lad.\"\n\n\n\nCHAPTER 122\n\nMidnight Aloft.--Thunder and Lightning.\n\n\nTHE MAIN-TOP-SAIL YARD.--TASHTEGO PASSING NEW LASHINGS AROUND IT.\n\n\n\"Um, um, um.  Stop that thunder!  Plenty too much thunder up here.\nWhat's the use of thunder?  Um, um, um.  We don't want thunder; we\nwant rum; give us a glass of rum.  Um, um, um!\"\n\n\n\nCHAPTER 123\n\nThe Musket.\n\n\nDuring the most violent shocks of the Typhoon, the man at the\nPequod's jaw-bone tiller had several times been reelingly hurled to\nthe deck by its spasmodic motions, even though preventer tackles had\nbeen attached to it--for they were slack--because some play to the\ntiller was indispensable.\n\nIn a severe gale like this, while the ship is but a tossed\nshuttlecock to the blast, it is by no means uncommon to see the\nneedles in the compasses, at intervals, go round and round.  It was\nthus with the Pequod's; at almost every shock the helmsman had not\nfailed to notice the whirling velocity with which they revolved upon\nthe cards; it is a sight that hardly anyone can behold without some\nsort of unwonted emotion.\n\nSome hours after midnight, the Typhoon abated so much, that through\nthe strenuous exertions of Starbuck and Stubb--one engaged forward\nand the other aft--the shivered remnants of the jib and fore and\nmain-top-sails were cut adrift from the spars, and went eddying away\nto leeward, like the feathers of an albatross, which sometimes are\ncast to the winds when that storm-tossed bird is on the wing.\n\nThe three corresponding new sails were now bent and reefed, and a\nstorm-trysail was set further aft; so that the ship soon went through\nthe water with some precision again; and the course--for the present,\nEast-south-east--which he was to steer, if practicable, was once more\ngiven to the helmsman.  For during the violence of the gale, he had\nonly steered according to its vicissitudes.  But as he was now\nbringing the ship as near her course as possible, watching the\ncompass meanwhile, lo! a good sign! the wind seemed coming round\nastern; aye, the foul breeze became fair!\n\nInstantly the yards were squared, to the lively song of \"HO! THE FAIR\nWIND! OH-YE-HO, CHEERLY MEN!\" the crew singing for joy, that so\npromising an event should so soon have falsified the evil portents\npreceding it.\n\nIn compliance with the standing order of his commander--to report\nimmediately, and at any one of the twenty-four hours, any decided\nchange in the affairs of the deck,--Starbuck had no sooner trimmed\nthe yards to the breeze--however reluctantly and gloomily,--than he\nmechanically went below to apprise Captain Ahab of the circumstance.\n\nEre knocking at his state-room, he involuntarily paused before it a\nmoment.  The cabin lamp--taking long swings this way and that--was\nburning fitfully, and casting fitful shadows upon the old man's\nbolted door,--a thin one, with fixed blinds inserted, in place of\nupper panels.  The isolated subterraneousness of the cabin made a\ncertain humming silence to reign there, though it was hooped round by\nall the roar of the elements.  The loaded muskets in the rack were\nshiningly revealed, as they stood upright against the forward\nbulkhead.  Starbuck was an honest, upright man; but out of Starbuck's\nheart, at that instant when he saw the muskets, there strangely\nevolved an evil thought; but so blent with its neutral or good\naccompaniments that for the instant he hardly knew it for itself.\n\n\"He would have shot me once,\" he murmured, \"yes, there's the very\nmusket that he pointed at me;--that one with the studded stock; let\nme touch it--lift it.  Strange, that I, who have handled so many\ndeadly lances, strange, that I should shake so now.  Loaded?  I must\nsee.  Aye, aye; and powder in the pan;--that's not good.  Best spill\nit?--wait.  I'll cure myself of this.  I'll hold the musket boldly\nwhile I think.--I come to report a fair wind to him.  But how fair?\nFair for death and doom,--THAT'S fair for Moby Dick.  It's a fair\nwind that's only fair for that accursed fish.--The very tube he\npointed at me!--the very one; THIS one--I hold it here; he would have\nkilled me with the very thing I handle now.--Aye and he would fain\nkill all his crew.  Does he not say he will not strike his spars to\nany gale?  Has he not dashed his heavenly quadrant? and in these same\nperilous seas, gropes he not his way by mere dead reckoning of the\nerror-abounding log? and in this very Typhoon, did he not swear that\nhe would have no lightning-rods?  But shall this crazed old man be\ntamely suffered to drag a whole ship's company down to doom with\nhim?--Yes, it would make him the wilful murderer of thirty men and\nmore, if this ship come to any deadly harm; and come to deadly harm,\nmy soul swears this ship will, if Ahab have his way.  If, then, he\nwere this instant--put aside, that crime would not be his.  Ha! is he\nmuttering in his sleep?  Yes, just there,--in there, he's sleeping.\nSleeping? aye, but still alive, and soon awake again.  I can't\nwithstand thee, then, old man.  Not reasoning; not remonstrance; not\nentreaty wilt thou hearken to; all this thou scornest.  Flat\nobedience to thy own flat commands, this is all thou breathest.  Aye,\nand say'st the men have vow'd thy vow; say'st all of us are Ahabs.\nGreat God forbid!--But is there no other way? no lawful way?--Make\nhim a prisoner to be taken home?  What! hope to wrest this old man's\nliving power from his own living hands?  Only a fool would try it.\nSay he were pinioned even; knotted all over with ropes and hawsers;\nchained down to ring-bolts on this cabin floor; he would be more\nhideous than a caged tiger, then.  I could not endure the sight;\ncould not possibly fly his howlings; all comfort, sleep itself,\ninestimable reason would leave me on the long intolerable voyage.\nWhat, then, remains?  The land is hundreds of leagues away, and\nlocked Japan the nearest.  I stand alone here upon an open sea, with\ntwo oceans and a whole continent between me and law.--Aye, aye, 'tis\nso.--Is heaven a murderer when its lightning strikes a would-be\nmurderer in his bed, tindering sheets and skin together?--And would I\nbe a murderer, then, if\"--and slowly, stealthily, and half sideways\nlooking, he placed the loaded musket's end against the door.\n\n\"On this level, Ahab's hammock swings within; his head this way.  A\ntouch, and Starbuck may survive to hug his wife and child again.--Oh\nMary!  Mary!--boy! boy! boy!--But if I wake thee not to death, old\nman, who can tell to what unsounded deeps Starbuck's body this day\nweek may sink, with all the crew!  Great God, where art Thou?  Shall\nI? shall I?--The wind has gone down and shifted, sir; the fore and\nmain topsails are reefed and set; she heads her course.\"\n\n\"Stern all!  Oh Moby Dick, I clutch thy heart at last!\"\n\nSuch were the sounds that now came hurtling from out the old man's\ntormented sleep, as if Starbuck's voice had caused the long dumb\ndream to speak.\n\nThe yet levelled musket shook like a drunkard's arm against the\npanel; Starbuck seemed wrestling with an angel; but turning from the\ndoor, he placed the death-tube in its rack, and left the place.\n\n\"He's too sound asleep, Mr. Stubb; go thou down, and wake him, and\ntell him.  I must see to the deck here.  Thou know'st what to say.\"\n\n\n\nCHAPTER 124\n\nThe Needle.\n\n\nNext morning the not-yet-subsided sea rolled in long slow billows of\nmighty bulk, and striving in the Pequod's gurgling track, pushed her\non like giants' palms outspread.  The strong, unstaggering breeze\nabounded so, that sky and air seemed vast outbellying sails; the\nwhole world boomed before the wind.  Muffled in the full morning\nlight, the invisible sun was only known by the spread intensity of\nhis place; where his bayonet rays moved on in stacks.  Emblazonings,\nas of crowned Babylonian kings and queens, reigned over everything.\nThe sea was as a crucible of molten gold, that bubblingly leaps with\nlight and heat.\n\nLong maintaining an enchanted silence, Ahab stood apart; and every\ntime the tetering ship loweringly pitched down her bowsprit, he\nturned to eye the bright sun's rays produced ahead; and when she\nprofoundly settled by the stern, he turned behind, and saw the sun's\nrearward place, and how the same yellow rays were blending with his\nundeviating wake.\n\n\"Ha, ha, my ship! thou mightest well be taken now for the sea-chariot\nof the sun.  Ho, ho! all ye nations before my prow, I bring the sun\nto ye!  Yoke on the further billows; hallo! a tandem, I drive the\nsea!\"\n\nBut suddenly reined back by some counter thought, he hurried towards\nthe helm, huskily demanding how the ship was heading.\n\n\"East-sou-east, sir,\" said the frightened steersman.\n\n\"Thou liest!\" smiting him with his clenched fist.  \"Heading East at\nthis hour in the morning, and the sun astern?\"\n\nUpon this every soul was confounded; for the phenomenon just then\nobserved by Ahab had unaccountably escaped every one else; but its\nvery blinding palpableness must have been the cause.\n\nThrusting his head half way into the binnacle, Ahab caught one\nglimpse of the compasses; his uplifted arm slowly fell; for a moment\nhe almost seemed to stagger.  Standing behind him Starbuck looked,\nand lo! the two compasses pointed East, and the Pequod was as\ninfallibly going West.\n\nBut ere the first wild alarm could get out abroad among the crew, the\nold man with a rigid laugh exclaimed, \"I have it!  It has happened\nbefore.  Mr. Starbuck, last night's thunder turned our\ncompasses--that's all.  Thou hast before now heard of such a thing, I\ntake it.\"\n\n\"Aye; but never before has it happened to me, sir,\" said the pale\nmate, gloomily.\n\nHere, it must needs be said, that accidents like this have in more\nthan one case occurred to ships in violent storms.  The magnetic\nenergy, as developed in the mariner's needle, is, as all know,\nessentially one with the electricity beheld in heaven; hence it is\nnot to be much marvelled at, that such things should be.  Instances\nwhere the lightning has actually struck the vessel, so as to smite\ndown some of the spars and rigging, the effect upon the needle has at\ntimes been still more fatal; all its loadstone virtue being\nannihilated, so that the before magnetic steel was of no more use\nthan an old wife's knitting needle.  But in either case, the needle\nnever again, of itself, recovers the original virtue thus marred or\nlost; and if the binnacle compasses be affected, the same fate\nreaches all the others that may be in the ship; even were the\nlowermost one inserted into the kelson.\n\nDeliberately standing before the binnacle, and eyeing the\ntranspointed compasses, the old man, with the sharp of his extended\nhand, now took the precise bearing of the sun, and satisfied that the\nneedles were exactly inverted, shouted out his orders for the ship's\ncourse to be changed accordingly.  The yards were hard up; and once\nmore the Pequod thrust her undaunted bows into the opposing wind, for\nthe supposed fair one had only been juggling her.\n\nMeanwhile, whatever were his own secret thoughts, Starbuck said\nnothing, but quietly he issued all requisite orders; while Stubb and\nFlask--who in some small degree seemed then to be sharing his\nfeelings--likewise unmurmuringly acquiesced.  As for the men, though\nsome of them lowly rumbled, their fear of Ahab was greater than their\nfear of Fate.  But as ever before, the pagan harpooneers remained\nalmost wholly unimpressed; or if impressed, it was only with a\ncertain magnetism shot into their congenial hearts from inflexible\nAhab's.\n\nFor a space the old man walked the deck in rolling reveries.  But\nchancing to slip with his ivory heel, he saw the crushed copper\nsight-tubes of the quadrant he had the day before dashed to the deck.\n\n\"Thou poor, proud heaven-gazer and sun's pilot! yesterday I wrecked\nthee, and to-day the compasses would fain have wrecked me.  So, so.\nBut Ahab is lord over the level loadstone yet.  Mr. Starbuck--a lance\nwithout a pole; a top-maul, and the smallest of the sail-maker's\nneedles.  Quick!\"\n\nAccessory, perhaps, to the impulse dictating the thing he was now\nabout to do, were certain prudential motives, whose object might have\nbeen to revive the spirits of his crew by a stroke of his subtile\nskill, in a matter so wondrous as that of the inverted compasses.\nBesides, the old man well knew that to steer by transpointed needles,\nthough clumsily practicable, was not a thing to be passed over by\nsuperstitious sailors, without some shudderings and evil portents.\n\n\"Men,\" said he, steadily turning upon the crew, as the mate handed\nhim the things he had demanded, \"my men, the thunder turned old\nAhab's needles; but out of this bit of steel Ahab can make one of his\nown, that will point as true as any.\"\n\nAbashed glances of servile wonder were exchanged by the sailors, as\nthis was said; and with fascinated eyes they awaited whatever magic\nmight follow.  But Starbuck looked away.\n\nWith a blow from the top-maul Ahab knocked off the steel head of the\nlance, and then handing to the mate the long iron rod remaining, bade\nhim hold it upright, without its touching the deck.  Then, with the\nmaul, after repeatedly smiting the upper end of this iron rod, he\nplaced the blunted needle endwise on the top of it, and less strongly\nhammered that, several times, the mate still holding the rod as\nbefore.  Then going through some small strange motions with\nit--whether indispensable to the magnetizing of the steel, or merely\nintended to augment the awe of the crew, is uncertain--he called for\nlinen thread; and moving to the binnacle, slipped out the two\nreversed needles there, and horizontally suspended the sail-needle by\nits middle, over one of the compass-cards.  At first, the steel went\nround and round, quivering and vibrating at either end; but at last\nit settled to its place, when Ahab, who had been intently watching\nfor this result, stepped frankly back from the binnacle, and pointing\nhis stretched arm towards it, exclaimed,--\"Look ye, for yourselves,\nif Ahab be not lord of the level loadstone!  The sun is East, and\nthat compass swears it!\"\n\nOne after another they peered in, for nothing but their own eyes\ncould persuade such ignorance as theirs, and one after another they\nslunk away.\n\nIn his fiery eyes of scorn and triumph, you then saw Ahab in all his\nfatal pride.\n\n\n\nCHAPTER 125\n\nThe Log and Line.\n\n\nWhile now the fated Pequod had been so long afloat this voyage, the\nlog and line had but very seldom been in use.  Owing to a confident\nreliance upon other means of determining the vessel's place, some\nmerchantmen, and many whalemen, especially when cruising, wholly\nneglect to heave the log; though at the same time, and frequently\nmore for form's sake than anything else, regularly putting down upon\nthe customary slate the course steered by the ship, as well as the\npresumed average rate of progression every hour.  It had been thus\nwith the Pequod.  The wooden reel and angular log attached hung, long\nuntouched, just beneath the railing of the after bulwarks.  Rains and\nspray had damped it; sun and wind had warped it; all the elements\nhad combined to rot a thing that hung so idly.  But heedless of all\nthis, his mood seized Ahab, as he happened to glance upon the reel,\nnot many hours after the magnet scene, and he remembered how his\nquadrant was no more, and recalled his frantic oath about the level\nlog and line.  The ship was sailing plungingly; astern the billows\nrolled in riots.\n\n\"Forward, there!  Heave the log!\"\n\nTwo seamen came.  The golden-hued Tahitian and the grizzly Manxman.\n\"Take the reel, one of ye, I'll heave.\"\n\nThey went towards the extreme stern, on the ship's lee side, where\nthe deck, with the oblique energy of the wind, was now almost dipping\ninto the creamy, sidelong-rushing sea.\n\nThe Manxman took the reel, and holding it high up, by the projecting\nhandle-ends of the spindle, round which the spool of line revolved,\nso stood with the angular log hanging downwards, till Ahab advanced\nto him.\n\nAhab stood before him, and was lightly unwinding some thirty or forty\nturns to form a preliminary hand-coil to toss overboard, when the old\nManxman, who was intently eyeing both him and the line, made bold to\nspeak.\n\n\"Sir, I mistrust it; this line looks far gone, long heat and wet have\nspoiled it.\"\n\n\"'Twill hold, old gentleman.  Long heat and wet, have they spoiled\nthee?  Thou seem'st to hold.  Or, truer perhaps, life holds thee;\nnot thou it.\"\n\n\"I hold the spool, sir.  But just as my captain says.  With these\ngrey hairs of mine 'tis not worth while disputing, 'specially with a\nsuperior, who'll ne'er confess.\"\n\n\"What's that?  There now's a patched professor in Queen Nature's\ngranite-founded College; but methinks he's too subservient.  Where\nwert thou born?\"\n\n\"In the little rocky Isle of Man, sir.\"\n\n\"Excellent!  Thou'st hit the world by that.\"\n\n\"I know not, sir, but I was born there.\"\n\n\"In the Isle of Man, hey?  Well, the other way, it's good.  Here's a\nman from Man; a man born in once independent Man, and now unmanned of\nMan; which is sucked in--by what?  Up with the reel!  The dead, blind\nwall butts all inquiring heads at last.  Up with it!  So.\"\n\nThe log was heaved.  The loose coils rapidly straightened out in a\nlong dragging line astern, and then, instantly, the reel began to\nwhirl.  In turn, jerkingly raised and lowered by the rolling billows,\nthe towing resistance of the log caused the old reelman to stagger\nstrangely.\n\n\"Hold hard!\"\n\nSnap! the overstrained line sagged down in one long festoon; the\ntugging log was gone.\n\n\"I crush the quadrant, the thunder turns the needles, and now the mad\nsea parts the log-line.  But Ahab can mend all.  Haul in here,\nTahitian; reel up, Manxman.  And look ye, let the carpenter make\nanother log, and mend thou the line.  See to it.\"\n\n\"There he goes now; to him nothing's happened; but to me, the skewer\nseems loosening out of the middle of the world.  Haul in, haul in,\nTahitian!  These lines run whole, and whirling out: come in broken,\nand dragging slow.  Ha, Pip? come to help; eh, Pip?\"\n\n\"Pip? whom call ye Pip?  Pip jumped from the whale-boat.  Pip's\nmissing.  Let's see now if ye haven't fished him up here, fisherman.\nIt drags hard; I guess he's holding on.  Jerk him, Tahiti!  Jerk him\noff; we haul in no cowards here.  Ho! there's his arm just breaking\nwater.  A hatchet! a hatchet! cut it off--we haul in no cowards here.\nCaptain Ahab! sir, sir! here's Pip, trying to get on board again.\"\n\n\"Peace, thou crazy loon,\" cried the Manxman, seizing him by the arm.\n\"Away from the quarter-deck!\"\n\n\"The greater idiot ever scolds the lesser,\" muttered Ahab, advancing.\n\"Hands off from that holiness!  Where sayest thou Pip was, boy?\n\n\"Astern there, sir, astern!  Lo! lo!\"\n\n\"And who art thou, boy?  I see not my reflection in the vacant pupils\nof thy eyes.  Oh God! that man should be a thing for immortal souls\nto sieve through!  Who art thou, boy?\"\n\n\"Bell-boy, sir; ship's-crier; ding, dong, ding!  Pip!  Pip!  Pip!  One\nhundred pounds of clay reward for Pip; five feet high--looks\ncowardly--quickest known by that!  Ding, dong, ding!  Who's seen Pip\nthe coward?\"\n\n\"There can be no hearts above the snow-line.  Oh, ye frozen heavens!\nlook down here.  Ye did beget this luckless child, and have abandoned\nhim, ye creative libertines.  Here, boy; Ahab's cabin shall be Pip's\nhome henceforth, while Ahab lives.  Thou touchest my inmost centre,\nboy; thou art tied to me by cords woven of my heart-strings.  Come,\nlet's down.\"\n\n\"What's this? here's velvet shark-skin,\" intently gazing at Ahab's\nhand, and feeling it.  \"Ah, now, had poor Pip but felt so kind a\nthing as this, perhaps he had ne'er been lost!  This seems to me,\nsir, as a man-rope; something that weak souls may hold by.  Oh, sir,\nlet old Perth now come and rivet these two hands together; the black\none with the white, for I will not let this go.\"\n\n\"Oh, boy, nor will I thee, unless I should thereby drag thee to worse\nhorrors than are here.  Come, then, to my cabin.  Lo! ye believers in\ngods all goodness, and in man all ill, lo you! see the omniscient\ngods oblivious of suffering man; and man, though idiotic, and knowing\nnot what he does, yet full of the sweet things of love and gratitude.\nCome!  I feel prouder leading thee by thy black hand, than though I\ngrasped an Emperor's!\"\n\n\"There go two daft ones now,\" muttered the old Manxman.  \"One daft\nwith strength, the other daft with weakness.  But here's the end of\nthe rotten line--all dripping, too.  Mend it, eh?  I think we had\nbest have a new line altogether.  I'll see Mr. Stubb about it.\"\n\n\n\nCHAPTER 126\n\nThe Life-Buoy.\n\n\nSteering now south-eastward by Ahab's levelled steel, and her\nprogress solely determined by Ahab's level log and line; the Pequod\nheld on her path towards the Equator.  Making so long a passage\nthrough such unfrequented waters, descrying no ships, and ere long,\nsideways impelled by unvarying trade winds, over waves monotonously\nmild; all these seemed the strange calm things preluding some riotous\nand desperate scene.\n\nAt last, when the ship drew near to the outskirts, as it were, of the\nEquatorial fishing-ground, and in the deep darkness that goes before\nthe dawn, was sailing by a cluster of rocky islets; the watch--then\nheaded by Flask--was startled by a cry so plaintively wild and\nunearthly--like half-articulated wailings of the ghosts of all\nHerod's murdered Innocents--that one and all, they started from their\nreveries, and for the space of some moments stood, or sat, or leaned\nall transfixedly listening, like the carved Roman slave, while that\nwild cry remained within hearing.  The Christian or civilized part of\nthe crew said it was mermaids, and shuddered; but the pagan\nharpooneers remained unappalled.  Yet the grey Manxman--the oldest\nmariner of all--declared that the wild thrilling sounds that were\nheard, were the voices of newly drowned men in the sea.\n\nBelow in his hammock, Ahab did not hear of this till grey dawn, when\nhe came to the deck; it was then recounted to him by Flask, not\nunaccompanied with hinted dark meanings.  He hollowly laughed, and\nthus explained the wonder.\n\nThose rocky islands the ship had passed were the resort of great\nnumbers of seals, and some young seals that had lost their dams, or\nsome dams that had lost their cubs, must have risen nigh the ship and\nkept company with her, crying and sobbing with their human sort of\nwail.  But this only the more affected some of them, because most\nmariners cherish a very superstitious feeling about seals, arising\nnot only from their peculiar tones when in distress, but also from\nthe human look of their round heads and semi-intelligent faces, seen\npeeringly uprising from the water alongside.  In the sea, under\ncertain circumstances, seals have more than once been mistaken for\nmen.\n\nBut the bodings of the crew were destined to receive a most plausible\nconfirmation in the fate of one of their number that morning.  At\nsun-rise this man went from his hammock to his mast-head at the fore;\nand whether it was that he was not yet half waked from his sleep (for\nsailors sometimes go aloft in a transition state), whether it was\nthus with the man, there is now no telling; but, be that as it may,\nhe had not been long at his perch, when a cry was heard--a cry and a\nrushing--and looking up, they saw a falling phantom in the air; and\nlooking down, a little tossed heap of white bubbles in the blue of\nthe sea.\n\nThe life-buoy--a long slender cask--was dropped from the stern, where\nit always hung obedient to a cunning spring; but no hand rose to\nseize it, and the sun having long beat upon this cask it had\nshrunken, so that it slowly filled, and that parched wood also\nfilled at its every pore; and the studded iron-bound cask followed\nthe sailor to the bottom, as if to yield him his pillow, though in\nsooth but a hard one.\n\nAnd thus the first man of the Pequod that mounted the mast to look\nout for the White Whale, on the White Whale's own peculiar ground;\nthat man was swallowed up in the deep.  But few, perhaps, thought of\nthat at the time.  Indeed, in some sort, they were not grieved at\nthis event, at least as a portent; for they regarded it, not as a\nforeshadowing of evil in the future, but as the fulfilment of an\nevil already presaged.  They declared that now they knew the reason\nof those wild shrieks they had heard the night before.  But again the\nold Manxman said nay.\n\nThe lost life-buoy was now to be replaced; Starbuck was directed to\nsee to it; but as no cask of sufficient lightness could be found, and\nas in the feverish eagerness of what seemed the approaching crisis of\nthe voyage, all hands were impatient of any toil but what was\ndirectly connected with its final end, whatever that might prove to\nbe; therefore, they were going to leave the ship's stern unprovided\nwith a buoy, when by certain strange signs and inuendoes Queequeg\nhinted a hint concerning his coffin.\n\n\"A life-buoy of a coffin!\" cried Starbuck, starting.\n\n\"Rather queer, that, I should say,\" said Stubb.\n\n\"It will make a good enough one,\" said Flask, \"the carpenter here can\narrange it easily.\"\n\n\"Bring it up; there's nothing else for it,\" said Starbuck, after a\nmelancholy pause.  \"Rig it, carpenter; do not look at me so--the\ncoffin, I mean.  Dost thou hear me?  Rig it.\"\n\n\"And shall I nail down the lid, sir?\" moving his hand as with a\nhammer.\n\n\"Aye.\"\n\n\"And shall I caulk the seams, sir?\" moving his hand as with a\ncaulking-iron.\n\n\"Aye.\"\n\n\"And shall I then pay over the same with pitch, sir?\" moving his hand\nas with a pitch-pot.\n\n\"Away! what possesses thee to this?  Make a life-buoy of the coffin,\nand no more.--Mr. Stubb, Mr. Flask, come forward with me.\"\n\n\"He goes off in a huff.  The whole he can endure; at the parts he\nbaulks.  Now I don't like this.  I make a leg for Captain Ahab, and\nhe wears it like a gentleman; but I make a bandbox for Queequeg, and\nhe won't put his head into it.  Are all my pains to go for nothing\nwith that coffin?  And now I'm ordered to make a life-buoy of it.\nIt's like turning an old coat; going to bring the flesh on the other\nside now.  I don't like this cobbling sort of business--I don't like\nit at all; it's undignified; it's not my place.  Let tinkers' brats\ndo tinkerings; we are their betters.  I like to take in hand none but\nclean, virgin, fair-and-square mathematical jobs, something that\nregularly begins at the beginning, and is at the middle when midway,\nand comes to an end at the conclusion; not a cobbler's job, that's at\nan end in the middle, and at the beginning at the end.  It's the old\nwoman's tricks to be giving cobbling jobs.  Lord! what an affection\nall old women have for tinkers.  I know an old woman of sixty-five\nwho ran away with a bald-headed young tinker once.  And that's the\nreason I never would work for lonely widow old women ashore, when I\nkept my job-shop in the Vineyard; they might have taken it into their\nlonely old heads to run off with me.  But heigh-ho! there are no caps\nat sea but snow-caps.  Let me see.  Nail down the lid; caulk the\nseams; pay over the same with pitch; batten them down tight, and hang\nit with the snap-spring over the ship's stern.  Were ever such things\ndone before with a coffin?  Some superstitious old carpenters, now,\nwould be tied up in the rigging, ere they would do the job.  But I'm\nmade of knotty Aroostook hemlock; I don't budge.  Cruppered with a\ncoffin!  Sailing about with a grave-yard tray!  But never mind.  We\nworkers in woods make bridal-bedsteads and card-tables, as well as\ncoffins and hearses.  We work by the month, or by the job, or by the\nprofit; not for us to ask the why and wherefore of our work, unless\nit be too confounded cobbling, and then we stash it if we can.  Hem!\nI'll do the job, now, tenderly.  I'll have me--let's see--how many in\nthe ship's company, all told?  But I've forgotten.  Any way, I'll\nhave me thirty separate, Turk's-headed life-lines, each three feet\nlong hanging all round to the coffin.  Then, if the hull go down,\nthere'll be thirty lively fellows all fighting for one coffin, a\nsight not seen very often beneath the sun!  Come hammer,\ncaulking-iron, pitch-pot, and marling-spike!  Let's to it.\"\n\n\n\nCHAPTER 127\n\nThe Deck.\n\n\nTHE COFFIN LAID UPON TWO LINE-TUBS, BETWEEN THE VICE-BENCH AND THE\nOPEN HATCHWAY; THE CARPENTER CAULKING ITS SEAMS; THE STRING OF\nTWISTED OAKUM SLOWLY UNWINDING FROM A LARGE ROLL OF IT PLACED IN THE\nBOSOM OF HIS FROCK.--AHAB COMES SLOWLY FROM THE CABIN-GANGWAY, AND\nHEARS PIP FOLLOWING HIM.\n\n\nBack, lad; I will be with ye again presently.  He goes!  Not this\nhand complies with my humor more genially than that boy.--Middle\naisle of a church!  What's here?\"\n\n\"Life-buoy, sir.  Mr. Starbuck's orders.  Oh, look, sir!  Beware the\nhatchway!\"\n\n\"Thank ye, man.  Thy coffin lies handy to the vault.\"\n\n\"Sir?  The hatchway? oh!  So it does, sir, so it does.\"\n\n\"Art not thou the leg-maker?  Look, did not this stump come from thy\nshop?\"\n\n\"I believe it did, sir; does the ferrule stand, sir?\"\n\n\"Well enough.  But art thou not also the undertaker?\"\n\n\"Aye, sir; I patched up this thing here as a coffin for Queequeg; but\nthey've set me now to turning it into something else.\"\n\n\"Then tell me; art thou not an arrant, all-grasping, intermeddling,\nmonopolising, heathenish old scamp, to be one day making legs, and\nthe next day coffins to clap them in, and yet again life-buoys out of\nthose same coffins?  Thou art as unprincipled as the gods, and as\nmuch of a jack-of-all-trades.\"\n\n\"But I do not mean anything, sir.  I do as I do.\"\n\n\"The gods again.  Hark ye, dost thou not ever sing working about a\ncoffin?  The Titans, they say, hummed snatches when chipping out the\ncraters for volcanoes; and the grave-digger in the play sings, spade\nin hand.  Dost thou never?\"\n\n\"Sing, sir?  Do I sing?  Oh, I'm indifferent enough, sir, for that;\nbut the reason why the grave-digger made music must have been because\nthere was none in his spade, sir.  But the caulking mallet is full of\nit.  Hark to it.\"\n\n\"Aye, and that's because the lid there's a sounding-board; and what\nin all things makes the sounding-board is this--there's naught\nbeneath.  And yet, a coffin with a body in it rings pretty much the\nsame, Carpenter.  Hast thou ever helped carry a bier, and heard the\ncoffin knock against the churchyard gate, going in?\n\n\"Faith, sir, I've--\"\n\n\"Faith?  What's that?\"\n\n\"Why, faith, sir, it's only a sort of exclamation-like--that's all,\nsir.\"\n\n\"Um, um; go on.\"\n\n\"I was about to say, sir, that--\"\n\n\"Art thou a silk-worm?  Dost thou spin thy own shroud out of thyself?\nLook at thy bosom!  Despatch! and get these traps out of sight.\"\n\n\"He goes aft.  That was sudden, now; but squalls come sudden in hot\nlatitudes.  I've heard that the Isle of Albemarle, one of the\nGallipagos, is cut by the Equator right in the middle.  Seems to me\nsome sort of Equator cuts yon old man, too, right in his middle.\nHe's always under the Line--fiery hot, I tell ye!  He's looking this\nway--come, oakum; quick.  Here we go again.  This wooden mallet is\nthe cork, and I'm the professor of musical glasses--tap, tap!\"\n\n(AHAB TO HIMSELF.)\n\n\"There's a sight!  There's a sound!  The grey-headed woodpecker\ntapping the hollow tree!  Blind and dumb might well be envied now.\nSee! that thing rests on two line-tubs, full of tow-lines.  A most\nmalicious wag, that fellow.  Rat-tat!  So man's seconds tick!  Oh!\nhow immaterial are all materials!  What things real are there, but\nimponderable thoughts?  Here now's the very dreaded symbol of grim\ndeath, by a mere hap, made the expressive sign of the help and hope\nof most endangered life.  A life-buoy of a coffin!  Does it go\nfurther?  Can it be that in some spiritual sense the coffin is, after\nall, but an immortality-preserver!  I'll think of that.  But no.  So\nfar gone am I in the dark side of earth, that its other side, the\ntheoretic bright one, seems but uncertain twilight to me.  Will ye\nnever have done, Carpenter, with that accursed sound?  I go below;\nlet me not see that thing here when I return again.  Now, then, Pip,\nwe'll talk this over; I do suck most wondrous philosophies from thee!\nSome unknown conduits from the unknown worlds must empty into thee!\"\n\n\n\nCHAPTER 128\n\nThe Pequod Meets The Rachel.\n\n\nNext day, a large ship, the Rachel, was descried, bearing directly\ndown upon the Pequod, all her spars thickly clustering with men.  At\nthe time the Pequod was making good speed through the water; but as\nthe broad-winged windward stranger shot nigh to her, the boastful\nsails all fell together as blank bladders that are burst, and all\nlife fled from the smitten hull.\n\n\"Bad news; she brings bad news,\" muttered the old Manxman.  But ere\nher commander, who, with trumpet to mouth, stood up in his boat; ere\nhe could hopefully hail, Ahab's voice was heard.\n\n\"Hast seen the White Whale?\"\n\n\"Aye, yesterday.  Have ye seen a whale-boat adrift?\"\n\nThrottling his joy, Ahab negatively answered this unexpected\nquestion; and would then have fain boarded the stranger, when the\nstranger captain himself, having stopped his vessel's way, was seen\ndescending her side.  A few keen pulls, and his boat-hook soon\nclinched the Pequod's main-chains, and he sprang to the deck.\nImmediately he was recognised by Ahab for a Nantucketer he knew.  But\nno formal salutation was exchanged.\n\n\"Where was he?--not killed!--not killed!\" cried Ahab, closely\nadvancing.  \"How was it?\"\n\nIt seemed that somewhat late on the afternoon of the day previous,\nwhile three of the stranger's boats were engaged with a shoal of\nwhales, which had led them some four or five miles from the ship; and\nwhile they were yet in swift chase to windward, the white hump and\nhead of Moby Dick had suddenly loomed up out of the water, not very\nfar to leeward; whereupon, the fourth rigged boat--a reserved\none--had been instantly lowered in chase.  After a keen sail before\nthe wind, this fourth boat--the swiftest keeled of all--seemed to\nhave succeeded in fastening--at least, as well as the man at the\nmast-head could tell anything about it.  In the distance he saw the\ndiminished dotted boat; and then a swift gleam of bubbling white\nwater; and after that nothing more; whence it was concluded that the\nstricken whale must have indefinitely run away with his pursuers, as\noften happens.  There was some apprehension, but no positive alarm,\nas yet.  The recall signals were placed in the rigging; darkness came\non; and forced to pick up her three far to windward boats--ere going\nin quest of the fourth one in the precisely opposite direction--the\nship had not only been necessitated to leave that boat to its fate\ntill near midnight, but, for the time, to increase her distance from\nit.  But the rest of her crew being at last safe aboard, she crowded\nall sail--stunsail on stunsail--after the missing boat; kindling a\nfire in her try-pots for a beacon; and every other man aloft on the\nlook-out.  But though when she had thus sailed a sufficient distance\nto gain the presumed place of the absent ones when last seen; though\nshe then paused to lower her spare boats to pull all around her; and\nnot finding anything, had again dashed on; again paused, and lowered\nher boats; and though she had thus continued doing till daylight;\nyet not the least glimpse of the missing keel had been seen.\n\nThe story told, the stranger Captain immediately went on to reveal\nhis object in boarding the Pequod.  He desired that ship to unite\nwith his own in the search; by sailing over the sea some four or five\nmiles apart, on parallel lines, and so sweeping a double horizon, as\nit were.\n\n\"I will wager something now,\" whispered Stubb to Flask, \"that some\none in that missing boat wore off that Captain's best coat; mayhap,\nhis watch--he's so cursed anxious to get it back.  Who ever heard of\ntwo pious whale-ships cruising after one missing whale-boat in the\nheight of the whaling season?  See, Flask, only see how pale he\nlooks--pale in the very buttons of his eyes--look--it wasn't the\ncoat--it must have been the--\"\n\n\"My boy, my own boy is among them.  For God's sake--I beg, I\nconjure\"--here exclaimed the stranger Captain to Ahab, who thus far\nhad but icily received his petition.  \"For eight-and-forty hours let\nme charter your ship--I will gladly pay for it, and roundly pay for\nit--if there be no other way--for eight-and-forty hours only--only\nthat--you must, oh, you must, and you SHALL do this thing.\"\n\n\"His son!\" cried Stubb, \"oh, it's his son he's lost!  I take back the\ncoat and watch--what says Ahab?  We must save that boy.\"\n\n\"He's drowned with the rest on 'em, last night,\" said the old Manx\nsailor standing behind them; \"I heard; all of ye heard their\nspirits.\"\n\nNow, as it shortly turned out, what made this incident of the\nRachel's the more melancholy, was the circumstance, that not only was\none of the Captain's sons among the number of the missing boat's\ncrew; but among the number of the other boat's crews, at the same\ntime, but on the other hand, separated from the ship during the dark\nvicissitudes of the chase, there had been still another son; as that\nfor a time, the wretched father was plunged to the bottom of the\ncruellest perplexity; which was only solved for him by his chief\nmate's instinctively adopting the ordinary procedure of a whale-ship\nin such emergencies, that is, when placed between jeopardized but\ndivided boats, always to pick up the majority first.  But the\ncaptain, for some unknown constitutional reason, had refrained from\nmentioning all this, and not till forced to it by Ahab's iciness did\nhe allude to his one yet missing boy; a little lad, but twelve years\nold, whose father with the earnest but unmisgiving hardihood of a\nNantucketer's paternal love, had thus early sought to initiate him in\nthe perils and wonders of a vocation almost immemorially the destiny\nof all his race.  Nor does it unfrequently occur, that Nantucket\ncaptains will send a son of such tender age away from them, for a\nprotracted three or four years' voyage in some other ship than their\nown; so that their first knowledge of a whaleman's career shall be\nunenervated by any chance display of a father's natural but untimely\npartiality, or undue apprehensiveness and concern.\n\nMeantime, now the stranger was still beseeching his poor boon of\nAhab; and Ahab still stood like an anvil, receiving every shock, but\nwithout the least quivering of his own.\n\n\"I will not go,\" said the stranger, \"till you say aye to me.  Do to\nme as you would have me do to you in the like case.  For YOU too have\na boy, Captain Ahab--though but a child, and nestling safely at home\nnow--a child of your old age too--Yes, yes, you relent; I see\nit--run, run, men, now, and stand by to square in the yards.\"\n\n\"Avast,\" cried Ahab--\"touch not a rope-yarn\"; then in a voice that\nprolongingly moulded every word--\"Captain Gardiner, I will not do it.\nEven now I lose time.  Good-bye, good-bye.  God bless ye, man, and\nmay I forgive myself, but I must go.  Mr. Starbuck, look at the\nbinnacle watch, and in three minutes from this present instant warn\noff all strangers: then brace forward again, and let the ship sail\nas before.\"\n\nHurriedly turning, with averted face, he descended into his cabin,\nleaving the strange captain transfixed at this unconditional and\nutter rejection of his so earnest suit.  But starting from his\nenchantment, Gardiner silently hurried to the side; more fell than\nstepped into his boat, and returned to his ship.\n\nSoon the two ships diverged their wakes; and long as the strange\nvessel was in view, she was seen to yaw hither and thither at every\ndark spot, however small, on the sea.  This way and that her yards\nwere swung round; starboard and larboard, she continued to tack;\nnow she beat against a head sea; and again it pushed her before it;\nwhile all the while, her masts and yards were thickly clustered with\nmen, as three tall cherry trees, when the boys are cherrying among\nthe boughs.\n\nBut by her still halting course and winding, woeful way, you plainly\nsaw that this ship that so wept with spray, still remained without\ncomfort.  She was Rachel, weeping for her children, because they were\nnot.\n\n\n\nCHAPTER 129\n\nThe Cabin.\n\n\n(AHAB MOVING TO GO ON DECK; PIP CATCHES HIM BY THE HAND TO FOLLOW.)\n\nLad, lad, I tell thee thou must not follow Ahab now.  The hour is\ncoming when Ahab would not scare thee from him, yet would not have\nthee by him.  There is that in thee, poor lad, which I feel too\ncuring to my malady.  Like cures like; and for this hunt, my malady\nbecomes my most desired health.  Do thou abide below here, where they\nshall serve thee, as if thou wert the captain.  Aye, lad, thou shalt\nsit here in my own screwed chair; another screw to it, thou must be.\"\n\n\"No, no, no! ye have not a whole body, sir; do ye but use poor me for\nyour one lost leg; only tread upon me, sir; I ask no more, so I\nremain a part of ye.\"\n\n\"Oh! spite of million villains, this makes me a bigot in the fadeless\nfidelity of man!--and a black! and crazy!--but methinks\nlike-cures-like applies to him too; he grows so sane again.\"\n\n\"They tell me, sir, that Stubb did once desert poor little Pip, whose\ndrowned bones now show white, for all the blackness of his living\nskin.  But I will never desert ye, sir, as Stubb did him.  Sir, I\nmust go with ye.\"\n\n\"If thou speakest thus to me much more, Ahab's purpose keels up in\nhim.  I tell thee no; it cannot be.\"\n\n\"Oh good master, master, master!\n\n\"Weep so, and I will murder thee! have a care, for Ahab too is mad.\nListen, and thou wilt often hear my ivory foot upon the deck, and\nstill know that I am there.  And now I quit thee.  Thy hand!--Met!\nTrue art thou, lad, as the circumference to its centre.  So: God for\never bless thee; and if it come to that,--God for ever save thee, let\nwhat will befall.\"\n\n(AHAB GOES; PIP STEPS ONE STEP FORWARD.)\n\n\n\"Here he this instant stood; I stand in his air,--but I'm alone.\nNow were even poor Pip here I could endure it, but he's missing.\nPip!  Pip!  Ding, dong, ding!  Who's seen Pip?  He must be up here;\nlet's try the door.  What? neither lock, nor bolt, nor bar; and yet\nthere's no opening it.  It must be the spell; he told me to stay\nhere: Aye, and told me this screwed chair was mine.  Here, then, I'll\nseat me, against the transom, in the ship's full middle, all her keel\nand her three masts before me.  Here, our old sailors say, in their\nblack seventy-fours great admirals sometimes sit at table, and lord\nit over rows of captains and lieutenants.  Ha! what's this? epaulets!\nepaulets! the epaulets all come crowding!  Pass round the decanters;\nglad to see ye; fill up, monsieurs!  What an odd feeling, now, when a\nblack boy's host to white men with gold lace upon their\ncoats!--Monsieurs, have ye seen one Pip?--a little negro lad, five\nfeet high, hang-dog look, and cowardly!  Jumped from a whale-boat\nonce;--seen him?  No!  Well then, fill up again, captains, and let's\ndrink shame upon all cowards!  I name no names.  Shame upon them!\nPut one foot upon the table.  Shame upon all cowards.--Hist! above\nthere, I hear ivory--Oh, master! master!  I am indeed down-hearted\nwhen you walk over me.  But here I'll stay, though this stern\nstrikes rocks; and they bulge through; and oysters come to join me.\"\n\n\n\nCHAPTER 130\n\nThe Hat.\n\n\nAnd now that at the proper time and place, after so long and wide a\npreliminary cruise, Ahab,--all other whaling waters swept--seemed to\nhave chased his foe into an ocean-fold, to slay him the more securely\nthere; now, that he found himself hard by the very latitude and\nlongitude where his tormenting wound had been inflicted; now that a\nvessel had been spoken which on the very day preceding had actually\nencountered Moby Dick;--and now that all his successive meetings with\nvarious ships contrastingly concurred to show the demoniac\nindifference with which the white whale tore his hunters, whether\nsinning or sinned against; now it was that there lurked a something\nin the old man's eyes, which it was hardly sufferable for feeble\nsouls to see.  As the unsetting polar star, which through the\nlivelong, arctic, six months' night sustains its piercing, steady,\ncentral gaze; so Ahab's purpose now fixedly gleamed down upon the\nconstant midnight of the gloomy crew.  It domineered above them so,\nthat all their bodings, doubts, misgivings, fears, were fain to hide\nbeneath their souls, and not sprout forth a single spear or leaf.\n\nIn this foreshadowing interval too, all humor, forced or natural,\nvanished.  Stubb no more strove to raise a smile; Starbuck no more\nstrove to check one.  Alike, joy and sorrow, hope and fear, seemed\nground to finest dust, and powdered, for the time, in the clamped\nmortar of Ahab's iron soul.  Like machines, they dumbly moved about\nthe deck, ever conscious that the old man's despot eye was on them.\n\nBut did you deeply scan him in his more secret confidential hours;\nwhen he thought no glance but one was on him; then you would have\nseen that even as Ahab's eyes so awed the crew's, the inscrutable\nParsee's glance awed his; or somehow, at least, in some wild way, at\ntimes affected it.  Such an added, gliding strangeness began to\ninvest the thin Fedallah now; such ceaseless shudderings shook him;\nthat the men looked dubious at him; half uncertain, as it seemed,\nwhether indeed he were a mortal substance, or else a tremulous shadow\ncast upon the deck by some unseen being's body.  And that shadow was\nalways hovering there.  For not by night, even, had Fedallah ever\ncertainly been known to slumber, or go below.  He would stand still\nfor hours: but never sat or leaned; his wan but wondrous eyes did\nplainly say--We two watchmen never rest.\n\nNor, at any time, by night or day could the mariners now step upon\nthe deck, unless Ahab was before them; either standing in his\npivot-hole, or exactly pacing the planks between two undeviating\nlimits,--the main-mast and the mizen; or else they saw him standing\nin the cabin-scuttle,--his living foot advanced upon the deck, as if\nto step; his hat slouched heavily over his eyes; so that however\nmotionless he stood, however the days and nights were added on, that\nhe had not swung in his hammock; yet hidden beneath that slouching\nhat, they could never tell unerringly whether, for all this, his eyes\nwere really closed at times; or whether he was still intently\nscanning them; no matter, though he stood so in the scuttle for a\nwhole hour on the stretch, and the unheeded night-damp gathered in\nbeads of dew upon that stone-carved coat and hat.  The clothes that\nthe night had wet, the next day's sunshine dried upon him; and so,\nday after day, and night after night; he went no more beneath the\nplanks; whatever he wanted from the cabin that thing he sent for.\n\nHe ate in the same open air; that is, his two only meals,--breakfast\nand dinner: supper he never touched; nor reaped his beard; which\ndarkly grew all gnarled, as unearthed roots of trees blown over,\nwhich still grow idly on at naked base, though perished in the upper\nverdure.  But though his whole life was now become one watch on deck;\nand though the Parsee's mystic watch was without intermission as his\nown; yet these two never seemed to speak--one man to the\nother--unless at long intervals some passing unmomentous matter made\nit necessary.  Though such a potent spell seemed secretly to join the\ntwain; openly, and to the awe-struck crew, they seemed pole-like\nasunder.  If by day they chanced to speak one word; by night, dumb\nmen were both, so far as concerned the slightest verbal interchange.\nAt times, for longest hours, without a single hail, they stood far\nparted in the starlight; Ahab in his scuttle, the Parsee by the\nmainmast; but still fixedly gazing upon each other; as if in the\nParsee Ahab saw his forethrown shadow, in Ahab the Parsee his\nabandoned substance.\n\nAnd yet, somehow, did Ahab--in his own proper self, as daily, hourly,\nand every instant, commandingly revealed to his subordinates,--Ahab\nseemed an independent lord; the Parsee but his slave.  Still again\nboth seemed yoked together, and an unseen tyrant driving them; the\nlean shade siding the solid rib.  For be this Parsee what he may, all\nrib and keel was solid Ahab.\n\nAt the first faintest glimmering of the dawn, his iron voice was\nheard from aft,--\"Man the mast-heads!\"--and all through the day,\ntill after sunset and after twilight, the same voice every hour, at\nthe striking of the helmsman's bell, was heard--\"What d'ye\nsee?--sharp! sharp!\"\n\nBut when three or four days had slided by, after meeting the\nchildren-seeking Rachel; and no spout had yet been seen; the\nmonomaniac old man seemed distrustful of his crew's fidelity; at\nleast, of nearly all except the Pagan harpooneers; he seemed to\ndoubt, even, whether Stubb and Flask might not willingly overlook the\nsight he sought.  But if these suspicions were really his, he\nsagaciously refrained from verbally expressing them, however his\nactions might seem to hint them.\n\n\"I will have the first sight of the whale myself,\"--he said.  \"Aye!\nAhab must have the doubloon! and with his own hands he rigged a nest\nof basketed bowlines; and sending a hand aloft, with a single sheaved\nblock, to secure to the main-mast head, he received the two ends of\nthe downward-reeved rope; and attaching one to his basket prepared a\npin for the other end, in order to fasten it at the rail.  This done,\nwith that end yet in his hand and standing beside the pin, he looked\nround upon his crew, sweeping from one to the other; pausing his\nglance long upon Daggoo, Queequeg, Tashtego; but shunning Fedallah;\nand then settling his firm relying eye upon the chief mate,\nsaid,--\"Take the rope, sir--I give it into thy hands, Starbuck.\"\nThen arranging his person in the basket, he gave the word for them to\nhoist him to his perch, Starbuck being the one who secured the rope\nat last; and afterwards stood near it.  And thus, with one hand\nclinging round the royal mast, Ahab gazed abroad upon the sea for\nmiles and miles,--ahead, astern, this side, and that,--within the\nwide expanded circle commanded at so great a height.\n\nWhen in working with his hands at some lofty almost isolated place in\nthe rigging, which chances to afford no foothold, the sailor at sea\nis hoisted up to that spot, and sustained there by the rope; under\nthese circumstances, its fastened end on deck is always given in\nstrict charge to some one man who has the special watch of it.\nBecause in such a wilderness of running rigging, whose various\ndifferent relations aloft cannot always be infallibly discerned by\nwhat is seen of them at the deck; and when the deck-ends of these\nropes are being every few minutes cast down from the fastenings, it\nwould be but a natural fatality, if, unprovided with a constant\nwatchman, the hoisted sailor should by some carelessness of the crew\nbe cast adrift and fall all swooping to the sea.  So Ahab's\nproceedings in this matter were not unusual; the only strange thing\nabout them seemed to be, that Starbuck, almost the one only man who\nhad ever ventured to oppose him with anything in the slightest degree\napproaching to decision--one of those too, whose faithfulness on the\nlook-out he had seemed to doubt somewhat;--it was strange, that this\nwas the very man he should select for his watchman; freely giving his\nwhole life into such an otherwise distrusted person's hands.\n\nNow, the first time Ahab was perched aloft; ere he had been there ten\nminutes; one of those red-billed savage sea-hawks which so often fly\nincommodiously close round the manned mast-heads of whalemen in these\nlatitudes; one of these birds came wheeling and screaming round his\nhead in a maze of untrackably swift circlings.  Then it darted a\nthousand feet straight up into the air; then spiralized downwards,\nand went eddying again round his head.\n\nBut with his gaze fixed upon the dim and distant horizon, Ahab seemed\nnot to mark this wild bird; nor, indeed, would any one else have\nmarked it much, it being no uncommon circumstance; only now almost\nthe least heedful eye seemed to see some sort of cunning meaning in\nalmost every sight.\n\n\"Your hat, your hat, sir!\" suddenly cried the Sicilian seaman, who\nbeing posted at the mizen-mast-head, stood directly behind Ahab,\nthough somewhat lower than his level, and with a deep gulf of air\ndividing them.\n\nBut already the sable wing was before the old man's eyes; the long\nhooked bill at his head: with a scream, the black hawk darted away\nwith his prize.\n\nAn eagle flew thrice round Tarquin's head, removing his cap to\nreplace it, and thereupon Tanaquil, his wife, declared that Tarquin\nwould be king of Rome.  But only by the replacing of the cap was that\nomen accounted good.  Ahab's hat was never restored; the wild hawk\nflew on and on with it; far in advance of the prow: and at last\ndisappeared; while from the point of that disappearance, a minute\nblack spot was dimly discerned, falling from that vast height into\nthe sea.\n\n\n\nCHAPTER 131\n\nThe Pequod Meets The Delight.\n\n\nThe intense Pequod sailed on; the rolling waves and days went by; the\nlife-buoy-coffin still lightly swung; and another ship, most\nmiserably misnamed the Delight, was descried.  As she drew nigh, all\neyes were fixed upon her broad beams, called shears, which, in some\nwhaling-ships, cross the quarter-deck at the height of eight or nine\nfeet; serving to carry the spare, unrigged, or disabled boats.\n\nUpon the stranger's shears were beheld the shattered, white ribs, and\nsome few splintered planks, of what had once been a whale-boat; but\nyou now saw through this wreck, as plainly as you see through the\npeeled, half-unhinged, and bleaching skeleton of a horse.\n\n\"Hast seen the White Whale?\"\n\n\"Look!\" replied the hollow-cheeked captain from his taffrail; and\nwith his trumpet he pointed to the wreck.\n\n\"Hast killed him?\"\n\n\"The harpoon is not yet forged that ever will do that,\" answered the\nother, sadly glancing upon a rounded hammock on the deck, whose\ngathered sides some noiseless sailors were busy in sewing together.\n\n\"Not forged!\" and snatching Perth's levelled iron from the crotch,\nAhab held it out, exclaiming--\"Look ye, Nantucketer; here in this\nhand I hold his death!  Tempered in blood, and tempered by lightning\nare these barbs; and I swear to temper them triply in that hot place\nbehind the fin, where the White Whale most feels his accursed life!\"\n\n\"Then God keep thee, old man--see'st thou that\"--pointing to the\nhammock--\"I bury but one of five stout men, who were alive only\nyesterday; but were dead ere night.  Only THAT one I bury; the rest\nwere buried before they died; you sail upon their tomb.\"  Then\nturning to his crew--\"Are ye ready there? place the plank then on the\nrail, and lift the body; so, then--Oh!  God\"--advancing towards the\nhammock with uplifted hands--\"may the resurrection and the life--\"\n\n\"Brace forward!  Up helm!\" cried Ahab like lightning to his men.\n\nBut the suddenly started Pequod was not quick enough to escape the\nsound of the splash that the corpse soon made as it struck the sea;\nnot so quick, indeed, but that some of the flying bubbles might have\nsprinkled her hull with their ghostly baptism.\n\nAs Ahab now glided from the dejected Delight, the strange life-buoy\nhanging at the Pequod's stern came into conspicuous relief.\n\n\"Ha! yonder! look yonder, men!\" cried a foreboding voice in her wake.\n\"In vain, oh, ye strangers, ye fly our sad burial; ye but turn us\nyour taffrail to show us your coffin!\"\n\n\n\nCHAPTER 132\n\nThe Symphony.\n\n\nIt was a clear steel-blue day.  The firmaments of air and sea were\nhardly separable in that all-pervading azure; only, the pensive air\nwas transparently pure and soft, with a woman's look, and the robust\nand man-like sea heaved with long, strong, lingering swells, as\nSamson's chest in his sleep.\n\nHither, and thither, on high, glided the snow-white wings of small,\nunspeckled birds; these were the gentle thoughts of the feminine air;\nbut to and fro in the deeps, far down in the bottomless blue, rushed\nmighty leviathans, sword-fish, and sharks; and these were the strong,\ntroubled, murderous thinkings of the masculine sea.\n\nBut though thus contrasting within, the contrast was only in shades\nand shadows without; those two seemed one; it was only the sex, as it\nwere, that distinguished them.\n\nAloft, like a royal czar and king, the sun seemed giving this gentle\nair to this bold and rolling sea; even as bride to groom.  And at the\ngirdling line of the horizon, a soft and tremulous motion--most seen\nhere at the Equator--denoted the fond, throbbing trust, the loving\nalarms, with which the poor bride gave her bosom away.\n\nTied up and twisted; gnarled and knotted with wrinkles; haggardly\nfirm and unyielding; his eyes glowing like coals, that still glow in\nthe ashes of ruin; untottering Ahab stood forth in the clearness of\nthe morn; lifting his splintered helmet of a brow to the fair girl's\nforehead of heaven.\n\nOh, immortal infancy, and innocency of the azure!  Invisible winged\ncreatures that frolic all round us!  Sweet childhood of air and sky!\nhow oblivious were ye of old Ahab's close-coiled woe!  But so have I\nseen little Miriam and Martha, laughing-eyed elves, heedlessly gambol\naround their old sire; sporting with the circle of singed locks which\ngrew on the marge of that burnt-out crater of his brain.\n\nSlowly crossing the deck from the scuttle, Ahab leaned over the side\nand watched how his shadow in the water sank and sank to his gaze,\nthe more and the more that he strove to pierce the profundity.  But\nthe lovely aromas in that enchanted air did at last seem to dispel,\nfor a moment, the cankerous thing in his soul.  That glad, happy air,\nthat winsome sky, did at last stroke and caress him; the step-mother\nworld, so long cruel--forbidding--now threw affectionate arms round\nhis stubborn neck, and did seem to joyously sob over him, as if over\none, that however wilful and erring, she could yet find it in her\nheart to save and to bless.  From beneath his slouched hat Ahab\ndropped a tear into the sea; nor did all the Pacific contain such\nwealth as that one wee drop.\n\nStarbuck saw the old man; saw him, how he heavily leaned over the\nside; and he seemed to hear in his own true heart the measureless\nsobbing that stole out of the centre of the serenity around.  Careful\nnot to touch him, or be noticed by him, he yet drew near to him, and\nstood there.\n\nAhab turned.\n\n\"Starbuck!\"\n\n\"Sir.\"\n\n\"Oh, Starbuck! it is a mild, mild wind, and a mild looking sky.  On\nsuch a day--very much such a sweetness as this--I struck my first\nwhale--a boy-harpooneer of eighteen!  Forty--forty--forty years\nago!--ago!  Forty years of continual whaling! forty years of\nprivation, and peril, and storm-time! forty years on the pitiless\nsea! for forty years has Ahab forsaken the peaceful land, for forty\nyears to make war on the horrors of the deep!  Aye and yes, Starbuck,\nout of those forty years I have not spent three ashore.  When I think\nof this life I have led; the desolation of solitude it has been; the\nmasoned, walled-town of a Captain's exclusiveness, which admits but\nsmall entrance to any sympathy from the green country without--oh,\nweariness! heaviness!  Guinea-coast slavery of solitary\ncommand!--when I think of all this; only half-suspected, not so\nkeenly known to me before--and how for forty years I have fed upon\ndry salted fare--fit emblem of the dry nourishment of my soil!--when\nthe poorest landsman has had fresh fruit to his daily hand, and\nbroken the world's fresh bread to my mouldy crusts--away, whole\noceans away, from that young girl-wife I wedded past fifty, and\nsailed for Cape Horn the next day, leaving but one dent in my\nmarriage pillow--wife? wife?--rather a widow with her husband alive!\nAye, I widowed that poor girl when I married her, Starbuck; and\nthen, the madness, the frenzy, the boiling blood and the smoking\nbrow, with which, for a thousand lowerings old Ahab has furiously,\nfoamingly chased his prey--more a demon than a man!--aye, aye! what a\nforty years' fool--fool--old fool, has old Ahab been!  Why this\nstrife of the chase? why weary, and palsy the arm at the oar, and the\niron, and the lance? how the richer or better is Ahab now?  Behold.\nOh, Starbuck! is it not hard, that with this weary load I bear, one\npoor leg should have been snatched from under me?  Here, brush this\nold hair aside; it blinds me, that I seem to weep.  Locks so grey did\nnever grow but from out some ashes!  But do I look very old, so very,\nvery old, Starbuck?  I feel deadly faint, bowed, and humped, as\nthough I were Adam, staggering beneath the piled centuries since\nParadise.  God!  God!  God!--crack my heart!--stave my\nbrain!--mockery! mockery! bitter, biting mockery of grey hairs, have\nI lived enough joy to wear ye; and seem and feel thus intolerably\nold?  Close! stand close to me, Starbuck; let me look into a human\neye; it is better than to gaze into sea or sky; better than to gaze\nupon God.  By the green land; by the bright hearth-stone! this is the\nmagic glass, man; I see my wife and my child in thine eye.  No, no;\nstay on board, on board!--lower not when I do; when branded Ahab\ngives chase to Moby Dick.  That hazard shall not be thine.  No, no!\nnot with the far away home I see in that eye!\"\n\n\"Oh, my Captain! my Captain! noble soul! grand old heart, after all!\nwhy should any one give chase to that hated fish!  Away with me! let\nus fly these deadly waters! let us home!  Wife and child, too, are\nStarbuck's--wife and child of his brotherly, sisterly, play-fellow\nyouth; even as thine, sir, are the wife and child of thy loving,\nlonging, paternal old age!  Away! let us away!--this instant let me\nalter the course!  How cheerily, how hilariously, O my Captain, would\nwe bowl on our way to see old Nantucket again!  I think, sir, they\nhave some such mild blue days, even as this, in Nantucket.\"\n\n\"They have, they have.  I have seen them--some summer days in the\nmorning.  About this time--yes, it is his noon nap now--the boy\nvivaciously wakes; sits up in bed; and his mother tells him of me, of\ncannibal old me; how I am abroad upon the deep, but will yet come\nback to dance him again.\"\n\n\"'Tis my Mary, my Mary herself!  She promised that my boy, every\nmorning, should be carried to the hill to catch the first glimpse of\nhis father's sail!  Yes, yes! no more! it is done! we head for\nNantucket!  Come, my Captain, study out the course, and let us away!\nSee, see! the boy's face from the window! the boy's hand on the\nhill!\"\n\nBut Ahab's glance was averted; like a blighted fruit tree he shook,\nand cast his last, cindered apple to the soil.\n\n\"What is it, what nameless, inscrutable, unearthly thing is it; what\ncozening, hidden lord and master, and cruel, remorseless emperor\ncommands me; that against all natural lovings and longings, I so keep\npushing, and crowding, and jamming myself on all the time; recklessly\nmaking me ready to do what in my own proper, natural heart, I durst\nnot so much as dare?  Is Ahab, Ahab?  Is it I, God, or who, that\nlifts this arm?  But if the great sun move not of himself; but is as an\nerrand-boy in heaven; nor one single star can revolve, but by some\ninvisible power; how then can this one small heart beat; this one\nsmall brain think thoughts; unless God does that beating, does that\nthinking, does that living, and not I.  By heaven, man, we are turned\nround and round in this world, like yonder windlass, and Fate is the\nhandspike.  And all the time, lo! that smiling sky, and this\nunsounded sea!  Look! see yon Albicore! who put it into him to chase\nand fang that flying-fish?  Where do murderers go, man!  Who's to\ndoom, when the judge himself is dragged to the bar?  But it is a\nmild, mild wind, and a mild looking sky; and the air smells now, as\nif it blew from a far-away meadow; they have been making hay\nsomewhere under the slopes of the Andes, Starbuck, and the mowers are\nsleeping among the new-mown hay.  Sleeping?  Aye, toil we how we may,\nwe all sleep at last on the field.  Sleep?  Aye, and rust amid\ngreenness; as last year's scythes flung down, and left in the half-cut\nswaths--Starbuck!\"\n\nBut blanched to a corpse's hue with despair, the Mate had stolen\naway.\n\nAhab crossed the deck to gaze over on the other side; but started at\ntwo reflected, fixed eyes in the water there.  Fedallah was\nmotionlessly leaning over the same rail.\n\n\n\nCHAPTER 133\n\nThe Chase--First Day.\n\n\nThat night, in the mid-watch, when the old man--as his wont at\nintervals--stepped forth from the scuttle in which he leaned, and\nwent to his pivot-hole, he suddenly thrust out his face fiercely,\nsnuffing up the sea air as a sagacious ship's dog will, in drawing\nnigh to some barbarous isle.  He declared that a whale must be near.\nSoon that peculiar odor, sometimes to a great distance given forth by\nthe living sperm whale, was palpable to all the watch; nor was any\nmariner surprised when, after inspecting the compass, and then the\ndog-vane, and then ascertaining the precise bearing of the odor as\nnearly as possible, Ahab rapidly ordered the ship's course to be\nslightly altered, and the sail to be shortened.\n\nThe acute policy dictating these movements was sufficiently\nvindicated at daybreak, by the sight of a long sleek on the sea\ndirectly and lengthwise ahead, smooth as oil, and resembling in the\npleated watery wrinkles bordering it, the polished metallic-like\nmarks of some swift tide-rip, at the mouth of a deep, rapid stream.\n\n\"Man the mast-heads!  Call all hands!\"\n\nThundering with the butts of three clubbed handspikes on the\nforecastle deck, Daggoo roused the sleepers with such judgment claps\nthat they seemed to exhale from the scuttle, so instantaneously did\nthey appear with their clothes in their hands.\n\n\"What d'ye see?\" cried Ahab, flattening his face to the sky.\n\n\"Nothing, nothing sir!\" was the sound hailing down in reply.\n\n\"T'gallant sails!--stunsails! alow and aloft, and on both sides!\"\n\nAll sail being set, he now cast loose the life-line, reserved for\nswaying him to the main royal-mast head; and in a few moments they\nwere hoisting him thither, when, while but two thirds of the way\naloft, and while peering ahead through the horizontal vacancy between\nthe main-top-sail and top-gallant-sail, he raised a gull-like cry in\nthe air.  \"There she blows!--there she blows!  A hump like a\nsnow-hill!  It is Moby Dick!\"\n\nFired by the cry which seemed simultaneously taken up by the three\nlook-outs, the men on deck rushed to the rigging to behold the famous\nwhale they had so long been pursuing.  Ahab had now gained his final\nperch, some feet above the other look-outs, Tashtego standing just\nbeneath him on the cap of the top-gallant-mast, so that the Indian's\nhead was almost on a level with Ahab's heel.  From this height the\nwhale was now seen some mile or so ahead, at every roll of the sea\nrevealing his high sparkling hump, and regularly jetting his silent\nspout into the air.  To the credulous mariners it seemed the same\nsilent spout they had so long ago beheld in the moonlit Atlantic and\nIndian Oceans.\n\n\"And did none of ye see it before?\" cried Ahab, hailing the perched\nmen all around him.\n\n\"I saw him almost that same instant, sir, that Captain Ahab did, and\nI cried out,\" said Tashtego.\n\n\"Not the same instant; not the same--no, the doubloon is mine, Fate\nreserved the doubloon for me.  I only; none of ye could have raised\nthe White Whale first.  There she blows!--there she blows!--there\nshe blows!  There again!--there again!\" he cried, in long-drawn,\nlingering, methodic tones, attuned to the gradual prolongings of the\nwhale's visible jets.  \"He's going to sound!  In stunsails!  Down\ntop-gallant-sails!  Stand by three boats.  Mr. Starbuck, remember,\nstay on board, and keep the ship.  Helm there!  Luff, luff a point!\nSo; steady, man, steady!  There go flukes!  No, no; only black water!\nAll ready the boats there?  Stand by, stand by!  Lower me, Mr.\nStarbuck; lower, lower,--quick, quicker!\" and he slid through the air\nto the deck.\n\n\"He is heading straight to leeward, sir,\" cried Stubb, \"right away\nfrom us; cannot have seen the ship yet.\"\n\n\"Be dumb, man!  Stand by the braces!  Hard down the helm!--brace up!\nShiver her!--shiver her!--So; well that!  Boats, boats!\"\n\nSoon all the boats but Starbuck's were dropped; all the boat-sails\nset--all the paddles plying; with rippling swiftness, shooting to\nleeward; and Ahab heading the onset.  A pale, death-glimmer lit up\nFedallah's sunken eyes; a hideous motion gnawed his mouth.\n\nLike noiseless nautilus shells, their light prows sped through the\nsea; but only slowly they neared the foe.  As they neared him, the\nocean grew still more smooth; seemed drawing a carpet over its waves;\nseemed a noon-meadow, so serenely it spread.  At length the\nbreathless hunter came so nigh his seemingly unsuspecting prey, that his\nentire dazzling hump was distinctly visible, sliding along the sea as\nif an isolated thing, and continually set in a revolving ring of\nfinest, fleecy, greenish foam.  He saw the vast, involved wrinkles of\nthe slightly projecting head beyond.  Before it, far out on the soft\nTurkish-rugged waters, went the glistening white shadow from his\nbroad, milky forehead, a musical rippling playfully accompanying the\nshade; and behind, the blue waters interchangeably flowed over into\nthe moving valley of his steady wake; and on either hand bright\nbubbles arose and danced by his side.  But these were broken again by\nthe light toes of hundreds of gay fowl softly feathering the sea,\nalternate with their fitful flight; and like to some flag-staff\nrising from the painted hull of an argosy, the tall but shattered\npole of a recent lance projected from the white whale's back; and at\nintervals one of the cloud of soft-toed fowls hovering, and to and\nfro skimming like a canopy over the fish, silently perched and rocked\non this pole, the long tail feathers streaming like pennons.\n\nA gentle joyousness--a mighty mildness of repose in swiftness,\ninvested the gliding whale.  Not the white bull Jupiter swimming away\nwith ravished Europa clinging to his graceful horns; his lovely,\nleering eyes sideways intent upon the maid; with smooth bewitching\nfleetness, rippling straight for the nuptial bower in Crete; not\nJove, not that great majesty Supreme! did surpass the glorified White\nWhale as he so divinely swam.\n\nOn each soft side--coincident with the parted swell, that but once\nleaving him, then flowed so wide away--on each bright side, the whale\nshed off enticings.  No wonder there had been some among the hunters\nwho namelessly transported and allured by all this serenity, had\nventured to assail it; but had fatally found that quietude but the\nvesture of tornadoes.  Yet calm, enticing calm, oh, whale! thou\nglidest on, to all who for the first time eye thee, no matter how\nmany in that same way thou may'st have bejuggled and destroyed\nbefore.\n\nAnd thus, through the serene tranquillities of the tropical sea,\namong waves whose hand-clappings were suspended by exceeding rapture,\nMoby Dick moved on, still withholding from sight the full terrors of\nhis submerged trunk, entirely hiding the wrenched hideousness of his\njaw.  But soon the fore part of him slowly rose from the water; for\nan instant his whole marbleized body formed a high arch, like\nVirginia's Natural Bridge, and warningly waving his bannered flukes\nin the air, the grand god revealed himself, sounded, and went out of\nsight.  Hoveringly halting, and dipping on the wing, the white\nsea-fowls longingly lingered over the agitated pool that he left.\n\nWith oars apeak, and paddles down, the sheets of their sails adrift,\nthe three boats now stilly floated, awaiting Moby Dick's\nreappearance.\n\n\"An hour,\" said Ahab, standing rooted in his boat's stern; and he\ngazed beyond the whale's place, towards the dim blue spaces and wide\nwooing vacancies to leeward.  It was only an instant; for again his\neyes seemed whirling round in his head as he swept the watery circle.\nThe breeze now freshened; the sea began to swell.\n\n\"The birds!--the birds!\" cried Tashtego.\n\nIn long Indian file, as when herons take wing, the white birds were\nnow all flying towards Ahab's boat; and when within a few yards began\nfluttering over the water there, wheeling round and round, with\njoyous, expectant cries.  Their vision was keener than man's; Ahab\ncould discover no sign in the sea.  But suddenly as he peered down\nand down into its depths, he profoundly saw a white living spot no\nbigger than a white weasel, with wonderful celerity uprising, and\nmagnifying as it rose, till it turned, and then there were plainly\nrevealed two long crooked rows of white, glistening teeth, floating\nup from the undiscoverable bottom.  It was Moby Dick's open mouth and\nscrolled jaw; his vast, shadowed bulk still half blending with the\nblue of the sea.  The glittering mouth yawned beneath the boat like\nan open-doored marble tomb; and giving one sidelong sweep with his\nsteering oar, Ahab whirled the craft aside from this tremendous\napparition.  Then, calling upon Fedallah to change places with him,\nwent forward to the bows, and seizing Perth's harpoon, commanded his\ncrew to grasp their oars and stand by to stern.\n\nNow, by reason of this timely spinning round the boat upon its axis,\nits bow, by anticipation, was made to face the whale's head while yet\nunder water.  But as if perceiving this stratagem, Moby Dick, with\nthat malicious intelligence ascribed to him, sidelingly transplanted\nhimself, as it were, in an instant, shooting his pleated head\nlengthwise beneath the boat.\n\nThrough and through; through every plank and each rib, it thrilled\nfor an instant, the whale obliquely lying on his back, in the manner\nof a biting shark, slowly and feelingly taking its bows full within\nhis mouth, so that the long, narrow, scrolled lower jaw curled high\nup into the open air, and one of the teeth caught in a row-lock.  The\nbluish pearl-white of the inside of the jaw was within six inches of\nAhab's head, and reached higher than that.  In this attitude the\nWhite Whale now shook the slight cedar as a mildly cruel cat her\nmouse.  With unastonished eyes Fedallah gazed, and crossed his arms;\nbut the tiger-yellow crew were tumbling over each other's heads to\ngain the uttermost stern.\n\nAnd now, while both elastic gunwales were springing in and out, as\nthe whale dallied with the doomed craft in this devilish way; and\nfrom his body being submerged beneath the boat, he could not be\ndarted at from the bows, for the bows were almost inside of him, as\nit were; and while the other boats involuntarily paused, as before a\nquick crisis impossible to withstand, then it was that monomaniac\nAhab, furious with this tantalizing vicinity of his foe, which placed\nhim all alive and helpless in the very jaws he hated; frenzied with\nall this, he seized the long bone with his naked hands, and wildly\nstrove to wrench it from its gripe.  As now he thus vainly strove,\nthe jaw slipped from him; the frail gunwales bent in, collapsed, and\nsnapped, as both jaws, like an enormous shears, sliding further aft,\nbit the craft completely in twain, and locked themselves fast again\nin the sea, midway between the two floating wrecks.  These floated\naside, the broken ends drooping, the crew at the stern-wreck clinging\nto the gunwales, and striving to hold fast to the oars to lash them\nacross.\n\nAt that preluding moment, ere the boat was yet snapped, Ahab, the\nfirst to perceive the whale's intent, by the crafty upraising of his\nhead, a movement that loosed his hold for the time; at that moment\nhis hand had made one final effort to push the boat out of the bite.\nBut only slipping further into the whale's mouth, and tilting over\nsideways as it slipped, the boat had shaken off his hold on the jaw;\nspilled him out of it, as he leaned to the push; and so he fell\nflat-faced upon the sea.\n\nRipplingly withdrawing from his prey, Moby Dick now lay at a little\ndistance, vertically thrusting his oblong white head up and down in\nthe billows; and at the same time slowly revolving his whole spindled\nbody; so that when his vast wrinkled forehead rose--some twenty or\nmore feet out of the water--the now rising swells, with all their\nconfluent waves, dazzlingly broke against it; vindictively tossing\ntheir shivered spray still higher into the air.*  So, in a gale, the\nbut half baffled Channel billows only recoil from the base of the\nEddystone, triumphantly to overleap its summit with their scud.\n\n\n*This motion is peculiar to the sperm whale.  It receives its\ndesignation (pitchpoling) from its being likened to that preliminary\nup-and-down poise of the whale-lance, in the exercise called\npitchpoling, previously described.  By this motion the whale must\nbest and most comprehensively view whatever objects may be encircling\nhim.\n\n\nBut soon resuming his horizontal attitude, Moby Dick swam swiftly\nround and round the wrecked crew; sideways churning the water in his\nvengeful wake, as if lashing himself up to still another and more\ndeadly assault.  The sight of the splintered boat seemed to madden\nhim, as the blood of grapes and mulberries cast before Antiochus's\nelephants in the book of Maccabees.  Meanwhile Ahab half smothered in\nthe foam of the whale's insolent tail, and too much of a cripple to\nswim,--though he could still keep afloat, even in the heart of such a\nwhirlpool as that; helpless Ahab's head was seen, like a tossed\nbubble which the least chance shock might burst.  From the boat's\nfragmentary stern, Fedallah incuriously and mildly eyed him; the\nclinging crew, at the other drifting end, could not succor him; more\nthan enough was it for them to look to themselves.  For so\nrevolvingly appalling was the White Whale's aspect, and so\nplanetarily swift the ever-contracting circles he made, that he\nseemed horizontally swooping upon them.  And though the other boats,\nunharmed, still hovered hard by; still they dared not pull into the\neddy to strike, lest that should be the signal for the instant\ndestruction of the jeopardized castaways, Ahab and all; nor in that\ncase could they themselves hope to escape.  With straining eyes,\nthen, they remained on the outer edge of the direful zone, whose\ncentre had now become the old man's head.\n\nMeantime, from the beginning all this had been descried from the\nship's mast heads; and squaring her yards, she had borne down upon\nthe scene; and was now so nigh, that Ahab in the water hailed\nher!--\"Sail on the\"--but that moment a breaking sea dashed on him\nfrom Moby Dick, and whelmed him for the time.  But struggling out of\nit again, and chancing to rise on a towering crest, he\nshouted,--\"Sail on the whale!--Drive him off!\"\n\nThe Pequod's prows were pointed; and breaking up the charmed circle,\nshe effectually parted the white whale from his victim.  As he\nsullenly swam off, the boats flew to the rescue.\n\nDragged into Stubb's boat with blood-shot, blinded eyes, the white\nbrine caking in his wrinkles; the long tension of Ahab's bodily\nstrength did crack, and helplessly he yielded to his body's doom: for\na time, lying all crushed in the bottom of Stubb's boat, like one\ntrodden under foot of herds of elephants.  Far inland, nameless wails\ncame from him, as desolate sounds from out ravines.\n\nBut this intensity of his physical prostration did but so much the\nmore abbreviate it.  In an instant's compass, great hearts sometimes\ncondense to one deep pang, the sum total of those shallow pains\nkindly diffused through feebler men's whole lives.  And so, such\nhearts, though summary in each one suffering; still, if the gods\ndecree it, in their life-time aggregate a whole age of woe, wholly\nmade up of instantaneous intensities; for even in their pointless\ncentres, those noble natures contain the entire circumferences of\ninferior souls.\n\n\"The harpoon,\" said Ahab, half way rising, and draggingly leaning on\none bended arm--\"is it safe?\"\n\n\"Aye, sir, for it was not darted; this is it,\" said Stubb, showing\nit.\n\n\"Lay it before me;--any missing men?\"\n\n\"One, two, three, four, five;--there were five oars, sir, and here\nare five men.\"\n\n\"That's good.--Help me, man; I wish to stand.  So, so, I see him!\nthere! there! going to leeward still; what a leaping spout!--Hands\noff from me!  The eternal sap runs up in Ahab's bones again!  Set the\nsail; out oars; the helm!\"\n\nIt is often the case that when a boat is stove, its crew, being\npicked up by another boat, help to work that second boat; and the\nchase is thus continued with what is called double-banked oars.  It\nwas thus now.  But the added power of the boat did not equal the\nadded power of the whale, for he seemed to have treble-banked his\nevery fin; swimming with a velocity which plainly showed, that if\nnow, under these circumstances, pushed on, the chase would prove an\nindefinitely prolonged, if not a hopeless one; nor could any crew\nendure for so long a period, such an unintermitted, intense straining\nat the oar; a thing barely tolerable only in some one brief\nvicissitude.  The ship itself, then, as it sometimes happens, offered\nthe most promising intermediate means of overtaking the chase.\nAccordingly, the boats now made for her, and were soon swayed up to\ntheir cranes--the two parts of the wrecked boat having been\npreviously secured by her--and then hoisting everything to her side,\nand stacking her canvas high up, and sideways outstretching it with\nstun-sails, like the double-jointed wings of an albatross; the Pequod\nbore down in the leeward wake of Moby-Dick.  At the well known,\nmethodic intervals, the whale's glittering spout was regularly\nannounced from the manned mast-heads; and when he would be reported\nas just gone down, Ahab would take the time, and then pacing the\ndeck, binnacle-watch in hand, so soon as the last second of the\nallotted hour expired, his voice was heard.--\"Whose is the doubloon\nnow?  D'ye see him?\" and if the reply was, No, sir! straightway he\ncommanded them to lift him to his perch.  In this way the day wore\non; Ahab, now aloft and motionless; anon, unrestingly pacing the\nplanks.\n\nAs he was thus walking, uttering no sound, except to hail the men\naloft, or to bid them hoist a sail still higher, or to spread one to\na still greater breadth--thus to and fro pacing, beneath his slouched\nhat, at every turn he passed his own wrecked boat, which had been\ndropped upon the quarter-deck, and lay there reversed; broken bow to\nshattered stern.  At last he paused before it; and as in an already\nover-clouded sky fresh troops of clouds will sometimes sail across,\nso over the old man's face there now stole some such added gloom as\nthis.\n\nStubb saw him pause; and perhaps intending, not vainly, though, to\nevince his own unabated fortitude, and thus keep up a valiant place\nin his Captain's mind, he advanced, and eyeing the wreck\nexclaimed--\"The thistle the ass refused; it pricked his mouth too\nkeenly, sir; ha! ha!\"\n\n\"What soulless thing is this that laughs before a wreck?  Man, man!\ndid I not know thee brave as fearless fire (and as mechanical) I\ncould swear thou wert a poltroon.  Groan nor laugh should be heard\nbefore a wreck.\"\n\n\"Aye, sir,\" said Starbuck drawing near, \"'tis a solemn sight; an\nomen, and an ill one.\"\n\n\"Omen? omen?--the dictionary!  If the gods think to speak outright to\nman, they will honourably speak outright; not shake their heads, and\ngive an old wives' darkling hint.--Begone!  Ye two are the opposite\npoles of one thing; Starbuck is Stubb reversed, and Stubb is\nStarbuck; and ye two are all mankind; and Ahab stands alone among the\nmillions of the peopled earth, nor gods nor men his neighbors!  Cold,\ncold--I shiver!--How now?  Aloft there!  D'ye see him?  Sing out for\nevery spout, though he spout ten times a second!\"\n\nThe day was nearly done; only the hem of his golden robe was\nrustling.  Soon, it was almost dark, but the look-out men still\nremained unset.\n\n\"Can't see the spout now, sir;--too dark\"--cried a voice from the\nair.\n\n\"How heading when last seen?\"\n\n\"As before, sir,--straight to leeward.\"\n\n\"Good! he will travel slower now 'tis night.  Down royals and\ntop-gallant stun-sails, Mr. Starbuck.  We must not run over him\nbefore morning; he's making a passage now, and may heave-to a while.\nHelm there! keep her full before the wind!--Aloft! come down!--Mr.\nStubb, send a fresh hand to the fore-mast head, and see it manned\ntill morning.\"--Then advancing towards the doubloon in the\nmain-mast--\"Men, this gold is mine, for I earned it; but I shall let\nit abide here till the White Whale is dead; and then, whosoever of ye\nfirst raises him, upon the day he shall be killed, this gold is that\nman's; and if on that day I shall again raise him, then, ten times\nits sum shall be divided among all of ye!  Away now!--the deck is\nthine, sir!\"\n\nAnd so saying, he placed himself half way within the scuttle, and\nslouching his hat, stood there till dawn, except when at intervals\nrousing himself to see how the night wore on.\n\n\n\nCHAPTER 134\n\nThe Chase--Second Day.\n\n\nAt day-break, the three mast-heads were punctually manned afresh.\n\n\"D'ye see him?\" cried Ahab after allowing a little space for the\nlight to spread.\n\n\"See nothing, sir.\"\n\n\"Turn up all hands and make sail! he travels faster than I thought\nfor;--the top-gallant sails!--aye, they should have been kept on her\nall night.  But no matter--'tis but resting for the rush.\"\n\nHere be it said, that this pertinacious pursuit of one particular\nwhale, continued through day into night, and through night into day,\nis a thing by no means unprecedented in the South sea fishery.  For\nsuch is the wonderful skill, prescience of experience, and invincible\nconfidence acquired by some great natural geniuses among the\nNantucket commanders; that from the simple observation of a whale\nwhen last descried, they will, under certain given circumstances,\npretty accurately foretell both the direction in which he will\ncontinue to swim for a time, while out of sight, as well as his\nprobable rate of progression during that period.  And, in these\ncases, somewhat as a pilot, when about losing sight of a coast, whose\ngeneral trending he well knows, and which he desires shortly to\nreturn to again, but at some further point; like as this pilot stands\nby his compass, and takes the precise bearing of the cape at present\nvisible, in order the more certainly to hit aright the remote, unseen\nheadland, eventually to be visited: so does the fisherman, at his\ncompass, with the whale; for after being chased, and diligently\nmarked, through several hours of daylight, then, when night obscures\nthe fish, the creature's future wake through the darkness is almost\nas established to the sagacious mind of the hunter, as the pilot's\ncoast is to him.  So that to this hunter's wondrous skill, the\nproverbial evanescence of a thing writ in water, a wake, is to all\ndesired purposes well nigh as reliable as the steadfast land.  And as\nthe mighty iron Leviathan of the modern railway is so familiarly\nknown in its every pace, that, with watches in their hands, men time\nhis rate as doctors that of a baby's pulse; and lightly say of it,\nthe up train or the down train will reach such or such a spot, at\nsuch or such an hour; even so, almost, there are occasions when these\nNantucketers time that other Leviathan of the deep, according to the\nobserved humor of his speed; and say to themselves, so many hours\nhence this whale will have gone two hundred miles, will have about\nreached this or that degree of latitude or longitude.  But to render\nthis acuteness at all successful in the end, the wind and the sea\nmust be the whaleman's allies; for of what present avail to the\nbecalmed or windbound mariner is the skill that assures him he is\nexactly ninety-three leagues and a quarter from his port?  Inferable\nfrom these statements, are many collateral subtile matters touching\nthe chase of whales.\n\nThe ship tore on; leaving such a furrow in the sea as when a\ncannon-ball, missent, becomes a plough-share and turns up the level\nfield.\n\n\"By salt and hemp!\" cried Stubb, \"but this swift motion of the deck\ncreeps up one's legs and tingles at the heart.  This ship and I are\ntwo brave fellows!--Ha, ha!  Some one take me up, and launch me,\nspine-wise, on the sea,--for by live-oaks! my spine's a keel.  Ha,\nha! we go the gait that leaves no dust behind!\"\n\n\"There she blows--she blows!--she blows!--right ahead!\" was now the\nmast-head cry.\n\n\"Aye, aye!\" cried Stubb, \"I knew it--ye can't escape--blow on and\nsplit your spout, O whale! the mad fiend himself is after ye! blow\nyour trump--blister your lungs!--Ahab will dam off your blood, as a\nmiller shuts his watergate upon the stream!\"\n\nAnd Stubb did but speak out for well nigh all that crew.  The\nfrenzies of the chase had by this time worked them bubblingly up,\nlike old wine worked anew.  Whatever pale fears and forebodings some\nof them might have felt before; these were not only now kept out of\nsight through the growing awe of Ahab, but they were broken up, and\non all sides routed, as timid prairie hares that scatter before the\nbounding bison.  The hand of Fate had snatched all their souls; and\nby the stirring perils of the previous day; the rack of the past\nnight's suspense; the fixed, unfearing, blind, reckless way in which\ntheir wild craft went plunging towards its flying mark; by all these\nthings, their hearts were bowled along.  The wind that made great\nbellies of their sails, and rushed the vessel on by arms invisible as\nirresistible; this seemed the symbol of that unseen agency which so\nenslaved them to the race.\n\nThey were one man, not thirty.  For as the one ship that held them\nall; though it was put together of all contrasting things--oak, and\nmaple, and pine wood; iron, and pitch, and hemp--yet all these ran\ninto each other in the one concrete hull, which shot on its way, both\nbalanced and directed by the long central keel; even so, all the\nindividualities of the crew, this man's valor, that man's fear; guilt\nand guiltiness, all varieties were welded into oneness, and were all\ndirected to that fatal goal which Ahab their one lord and keel did\npoint to.\n\nThe rigging lived.  The mast-heads, like the tops of tall palms, were\noutspreadingly tufted with arms and legs.  Clinging to a spar with\none hand, some reached forth the other with impatient wavings;\nothers, shading their eyes from the vivid sunlight, sat far out on\nthe rocking yards; all the spars in full bearing of mortals, ready\nand ripe for their fate.  Ah! how they still strove through that\ninfinite blueness to seek out the thing that might destroy them!\n\n\"Why sing ye not out for him, if ye see him?\" cried Ahab, when, after\nthe lapse of some minutes since the first cry, no more had been\nheard.  \"Sway me up, men; ye have been deceived; not Moby Dick casts\none odd jet that way, and then disappears.\"\n\nIt was even so; in their headlong eagerness, the men had mistaken\nsome other thing for the whale-spout, as the event itself soon\nproved; for hardly had Ahab reached his perch; hardly was the rope\nbelayed to its pin on deck, when he struck the key-note to an\norchestra, that made the air vibrate as with the combined discharges\nof rifles.  The triumphant halloo of thirty buckskin lungs was heard,\nas--much nearer to the ship than the place of the imaginary jet, less\nthan a mile ahead--Moby Dick bodily burst into view!  For not by any\ncalm and indolent spoutings; not by the peaceable gush of that mystic\nfountain in his head, did the White Whale now reveal his vicinity;\nbut by the far more wondrous phenomenon of breaching.  Rising with\nhis utmost velocity from the furthest depths, the Sperm Whale thus\nbooms his entire bulk into the pure element of air, and piling up a\nmountain of dazzling foam, shows his place to the distance of seven\nmiles and more.  In those moments, the torn, enraged waves he shakes\noff, seem his mane; in some cases, this breaching is his act of\ndefiance.\n\n\"There she breaches! there she breaches!\" was the cry, as in his\nimmeasurable bravadoes the White Whale tossed himself salmon-like to\nHeaven.  So suddenly seen in the blue plain of the sea, and relieved\nagainst the still bluer margin of the sky, the spray that he raised,\nfor the moment, intolerably glittered and glared like a glacier; and\nstood there gradually fading and fading away from its first sparkling\nintensity, to the dim mistiness of an advancing shower in a vale.\n\n\"Aye, breach your last to the sun, Moby Dick!\" cried Ahab, \"thy hour\nand thy harpoon are at hand!--Down! down all of ye, but one man at\nthe fore.  The boats!--stand by!\"\n\nUnmindful of the tedious rope-ladders of the shrouds, the men, like\nshooting stars, slid to the deck, by the isolated backstays and\nhalyards; while Ahab, less dartingly, but still rapidly was dropped\nfrom his perch.\n\n\"Lower away,\" he cried, so soon as he had reached his boat--a spare\none, rigged the afternoon previous.  \"Mr. Starbuck, the ship is\nthine--keep away from the boats, but keep near them.  Lower, all!\"\n\nAs if to strike a quick terror into them, by this time being the\nfirst assailant himself, Moby Dick had turned, and was now coming for\nthe three crews.  Ahab's boat was central; and cheering his men, he\ntold them he would take the whale head-and-head,--that is, pull\nstraight up to his forehead,--a not uncommon thing; for when within a\ncertain limit, such a course excludes the coming onset from the\nwhale's sidelong vision.  But ere that close limit was gained, and\nwhile yet all three boats were plain as the ship's three masts to his\neye; the White Whale churning himself into furious speed, almost in\nan instant as it were, rushing among the boats with open jaws, and a\nlashing tail, offered appalling battle on every side; and heedless of\nthe irons darted at him from every boat, seemed only intent on\nannihilating each separate plank of which those boats were made.  But\nskilfully manoeuvred, incessantly wheeling like trained chargers in\nthe field; the boats for a while eluded him; though, at times, but by\na plank's breadth; while all the time, Ahab's unearthly slogan tore\nevery other cry but his to shreds.\n\nBut at last in his untraceable evolutions, the White Whale so crossed\nand recrossed, and in a thousand ways entangled the slack of the\nthree lines now fast to him, that they foreshortened, and, of\nthemselves, warped the devoted boats towards the planted irons in\nhim; though now for a moment the whale drew aside a little, as if to\nrally for a more tremendous charge.  Seizing that opportunity, Ahab\nfirst paid out more line: and then was rapidly hauling and jerking\nin upon it again--hoping that way to disencumber it of some\nsnarls--when lo!--a sight more savage than the embattled teeth of\nsharks!\n\nCaught and twisted--corkscrewed in the mazes of the line, loose\nharpoons and lances, with all their bristling barbs and points, came\nflashing and dripping up to the chocks in the bows of Ahab's boat.\nOnly one thing could be done.  Seizing the boat-knife, he critically\nreached within--through--and then, without--the rays of steel;\ndragged in the line beyond, passed it, inboard, to the bowsman, and\nthen, twice sundering the rope near the chocks--dropped the\nintercepted fagot of steel into the sea; and was all fast again.\nThat instant, the White Whale made a sudden rush among the remaining\ntangles of the other lines; by so doing, irresistibly dragged the\nmore involved boats of Stubb and Flask towards his flukes; dashed\nthem together like two rolling husks on a surf-beaten beach, and\nthen, diving down into the sea, disappeared in a boiling maelstrom,\nin which, for a space, the odorous cedar chips of the wrecks danced\nround and round, like the grated nutmeg in a swiftly stirred bowl of\npunch.\n\nWhile the two crews were yet circling in the waters, reaching out\nafter the revolving line-tubs, oars, and other floating furniture,\nwhile aslope little Flask bobbed up and down like an empty vial,\ntwitching his legs upwards to escape the dreaded jaws of sharks; and\nStubb was lustily singing out for some one to ladle him up; and while\nthe old man's line--now parting--admitted of his pulling into the\ncreamy pool to rescue whom he could;--in that wild simultaneousness\nof a thousand concreted perils,--Ahab's yet unstricken boat seemed\ndrawn up towards Heaven by invisible wires,--as, arrow-like, shooting\nperpendicularly from the sea, the White Whale dashed his broad\nforehead against its bottom, and sent it, turning over and over, into\nthe air; till it fell again--gunwale downwards--and Ahab and his men\nstruggled out from under it, like seals from a sea-side cave.\n\nThe first uprising momentum of the whale--modifying its direction as\nhe struck the surface--involuntarily launched him along it, to a\nlittle distance from the centre of the destruction he had made; and\nwith his back to it, he now lay for a moment slowly feeling with his\nflukes from side to side; and whenever a stray oar, bit of plank, the\nleast chip or crumb of the boats touched his skin, his tail swiftly\ndrew back, and came sideways smiting the sea.  But soon, as if\nsatisfied that his work for that time was done, he pushed his pleated\nforehead through the ocean, and trailing after him the intertangled\nlines, continued his leeward way at a traveller's methodic pace.\n\nAs before, the attentive ship having descried the whole fight, again\ncame bearing down to the rescue, and dropping a boat, picked up the\nfloating mariners, tubs, oars, and whatever else could be caught at,\nand safely landed them on her decks.  Some sprained shoulders,\nwrists, and ankles; livid contusions; wrenched harpoons and lances;\ninextricable intricacies of rope; shattered oars and planks; all\nthese were there; but no fatal or even serious ill seemed to have\nbefallen any one.  As with Fedallah the day before, so Ahab was now\nfound grimly clinging to his boat's broken half, which afforded a\ncomparatively easy float; nor did it so exhaust him as the previous\nday's mishap.\n\nBut when he was helped to the deck, all eyes were fastened upon him;\nas instead of standing by himself he still half-hung upon the\nshoulder of Starbuck, who had thus far been the foremost to assist\nhim.  His ivory leg had been snapped off, leaving but one short sharp\nsplinter.\n\n\"Aye, aye, Starbuck, 'tis sweet to lean sometimes, be the leaner who\nhe will; and would old Ahab had leaned oftener than he has.\"\n\n\"The ferrule has not stood, sir,\" said the carpenter, now coming up;\n\"I put good work into that leg.\"\n\n\"But no bones broken, sir, I hope,\" said Stubb with true concern.\n\n\"Aye! and all splintered to pieces, Stubb!--d'ye see it.--But even\nwith a broken bone, old Ahab is untouched; and I account no living\nbone of mine one jot more me, than this dead one that's lost.  Nor\nwhite whale, nor man, nor fiend, can so much as graze old Ahab in his\nown proper and inaccessible being.  Can any lead touch yonder floor,\nany mast scrape yonder roof?--Aloft there! which way?\"\n\n\"Dead to leeward, sir.\"\n\n\"Up helm, then; pile on the sail again, ship keepers! down the rest\nof the spare boats and rig them--Mr. Starbuck away, and muster the\nboat's crews.\"\n\n\"Let me first help thee towards the bulwarks, sir.\"\n\n\"Oh, oh, oh! how this splinter gores me now!  Accursed fate! that the\nunconquerable captain in the soul should have such a craven mate!\"\n\n\"Sir?\"\n\n\"My body, man, not thee.  Give me something for a cane--there, that\nshivered lance will do.  Muster the men.  Surely I have not seen him\nyet.  By heaven it cannot be!--missing?--quick! call them all.\"\n\nThe old man's hinted thought was true.  Upon mustering the company,\nthe Parsee was not there.\n\n\"The Parsee!\" cried Stubb--\"he must have been caught in--\"\n\n\"The black vomit wrench thee!--run all of ye above, alow, cabin,\nforecastle--find him--not gone--not gone!\"\n\nBut quickly they returned to him with the tidings that the Parsee was\nnowhere to be found.\n\n\"Aye, sir,\" said Stubb--\"caught among the tangles of your line--I\nthought I saw him dragging under.\"\n\n\"MY line! MY line?  Gone?--gone?  What means that little word?--What\ndeath-knell rings in it, that old Ahab shakes as if he were the\nbelfry.  The harpoon, too!--toss over the litter there,--d'ye see\nit?--the forged iron, men, the white whale's--no, no, no,--blistered\nfool! this hand did dart it!--'tis in the fish!--Aloft there!  Keep\nhim nailed--Quick!--all hands to the rigging of the boats--collect\nthe oars--harpooneers! the irons, the irons!--hoist the royals higher--a\npull on all the sheets!--helm there! steady, steady for your life!\nI'll ten times girdle the unmeasured globe; yea and dive straight\nthrough it, but I'll slay him yet!\n\n\"Great God! but for one single instant show thyself,\" cried Starbuck;\n\"never, never wilt thou capture him, old man--In Jesus' name no more\nof this, that's worse than devil's madness.  Two days chased; twice\nstove to splinters; thy very leg once more snatched from under thee;\nthy evil shadow gone--all good angels mobbing thee with warnings:--\nwhat more wouldst thou have?--Shall we keep chasing this murderous\nfish till he swamps the last man?  Shall we be dragged by him to the\nbottom of the sea?  Shall we be towed by him to the infernal world?\nOh, oh,--Impiety and blasphemy to hunt him more!\"\n\n\"Starbuck, of late I've felt strangely moved to thee; ever since that\nhour we both saw--thou know'st what, in one another's eyes.  But in\nthis matter of the whale, be the front of thy face to me as the palm\nof this hand--a lipless, unfeatured blank.  Ahab is for ever Ahab,\nman.  This whole act's immutably decreed.  'Twas rehearsed by thee\nand me a billion years before this ocean rolled.  Fool!  I am the\nFates' lieutenant; I act under orders.  Look thou, underling! that\nthou obeyest mine.--Stand round me, men.  Ye see an old man cut down\nto the stump; leaning on a shivered lance; propped up on a lonely\nfoot.  'Tis Ahab--his body's part; but Ahab's soul's a centipede,\nthat moves upon a hundred legs.  I feel strained, half stranded, as\nropes that tow dismasted frigates in a gale; and I may look so.  But\nere I break, yell hear me crack; and till ye hear THAT, know that\nAhab's hawser tows his purpose yet.  Believe ye, men, in the things\ncalled omens?  Then laugh aloud, and cry encore!  For ere they drown,\ndrowning things will twice rise to the surface; then rise again, to\nsink for evermore.  So with Moby Dick--two days he's floated--tomorrow\nwill be the third.  Aye, men, he'll rise once more,--but only to\nspout his last!  D'ye feel brave men, brave?\"\n\n\"As fearless fire,\" cried Stubb.\n\n\"And as mechanical,\" muttered Ahab.  Then as the men went forward, he\nmuttered on: \"The things called omens!  And yesterday I talked the\nsame to Starbuck there, concerning my broken boat.  Oh! how valiantly\nI seek to drive out of others' hearts what's clinched so fast in\nmine!--The Parsee--the Parsee!--gone, gone? and he was to go\nbefore:--but still was to be seen again ere I could perish--How's\nthat?--There's a riddle now might baffle all the lawyers backed by\nthe ghosts of the whole line of judges:--like a hawk's beak it pecks\nmy brain.  I'LL, I'LL solve it, though!\"\n\nWhen dusk descended, the whale was still in sight to leeward.\n\nSo once more the sail was shortened, and everything passed nearly as\non the previous night; only, the sound of hammers, and the hum of the\ngrindstone was heard till nearly daylight, as the men toiled by\nlanterns in the complete and careful rigging of the spare boats and\nsharpening their fresh weapons for the morrow.  Meantime, of the\nbroken keel of Ahab's wrecked craft the carpenter made him another\nleg; while still as on the night before, slouched Ahab stood fixed\nwithin his scuttle; his hid, heliotrope glance anticipatingly gone\nbackward on its dial; sat due eastward for the earliest sun.\n\n\n\nCHAPTER 135\n\nThe Chase.--Third Day.\n\n\nThe morning of the third day dawned fair and fresh, and once more the\nsolitary night-man at the fore-mast-head was relieved by crowds of\nthe daylight look-outs, who dotted every mast and almost every spar.\n\n\"D'ye see him?\" cried Ahab; but the whale was not yet in sight.\n\n\"In his infallible wake, though; but follow that wake, that's all.\nHelm there; steady, as thou goest, and hast been going.  What a\nlovely day again! were it a new-made world, and made for a\nsummer-house to the angels, and this morning the first of its\nthrowing open to them, a fairer day could not dawn upon that world.\nHere's food for thought, had Ahab time to think; but Ahab never\nthinks; he only feels, feels, feels; THAT'S tingling enough for\nmortal man! to think's audacity.  God only has that right and\nprivilege.  Thinking is, or ought to be, a coolness and a calmness;\nand our poor hearts throb, and our poor brains beat too much for\nthat.  And yet, I've sometimes thought my brain was very calm--frozen\ncalm, this old skull cracks so, like a glass in which the contents\nturned to ice, and shiver it.  And still this hair is growing now;\nthis moment growing, and heat must breed it; but no, it's like that\nsort of common grass that will grow anywhere, between the earthy\nclefts of Greenland ice or in Vesuvius lava.  How the wild winds blow\nit; they whip it about me as the torn shreds of split sails lash the\ntossed ship they cling to.  A vile wind that has no doubt blown ere\nthis through prison corridors and cells, and wards of hospitals, and\nventilated them, and now comes blowing hither as innocent as fleeces.\nOut upon it!--it's tainted.  Were I the wind, I'd blow no more on\nsuch a wicked, miserable world.  I'd crawl somewhere to a cave, and\nslink there.  And yet, 'tis a noble and heroic thing, the wind! who\never conquered it?  In every fight it has the last and bitterest\nblow.  Run tilting at it, and you but run through it.  Ha! a coward\nwind that strikes stark naked men, but will not stand to receive a\nsingle blow.  Even Ahab is a braver thing--a nobler thing than THAT.\nWould now the wind but had a body; but all the things that most\nexasperate and outrage mortal man, all these things are bodiless, but\nonly bodiless as objects, not as agents.  There's a most special, a\nmost cunning, oh, a most malicious difference!  And yet, I say again,\nand swear it now, that there's something all glorious and gracious in\nthe wind.  These warm Trade Winds, at least, that in the clear\nheavens blow straight on, in strong and steadfast, vigorous mildness;\nand veer not from their mark, however the baser currents of the sea\nmay turn and tack, and mightiest Mississippies of the land swift and\nswerve about, uncertain where to go at last.  And by the eternal\nPoles! these same Trades that so directly blow my good ship on; these\nTrades, or something like them--something so unchangeable, and full\nas strong, blow my keeled soul along!  To it!  Aloft there!  What\nd'ye see?\"\n\n\"Nothing, sir.\"\n\n\"Nothing! and noon at hand!  The doubloon goes a-begging!  See the\nsun!  Aye, aye, it must be so.  I've oversailed him.  How, got the\nstart?  Aye, he's chasing ME now; not I, HIM--that's bad; I might\nhave known it, too.  Fool! the lines--the harpoons he's towing.  Aye,\naye, I have run him by last night.  About! about!  Come down, all of\nye, but the regular look outs!  Man the braces!\"\n\nSteering as she had done, the wind had been somewhat on the Pequod's\nquarter, so that now being pointed in the reverse direction, the\nbraced ship sailed hard upon the breeze as she rechurned the cream in\nher own white wake.\n\n\"Against the wind he now steers for the open jaw,\" murmured Starbuck\nto himself, as he coiled the new-hauled main-brace upon the rail.\n\"God keep us, but already my bones feel damp within me, and from the\ninside wet my flesh.  I misdoubt me that I disobey my God in obeying\nhim!\"\n\n\"Stand by to sway me up!\" cried Ahab, advancing to the hempen basket.\n\"We should meet him soon.\"\n\n\"Aye, aye, sir,\" and straightway Starbuck did Ahab's bidding, and\nonce more Ahab swung on high.\n\nA whole hour now passed; gold-beaten out to ages.  Time itself now\nheld long breaths with keen suspense.  But at last, some three points\noff the weather bow, Ahab descried the spout again, and instantly\nfrom the three mast-heads three shrieks went up as if the tongues of\nfire had voiced it.\n\n\"Forehead to forehead I meet thee, this third time, Moby Dick!  On\ndeck there!--brace sharper up; crowd her into the wind's eye.  He's\ntoo far off to lower yet, Mr. Starbuck.  The sails shake!  Stand over\nthat helmsman with a top-maul!  So, so; he travels fast, and I must\ndown.  But let me have one more good round look aloft here at the\nsea; there's time for that.  An old, old sight, and yet somehow so\nyoung; aye, and not changed a wink since I first saw it, a boy, from\nthe sand-hills of Nantucket!  The same!--the same!--the same to Noah\nas to me.  There's a soft shower to leeward.  Such lovely\nleewardings!  They must lead somewhere--to something else than common\nland, more palmy than the palms.  Leeward! the white whale goes that\nway; look to windward, then; the better if the bitterer quarter.  But\ngood bye, good bye, old mast-head!  What's this?--green? aye, tiny\nmosses in these warped cracks.  No such green weather stains on\nAhab's head!  There's the difference now between man's old age and\nmatter's.  But aye, old mast, we both grow old together; sound in our\nhulls, though, are we not, my ship?  Aye, minus a leg, that's all.\nBy heaven this dead wood has the better of my live flesh every way.\nI can't compare with it; and I've known some ships made of dead trees\noutlast the lives of men made of the most vital stuff of vital\nfathers.  What's that he said? he should still go before me, my\npilot; and yet to be seen again?  But where?  Will I have eyes at the\nbottom of the sea, supposing I descend those endless stairs? and all\nnight I've been sailing from him, wherever he did sink to.  Aye, aye,\nlike many more thou told'st direful truth as touching thyself, O\nParsee; but, Ahab, there thy shot fell short.  Good-bye,\nmast-head--keep a good eye upon the whale, the while I'm gone.  We'll\ntalk to-morrow, nay, to-night, when the white whale lies down there,\ntied by head and tail.\"\n\nHe gave the word; and still gazing round him, was steadily lowered\nthrough the cloven blue air to the deck.\n\nIn due time the boats were lowered; but as standing in his shallop's\nstern, Ahab just hovered upon the point of the descent, he waved to\nthe mate,--who held one of the tackle-ropes on deck--and bade him\npause.\n\n\"Starbuck!\"\n\n\"Sir?\"\n\n\"For the third time my soul's ship starts upon this voyage,\nStarbuck.\"\n\n\"Aye, sir, thou wilt have it so.\"\n\n\"Some ships sail from their ports, and ever afterwards are missing,\nStarbuck!\"\n\n\"Truth, sir: saddest truth.\"\n\n\"Some men die at ebb tide; some at low water; some at the full of the\nflood;--and I feel now like a billow that's all one crested comb,\nStarbuck.  I am old;--shake hands with me, man.\"\n\nTheir hands met; their eyes fastened; Starbuck's tears the glue.\n\n\"Oh, my captain, my captain!--noble heart--go not--go not!--see, it's\na brave man that weeps; how great the agony of the persuasion then!\"\n\n\"Lower away!\"--cried Ahab, tossing the mate's arm from him.  \"Stand\nby the crew!\"\n\nIn an instant the boat was pulling round close under the stern.\n\n\"The sharks! the sharks!\" cried a voice from the low cabin-window\nthere; \"O master, my master, come back!\"\n\nBut Ahab heard nothing; for his own voice was high-lifted then; and\nthe boat leaped on.\n\nYet the voice spake true; for scarce had he pushed from the ship,\nwhen numbers of sharks, seemingly rising from out the dark waters\nbeneath the hull, maliciously snapped at the blades of the oars,\nevery time they dipped in the water; and in this way accompanied the\nboat with their bites.  It is a thing not uncommonly happening to the\nwhale-boats in those swarming seas; the sharks at times apparently\nfollowing them in the same prescient way that vultures hover over the\nbanners of marching regiments in the east.  But these were the first\nsharks that had been observed by the Pequod since the White Whale had\nbeen first descried; and whether it was that Ahab's crew were all\nsuch tiger-yellow barbarians, and therefore their flesh more musky to\nthe senses of the sharks--a matter sometimes well known to affect\nthem,--however it was, they seemed to follow that one boat without\nmolesting the others.\n\n\"Heart of wrought steel!\" murmured Starbuck gazing over the side, and\nfollowing with his eyes the receding boat--\"canst thou yet ring\nboldly to that sight?--lowering thy keel among ravening sharks, and\nfollowed by them, open-mouthed to the chase; and this the critical\nthird day?--For when three days flow together in one continuous\nintense pursuit; be sure the first is the morning, the second the\nnoon, and the third the evening and the end of that thing--be that\nend what it may.  Oh! my God! what is this that shoots through me,\nand leaves me so deadly calm, yet expectant,--fixed at the top of a\nshudder!  Future things swim before me, as in empty outlines and\nskeletons; all the past is somehow grown dim.  Mary, girl! thou\nfadest in pale glories behind me; boy!  I seem to see but thy eyes\ngrown wondrous blue.  Strangest problems of life seem clearing; but\nclouds sweep between--Is my journey's end coming?  My legs feel\nfaint; like his who has footed it all day.  Feel thy heart,--beats\nit yet?  Stir thyself, Starbuck!--stave it off--move, move! speak\naloud!--Mast-head there!  See ye my boy's hand on the\nhill?--Crazed;--aloft there!--keep thy keenest eye upon the boats:--\nmark well the whale!--Ho! again!--drive off that hawk! see! he\npecks--he tears the vane\"--pointing to the red flag flying at the\nmain-truck--\"Ha! he soars away with it!--Where's the old man now?\nsee'st thou that sight, oh Ahab!--shudder, shudder!\"\n\nThe boats had not gone very far, when by a signal from the\nmast-heads--a downward pointed arm, Ahab knew that the whale had\nsounded; but intending to be near him at the next rising, he held on\nhis way a little sideways from the vessel; the becharmed crew\nmaintaining the profoundest silence, as the head-beat waves hammered\nand hammered against the opposing bow.\n\n\"Drive, drive in your nails, oh ye waves! to their uttermost heads\ndrive them in! ye but strike a thing without a lid; and no coffin and\nno hearse can be mine:--and hemp only can kill me!  Ha! ha!\"\n\nSuddenly the waters around them slowly swelled in broad circles; then\nquickly upheaved, as if sideways sliding from a submerged berg of\nice, swiftly rising to the surface.  A low rumbling sound was heard;\na subterraneous hum; and then all held their breaths; as bedraggled\nwith trailing ropes, and harpoons, and lances, a vast form shot\nlengthwise, but obliquely from the sea.  Shrouded in a thin drooping\nveil of mist, it hovered for a moment in the rainbowed air; and then\nfell swamping back into the deep.  Crushed thirty feet upwards, the\nwaters flashed for an instant like heaps of fountains, then brokenly\nsank in a shower of flakes, leaving the circling surface creamed like\nnew milk round the marble trunk of the whale.\n\n\"Give way!\" cried Ahab to the oarsmen, and the boats darted forward\nto the attack; but maddened by yesterday's fresh irons that corroded\nin him, Moby Dick seemed combinedly possessed by all the angels that\nfell from heaven.  The wide tiers of welded tendons overspreading his\nbroad white forehead, beneath the transparent skin, looked knitted\ntogether; as head on, he came churning his tail among the boats; and\nonce more flailed them apart; spilling out the irons and lances from\nthe two mates' boats, and dashing in one side of the upper part of\ntheir bows, but leaving Ahab's almost without a scar.\n\nWhile Daggoo and Queequeg were stopping the strained planks; and as\nthe whale swimming out from them, turned, and showed one entire flank\nas he shot by them again; at that moment a quick cry went up.  Lashed\nround and round to the fish's back; pinioned in the turns upon turns\nin which, during the past night, the whale had reeled the involutions\nof the lines around him, the half torn body of the Parsee was seen;\nhis sable raiment frayed to shreds; his distended eyes turned full\nupon old Ahab.\n\nThe harpoon dropped from his hand.\n\n\"Befooled, befooled!\"--drawing in a long lean breath--\"Aye, Parsee!\nI see thee again.--Aye, and thou goest before; and this, THIS then is\nthe hearse that thou didst promise.  But I hold thee to the last\nletter of thy word.  Where is the second hearse?  Away, mates, to the\nship! those boats are useless now; repair them if ye can in time, and\nreturn to me; if not, Ahab is enough to die--Down, men! the first\nthing that but offers to jump from this boat I stand in, that thing I\nharpoon.  Ye are not other men, but my arms and my legs; and so obey\nme.--Where's the whale? gone down again?\"\n\nBut he looked too nigh the boat; for as if bent upon escaping with\nthe corpse he bore, and as if the particular place of the last\nencounter had been but a stage in his leeward voyage, Moby Dick was\nnow again steadily swimming forward; and had almost passed the\nship,--which thus far had been sailing in the contrary direction to\nhim, though for the present her headway had been stopped.  He seemed\nswimming with his utmost velocity, and now only intent upon pursuing\nhis own straight path in the sea.\n\n\"Oh!  Ahab,\" cried Starbuck, \"not too late is it, even now, the third\nday, to desist.  See!  Moby Dick seeks thee not.  It is thou, thou,\nthat madly seekest him!\"\n\nSetting sail to the rising wind, the lonely boat was swiftly impelled\nto leeward, by both oars and canvas.  And at last when Ahab was\nsliding by the vessel, so near as plainly to distinguish Starbuck's\nface as he leaned over the rail, he hailed him to turn the vessel\nabout, and follow him, not too swiftly, at a judicious interval.\nGlancing upwards, he saw Tashtego, Queequeg, and Daggoo, eagerly\nmounting to the three mast-heads; while the oarsmen were rocking in\nthe two staved boats which had but just been hoisted to the side, and\nwere busily at work in repairing them.  One after the other, through\nthe port-holes, as he sped, he also caught flying glimpses of Stubb\nand Flask, busying themselves on deck among bundles of new irons and\nlances.  As he saw all this; as he heard the hammers in the broken\nboats; far other hammers seemed driving a nail into his heart.  But\nhe rallied.  And now marking that the vane or flag was gone from the\nmain-mast-head, he shouted to Tashtego, who had just gained that\nperch, to descend again for another flag, and a hammer and nails, and\nso nail it to the mast.\n\nWhether fagged by the three days' running chase, and the resistance\nto his swimming in the knotted hamper he bore; or whether it was some\nlatent deceitfulness and malice in him: whichever was true, the White\nWhale's way now began to abate, as it seemed, from the boat so\nrapidly nearing him once more; though indeed the whale's last start\nhad not been so long a one as before.  And still as Ahab glided over\nthe waves the unpitying sharks accompanied him; and so pertinaciously\nstuck to the boat; and so continually bit at the plying oars, that\nthe blades became jagged and crunched, and left small splinters in\nthe sea, at almost every dip.\n\n\"Heed them not! those teeth but give new rowlocks to your oars.  Pull\non! 'tis the better rest, the shark's jaw than the yielding water.\"\n\n\"But at every bite, sir, the thin blades grow smaller and smaller!\"\n\n\"They will last long enough! pull on!--But who can tell\"--he\nmuttered--\"whether these sharks swim to feast on the whale or on\nAhab?--But pull on!  Aye, all alive, now--we near him.  The helm!\ntake the helm! let me pass,\"--and so saying two of the oarsmen helped\nhim forward to the bows of the still flying boat.\n\nAt length as the craft was cast to one side, and ran ranging along\nwith the White Whale's flank, he seemed strangely oblivious of its\nadvance--as the whale sometimes will--and Ahab was fairly within the\nsmoky mountain mist, which, thrown off from the whale's spout, curled\nround his great, Monadnock hump; he was even thus close to him; when,\nwith body arched back, and both arms lengthwise high-lifted to the\npoise, he darted his fierce iron, and his far fiercer curse into the\nhated whale.  As both steel and curse sank to the socket, as if\nsucked into a morass, Moby Dick sideways writhed; spasmodically\nrolled his nigh flank against the bow, and, without staving a hole in\nit, so suddenly canted the boat over, that had it not been for the\nelevated part of the gunwale to which he then clung, Ahab would once\nmore have been tossed into the sea.  As it was, three of the\noarsmen--who foreknew not the precise instant of the dart, and were\ntherefore unprepared for its effects--these were flung out; but so\nfell, that, in an instant two of them clutched the gunwale again, and\nrising to its level on a combing wave, hurled themselves bodily\ninboard again; the third man helplessly dropping astern, but still\nafloat and swimming.\n\nAlmost simultaneously, with a mighty volition of ungraduated,\ninstantaneous swiftness, the White Whale darted through the weltering\nsea.  But when Ahab cried out to the steersman to take new turns with\nthe line, and hold it so; and commanded the crew to turn round on\ntheir seats, and tow the boat up to the mark; the moment the\ntreacherous line felt that double strain and tug, it snapped in the\nempty air!\n\n\"What breaks in me?  Some sinew cracks!--'tis whole again; oars!\noars!  Burst in upon him!\"\n\nHearing the tremendous rush of the sea-crashing boat, the whale\nwheeled round to present his blank forehead at bay; but in that\nevolution, catching sight of the nearing black hull of the ship;\nseemingly seeing in it the source of all his persecutions; bethinking\nit--it may be--a larger and nobler foe; of a sudden, he bore down\nupon its advancing prow, smiting his jaws amid fiery showers of foam.\n\nAhab staggered; his hand smote his forehead.  \"I grow blind; hands!\nstretch out before me that I may yet grope my way.  Is't night?\"\n\n\"The whale!  The ship!\" cried the cringing oarsmen.\n\n\"Oars! oars!  Slope downwards to thy depths, O sea, that ere it be\nfor ever too late, Ahab may slide this last, last time upon his\nmark!  I see: the ship! the ship!  Dash on, my men!  Will ye not\nsave my ship?\"\n\nBut as the oarsmen violently forced their boat through the\nsledge-hammering seas, the before whale-smitten bow-ends of two\nplanks burst through, and in an instant almost, the temporarily\ndisabled boat lay nearly level with the waves; its half-wading,\nsplashing crew, trying hard to stop the gap and bale out the pouring\nwater.\n\nMeantime, for that one beholding instant, Tashtego's mast-head hammer\nremained suspended in his hand; and the red flag, half-wrapping him\nas with a plaid, then streamed itself straight out from him, as his\nown forward-flowing heart; while Starbuck and Stubb, standing upon\nthe bowsprit beneath, caught sight of the down-coming monster just as\nsoon as he.\n\n\"The whale, the whale!  Up helm, up helm!  Oh, all ye sweet powers of\nair, now hug me close!  Let not Starbuck die, if die he must, in a\nwoman's fainting fit.  Up helm, I say--ye fools, the jaw! the jaw!\nIs this the end of all my bursting prayers? all my life-long\nfidelities?  Oh, Ahab, Ahab, lo, thy work.  Steady! helmsman, steady.\nNay, nay!  Up helm again!  He turns to meet us!  Oh, his\nunappeasable brow drives on towards one, whose duty tells him he\ncannot depart.  My God, stand by me now!\"\n\n\"Stand not by me, but stand under me, whoever you are that will now\nhelp Stubb; for Stubb, too, sticks here.  I grin at thee, thou\ngrinning whale!  Who ever helped Stubb, or kept Stubb awake, but\nStubb's own unwinking eye?  And now poor Stubb goes to bed upon a\nmattrass that is all too soft; would it were stuffed with brushwood!\nI grin at thee, thou grinning whale!  Look ye, sun, moon, and stars!\nI call ye assassins of as good a fellow as ever spouted up his ghost.\nFor all that, I would yet ring glasses with ye, would ye but hand\nthe cup!  Oh, oh! oh, oh! thou grinning whale, but there'll be plenty\nof gulping soon!  Why fly ye not, O Ahab!  For me, off shoes and\njacket to it; let Stubb die in his drawers!  A most mouldy and over\nsalted death, though;--cherries! cherries! cherries!  Oh, Flask, for\none red cherry ere we die!\"\n\n\"Cherries?  I only wish that we were where they grow.  Oh, Stubb, I\nhope my poor mother's drawn my part-pay ere this; if not, few coppers\nwill now come to her, for the voyage is up.\"\n\nFrom the ship's bows, nearly all the seamen now hung inactive;\nhammers, bits of plank, lances, and harpoons, mechanically retained\nin their hands, just as they had darted from their various\nemployments; all their enchanted eyes intent upon the whale, which\nfrom side to side strangely vibrating his predestinating head, sent a\nbroad band of overspreading semicircular foam before him as he\nrushed.  Retribution, swift vengeance, eternal malice were in his\nwhole aspect, and spite of all that mortal man could do, the solid\nwhite buttress of his forehead smote the ship's starboard bow, till\nmen and timbers reeled.  Some fell flat upon their faces.  Like\ndislodged trucks, the heads of the harpooneers aloft shook on their\nbull-like necks.  Through the breach, they heard the waters pour, as\nmountain torrents down a flume.\n\n\"The ship!  The hearse!--the second hearse!\" cried Ahab from the\nboat; \"its wood could only be American!\"\n\nDiving beneath the settling ship, the whale ran quivering along its\nkeel; but turning under water, swiftly shot to the surface again, far\noff the other bow, but within a few yards of Ahab's boat, where, for\na time, he lay quiescent.\n\n\"I turn my body from the sun.  What ho, Tashtego! let me hear thy\nhammer.  Oh! ye three unsurrendered spires of mine; thou uncracked\nkeel; and only god-bullied hull; thou firm deck, and haughty helm,\nand Pole-pointed prow,--death-glorious ship! must ye then perish,\nand without me?  Am I cut off from the last fond pride of meanest\nshipwrecked captains?  Oh, lonely death on lonely life!  Oh, now I\nfeel my topmost greatness lies in my topmost grief.  Ho, ho! from all\nyour furthest bounds, pour ye now in, ye bold billows of my whole\nforegone life, and top this one piled comber of my death!  Towards\nthee I roll, thou all-destroying but unconquering whale; to the last\nI grapple with thee; from hell's heart I stab at thee; for hate's\nsake I spit my last breath at thee.  Sink all coffins and all hearses\nto one common pool! and since neither can be mine, let me then tow to\npieces, while still chasing thee, though tied to thee, thou damned\nwhale!  THUS, I give up the spear!\"\n\nThe harpoon was darted; the stricken whale flew forward; with\nigniting velocity the line ran through the grooves;--ran foul.  Ahab\nstooped to clear it; he did clear it; but the flying turn caught him\nround the neck, and voicelessly as Turkish mutes bowstring their\nvictim, he was shot out of the boat, ere the crew knew he was gone.\nNext instant, the heavy eye-splice in the rope's final end flew out\nof the stark-empty tub, knocked down an oarsman, and smiting the sea,\ndisappeared in its depths.\n\nFor an instant, the tranced boat's crew stood still; then turned.\n\"The ship?  Great God, where is the ship?\"  Soon they through dim,\nbewildering mediums saw her sidelong fading phantom, as in the\ngaseous Fata Morgana; only the uppermost masts out of water; while\nfixed by infatuation, or fidelity, or fate, to their once lofty\nperches, the pagan harpooneers still maintained their sinking\nlookouts on the sea.  And now, concentric circles seized the lone\nboat itself, and all its crew, and each floating oar, and every\nlance-pole, and spinning, animate and inanimate, all round and round\nin one vortex, carried the smallest chip of the Pequod out of sight.\n\nBut as the last whelmings intermixingly poured themselves over the\nsunken head of the Indian at the mainmast, leaving a few inches of\nthe erect spar yet visible, together with long streaming yards of the\nflag, which calmly undulated, with ironical coincidings, over the\ndestroying billows they almost touched;--at that instant, a red arm\nand a hammer hovered backwardly uplifted in the open air, in the act\nof nailing the flag faster and yet faster to the subsiding spar.  A\nsky-hawk that tauntingly had followed the main-truck downwards from\nits natural home among the stars, pecking at the flag, and\nincommoding Tashtego there; this bird now chanced to intercept its\nbroad fluttering wing between the hammer and the wood; and\nsimultaneously feeling that etherial thrill, the submerged savage\nbeneath, in his death-gasp, kept his hammer frozen there; and so the\nbird of heaven, with archangelic shrieks, and his imperial beak\nthrust upwards, and his whole captive form folded in the flag of\nAhab, went down with his ship, which, like Satan, would not sink to\nhell till she had dragged a living part of heaven along with her, and\nhelmeted herself with it.\n\nNow small fowls flew screaming over the yet yawning gulf; a sullen\nwhite surf beat against its steep sides; then all collapsed, and the\ngreat shroud of the sea rolled on as it rolled five thousand years\nago.\n\n\n\nEpilogue\n\n\"AND I ONLY AM ESCAPED ALONE TO TELL THEE\"\nJob.\n\nThe drama's done.  Why then here does any one step forth?--Because\none did survive the wreck.\n\nIt so chanced, that after the Parsee's disappearance, I was he whom\nthe Fates ordained to take the place of Ahab's bowsman, when that\nbowsman assumed the vacant post; the same, who, when on the last day\nthe three men were tossed from out of the rocking boat, was dropped\nastern.  So, floating on the margin of the ensuing scene, and in full\nsight of it, when the halfspent suction of the sunk ship reached me,\nI was then, but slowly, drawn towards the closing vortex.  When I\nreached it, it had subsided to a creamy pool.  Round and round, then,\nand ever contracting towards the button-like black bubble at the axis\nof that slowly wheeling circle, like another Ixion I did revolve.\nTill, gaining that vital centre, the black bubble upward burst; and\nnow, liberated by reason of its cunning spring, and, owing to its\ngreat buoyancy, rising with great force, the coffin life-buoy shot\nlengthwise from the sea, fell over, and floated by my side.  Buoyed\nup by that coffin, for almost one whole day and night, I floated on a\nsoft and dirgelike main.  The unharming sharks, they glided by as if\nwith padlocks on their mouths; the savage sea-hawks sailed with\nsheathed beaks.  On the second day, a sail drew near, nearer, and\npicked me up at last.  It was the devious-cruising Rachel, that in\nher retracing search after her missing children, only found another\norphan.\n\n\n\n\nEnd of this Project Gutenberg etext of Moby Dick, by Herman Melville\n\n"
  },
  {
    "path": "okio-assetfilesystem/src/androidTest/kotlin/okio/assetfilesystem/AssetFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio.assetfilesystem\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport assertk.assertThat\nimport assertk.assertions.containsAll\nimport assertk.assertions.containsExactly\nimport assertk.assertions.hasMessage\nimport assertk.assertions.isEmpty\nimport assertk.assertions.isEqualTo\nimport assertk.assertions.isFalse\nimport assertk.assertions.isNotNull\nimport assertk.assertions.isNull\nimport assertk.assertions.isTrue\nimport kotlin.test.assertFailsWith\nimport okio.Buffer\nimport okio.BufferedSource\nimport okio.FileHandle\nimport okio.FileNotFoundException\nimport okio.IOException\nimport okio.Path.Companion.toPath\nimport okio.buffer\nimport org.junit.Test\n\nclass AssetFileSystemTest {\n  private val context = InstrumentationRegistry.getInstrumentation().context\n  private val fs = context.assets.asFileSystem()\n\n  @Test fun canonicalizeValid() {\n    assertThat(fs.canonicalize(\"/\".toPath())).isEqualTo(\"/\".toPath())\n    assertThat(fs.canonicalize(\".\".toPath())).isEqualTo(\"/\".toPath())\n    assertThat(fs.canonicalize(\"not/a/path/../../..\".toPath())).isEqualTo(\"/\".toPath())\n    assertThat(fs.canonicalize(\"file.txt\".toPath())).isEqualTo(\"/file.txt\".toPath())\n    assertThat(fs.canonicalize(\"stuff/../file.txt\".toPath())).isEqualTo(\"/file.txt\".toPath())\n    assertThat(fs.canonicalize(\"dir\".toPath())).isEqualTo(\"/dir\".toPath())\n    assertThat(fs.canonicalize(\"dir/whevs/..\".toPath())).isEqualTo(\"/dir\".toPath())\n    assertThat(fs.canonicalize(\"dir/nested.txt\".toPath())).isEqualTo(\"/dir/nested.txt\".toPath())\n    assertThat(fs.canonicalize(\"dir/whevs/../nested.txt\".toPath())).isEqualTo(\"/dir/nested.txt\".toPath())\n  }\n\n  @Test fun canonicalizeInvalidThrows() {\n    assertFailsWith<FileNotFoundException> {\n      fs.canonicalize(\"not/a/path\".toPath())\n    }\n  }\n\n  @Test fun listRoot() {\n    val list = fs.list(\"/\".toPath())\n    assertThat(list).containsAll(\n      \"dir\".toPath(),\n      \"file.txt\".toPath(),\n      \"moby10b.txt\".toPath(),\n    )\n  }\n\n  @Test fun listRootCanonicalizes() {\n    val list = fs.list(\"foo/bar/../..\".toPath())\n    assertThat(list).containsAll(\n      \"dir\".toPath(),\n      \"file.txt\".toPath(),\n      \"moby10b.txt\".toPath(),\n    )\n  }\n\n  @Test fun listDirectory() {\n    val list = fs.list(\"dir\".toPath())\n    assertThat(list).containsExactly(\"nested.txt\".toPath())\n  }\n\n  @Test fun listDirectoryCanonicalizes() {\n    val list = fs.list(\"dir/not/real/../..\".toPath())\n    assertThat(list).containsExactly(\"nested.txt\".toPath())\n  }\n\n  @Test fun listNonExistentDirectoryThrows() {\n    assertFailsWith<FileNotFoundException> {\n      fs.list(\"nope/\".toPath())\n    }\n  }\n\n  @Test fun listFileThrows() {\n    assertFailsWith<FileNotFoundException> {\n      fs.list(\"dir/nested.txt\".toPath())\n    }\n  }\n\n  @Test fun listOrNullDirectory() {\n    val list = fs.listOrNull(\"dir\".toPath())\n    assertThat(list).isNotNull().containsExactly(\"nested.txt\".toPath())\n  }\n\n  @Test fun listOrNullDirectoryCanonicalizes() {\n    val list = fs.listOrNull(\"dir/not/real/../..\".toPath())\n    assertThat(list).isNotNull().containsExactly(\"nested.txt\".toPath())\n  }\n\n  @Test fun listOrNullNonExistentDirectory() {\n    val list = fs.listOrNull(\"nope\".toPath())\n    assertThat(list).isNull()\n  }\n\n  @Test fun listOrNullFile() {\n    val list = fs.listOrNull(\"dir/nested.txt\".toPath())\n    assertThat(list).isNull()\n  }\n\n  @Test fun metadataFile() {\n    val metadata = fs.metadataOrNull(\"file.txt\".toPath())!!\n\n    // Data we can get:\n    assertThat(metadata.isRegularFile).isTrue()\n    assertThat(metadata.isDirectory).isFalse()\n\n    // Data we cannot get or is impossible:\n    assertThat(metadata.size).isNull()\n    assertThat(metadata.symlinkTarget).isNull()\n    assertThat(metadata.createdAtMillis).isNull()\n    assertThat(metadata.lastModifiedAtMillis).isNull()\n    assertThat(metadata.lastAccessedAtMillis).isNull()\n    assertThat(metadata.extras).isEmpty()\n  }\n\n  @Test fun metadataDirectory() {\n    val metadata = fs.metadataOrNull(\"dir\".toPath())!!\n\n    // Data we can get:\n    assertThat(metadata.isRegularFile).isFalse()\n    assertThat(metadata.isDirectory).isTrue()\n\n    // Data we cannot get or is impossible:\n    assertThat(metadata.symlinkTarget).isNull()\n    assertThat(metadata.size).isNull()\n    assertThat(metadata.createdAtMillis).isNull()\n    assertThat(metadata.lastModifiedAtMillis).isNull()\n    assertThat(metadata.lastAccessedAtMillis).isNull()\n    assertThat(metadata.extras).isEmpty()\n  }\n\n  @Test fun metadataDirectoryCanonicalizes() {\n    val metadata = fs.metadataOrNull(\"dir/not/real/../..\".toPath())!!\n    assertThat(metadata.isDirectory).isTrue()\n  }\n\n  @Test fun metadataNonExistentPath() {\n    val metadata = fs.metadataOrNull(\"not/a/path\".toPath())\n    assertThat(metadata).isNull()\n  }\n\n  @Test fun sourceFile() {\n    val file = fs.source(\"file.txt\".toPath()).buffer().use(BufferedSource::readUtf8)\n    assertThat(file).isEqualTo(\"File!\\n\")\n    val nested = fs.source(\"dir/nested.txt\".toPath()).buffer().use(BufferedSource::readUtf8)\n    assertThat(nested).isEqualTo(\"Nested!\\n\")\n  }\n\n  @Test fun sourceDirectory() {\n    assertFailsWith<FileNotFoundException> {\n      fs.source(\"dir\".toPath())\n    }\n  }\n\n  @Test fun sourceNonExistent() {\n    assertFailsWith<FileNotFoundException> {\n      fs.source(\"not/a/path\".toPath())\n    }\n  }\n\n  @Test fun openReadOnlyInvalidThrows() {\n    assertFailsWith<FileNotFoundException> {\n      fs.openReadOnly(\"not/a/path\".toPath())\n    }\n  }\n\n  @Test fun openReadOnlyDirectoryThrows() {\n    assertFailsWith<FileNotFoundException> {\n      fs.openReadOnly(\"dir\".toPath())\n    }\n  }\n\n  @Test fun openReadOnlySize() {\n    val smallSize = fs.openReadOnly(\"file.txt\".toPath()).use(FileHandle::size)\n    assertThat(smallSize).isEqualTo(6)\n\n    val mobySize = fs.openReadOnly(\"moby10b.txt\".toPath()).use(FileHandle::size)\n    assertThat(mobySize).isEqualTo(1232923)\n  }\n\n  @Test fun openReadOnlyRandomAccessForward() {\n    fs.openReadOnly(\"moby10b.txt\".toPath()).use { handle ->\n      val buffer = Buffer()\n      handle.read(34251, buffer, 16)\n      assertThat(buffer.readUtf8()).isEqualTo(\"Call me Ishmael.\")\n      handle.read(148605, buffer, 49)\n      assertThat(buffer.readUtf8()).isEqualTo(\"It is not down in any map; true places never are.\")\n      handle.read(1051694, buffer, 50)\n      assertThat(buffer.readUtf8()).isEqualTo(\"his forehead's veins swelled like overladen brooks\")\n      handle.read(148605, buffer, 49)\n      assertThat(buffer.readUtf8()).isEqualTo(\"It is not down in any map; true places never are.\")\n      handle.read(34251, buffer, 16)\n      assertThat(buffer.readUtf8()).isEqualTo(\"Call me Ishmael.\")\n    }\n  }\n\n  @Test fun openReadOnlyRandomAccessThenSize() {\n    fs.openReadOnly(\"moby10b.txt\".toPath()).use { handle ->\n      val buffer = Buffer()\n      handle.read(34251, buffer, 16)\n      assertThat(buffer.readUtf8()).isEqualTo(\"Call me Ishmael.\")\n\n      assertThat(handle.size()).isEqualTo(1232923)\n    }\n  }\n\n  @Test fun openReadOnlyFlushThrows() {\n    fs.openReadOnly(\"file.txt\".toPath()).use { handle ->\n      val t = assertFailsWith<IllegalStateException> {\n        handle.flush()\n      }\n      assertThat(t).hasMessage(\"file handle is read-only\")\n    }\n  }\n\n  @Test fun openReadOnlyResizeThrows() {\n    fs.openReadOnly(\"file.txt\".toPath()).use { handle ->\n      val t = assertFailsWith<IllegalStateException> {\n        handle.resize(10L)\n      }\n      assertThat(t).hasMessage(\"file handle is read-only\")\n    }\n  }\n\n  @Test fun openReadOnlyWriteThrows() {\n    fs.openReadOnly(\"file.txt\".toPath()).use { handle ->\n      val t = assertFailsWith<IllegalStateException> {\n        handle.write(0, Buffer().writeUtf8(\"Sup\"), 3)\n      }\n      assertThat(t).hasMessage(\"file handle is read-only\")\n    }\n  }\n\n  @Test fun sinkThrows() {\n    val t = assertFailsWith<IOException> {\n      fs.sink(\"file.txt\".toPath())\n    }\n    assertThat(t).hasMessage(\"asset file systems are read-only\")\n  }\n\n  @Test fun appendingSinkThrows() {\n    val t = assertFailsWith<IOException> {\n      fs.appendingSink(\"file.txt\".toPath())\n    }\n    assertThat(t).hasMessage(\"asset file systems are read-only\")\n  }\n\n  @Test fun createDirectoryThrows() {\n    val t = assertFailsWith<IOException> {\n      fs.createDirectory(\"new-dir\".toPath(), mustCreate = true)\n    }\n    assertThat(t).hasMessage(\"asset file systems are read-only\")\n  }\n\n  @Test fun atomicMoveThrows() {\n    val t = assertFailsWith<IOException> {\n      fs.atomicMove(\"file.txt\".toPath(), \"new-file.txt\".toPath())\n    }\n    assertThat(t).hasMessage(\"asset file systems are read-only\")\n  }\n\n  @Test fun deleteThrows() {\n    val t = assertFailsWith<IOException> {\n      fs.delete(\"file.txt\".toPath())\n    }\n    assertThat(t).hasMessage(\"asset file systems are read-only\")\n  }\n\n  @Test fun createSymlinkThrows() {\n    val t = assertFailsWith<IOException> {\n      fs.createSymlink(\"file.txt\".toPath(), \"new-file.txt\".toPath())\n    }\n    assertThat(t).hasMessage(\"asset file systems are read-only\")\n  }\n\n  @Test fun openReadWriteThrows() {\n    val t = assertFailsWith<IOException> {\n      fs.openReadWrite(\"file.txt\".toPath())\n    }\n    assertThat(t).hasMessage(\"asset file systems are read-only\")\n  }\n}\n"
  },
  {
    "path": "okio-assetfilesystem/src/main/kotlin/okio/assetfilesystem/AssetFileSystem.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio.assetfilesystem\n\nimport android.content.res.AssetManager\nimport java.io.FileNotFoundException\nimport java.io.IOException\nimport java.io.InputStream\nimport okio.FileHandle\nimport okio.FileMetadata\nimport okio.FileSystem\nimport okio.Path\nimport okio.Path.Companion.toPath\nimport okio.Sink\nimport okio.Source\nimport okio.source\n\n/**\n * Expose this [AssetManager] as an Okio [FileSystem].\n *\n * Note: Assets are a read-only view on a file system and so any attempt to mutate\n * will throw an [IOException].\n */\nfun AssetManager.asFileSystem(): FileSystem = AssetFileSystem(this)\n\nprivate class AssetFileSystem(\n  private val assets: AssetManager,\n) : FileSystem() {\n  override fun canonicalize(path: Path): Path {\n    val canonical = canonicalizeInternal(path)\n    if (canonical.existsInternal()) {\n      return canonical\n    }\n    throw FileNotFoundException(\"$path\")\n  }\n\n  private fun canonicalizeInternal(path: Path) = ROOT.resolve(path, normalize = true)\n\n  private fun Path.toAssetRelativePathString(): String {\n    return toString().removePrefix(\"/\")\n  }\n\n  /**\n   * Determine if [this] is a valid path to a file or directory.\n   *\n   * If this function returns true, a call to [AssetManager.open] will either return successfully\n   * or throw [FileNotFoundException] based on whether [this] is a file or directory, respectively.\n   */\n  private fun Path.existsInternal(): Boolean {\n    if (this == ROOT) {\n      return true\n    }\n\n    // Both non-existent paths and paths to existing files return an empty array when listing.\n    // Determine if a path exists by checking if its name is present in the parent's list.\n    val parent = checkNotNull(parent) { \"Path has no parent. Did you canonicalize? $this\" }\n    val children = assets.list(parent.toAssetRelativePathString()).orEmpty()\n    return name in children\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    val canonical = canonicalizeInternal(path)\n    if (canonical.existsInternal()) {\n      val pathString = canonical.toAssetRelativePathString()\n      return try {\n        assets.open(pathString).close()\n        FileMetadata(\n          isRegularFile = true,\n          isDirectory = false,\n        )\n      } catch (_: FileNotFoundException) {\n        FileMetadata(\n          isRegularFile = false,\n          isDirectory = true,\n        )\n      }\n    }\n    return null\n  }\n\n  override fun list(dir: Path): List<Path> {\n    val canonical = canonicalizeInternal(dir)\n    if (canonical.existsInternal()) {\n      val pathString = canonical.toAssetRelativePathString()\n      try {\n        // This will throw if the path points to a file.\n        assets.open(pathString).close()\n      } catch (_: FileNotFoundException) {\n        return assets.list(pathString)\n          ?.map { it.toPath() }\n          .orEmpty()\n      }\n    }\n    throw FileNotFoundException(\"$dir\")\n  }\n\n  override fun listOrNull(dir: Path): List<Path>? {\n    return try {\n      list(dir)\n    } catch (_: IOException) {\n      null\n    }\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    val pathString = canonicalizeInternal(file).toAssetRelativePathString()\n    val inputStream = assets.open(pathString)\n    return AssetFileHandle(assets, pathString, inputStream)\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    throw IOException(\"asset file systems are read-only\")\n  }\n\n  override fun source(file: Path): Source {\n    return assets.open(canonicalizeInternal(file).toAssetRelativePathString()).source()\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    throw IOException(\"asset file systems are read-only\")\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    throw IOException(\"asset file systems are read-only\")\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    throw IOException(\"asset file systems are read-only\")\n  }\n\n  override fun atomicMove(source: Path, target: Path) {\n    throw IOException(\"asset file systems are read-only\")\n  }\n\n  override fun delete(path: Path, mustExist: Boolean) {\n    throw IOException(\"asset file systems are read-only\")\n  }\n\n  override fun createSymlink(source: Path, target: Path) {\n    throw IOException(\"asset file systems are read-only\")\n  }\n\n  private companion object {\n    val ROOT = \"/\".toPath()\n  }\n}\n\nprivate class AssetFileHandle(\n  private val assets: AssetManager,\n  private val pathString: String,\n  private var inputStream: InputStream,\n) : FileHandle(false) {\n  private var currentOffset = 0\n  private var size = -1\n\n  override fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    // If we need to jump backwards or have reached the end of the file,\n    // close the existing stream and open a new one.\n    if (currentOffset > fileOffset || currentOffset == size) {\n      inputStream.close()\n      inputStream = assets.open(pathString)\n      currentOffset = 0\n    }\n\n    while (true) {\n      val skip = fileOffset - currentOffset\n      if (skip == 0L) break\n      val skipped = inputStream.skip(skip).toInt()\n      if (skipped == 0) {\n        // Since we know skip is never negative, a skip of 0 means EOF.\n        // Record this as the file size to trigger stream recreation.\n        size = currentOffset\n        throw IllegalArgumentException(\"fileOffset $fileOffset > size $size\")\n      }\n      currentOffset += skipped\n    }\n\n    val read = inputStream.read(array, arrayOffset, byteCount)\n    if (read == -1) {\n      // A read of -1 means EOF. Record this as the file size to trigger stream recreation.\n      size = currentOffset\n    } else {\n      currentOffset += read\n    }\n    return read\n  }\n\n  override fun protectedSize(): Long {\n    if (size == -1) {\n      while (true) {\n        val skipped = inputStream.skip(1024 * 1024).toInt()\n        if (skipped == 0) {\n          size = currentOffset\n          break\n        }\n        currentOffset += skipped\n      }\n    }\n    return size.toLong()\n  }\n\n  override fun protectedClose() {\n    inputStream.close()\n  }\n\n  override fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    throw AssertionError()\n  }\n\n  override fun protectedFlush() {\n    throw AssertionError()\n  }\n\n  override fun protectedResize(size: Long) {\n    throw AssertionError()\n  }\n}\n"
  },
  {
    "path": "okio-bom/build.gradle.kts",
    "content": "plugins {\n  id(\"com.vanniktech.maven.publish.base\")\n  id(\"java-platform\")\n}\n\ncollectBomConstraints()\n\nextensions.configure<PublishingExtension> {\n  publications.create(\"maven\", MavenPublication::class) {\n    from(project.components.getByName(\"javaPlatform\"))\n  }\n}\n"
  },
  {
    "path": "okio-fakefilesystem/README.md",
    "content": "Okio Fake File System\n---------------------\n\nThis module contains an in-memory file system.\n"
  },
  {
    "path": "okio-fakefilesystem/api/okio-fakefilesystem.api",
    "content": "public final class okio/fakefilesystem/FakeFileSystem : okio/FileSystem {\n\tpublic fun <init> ()V\n\tpublic fun <init> (Lkotlin/time/Clock;)V\n\tpublic synthetic fun <init> (Lkotlin/time/Clock;ILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic synthetic fun <init> (Lkotlinx/datetime/Clock;)V\n\tpublic synthetic fun <init> (Lkotlinx/datetime/Clock;ILkotlin/jvm/internal/DefaultConstructorMarker;)V\n\tpublic final fun allPaths ()Ljava/util/Set;\n\tpublic fun appendingSink (Lokio/Path;Z)Lokio/Sink;\n\tpublic fun atomicMove (Lokio/Path;Lokio/Path;)V\n\tpublic fun canonicalize (Lokio/Path;)Lokio/Path;\n\tpublic final fun checkNoOpenFiles ()V\n\tpublic fun close ()V\n\tpublic fun createDirectory (Lokio/Path;Z)V\n\tpublic fun createSymlink (Lokio/Path;Lokio/Path;)V\n\tpublic fun delete (Lokio/Path;Z)V\n\tpublic final fun emulateUnix ()V\n\tpublic final fun emulateWindows ()V\n\tpublic final fun getAllowClobberingEmptyDirectories ()Z\n\tpublic final fun getAllowDeletingOpenFiles ()Z\n\tpublic final fun getAllowMovingOpenFiles ()Z\n\tpublic final fun getAllowReadsWhileWriting ()Z\n\tpublic final fun getAllowSymlinks ()Z\n\tpublic final fun getAllowWritesWhileWriting ()Z\n\tpublic final fun getClock ()Lkotlin/time/Clock;\n\tpublic final fun getWorkingDirectory ()Lokio/Path;\n\tpublic fun list (Lokio/Path;)Ljava/util/List;\n\tpublic fun listOrNull (Lokio/Path;)Ljava/util/List;\n\tpublic fun metadataOrNull (Lokio/Path;)Lokio/FileMetadata;\n\tpublic final fun openPaths ()Ljava/util/List;\n\tpublic fun openReadOnly (Lokio/Path;)Lokio/FileHandle;\n\tpublic fun openReadWrite (Lokio/Path;ZZ)Lokio/FileHandle;\n\tpublic final fun setAllowClobberingEmptyDirectories (Z)V\n\tpublic final fun setAllowDeletingOpenFiles (Z)V\n\tpublic final fun setAllowMovingOpenFiles (Z)V\n\tpublic final fun setAllowReadsWhileWriting (Z)V\n\tpublic final fun setAllowSymlinks (Z)V\n\tpublic final fun setAllowWritesWhileWriting (Z)V\n\tpublic final fun setExtra (Lokio/Path;Lkotlin/reflect/KClass;Ljava/lang/Object;)V\n\tpublic final fun setWorkingDirectory (Lokio/Path;)V\n\tpublic fun sink (Lokio/Path;Z)Lokio/Sink;\n\tpublic fun source (Lokio/Path;)Lokio/Source;\n\tpublic fun toString ()Ljava/lang/String;\n}\n\n"
  },
  {
    "path": "okio-fakefilesystem/build.gradle.kts",
    "content": "import com.vanniktech.maven.publish.JavadocJar\nimport com.vanniktech.maven.publish.KotlinMultiplatform\nimport com.vanniktech.maven.publish.MavenPublishBaseExtension\nimport org.jetbrains.kotlin.gradle.dsl.JsModuleKind\n\nplugins {\n  kotlin(\"multiplatform\")\n  id(\"org.jetbrains.dokka\")\n  id(\"com.vanniktech.maven.publish.base\")\n  id(\"binary-compatibility-validator\")\n  id(\"build-support\")\n}\n\nkotlin {\n  jvm {\n  }\n  if (kmpJsEnabled) {\n    js {\n      compilerOptions {\n        moduleKind = JsModuleKind.MODULE_UMD\n        sourceMap = true\n      }\n      nodejs {\n        testTask {\n          useMocha {\n            timeout = \"30s\"\n          }\n        }\n      }\n      browser {\n      }\n    }\n  }\n  if (kmpNativeEnabled) {\n    configureOrCreateNativePlatforms()\n  }\n  sourceSets {\n    all {\n      languageSettings.apply {\n        optIn(\"kotlin.time.ExperimentalTime\")\n      }\n    }\n    val commonMain by getting {\n      dependencies {\n        api(libs.kotlin.time)\n        api(projects.okio)\n      }\n    }\n    val commonTest by getting\n    if (kmpWasmEnabled) {\n      // Add support for wasmWasi when https://github.com/Kotlin/kotlinx-datetime/issues/324 is resolved.\n      configureOrCreateWasmPlatform(wasi = false)\n      createSourceSet(\"wasmMain\", parent = commonMain, children = listOf(\"wasmJs\"))\n      createSourceSet(\"wasmTest\", parent = commonTest, children = listOf(\"wasmJs\"))\n    }\n\n    val nonJvmMain by creating {\n      dependsOn(commonMain)\n    }\n    if (kmpJsEnabled) {\n      getByName(\"jsMain\").dependsOn(nonJvmMain)\n    }\n    if (kmpNativeEnabled) {\n      for (childTarget in nativeTargets) {\n        get(\"${childTarget}Main\").dependsOn(nonJvmMain)\n      }\n    }\n    if (kmpWasmEnabled) {\n      getByName(\"wasmMain\").dependsOn(nonJvmMain)\n    }\n  }\n}\n\ntasks {\n  val jvmJar by getting(Jar::class) {\n    // BundleTaskConvention() crashes unless there's a 'main' source set.\n    sourceSets.create(SourceSet.MAIN_SOURCE_SET_NAME)\n    val bndExtension = aQute.bnd.gradle.BundleTaskExtension(this)\n    bndExtension.setBnd(\n      \"\"\"\n      Export-Package: okio.fakefilesystem\n      Automatic-Module-Name: okio.fakefilesystem\n      Bundle-SymbolicName: com.squareup.okio.fakefilesystem\n      \"\"\"\n    )\n    // Call the convention when the task has finished to modify the jar to contain OSGi metadata.\n    doLast {\n      bndExtension.buildAction()\n        .execute(this)\n    }\n  }\n}\n\nconfigure<MavenPublishBaseExtension> {\n  configure(\n    KotlinMultiplatform(javadocJar = JavadocJar.Empty())\n  )\n}\n"
  },
  {
    "path": "okio-fakefilesystem/src/commonMain/kotlin/okio/fakefilesystem/FakeFileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio.fakefilesystem\n\nimport kotlin.jvm.JvmName\nimport kotlin.reflect.KClass\nimport kotlin.time.Instant\nimport kotlinx.datetime.Clock\nimport okio.ArrayIndexOutOfBoundsException\nimport okio.Buffer\nimport okio.ByteString\nimport okio.FileHandle\nimport okio.FileMetadata\nimport okio.FileNotFoundException\nimport okio.FileSystem\nimport okio.IOException\nimport okio.Path\nimport okio.Path.Companion.toPath\nimport okio.Sink\nimport okio.Source\nimport okio.fakefilesystem.FakeFileSystem.Element.Directory\nimport okio.fakefilesystem.FakeFileSystem.Element.File\nimport okio.fakefilesystem.FakeFileSystem.Element.Symlink\nimport okio.fakefilesystem.FakeFileSystem.Operation.READ\nimport okio.fakefilesystem.FakeFileSystem.Operation.WRITE\n\n/**\n * A fully in-memory file system useful for testing. It includes features to support writing\n * better tests.\n *\n * Use [openPaths] to see which paths have been opened for read or write, but not yet closed. Tests\n * should call [checkNoOpenFiles] in `tearDown()` to confirm that no file streams were leaked.\n *\n * Strict By Default\n * -----------------\n *\n * These actions are not allowed and throw an [IOException] if attempted:\n *\n *  * Moving a file that is currently open for reading or writing.\n *  * Deleting a file that is currently open for reading or writing.\n *  * Moving a file to a path that currently resolves to an empty directory.\n *  * Reading and writing the same file at the same time.\n *  * Opening a file for writing that is already open for writing.\n *\n * Programs that do not attempt any of the above operations should work fine on both UNIX and\n * Windows systems. Relax these constraints individually or call [emulateWindows] or [emulateUnix];\n * to apply the constraints of a particular operating system.\n *\n * Closeable\n * ---------\n *\n * This file system cannot be used after it is closed. Closing it does not close any of its open\n * streams; those must be closed directly.\n */\nclass FakeFileSystem private constructor(\n  private val clockNowMillis: () -> Long,\n) : FileSystem() {\n\n  constructor() : this(clockNowMillis = defaultClockNowMillis)\n\n  constructor(clock: kotlin.time.Clock = kotlin.time.Clock.System) : this(\n    clockNowMillis = { clock.now().toEpochMilliseconds() },\n  )\n\n  // Avoid calling kotlinx.datetime.Clock.System.now() because it crashes at runtime if the Kotlin\n  // stdlib isn't 2.1.20+. (That'll be the case when running in Gradle 8.x.)\n  @Deprecated(\n    \"Use the constructor that accepts a kotlin.time.Clock, or the no-args constructor\",\n    level = DeprecationLevel.HIDDEN,\n  )\n  constructor(clock: Clock = Clock.System) : this(\n    when {\n      clock === Clock.System -> defaultClockNowMillis\n      else -> {\n        { clock.now().toEpochMilliseconds() }\n      }\n    },\n  )\n\n  /** Returns the clock used to timestamp files. */\n  // We construct this on-demand to avoid a NoClassDefFoundError if there's no kotlin.time.Clock.\n  val clock: kotlin.time.Clock\n    get() = object : kotlin.time.Clock {\n      override fun now() = Instant.fromEpochMilliseconds(clockNowMillis())\n    }\n\n  /** File system roots. Each element is a Directory and is created on-demand. */\n  private val roots = mutableMapOf<Path, Directory>()\n\n  /** Files that are currently open and need to be closed to avoid resource leaks. */\n  private val openFiles = mutableListOf<OpenFile>()\n\n  /** Forbid all access after [close]. */\n  private var closed = false\n\n  /**\n   * An absolute path with this file system's current working directory. Relative paths will be\n   * resolved against this directory when they are used.\n   */\n  var workingDirectory: Path = \"/\".toPath()\n    set(value) {\n      require(value.isAbsolute) {\n        \"expected an absolute path but was $value\"\n      }\n      field = value\n    }\n\n  /**\n   * True to allow files to be moved even if they're currently open for read or write. UNIX file\n   * systems typically allow open files to be moved; Windows file systems do not.\n   */\n  var allowMovingOpenFiles = false\n\n  /**\n   * True to allow files to be deleted even if they're currently open for read or write. UNIX file\n   * systems typically allow open files to be deleted; Windows file systems do not.\n   */\n  var allowDeletingOpenFiles = false\n\n  /**\n   * True to allow the target of an [atomicMove] operation to be an empty directory. Windows file\n   * systems typically allow files to replace empty directories; UNIX file systems do not.\n   */\n  var allowClobberingEmptyDirectories = false\n\n  /**\n   * True to permit a file to have multiple [sinks][sink] open at the same time. Both Windows and\n   * UNIX file systems permit this but the result may be undefined.\n   */\n  var allowWritesWhileWriting = false\n\n  /**\n   * True to permit a file to have a [source] and [sink] open at the same time. Both Windows and\n   * UNIX file systems permit this but the result may be undefined.\n   */\n  var allowReadsWhileWriting = false\n\n  /**\n   * True to allow symlinks to be created. UNIX file systems typically allow symlinks; Windows file\n   * systems do not. Setting this to false after creating a symlink does not prevent that symlink\n   * from being returned or used.\n   */\n  var allowSymlinks = false\n\n  /**\n   * Canonical paths for every file and directory in this file system. This omits file system roots\n   * like `C:\\` and `/`.\n   */\n  @get:JvmName(\"allPaths\")\n  val allPaths: Set<Path>\n    get() {\n      val result = mutableListOf<Path>()\n      for (path in roots.keys) {\n        result += listRecursively(path)\n      }\n      result.sort()\n      return result.toSet()\n    }\n\n  /**\n   * Canonical paths currently opened for reading or writing in the order they were opened. This may\n   * contain duplicates if a single path is open by multiple readers.\n   *\n   * Note that this may contain paths not present in [allPaths]. This occurs if a file is deleted\n   * while it is still open.\n   *\n   * The returned list is ordered by the order that the paths were opened.\n   */\n  @get:JvmName(\"openPaths\")\n  val openPaths: List<Path>\n    get() = openFiles.map { it.canonicalPath }\n\n  /**\n   * Confirm that all files that have been opened on this file system (with [source], [sink], and\n   * [appendingSink]) have since been closed. Call this in your test's `tearDown()` function to\n   * confirm that your program hasn't leaked any open files.\n   *\n   * Forgetting to close a file on a real file system is a severe error that may lead to a program\n   * crash. The operating system enforces a limit on how many files may be open simultaneously. On\n   * Linux this is [getrlimit] and is commonly adjusted with the `ulimit` command.\n   *\n   * [getrlimit]: https://man7.org/linux/man-pages/man2/getrlimit.2.html\n   *\n   * @throws IllegalStateException if any files are open when this function is called.\n   */\n  fun checkNoOpenFiles() {\n    val firstOpenFile = openFiles.firstOrNull() ?: return\n    throw IllegalStateException(\n      \"\"\"\n      |expected 0 open files, but found:\n      |    ${openFiles.joinToString(separator = \"\\n    \") { it.canonicalPath.toString() }}\n      \"\"\".trimMargin(),\n      firstOpenFile.backtrace,\n    )\n  }\n\n  /**\n   * Configure this file system to use a Windows-like working directory (`F:\\`, unless the working\n   * directory is already Windows-like) and to follow a Windows-like policy on what operations\n   * are permitted.\n   */\n  fun emulateWindows() {\n    if (\"\\\\\" !in workingDirectory.toString()) {\n      workingDirectory = \"F:\\\\\".toPath()\n    }\n    allowMovingOpenFiles = false\n    allowDeletingOpenFiles = false\n    allowClobberingEmptyDirectories = true\n    allowWritesWhileWriting = true\n    allowReadsWhileWriting = true\n  }\n\n  /**\n   * Configure this file system to use a UNIX-like working directory (`/`, unless the working\n   * directory is already UNIX-like) and to follow a UNIX-like policy on what operations are\n   * permitted.\n   */\n  fun emulateUnix() {\n    if (\"/\" !in workingDirectory.toString()) {\n      workingDirectory = \"/\".toPath()\n    }\n    allowMovingOpenFiles = true\n    allowDeletingOpenFiles = true\n    allowClobberingEmptyDirectories = false\n    allowWritesWhileWriting = true\n    allowReadsWhileWriting = true\n    allowSymlinks = true\n  }\n\n  override fun canonicalize(path: Path): Path {\n    val canonicalPath = canonicalizeInternal(path)\n\n    val lookupResult = lookupPath(canonicalPath)\n    if (lookupResult?.element == null) {\n      throw FileNotFoundException(\"no such file: $path\")\n    }\n\n    return lookupResult.path\n  }\n\n  /** Don't throw [FileNotFoundException] if the path doesn't identify a file. */\n  private fun canonicalizeInternal(path: Path): Path {\n    check(!closed) { \"closed\" }\n    return workingDirectory.resolve(path, normalize = true)\n  }\n\n  /**\n   * Sets the metadata of type [type] on [path] to [value]. If [value] is null this clears that\n   * metadata.\n   *\n   * Extras are not copied by [copy] but they are moved with [atomicMove].\n   *\n   * @throws IOException if [path] does not exist.\n   */\n  @Throws(IOException::class)\n  fun <T : Any> setExtra(path: Path, type: KClass<out T>, value: T?) {\n    val canonicalPath = canonicalizeInternal(path)\n    val lookupResult = lookupPath(\n      canonicalPath = canonicalPath,\n      createRootOnDemand = canonicalPath.isRoot,\n      resolveLastSymlink = false,\n    )\n    val element = lookupResult?.element ?: throw FileNotFoundException(\"no such file: $path\")\n    if (value == null) {\n      element.extras.remove(type)\n    } else {\n      element.extras[type] = value\n    }\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    val canonicalPath = canonicalizeInternal(path)\n    val lookupResult = lookupPath(\n      canonicalPath = canonicalPath,\n      createRootOnDemand = canonicalPath.isRoot,\n      resolveLastSymlink = false,\n    )\n    return lookupResult?.element?.metadata\n  }\n\n  override fun list(dir: Path): List<Path> = list(dir, throwOnFailure = true)!!\n\n  override fun listOrNull(dir: Path): List<Path>? = list(dir, throwOnFailure = false)\n\n  private fun list(dir: Path, throwOnFailure: Boolean): List<Path>? {\n    val canonicalPath = canonicalizeInternal(dir)\n    val lookupResult = lookupPath(canonicalPath)\n    if (lookupResult?.element == null) {\n      if (throwOnFailure) throw FileNotFoundException(\"no such directory: $dir\") else return null\n    }\n    val element = lookupResult.element as? Directory\n      ?: if (throwOnFailure) throw IOException(\"not a directory: $dir\") else return null\n\n    element.access(nowMillis = clockNowMillis())\n    return element.children.keys.map { dir / it }.sorted()\n  }\n\n  override fun source(file: Path): Source {\n    val fileHandle = openReadOnly(file)\n    return fileHandle.source()\n      .also { fileHandle.close() }\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    val fileHandle = open(file, readWrite = true, mustCreate = mustCreate)\n    fileHandle.resize(0L) // If the file already has data, get rid of it.\n    return fileHandle.sink()\n      .also { fileHandle.close() }\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    val fileHandle = open(file, readWrite = true, mustExist = mustExist)\n    return fileHandle.appendingSink()\n      .also { fileHandle.close() }\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    return open(file, readWrite = false)\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    return open(file, readWrite = true, mustCreate = mustCreate, mustExist = mustExist)\n  }\n\n  private fun open(\n    file: Path,\n    readWrite: Boolean,\n    mustCreate: Boolean = false,\n    mustExist: Boolean = false,\n  ): FileHandle {\n    require(!mustCreate || !mustExist) {\n      \"Cannot require mustCreate and mustExist at the same time.\"\n    }\n\n    val canonicalPath = canonicalizeInternal(file)\n    val lookupResult = lookupPath(canonicalPath, createRootOnDemand = readWrite)\n    val nowMillis = clockNowMillis()\n    val element: File\n    val operation: Operation\n\n    if (lookupResult?.element == null && mustExist) {\n      throw IOException(\"$file doesn't exist.\")\n    }\n    if (lookupResult?.element != null && mustCreate) {\n      throw IOException(\"$file already exists.\")\n    }\n\n    if (readWrite) {\n      // Note that this case is used for both write and read/write.\n      if (lookupResult?.element is Directory) {\n        throw IOException(\"destination is a directory: $file\")\n      }\n      if (!allowWritesWhileWriting) {\n        findOpenFile(canonicalPath, operation = WRITE)?.let {\n          throw IOException(\"file is already open for writing $file\", it.backtrace)\n        }\n      }\n      if (!allowReadsWhileWriting) {\n        findOpenFile(canonicalPath, operation = READ)?.let {\n          throw IOException(\"file is already open for reading $file\", it.backtrace)\n        }\n      }\n\n      val parent = lookupResult?.parent\n        ?: throw FileNotFoundException(\"parent directory does not exist\")\n      parent.access(nowMillis, true)\n\n      val existing = lookupResult.element\n      element = File(createdAtMillis = existing?.createdAtMillis ?: nowMillis)\n      parent.children[lookupResult.segment!!] = element\n      operation = WRITE\n\n      if (existing is File) {\n        element.data = existing.data\n      }\n    } else {\n      val existing = lookupResult?.element\n        ?: throw FileNotFoundException(\"no such file: $file\")\n      element = existing as? File ?: throw IOException(\"not a file: $file\")\n      operation = READ\n\n      if (!allowReadsWhileWriting) {\n        findOpenFile(canonicalPath, operation = WRITE)?.let {\n          throw IOException(\"file is already open for writing $file\", it.backtrace)\n        }\n      }\n    }\n\n    element.access(nowMillis = clockNowMillis(), modified = readWrite)\n\n    val openFile = OpenFile(canonicalPath, operation, Exception(\"file opened for $operation here\"))\n    openFiles += openFile\n\n    return FakeFileHandle(\n      readWrite = readWrite,\n      openFile = openFile,\n      file = element,\n    )\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    val canonicalPath = canonicalizeInternal(dir)\n\n    val lookupResult = lookupPath(canonicalPath, createRootOnDemand = true)\n\n    if (canonicalPath.isRoot) {\n      // Looking it up was sufficient. Don't crash when creating roots that already exist.\n      return\n    }\n\n    if (mustCreate && lookupResult?.element != null) {\n      throw IOException(\"already exists: $dir\")\n    }\n\n    val parentDirectory = lookupResult.requireParent()\n    parentDirectory.children[canonicalPath.nameBytes] =\n      Directory(createdAtMillis = clockNowMillis())\n  }\n\n  override fun atomicMove(\n    source: Path,\n    target: Path,\n  ) {\n    val canonicalSource = canonicalizeInternal(source)\n    val canonicalTarget = canonicalizeInternal(target)\n\n    val targetLookupResult = lookupPath(canonicalTarget, createRootOnDemand = true)\n    val sourceLookupResult = lookupPath(canonicalSource, resolveLastSymlink = false)\n\n    // Universal constraints.\n    if (targetLookupResult?.element is Directory) {\n      throw IOException(\"target is a directory: $target\")\n    }\n    val targetParent = targetLookupResult.requireParent()\n    if (!allowMovingOpenFiles) {\n      findOpenFile(canonicalSource)?.let {\n        throw IOException(\"source is open $source\", it.backtrace)\n      }\n      findOpenFile(canonicalTarget)?.let {\n        throw IOException(\"target is open $target\", it.backtrace)\n      }\n    }\n    if (!allowClobberingEmptyDirectories) {\n      if (sourceLookupResult?.element is Directory && targetLookupResult?.element is File) {\n        throw IOException(\"source is a directory and target is a file\")\n      }\n    }\n\n    val sourceParent = sourceLookupResult.requireParent()\n    val removed = sourceParent.children.remove(canonicalSource.nameBytes)\n      ?: throw FileNotFoundException(\"source doesn't exist: $source\")\n    targetParent.children[canonicalTarget.nameBytes] = removed\n  }\n\n  override fun delete(path: Path, mustExist: Boolean) {\n    val canonicalPath = canonicalizeInternal(path)\n\n    val lookupResult = lookupPath(\n      canonicalPath = canonicalPath,\n      createRootOnDemand = true,\n      resolveLastSymlink = false,\n    )\n\n    if (lookupResult?.element == null) {\n      if (mustExist) {\n        throw FileNotFoundException(\"no such file: $path\")\n      } else {\n        return\n      }\n    }\n\n    if (lookupResult.element is Directory && lookupResult.element.children.isNotEmpty()) {\n      throw IOException(\"non-empty directory\")\n    }\n\n    if (!allowDeletingOpenFiles) {\n      findOpenFile(canonicalPath)?.let {\n        throw IOException(\"file is open $path\", it.backtrace)\n      }\n    }\n\n    val directory = lookupResult.requireParent()\n    directory.children.remove(canonicalPath.nameBytes)\n  }\n\n  override fun createSymlink(\n    source: Path,\n    target: Path,\n  ) {\n    val canonicalSource = canonicalizeInternal(source)\n\n    val existingLookupResult = lookupPath(canonicalSource, createRootOnDemand = true)\n    if (existingLookupResult?.element != null) {\n      throw IOException(\"already exists: $source\")\n    }\n    val parent = existingLookupResult.requireParent()\n\n    if (!allowSymlinks) {\n      throw IOException(\"symlinks are not supported\")\n    }\n\n    parent.children[canonicalSource.nameBytes] = Symlink(createdAtMillis = clockNowMillis(), target)\n  }\n\n  /**\n   * Walks the file system looking for [canonicalPath], following symlinks encountered along the\n   * way. This function is designed to be used both when looking up existing files and when creating\n   * new files into an existing directory.\n   *\n   * It returns either:\n   *\n   *  * a path lookup result with an element if that file or directory or symlink exists. This is\n   *    useful when reading or writing an existing fie.\n   *\n   *  * a path lookup result that only got as far as the canonical path's parent, if the parent\n   *    exists but the child file does not. This is useful when creating a new file.\n   *\n   *  * null, if not even the parent directory exists. A file cannot yet be created with this path\n   *    because there is no parent to attach it to.\n   *\n   * This will create the root of the returned path if it does not exist.\n   *\n   * @param canonicalPath a normalized path, typically the result of [FakeFileSystem.canonicalizeInternal].\n   * @param recurseCount used internally to detect cycles.\n   * @param resolveLastSymlink true if the result's element must not itself be a symlink. Use this\n   *     for looking up metadata, or operations that apply to the path like delete and move. We\n   *     always follow symlinks for enclosing directories.\n   * @param createRootOnDemand true to create a root directory like `C:\\` or `/` if it doesn't\n   *     exist. Pass true for mutating operations.\n   */\n  private fun lookupPath(\n    canonicalPath: Path,\n    recurseCount: Int = 0,\n    resolveLastSymlink: Boolean = true,\n    createRootOnDemand: Boolean = false,\n  ): PathLookupResult? {\n    // 40 is chosen for consistency with the Linux kernel (which previously used 8).\n    if (recurseCount > 40) {\n      throw IOException(\"symlink cycle?\")\n    }\n\n    val rootPath = canonicalPath.root!!\n    var root = roots[rootPath]\n\n    // If the path is a root, create it on demand.\n    if (root == null) {\n      if (!createRootOnDemand) return null\n      root = Directory(createdAtMillis = clockNowMillis())\n      roots[rootPath] = root\n    }\n\n    var parent: Directory? = null\n    var lastSegment: ByteString? = null\n    var current: Element = root\n    var currentPath: Path = rootPath\n\n    var segmentsTraversed = 0\n    val segments = canonicalPath.segmentsBytes\n    for (segment in segments) {\n      lastSegment = segment\n\n      // Push the newest segment.\n      if (current !is Directory) {\n        throw IOException(\"not a directory: $currentPath\")\n      }\n      parent = current\n      current = current.children[segment] ?: break\n      currentPath /= segment\n      segmentsTraversed++\n\n      // If it's a symlink, recurse to follow it.\n      val isLastSegment = segmentsTraversed == segments.size\n      val followSymlinks = !isLastSegment || resolveLastSymlink\n      if (current is Symlink && followSymlinks) {\n        current.access(nowMillis = clockNowMillis())\n        // We wanna normalize it in case the target is relative and starts with `..`.\n        currentPath = currentPath.parent!!.resolve(current.target, normalize = true)\n        val symlinkLookupResult = lookupPath(\n          canonicalPath = currentPath,\n          recurseCount = recurseCount + 1,\n          createRootOnDemand = createRootOnDemand,\n        ) ?: break\n        parent = symlinkLookupResult.parent\n        lastSegment = symlinkLookupResult.segment\n        current = symlinkLookupResult.element ?: break\n        currentPath = symlinkLookupResult.path\n      }\n    }\n\n    return when (segmentsTraversed) {\n      segments.size -> {\n        PathLookupResult(currentPath, parent, lastSegment, current) // The file.\n      }\n      segments.size - 1 -> {\n        PathLookupResult(currentPath, parent, lastSegment, null) // The enclosing directory.\n      }\n      else -> null // We found nothing.\n    }\n  }\n\n  private class PathLookupResult(\n    /** The canonical path for the looked up path or its enclosing directory. */\n    val path: Path,\n    /** Only null if the looked up path is a root. */\n    val parent: Directory?,\n    /** Only null if the looked up path is a root. */\n    val segment: ByteString?,\n    /** Non-null if this is a root. Also not null if this file exists. */\n    val element: Element?,\n  )\n\n  private fun PathLookupResult?.requireParent(): Directory {\n    return this?.parent ?: throw IOException(\"parent directory does not exist\")\n  }\n\n  private sealed class Element(\n    val createdAtMillis: Long,\n  ) {\n    var lastModifiedAtMillis: Long = createdAtMillis\n    var lastAccessedAtMillis: Long = createdAtMillis\n    val extras = mutableMapOf<KClass<*>, Any>()\n\n    class File(createdAtMillis: Long) : Element(createdAtMillis) {\n      var data: ByteString = ByteString.EMPTY\n\n      override val metadata: FileMetadata\n        get() = FileMetadata(\n          isRegularFile = true,\n          size = data.size.toLong(),\n          createdAtMillis = createdAtMillis,\n          lastModifiedAtMillis = lastModifiedAtMillis,\n          lastAccessedAtMillis = lastAccessedAtMillis,\n          extras = extras,\n        )\n    }\n\n    class Directory(createdAtMillis: Long) : Element(createdAtMillis) {\n      /** Keys are path segments. */\n      val children = mutableMapOf<ByteString, Element>()\n\n      override val metadata: FileMetadata\n        get() = FileMetadata(\n          isDirectory = true,\n          createdAtMillis = createdAtMillis,\n          lastModifiedAtMillis = lastModifiedAtMillis,\n          lastAccessedAtMillis = lastAccessedAtMillis,\n          extras = extras,\n        )\n    }\n\n    class Symlink(\n      createdAtMillis: Long,\n      /** This may be an absolute or relative path. */\n      val target: Path,\n    ) : Element(createdAtMillis) {\n      override val metadata: FileMetadata\n        get() = FileMetadata(\n          symlinkTarget = target,\n          createdAtMillis = createdAtMillis,\n          lastModifiedAtMillis = lastModifiedAtMillis,\n          lastAccessedAtMillis = lastAccessedAtMillis,\n          extras = extras,\n        )\n    }\n\n    fun access(\n      nowMillis: Long,\n      modified: Boolean = false,\n    ) {\n      lastAccessedAtMillis = nowMillis\n      if (modified) {\n        lastModifiedAtMillis = nowMillis\n      }\n    }\n\n    abstract val metadata: FileMetadata\n  }\n\n  private fun findOpenFile(\n    canonicalPath: Path,\n    operation: Operation? = null,\n  ): OpenFile? {\n    return openFiles.firstOrNull {\n      it.canonicalPath == canonicalPath && (operation == null || operation == it.operation)\n    }\n  }\n\n  private fun checkOffsetAndCount(\n    size: Long,\n    offset: Long,\n    byteCount: Long,\n  ) {\n    if (offset or byteCount < 0 || offset > size || size - offset < byteCount) {\n      throw ArrayIndexOutOfBoundsException(\"size=$size offset=$offset byteCount=$byteCount\")\n    }\n  }\n\n  private class OpenFile(\n    val canonicalPath: Path,\n    val operation: Operation,\n    val backtrace: Throwable,\n  )\n\n  private enum class Operation {\n    READ,\n    WRITE,\n  }\n\n  private inner class FakeFileHandle(\n    readWrite: Boolean,\n    private val openFile: OpenFile,\n    private val file: File,\n  ) : FileHandle(readWrite) {\n    private var closed = false\n\n    override fun protectedResize(size: Long) {\n      check(!closed) { \"closed\" }\n\n      val delta = size - file.data.size\n      if (delta > 0) {\n        file.data = Buffer()\n          .write(file.data)\n          .write(ByteArray(delta.toInt()))\n          .readByteString()\n      } else {\n        file.data = file.data.substring(0, size.toInt())\n      }\n\n      file.access(nowMillis = clockNowMillis(), modified = true)\n    }\n\n    override fun protectedSize(): Long {\n      check(!closed) { \"closed\" }\n      return file.data.size.toLong()\n    }\n\n    override fun protectedRead(\n      fileOffset: Long,\n      array: ByteArray,\n      arrayOffset: Int,\n      byteCount: Int,\n    ): Int {\n      check(!closed) { \"closed\" }\n      checkOffsetAndCount(array.size.toLong(), arrayOffset.toLong(), byteCount.toLong())\n\n      val fileOffsetInt = fileOffset.toInt()\n      val toCopy = minOf(file.data.size - fileOffsetInt, byteCount)\n      if (toCopy <= 0) return -1\n      file.data.copyInto(fileOffsetInt, array, arrayOffset, toCopy)\n      return toCopy\n    }\n\n    override fun protectedWrite(\n      fileOffset: Long,\n      array: ByteArray,\n      arrayOffset: Int,\n      byteCount: Int,\n    ) {\n      check(!closed) { \"closed\" }\n      checkOffsetAndCount(array.size.toLong(), arrayOffset.toLong(), byteCount.toLong())\n\n      val buffer = Buffer()\n      buffer.write(file.data, 0, minOf(fileOffset.toInt(), file.data.size))\n      while (buffer.size < fileOffset) {\n        buffer.writeByte(0)\n      }\n      buffer.write(array, arrayOffset, byteCount)\n      if (buffer.size < file.data.size) {\n        buffer.write(file.data, buffer.size.toInt(), file.data.size - buffer.size.toInt())\n      }\n      file.data = buffer.snapshot()\n      file.access(nowMillis = clockNowMillis(), modified = true)\n    }\n\n    override fun protectedFlush() {\n      check(!closed) { \"closed\" }\n    }\n\n    override fun protectedClose() {\n      if (closed) return\n      closed = true\n      file.access(nowMillis = clockNowMillis(), modified = readWrite)\n      openFiles -= openFile\n    }\n\n    override fun toString() = \"FileHandler(${openFile.canonicalPath})\"\n  }\n\n  override fun close() {\n    closed = true\n  }\n\n  override fun toString() = \"FakeFileSystem\"\n}\n"
  },
  {
    "path": "okio-fakefilesystem/src/commonMain/kotlin/okio/fakefilesystem/FileMetadataCommon.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\n@file:JvmMultifileClass\n@file:JvmName(\"-Time\")\n\npackage okio.fakefilesystem\n\nimport kotlin.jvm.JvmMultifileClass\nimport kotlin.jvm.JvmName\nimport kotlin.reflect.KClass\nimport kotlinx.datetime.Instant\nimport okio.FileMetadata\nimport okio.Path\n\n@JvmName(\"newFileMetadata\")\ninternal fun FileMetadata(\n  isRegularFile: Boolean = false,\n  isDirectory: Boolean = false,\n  symlinkTarget: Path? = null,\n  size: Long? = null,\n  createdAt: Instant? = null,\n  lastModifiedAt: Instant? = null,\n  lastAccessedAt: Instant? = null,\n  extras: Map<KClass<*>, Any> = mapOf(),\n): FileMetadata {\n  return FileMetadata(\n    isRegularFile = isRegularFile,\n    isDirectory = isDirectory,\n    symlinkTarget = symlinkTarget,\n    size = size,\n    createdAtMillis = createdAt?.toEpochMilliseconds(),\n    lastModifiedAtMillis = lastModifiedAt?.toEpochMilliseconds(),\n    lastAccessedAtMillis = lastAccessedAt?.toEpochMilliseconds(),\n    extras = extras,\n  )\n}\n\n/**\n * Get the time from the best available clock.\n *\n * We'd prefer `kotlin.time.Clock` but it requires Kotlin 2.1.20+ and that isn't available to\n * Gradle plugins (at least for Gradle 8.x).\n */\ninternal expect val defaultClockNowMillis: () -> Long\n"
  },
  {
    "path": "okio-fakefilesystem/src/jvmMain/kotlin/okio/fakefilesystem/FileMetadataJvm.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\n@file:JvmMultifileClass\n@file:JvmName(\"-Time\")\n\npackage okio.fakefilesystem\n\ninternal actual val defaultClockNowMillis: () -> Long = { System.currentTimeMillis() }\n"
  },
  {
    "path": "okio-fakefilesystem/src/nonJvmMain/kotlin/okio/fakefilesystem/FileMetadataNonJvm.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio.fakefilesystem\n\nimport kotlin.time.Clock\n\ninternal actual val defaultClockNowMillis: () -> Long = { Clock.System.now().toEpochMilliseconds() }\n"
  },
  {
    "path": "okio-nodefilesystem/build.gradle.kts",
    "content": "import com.vanniktech.maven.publish.JavadocJar\nimport com.vanniktech.maven.publish.KotlinMultiplatform\nimport com.vanniktech.maven.publish.MavenPublishBaseExtension\nimport org.jetbrains.kotlin.gradle.dsl.JsModuleKind\n\nplugins {\n  kotlin(\"multiplatform\")\n  id(\"app.cash.burst\")\n  id(\"org.jetbrains.dokka\")\n  id(\"com.vanniktech.maven.publish.base\")\n  id(\"binary-compatibility-validator\")\n  id(\"build-support\")\n}\n\nkotlin {\n  js {\n    compilerOptions {\n      moduleKind = JsModuleKind.MODULE_UMD\n      sourceMap = true\n    }\n    nodejs {\n      testTask {\n        useMocha {\n          timeout = \"30s\"\n        }\n      }\n    }\n  }\n  sourceSets {\n    matching { it.name.endsWith(\"Test\") }.all {\n      languageSettings {\n        optIn(\"kotlin.time.ExperimentalTime\")\n      }\n    }\n    commonMain {\n      dependencies {\n        implementation(projects.okio)\n        // Uncomment this to generate fs.fs.module_node.kt. Use it when updating fs.kt.\n        // implementation(npm(\"@types/node\", \"14.14.16\", true))\n      }\n    }\n    commonTest {\n      dependencies {\n        implementation(libs.kotlin.test)\n        implementation(libs.kotlin.time)\n\n        implementation(projects.okioFakefilesystem)\n        implementation(projects.okioTestingSupport)\n      }\n    }\n  }\n}\n\nconfigure<MavenPublishBaseExtension> {\n  configure(\n    KotlinMultiplatform(javadocJar = JavadocJar.Empty())\n  )\n}\n"
  },
  {
    "path": "okio-nodefilesystem/src/commonMain/kotlin/okio/FileSink.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\ninternal class FileSink(\n  private val fd: Number,\n) : Sink {\n  private var closed = false\n\n  override fun write(source: Buffer, byteCount: Long) {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    require(source.size >= byteCount) { \"source.size=${source.size} < byteCount=$byteCount\" }\n    check(!closed) { \"closed\" }\n\n    val data = source.readByteArray(byteCount)\n    val writtenByteCount = writeSync(fd, data)\n    if (writtenByteCount.toLong() != byteCount) {\n      throw IOException(\"expected $byteCount but was $writtenByteCount\")\n    }\n  }\n\n  override fun flush() {\n  }\n\n  override fun timeout(): Timeout {\n    return Timeout.NONE\n  }\n\n  override fun close() {\n    if (closed) return\n    closed = true\n    closeSync(fd)\n  }\n}\n"
  },
  {
    "path": "okio-nodefilesystem/src/commonMain/kotlin/okio/FileSource.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\ninternal class FileSource(\n  private val fd: Number,\n) : Source {\n  private var position_ = 0L\n  private var closed = false\n\n  override fun read(sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    check(!closed) { \"closed\" }\n\n    val data = ByteArray(byteCount.toInt())\n    val readByteCount = readSync(\n      fd = fd,\n      buffer = data,\n      length = byteCount.toDouble(),\n      offset = 0.0,\n      position = position_.toDouble(),\n    ).toInt()\n\n    if (readByteCount == 0) return -1L\n\n    position_ += readByteCount\n\n    sink.write(data, offset = 0, byteCount = readByteCount)\n\n    return readByteCount.toLong()\n  }\n\n  override fun timeout(): Timeout = Timeout.NONE\n\n  override fun close() {\n    if (closed) return\n    closed = true\n    closeSync(fd)\n  }\n}\n"
  },
  {
    "path": "okio-nodefilesystem/src/commonMain/kotlin/okio/FsJs.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\n\n/**\n * This class declares the subset of Node.js file system APIs that we need in Okio.\n *\n *\n * Why not Dukat?\n * --------------\n *\n * This file does manually what ideally [Dukat] would do automatically.\n *\n * Dukat's generated stubs need awkward call sites to disambiguate overloads. For example, to call\n * `mkdirSync()` we must specify an options parameter even though we just want the default:\n *\n *   mkdirSync(dir.toString(), options = undefined as MakeDirectoryOptions?)\n *\n * By defining our own externals, we can omit the unwanted optional parameter from the declaration.\n * This leads to nicer calling code!\n *\n *   mkdirSync(dir.toString())\n *\n * Dukat also gets the nullability wrong for `Dirent.readSync()`.\n *\n *\n * Why not Kotlinx-nodejs?\n * -----------------------\n *\n * Even better than using Dukat directly would be to use the [official artifact][kotlinx_nodejs],\n * itself generated with Dukat. We also don't use the official Node.js artifact for the reasons\n * above, and also because it has an unstable API.\n *\n *\n * Updating this file\n * ------------------\n *\n * To declare new external APIs, run Dukat to generate a full set of Node stubs. The easiest way to\n * do this is to add an NPM dependency on `@types/node` in `jsMain`, like this:\n *\n * ```kotlin\n * jsMain {\n *   ...\n *   dependencies {\n *     implementation(npm(\"@types/node\", \"14.14.16\", true))\n *     ...\n *   }\n * }\n * ```\n *\n * This will create a file with a full set of APIs to copy-paste from.\n *\n * ```\n * okio/build/externals/okio-parent-okio/src/fs.fs.module_node.kt\n * ```\n *\n * [Dukat]: https://github.com/kotlin/dukat\n * [kotlinx_nodejs]: https://github.com/Kotlin/kotlinx-nodejs\n */\n@file:JsModule(\"fs\")\n@file:JsNonModule\n\npackage okio\n\nimport kotlin.js.Date\n\ninternal external fun closeSync(fd: Number)\n\ninternal external fun mkdirSync(path: String): String?\n\ninternal external fun openSync(path: String, flags: String): Double\n\ninternal external fun opendirSync(path: String): Dir\n\ninternal external fun readlinkSync(path: String): String\n\ninternal external fun readSync(fd: Number, buffer: ByteArray, offset: Double, length: Double, position: Double?): Double\n\ninternal external fun realpathSync(path: String): String\n\ninternal external fun renameSync(oldPath: String, newPath: String)\n\ninternal external fun rmdirSync(path: String)\n\ninternal external fun lstatSync(path: String): Stats\n\ninternal external fun fstatSync(fd: Number): Stats\n\ninternal external fun unlinkSync(path: String)\n\ninternal external fun writeSync(fd: Number, buffer: ByteArray): Double\n\ninternal external fun writeSync(fd: Number, buffer: ByteArray, offset: Double, length: Double, position: Double): Double\n\ninternal external fun ftruncateSync(fd: Number, len: Double)\n\ninternal external fun symlinkSync(target: String, path: String)\n\ninternal open external class Dir {\n  open var path: String\n  open fun closeSync()\n\n  // Note that dukat's signature of readSync() returns a non-nullable Dirent; that's incorrect.\n  open fun readSync(): Dirent?\n}\n\ninternal open external class Dirent {\n  open fun isFile(): Boolean\n  open fun isDirectory(): Boolean\n  open fun isBlockDevice(): Boolean\n  open fun isCharacterDevice(): Boolean\n  open fun isSymbolicLink(): Boolean\n  open fun isFIFO(): Boolean\n  open fun isSocket(): Boolean\n  open var name: String\n}\n\ninternal external interface StatsBase<T> {\n  fun isFile(): Boolean\n  fun isDirectory(): Boolean\n  fun isBlockDevice(): Boolean\n  fun isCharacterDevice(): Boolean\n  fun isSymbolicLink(): Boolean\n  fun isFIFO(): Boolean\n  fun isSocket(): Boolean\n  var dev: T\n  var ino: T\n  var mode: T\n  var nlink: T\n  var uid: T\n  var gid: T\n  var rdev: T\n  var size: T\n  var blksize: T\n  var blocks: T\n  var atimeMs: T\n  var mtimeMs: T\n  var ctimeMs: T\n  var birthtimeMs: T\n  var atime: Date\n  var mtime: Date\n  var ctime: Date\n  var birthtime: Date\n}\n\ninternal open external class Stats : StatsBase<Number> {\n  override fun isFile(): Boolean\n  override fun isDirectory(): Boolean\n  override fun isBlockDevice(): Boolean\n  override fun isCharacterDevice(): Boolean\n  override fun isSymbolicLink(): Boolean\n  override fun isFIFO(): Boolean\n  override fun isSocket(): Boolean\n  override var dev: Number\n  override var ino: Number\n  override var mode: Number\n  override var nlink: Number\n  override var uid: Number\n  override var gid: Number\n  override var rdev: Number\n  override var size: Number\n  override var blksize: Number\n  override var blocks: Number\n  override var atimeMs: Number\n  override var mtimeMs: Number\n  override var ctimeMs: Number\n  override var birthtimeMs: Number\n  override var atime: Date\n  override var mtime: Date\n  override var ctime: Date\n  override var birthtime: Date\n}\n"
  },
  {
    "path": "okio-nodefilesystem/src/commonMain/kotlin/okio/NodeJsFileHandle.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\ninternal class NodeJsFileHandle(\n  private val fd: Number,\n  readWrite: Boolean,\n) : FileHandle(readWrite) {\n  override fun protectedSize(): Long {\n    val stats = fstatSync(fd)\n    return stats.size.toLong()\n  }\n\n  override fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    val readByteCount = readSync(\n      fd = fd,\n      buffer = array,\n      length = byteCount.toDouble(),\n      offset = arrayOffset.toDouble(),\n      position = fileOffset.toDouble(),\n    ).toInt()\n\n    if (readByteCount == 0) return -1\n\n    return readByteCount\n  }\n\n  override fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    val writtenByteCount = writeSync(\n      fd = fd,\n      buffer = array,\n      offset = arrayOffset.toDouble(),\n      length = byteCount.toDouble(),\n      position = fileOffset.toDouble(),\n    )\n\n    if (writtenByteCount.toInt() != byteCount) {\n      throw IOException(\"expected $byteCount but was $writtenByteCount\")\n    }\n  }\n\n  override fun protectedFlush() {\n  }\n\n  override fun protectedResize(size: Long) {\n    ftruncateSync(fd, size.toDouble())\n  }\n\n  override fun protectedClose() {\n    closeSync(fd)\n  }\n}\n"
  },
  {
    "path": "okio-nodefilesystem/src/commonMain/kotlin/okio/NodeJsFileSystem.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport okio.Path.Companion.toPath\n\n/**\n * Use [Node.js APIs][node_fs] to implement the Okio file system interface.\n *\n * This class needs to make calls to some fs APIs that have multiple competing overloads. To\n * unambiguously select an overload this passes `undefined` as the target type to some functions.\n *\n * [node_fs]: https://nodejs.org/dist/latest-v14.x/docs/api/fs.html\n */\nobject NodeJsFileSystem : FileSystem() {\n  private var S_IFMT = 0xf000 // fs.constants.S_IFMT\n  private var S_IFREG = 0x8000 // fs.constants.S_IFREG\n  private var S_IFDIR = 0x4000 // fs.constants.S_IFDIR\n  private var S_IFLNK = 0xa000 // fs.constants.S_IFLNK\n\n  override fun canonicalize(path: Path): Path {\n    try {\n      val canonicalPath = realpathSync(path.toString())\n      return canonicalPath.toPath()\n    } catch (e: Throwable) {\n      throw e.toIOException()\n    }\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    val pathString = path.toString()\n    val stat = try {\n      lstatSync(pathString)\n    } catch (e: Throwable) {\n      if (e.errorCode == \"ENOENT\") return null // \"No such file or directory\".\n      throw IOException(e.message)\n    }\n\n    var symlinkTarget: Path? = null\n    if ((stat.mode.toInt() and S_IFMT) == S_IFLNK) {\n      try {\n        symlinkTarget = readlinkSync(pathString).toPath()\n      } catch (e: Throwable) {\n        throw e.toIOException()\n      }\n    }\n\n    return FileMetadata(\n      isRegularFile = (stat.mode.toInt() and S_IFMT) == S_IFREG,\n      isDirectory = (stat.mode.toInt() and S_IFMT) == S_IFDIR,\n      symlinkTarget = symlinkTarget,\n      size = stat.size.toLong(),\n      createdAtMillis = stat.birthtimeMs.toLong(),\n      lastModifiedAtMillis = stat.mtimeMs.toLong(),\n      lastAccessedAtMillis = stat.atimeMs.toLong(),\n    )\n  }\n\n  /**\n   * Returns the error code on this `SystemError`. This uses `asDynamic()` because our JS bindings\n   * don't (yet) include the `SystemError` type.\n   *\n   * https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_systemerror\n   * https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_common_system_errors\n   */\n  private val Throwable.errorCode\n    get() = asDynamic().code\n\n  override fun list(dir: Path): List<Path> = list(dir, throwOnFailure = true)!!\n\n  override fun listOrNull(dir: Path): List<Path>? = list(dir, throwOnFailure = false)\n\n  private fun list(dir: Path, throwOnFailure: Boolean): List<Path>? {\n    try {\n      val opendir = opendirSync(dir.toString())\n      try {\n        val result = mutableListOf<Path>()\n        while (true) {\n          val dirent = opendir.readSync() ?: break\n          result += dir / dirent.name\n        }\n        result.sort()\n        return result\n      } finally {\n        opendir.closeSync()\n      }\n    } catch (e: Throwable) {\n      if (throwOnFailure) {\n        throw e.toIOException()\n      } else {\n        return null\n      }\n    }\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    val fd = openFd(file, flags = \"r\")\n    return NodeJsFileHandle(fd, readWrite = false)\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    require(!mustCreate || !mustExist) {\n      \"Cannot require mustCreate and mustExist at the same time.\"\n    }\n    val fd = if (Path.DIRECTORY_SEPARATOR == \"\\\\\") {\n      // On NodeJS on Windows there's no file system flag that does all of the following:\n      //  - open a file for reading, writing, seeking, and resizing\n      //  - create it doesn't exist\n      //  - do not truncate it if it does exist\n      // Work around this by attempting to open a file that does exist (r+), falling back to\n      // creating a file that does not exist (wx+) if that throws. This is not atomic.\n      // https://nodejs.org/api/fs.html#fs_file_system_flags\n      try {\n        if (mustCreate && exists(file)) throw IOException(\"$file already exists.\")\n        openFd(file, \"r+\")\n      } catch (e: FileNotFoundException) {\n        if (mustExist) throw IOException(\"$file doesn't exist.\")\n        openFd(file, \"wx+\")\n      }\n    } else {\n      // Note that on Linux, positional writes don't work when the file is opened in append mode, so\n      // we don't want to use the `a` flag,\n      val flags = when {\n        mustCreate -> \"wx+\"\n        mustExist || exists(file) -> \"r+\"\n        else -> \"w+\"\n      }\n      openFd(file, flags)\n    }\n    return NodeJsFileHandle(fd, readWrite = true)\n  }\n\n  override fun source(file: Path): Source {\n    val fd = openFd(file, flags = \"r\")\n    return FileSource(fd)\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    val fd = openFd(file, flags = if (mustCreate) \"wx\" else \"w\")\n    return FileSink(fd)\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    // There is a `r+` flag which we could have used to force existence of [file] but this flag\n    // doesn't allow opening for appending, and we don't currently have a way to move the cursor to\n    // the end of the file. We are then forcing existence non-atomically.\n    if (mustExist && !exists(file)) throw IOException(\"$file doesn't exist.\")\n    val fd = openFd(file, flags = \"a\")\n    return FileSink(fd)\n  }\n\n  private fun openFd(file: Path, flags: String): Double {\n    try {\n      return openSync(file.toString(), flags = flags)\n    } catch (e: Throwable) {\n      throw e.toIOException()\n    }\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    try {\n      mkdirSync(dir.toString())\n    } catch (e: Throwable) {\n      val alreadyExist = metadataOrNull(dir)?.isDirectory == true\n      if (alreadyExist) {\n        if (mustCreate) {\n          throw IOException(\"$dir already exist.\")\n        } else {\n          return\n        }\n      }\n\n      throw e.toIOException()\n    }\n  }\n\n  override fun atomicMove(source: Path, target: Path) {\n    try {\n      renameSync(source.toString(), target.toString())\n    } catch (e: Throwable) {\n      throw e.toIOException()\n    }\n  }\n\n  /**\n   * We don't know if [path] is a file or a directory, but we don't (yet) have an API to delete\n   * either type. Just try each in sequence.\n   *\n   * TODO(jwilson): switch to fs.rmSync() when our minimum requirements are Node 14.14.0.\n   */\n  override fun delete(path: Path, mustExist: Boolean) {\n    try {\n      unlinkSync(path.toString())\n      return\n    } catch (e: Throwable) {\n    }\n    try {\n      rmdirSync(path.toString())\n    } catch (e: Throwable) {\n      if (e.errorCode == \"ENOENT\") {\n        if (mustExist) {\n          throw FileNotFoundException(\"no such file: $path\")\n        } else {\n          return\n        }\n      }\n      throw e.toIOException()\n    }\n  }\n\n  override fun createSymlink(source: Path, target: Path) {\n    if (source.parent == null || !exists(source.parent!!)) {\n      throw IOException(\"parent directory does not exist: ${source.parent}\")\n    }\n\n    if (exists(source)) {\n      throw IOException(\"already exists: $source\")\n    }\n\n    symlinkSync(target.toString(), source.toString())\n  }\n\n  private fun Throwable.toIOException(): IOException {\n    return when (errorCode) {\n      \"ENOENT\" -> FileNotFoundException(message)\n      else -> IOException(message)\n    }\n  }\n\n  override fun toString() = \"NodeJsSystemFileSystem\"\n}\n"
  },
  {
    "path": "okio-nodefilesystem/src/commonTest/kotlin/okio/NodeJsFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.time.Clock\n\nclass NodeJsFileSystemTest : AbstractFileSystemTest(\n  clock = Clock.System,\n  fileSystem = NodeJsFileSystem,\n  windowsLimitations = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n  closeBehavior = CloseBehavior.DoesNothing,\n)\n"
  },
  {
    "path": "okio-testing-support/README.md",
    "content": "Okio Testing Support\n====================\n\nThis module offers utilities and support for testing Okio itself. It's not intended for use by\nother projects or consumers of the Okio library.\n"
  },
  {
    "path": "okio-testing-support/build.gradle.kts",
    "content": "import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTool\n\nplugins {\n  kotlin(\"multiplatform\")\n  id(\"app.cash.burst\")\n  id(\"build-support\")\n}\n\nkotlin {\n  configureOrCreateOkioPlatforms()\n\n  sourceSets {\n    all {\n      languageSettings.apply {\n        optIn(\"kotlin.time.ExperimentalTime\")\n      }\n    }\n\n    val commonMain by getting {\n      dependencies {\n        api(projects.okio)\n        api(libs.kotlin.test)\n        api(libs.burst.runtime)\n        api(libs.test.assertk)\n      }\n    }\n\n    val nonWasmMain by creating {\n      dependsOn(commonMain)\n      dependencies {\n        api(libs.kotlin.time)\n        implementation(projects.okioFakefilesystem)\n      }\n    }\n\n    val zlibMain by creating {\n      dependsOn(commonMain)\n    }\n\n    if (kmpJsEnabled) {\n      val jsMain by getting {\n        dependsOn(nonWasmMain)\n      }\n    }\n\n    val jvmMain by getting {\n      dependsOn(nonWasmMain)\n      dependsOn(zlibMain)\n      dependencies {\n        // On the JVM the kotlin-test library resolves to one of three implementations based on\n        // which testing framework is in use. JUnit is used downstream, but Gradle can't know that\n        // here and thus fails to select a variant automatically. Declare it manually instead.\n        api(libs.kotlin.test.junit)\n      }\n    }\n\n    if (kmpNativeEnabled) {\n      createSourceSet(\"nativeMain\", children = nativeTargets)\n        .also { nativeMain ->\n          nativeMain.dependsOn(nonWasmMain)\n          nativeMain.dependsOn(zlibMain)\n        }\n    }\n\n    if (kmpWasmEnabled) {\n      createSourceSet(\"wasmMain\", children = wasmTargets)\n        .also { wasmMain ->\n          wasmMain.dependsOn(commonMain)\n        }\n      val wasmWasiMain by getting {\n        dependencies {\n          implementation(project(\":okio-wasifilesystem\"))\n        }\n      }\n    }\n  }\n}\n\n/*\n * AbstractFileSystemTest expects a file with specific metadata:\n *\n *   path: build/AbstractFileSystemTestFiles/metadata.txt\n *   createdAt: 2026-01-01T01:01:01Z\n *   lastModifiedAt: 2026-02-02T02:02:02Z\n *\n * It would be nicer to do this in the test itself with exec(), but we don't yet have a handy\n * multiplatform API for that.\n */\nval touchAbstractFileSystemTestFilesCreatedAt by tasks.registering(Exec::class) {\n  val sampleFile = project.file(\"build/AbstractFileSystemTestFiles/metadata.txt\")\n  doFirst {\n    sampleFile.parentFile.mkdirs()\n  }\n  environment(\"TZ\" to \"UTC\")\n  commandLine(\"touch\", \"-t\", \"202601010101.01\", sampleFile.path)\n}\nval touchAbstractFileSystemTestFilesModifiedAt by tasks.registering(Exec::class) {\n  dependsOn(touchAbstractFileSystemTestFilesCreatedAt)\n  val sampleFile = project.file(\"build/AbstractFileSystemTestFiles/metadata.txt\")\n  environment(\"TZ\" to \"UTC\")\n  commandLine(\"touch\", \"-t\", \"202602020202.02\", sampleFile.path)\n}\ntasks.withType<KotlinCompileTool> {\n  dependsOn(\n    touchAbstractFileSystemTestFilesCreatedAt,\n    touchAbstractFileSystemTestFilesModifiedAt,\n  )\n}\n"
  },
  {
    "path": "okio-testing-support/src/commonMain/kotlin/okio/AbstractFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport kotlin.test.Ignore\nimport kotlin.test.Test\nimport kotlin.test.assertContentEquals\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNull\nimport kotlin.test.assertTrue\nimport kotlin.test.fail\nimport kotlin.time.Clock\nimport kotlin.time.Duration.Companion.milliseconds\nimport kotlin.time.Duration.Companion.minutes\nimport kotlin.time.Duration.Companion.seconds\nimport kotlin.time.Instant\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.ByteString.Companion.toByteString\nimport okio.Path.Companion.toPath\n\n/** This test assumes that okio-files/ is the current working directory when executed. */\nabstract class AbstractFileSystemTest(\n  val clock: Clock,\n  val fileSystem: FileSystem,\n  val windowsLimitations: Boolean,\n  val allowClobberingEmptyDirectories: Boolean,\n  val allowAtomicMoveFromFileToDirectory: Boolean,\n  val allowRenameWhenTargetIsOpen: Boolean = !windowsLimitations,\n  val closeBehavior: CloseBehavior,\n  temporaryDirectory: Path,\n) {\n  @InterceptTest\n  private val baseTestDirectory = TestDirectory(fileSystem, temporaryDirectory)\n  protected val base: Path get() = baseTestDirectory.path\n\n  private val isNodeJsFileSystem = fileSystem::class.simpleName?.startsWith(\"NodeJs\") ?: false\n  private val isWasiFileSystem = fileSystem::class.simpleName?.startsWith(\"Wasi\") ?: false\n  private val isWrappingJimFileSystem = this::class.simpleName?.contains(\"JimFileSystem\") ?: false\n\n  @Test\n  fun doesNotExistsWithInvalidPathDoesNotThrow() {\n    if (isNodeJsFileSystemOnWindows()) return\n\n    val slash = Path.DIRECTORY_SEPARATOR\n    // We are testing: `\\\\127.0.0.1\\..\\localhost\\c$\\Windows`.\n    val file =\n      \"${slash}${slash}127.0.0.1$slash..${slash}localhost${slash}c\\$${slash}Windows\".toPath()\n\n    assertFalse(fileSystem.exists(file))\n  }\n\n  @Test\n  fun canonicalizeDotReturnsCurrentWorkingDirectory() {\n    if (fileSystem.isFakeFileSystem || fileSystem is ForwardingFileSystem) return\n    val cwd = fileSystem.canonicalize(\".\".toPath())\n    val cwdString = cwd.toString()\n    val slash = Path.DIRECTORY_SEPARATOR\n    assertTrue(cwdString) {\n      if (isWrappingJimFileSystem) {\n        cwdString.endsWith(\"work\")\n      } else if (isWasiFileSystem) {\n        cwdString.endsWith(\"/tmp\")\n      } else {\n        cwdString.endsWith(\"okio${slash}okio\") ||\n          cwdString.endsWith(\"${slash}okio-parent-okio-nodefilesystem-test\") ||\n          cwdString.contains(\"/CoreSimulator/Devices/\") || // iOS simulator.\n          cwdString == \"/\" // Android emulator.\n      }\n    }\n  }\n\n  @Test\n  fun currentWorkingDirectoryIsADirectory() {\n    val metadata = fileSystem.metadata(\".\".toPath())\n    assertTrue(metadata.isDirectory)\n    assertFalse(metadata.isRegularFile)\n  }\n\n  @Test\n  fun canonicalizeAbsolutePathNoSuchFile() {\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.canonicalize(base / \"no-such-file\")\n    }\n  }\n\n  @Test\n  fun canonicalizeRelativePathNoSuchFile() {\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.canonicalize(\"no-such-file\".toPath())\n    }\n  }\n\n  @Test\n  fun canonicalizeFollowsSymlinkDirectories() {\n    if (!supportsSymlink()) return\n    val base = fileSystem.canonicalize(base)\n\n    fileSystem.createDirectory(base / \"real-directory\")\n\n    val expected = base / \"real-directory\" / \"real-file.txt\"\n    expected.writeUtf8(\"hello\")\n\n    fileSystem.createSymlink(base / \"symlink-directory\", base / \"real-directory\")\n\n    val canonicalPath = fileSystem.canonicalize(base / \"symlink-directory\" / \"real-file.txt\")\n    assertEquals(expected, canonicalPath)\n  }\n\n  @Test\n  fun canonicalizeFollowsSymlinkFiles() {\n    if (!supportsSymlink()) return\n    val base = fileSystem.canonicalize(base)\n\n    fileSystem.createDirectory(base / \"real-directory\")\n\n    val expected = base / \"real-directory\" / \"real-file.txt\"\n    expected.writeUtf8(\"hello\")\n\n    fileSystem.createSymlink(\n      base / \"real-directory\" / \"symlink-file.txt\",\n      expected,\n    )\n\n    val canonicalPath = fileSystem.canonicalize(base / \"real-directory\" / \"symlink-file.txt\")\n    assertEquals(expected, canonicalPath)\n  }\n\n  @Test\n  fun canonicalizeFollowsMultipleDirectoriesAndMultipleFiles() {\n    if (!supportsSymlink()) return\n    val base = fileSystem.canonicalize(base)\n\n    fileSystem.createDirectory(base / \"real-directory\")\n\n    val expected = base / \"real-directory\" / \"real-file.txt\"\n    expected.writeUtf8(\"hello\")\n\n    fileSystem.createSymlink(\n      base / \"real-directory\" / \"one-symlink-file.txt\",\n      expected,\n    )\n\n    fileSystem.createSymlink(\n      base / \"real-directory\" / \"two-symlink-file.txt\",\n      base / \"real-directory\" / \"one-symlink-file.txt\",\n    )\n\n    fileSystem.createSymlink(\n      base / \"one-symlink-directory\",\n      base / \"real-directory\",\n    )\n\n    fileSystem.createSymlink(\n      base / \"two-symlink-directory\",\n      base / \"one-symlink-directory\",\n    )\n\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"two-symlink-directory\" / \"two-symlink-file.txt\"),\n    )\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"two-symlink-directory\" / \"one-symlink-file.txt\"),\n    )\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"two-symlink-directory\" / \"real-file.txt\"),\n    )\n\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"one-symlink-directory\" / \"two-symlink-file.txt\"),\n    )\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"one-symlink-directory\" / \"one-symlink-file.txt\"),\n    )\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"one-symlink-directory\" / \"real-file.txt\"),\n    )\n\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"real-directory\" / \"two-symlink-file.txt\"),\n    )\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"real-directory\" / \"one-symlink-file.txt\"),\n    )\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(expected),\n    )\n  }\n\n  @Test\n  fun canonicalizeReturnsDeeperPath() {\n    if (!supportsSymlink()) return\n    val base = fileSystem.canonicalize(base)\n\n    fileSystem.createDirectories(base / \"a\" / \"b\" / \"c\")\n\n    val expected = base / \"a\" / \"b\" / \"c\" / \"d.txt\"\n    expected.writeUtf8(\"hello\")\n\n    fileSystem.createSymlink(\n      base / \"e.txt\",\n      \"a\".toPath() / \"b\" / \"c\" / \"d.txt\",\n    )\n\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"e.txt\"),\n    )\n  }\n\n  @Test\n  fun canonicalizeReturnsShallowerPath() {\n    if (!supportsSymlink()) return\n    val base = fileSystem.canonicalize(base)\n\n    val expected = base / \"a.txt\"\n    expected.writeUtf8(\"hello\")\n\n    fileSystem.createDirectories(base / \"b\" / \"c\" / \"d\")\n    fileSystem.createSymlink(\n      base / \"b\" / \"c\" / \"d\" / \"e.txt\",\n      \"../\".toPath() / \"..\" / \"..\" / \"a.txt\",\n    )\n\n    assertEquals(\n      expected,\n      fileSystem.canonicalize(base / \"b\" / \"c\" / \"d\" / \"e.txt\"),\n    )\n  }\n\n  @Test\n  fun list() {\n    val target = base / \"list\"\n    target.writeUtf8(\"hello, world!\")\n    val entries = fileSystem.list(base)\n    assertTrue(entries.toString()) { target in entries }\n  }\n\n  @Test\n  fun listOnRelativePathReturnsRelativePaths() {\n    // Make sure there's always at least one file so our assertion is useful.\n    if (fileSystem.isFakeFileSystem) {\n      val workingDirectory = \"/directory\".toPath()\n      fileSystem.createDirectory(workingDirectory)\n      fileSystem.workingDirectory = workingDirectory\n      fileSystem.write(\"a.txt\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    } else if (isWrappingJimFileSystem || isWasiFileSystem) {\n      fileSystem.write(\"a.txt\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    }\n\n    val entries = fileSystem.list(\".\".toPath())\n    assertTrue(entries.toString()) { entries.isNotEmpty() && entries.all { it.isRelative } }\n  }\n\n  @Test\n  fun listOnRelativePathWhichIsNotDotReturnsRelativePaths() {\n    if (isNodeJsFileSystem) return\n\n    // Make sure there's always at least one file so our assertion is useful. We copy the first 2\n    // entries of the real working directory of the JVM to validate the results on all environment.\n    if (\n      fileSystem.isFakeFileSystem ||\n      fileSystem is ForwardingFileSystem && fileSystem.delegate.isFakeFileSystem\n    ) {\n      val workingDirectory = \"/directory\".toPath()\n      fileSystem.createDirectory(workingDirectory)\n      fileSystem.workingDirectory = workingDirectory\n      val apiDir = \"api\".toPath()\n      fileSystem.createDirectory(apiDir)\n      fileSystem.write(apiDir / \"okio.api\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    } else if (isWrappingJimFileSystem || isWasiFileSystem) {\n      val apiDir = \"api\".toPath()\n      fileSystem.createDirectory(apiDir)\n      fileSystem.write(apiDir / \"okio.api\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    }\n\n    try {\n      assertEquals(\n        listOf(\"api\".toPath() / \"okio.api\".toPath()),\n        fileSystem.list(\"api\".toPath()),\n        // List some entries to help debugging.\n        fileSystem.listRecursively(\".\".toPath()).take(5).toList().joinToString(),\n      )\n    } catch (e: Throwable) {\n      if (e !is AssertionError && e !is FileNotFoundException) { throw e }\n\n      // Non JVM environments.\n      val firstChild = fileSystem.list(\"Library\".toPath()).first()\n      assertTrue(\n        // List some entries to help debugging.\n        fileSystem.listRecursively(\".\".toPath()).take(5).toList().joinToString(),\n      ) {\n        // To avoid relying too much on the environment we check that the path contains its parent\n        // once and that it's relative.\n        firstChild.isRelative &&\n          firstChild.toString().startsWith(\"Library\") &&\n          firstChild.toString().split(\"Library\").size == 2\n      }\n    }\n  }\n\n  @Test\n  fun listOrNullOnRelativePathWhichIsNotDotReturnsRelativePaths() {\n    if (isNodeJsFileSystem) return\n\n    // Make sure there's always at least one file so our assertion is useful. We copy the first 2\n    // entries of the real working directory of the JVM to validate the results on all environment.\n    if (\n      fileSystem.isFakeFileSystem ||\n      fileSystem is ForwardingFileSystem && fileSystem.delegate.isFakeFileSystem\n    ) {\n      val workingDirectory = \"/directory\".toPath()\n      fileSystem.createDirectory(workingDirectory)\n      fileSystem.workingDirectory = workingDirectory\n      val apiDir = \"api\".toPath()\n      fileSystem.createDirectory(apiDir)\n      fileSystem.write(apiDir / \"okio.api\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    } else if (isWrappingJimFileSystem) {\n      val apiDir = \"api\".toPath()\n      fileSystem.createDirectory(apiDir)\n      fileSystem.write(apiDir / \"okio.api\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    }\n\n    try {\n      assertEquals(\n        listOf(\"api\".toPath() / \"okio.api\".toPath()),\n        fileSystem.listOrNull(\"api\".toPath()),\n        // List some entries to help debugging.\n        fileSystem.listRecursively(\".\".toPath()).take(5).toList().joinToString(),\n      )\n    } catch (e: Throwable) {\n      if (e !is AssertionError && e !is FileNotFoundException) { throw e }\n\n      // Non JVM environments.\n      val firstChild = fileSystem.list(\"Library\".toPath()).first()\n      assertTrue(\n        // List some entries to help debugging.\n        fileSystem.listRecursively(\".\".toPath()).take(5).toList().joinToString(),\n      ) {\n        // To avoid relying too much on the environment we check that the path contains its parent\n        // once and that it's relative.\n        firstChild.isRelative &&\n          firstChild.toString().startsWith(\"Library\") &&\n          firstChild.toString().split(\"Library\").size == 2\n      }\n    }\n  }\n\n  @Test\n  fun listResultsAreSorted() {\n    val fileA = base / \"a\"\n    val fileB = base / \"b\"\n    val fileC = base / \"c\"\n    val fileD = base / \"d\"\n\n    // Create files in a different order than the sorted order, so a file system that returns files\n    // in creation-order or reverse-creation order won't pass by accident.\n    fileD.writeUtf8(\"fileD\")\n    fileB.writeUtf8(\"fileB\")\n    fileC.writeUtf8(\"fileC\")\n    fileA.writeUtf8(\"fileA\")\n\n    val entries = fileSystem.list(base)\n    assertEquals(entries, listOf(fileA, fileB, fileC, fileD))\n  }\n\n  @Test\n  fun listNoSuchDirectory() {\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.list(base / \"no-such-directory\")\n    }\n  }\n\n  @Test\n  fun listFile() {\n    val target = base / \"list\"\n    target.writeUtf8(\"hello, world!\")\n    val exception = assertFailsWith<IOException> {\n      fileSystem.list(target)\n    }\n    assertTrue(exception !is FileNotFoundException)\n  }\n\n  @Test\n  fun listOrNull() {\n    val target = base / \"list\"\n    target.writeUtf8(\"hello, world!\")\n    val entries = fileSystem.listOrNull(base)!!\n    assertTrue(entries.toString()) { target in entries }\n  }\n\n  @Test\n  fun listOrNullOnRelativePathReturnsRelativePaths() {\n    // Make sure there's always at least one file so our assertion is useful.\n    if (fileSystem.isFakeFileSystem) {\n      val workingDirectory = \"/directory\".toPath()\n      fileSystem.createDirectory(workingDirectory)\n      fileSystem.workingDirectory = workingDirectory\n      fileSystem.write(\"a.txt\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    } else if (isWrappingJimFileSystem) {\n      fileSystem.write(\"a.txt\".toPath()) {\n        writeUtf8(\"hello, world!\")\n      }\n    }\n\n    val entries = fileSystem.listOrNull(\".\".toPath())\n    assertTrue(entries.toString()) { entries!!.isNotEmpty() && entries.all { it.isRelative } }\n  }\n\n  @Test\n  fun listOrNullResultsAreSorted() {\n    val fileA = base / \"a\"\n    val fileB = base / \"b\"\n    val fileC = base / \"c\"\n    val fileD = base / \"d\"\n\n    // Create files in a different order than the sorted order, so a file system that returns files\n    // in creation-order or reverse-creation order won't pass by accident.\n    fileD.writeUtf8(\"fileD\")\n    fileB.writeUtf8(\"fileB\")\n    fileC.writeUtf8(\"fileC\")\n    fileA.writeUtf8(\"fileA\")\n\n    val entries = fileSystem.listOrNull(base)\n    assertEquals(entries, listOf(fileA, fileB, fileC, fileD))\n  }\n\n  @Test\n  fun listOrNullNoSuchDirectory() {\n    assertNull(fileSystem.listOrNull(base / \"no-such-directory\"))\n  }\n\n  @Test\n  fun listOrNullFile() {\n    val target = base / \"list\"\n    target.writeUtf8(\"hello, world!\")\n    assertNull(fileSystem.listOrNull(target))\n  }\n\n  @Test\n  fun listRecursivelyReturnsEmpty() {\n    val entries = fileSystem.listRecursively(base)\n    assertEquals(entries.toList(), listOf())\n  }\n\n  @Test\n  fun listRecursivelyReturnsSingleFile() {\n    val baseA = base / \"a\"\n    baseA.writeUtf8(\"a\")\n    val entries = fileSystem.listRecursively(base)\n    assertEquals(entries.toList(), listOf(baseA))\n  }\n\n  @Test\n  fun listRecursivelyRecurses() {\n    val baseA = base / \"a\"\n    val baseAB = baseA / \"b\"\n    baseA.createDirectory()\n    baseAB.writeUtf8(\"ab\")\n    val entries = fileSystem.listRecursively(base)\n    assertEquals(listOf(baseA, baseAB), entries.toList())\n  }\n\n  @Test\n  fun listRecursivelyNoSuchFile() {\n    val baseA = base / \"a\"\n    val sequence = fileSystem.listRecursively(baseA)\n    assertFailsWith<FileNotFoundException> {\n      sequence.first()\n    }\n  }\n\n  /**\n   * Note that this is different from `Files.walk` in java.nio which returns the argument even if\n   * it is not a directory.\n   */\n  @Test\n  fun listRecursivelyNotADirectory() {\n    val baseA = base / \"a\"\n    baseA.writeUtf8(\"a\")\n    val sequence = fileSystem.listRecursively(baseA)\n    val exception = assertFailsWith<IOException> {\n      sequence.first()\n    }\n    assertTrue(exception !is FileNotFoundException)\n  }\n\n  @Test\n  fun listRecursivelyIsDepthFirst() {\n    val baseA = base / \"a\"\n    val baseB = base / \"b\"\n    val baseA1 = baseA / \"1\"\n    val baseA2 = baseA / \"2\"\n    val baseB1 = baseB / \"1\"\n    val baseB2 = baseB / \"2\"\n    baseA.createDirectory()\n    baseB.createDirectory()\n    baseA1.writeUtf8(\"a1\")\n    baseA2.writeUtf8(\"a2\")\n    baseB1.writeUtf8(\"b1\")\n    baseB2.writeUtf8(\"b2\")\n    val entries = fileSystem.listRecursively(base)\n    assertEquals(listOf(baseA, baseA1, baseA2, baseB, baseB1, baseB2), entries.toList())\n  }\n\n  @Test\n  fun listRecursivelyIsLazy() {\n    val baseA = base / \"a\"\n    val baseB = base / \"b\"\n    baseA.createDirectory()\n    baseB.createDirectory()\n    val entries = fileSystem.listRecursively(base).iterator()\n\n    // This call will enqueue up the children of base, baseA and baseB.\n    assertEquals(baseA, entries.next())\n    val baseA1 = baseA / \"1\"\n    val baseA2 = baseA / \"2\"\n    baseA1.writeUtf8(\"a1\")\n    baseA2.writeUtf8(\"a2\")\n\n    // This call will enqueue the children of baseA, baseA1 and baseA2.\n    assertEquals(baseA1, entries.next())\n    assertEquals(baseA2, entries.next())\n    assertEquals(baseB, entries.next())\n\n    // This call will enqueue the children of baseB, baseB1 and baseB2.\n    val baseB1 = baseB / \"1\"\n    val baseB2 = baseB / \"2\"\n    baseB1.writeUtf8(\"b1\")\n    baseB2.writeUtf8(\"b2\")\n    assertEquals(baseB1, entries.next())\n    assertEquals(baseB2, entries.next())\n    assertFalse(entries.hasNext())\n  }\n\n  /**\n   * This test creates directories that should be listed lazily, and then deletes them! The test\n   * wants to confirm that the sequence is resilient to such changes.\n   */\n  @Test\n  fun listRecursivelySilentlyIgnoresListFailures() {\n    val baseA = base / \"a\"\n    val baseB = base / \"b\"\n    baseA.createDirectory()\n    baseB.createDirectory()\n    val entries = fileSystem.listRecursively(base).iterator()\n    assertEquals(baseA, entries.next())\n    assertEquals(baseB, entries.next())\n    fileSystem.delete(baseA)\n    fileSystem.delete(baseB)\n    assertFalse(entries.hasNext())\n  }\n\n  @Test\n  fun listRecursivelySequenceIterationsAreIndependent() {\n    val sequence = fileSystem.listRecursively(base)\n    val iterator1 = sequence.iterator()\n    assertFalse(iterator1.hasNext())\n    val baseA = base / \"a\"\n    baseA.writeUtf8(\"a\")\n    val iterator2 = sequence.iterator()\n    assertEquals(baseA, iterator2.next())\n    assertFalse(iterator2.hasNext())\n  }\n\n  @Test\n  fun listRecursivelyFollowsSymlinks() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAA = baseA / \"a\"\n    val baseB = base / \"b\"\n    val baseBA = baseB / \"a\"\n    baseA.createDirectory()\n    baseAA.writeUtf8(\"aa\")\n    fileSystem.createSymlink(baseB, baseA)\n\n    val sequence = fileSystem.listRecursively(base, followSymlinks = true)\n    assertEquals(listOf(baseA, baseAA, baseB, baseBA), sequence.toList())\n  }\n\n  @Test\n  fun listRecursivelyDoesNotFollowSymlinks() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAA = baseA / \"a\"\n    val baseB = base / \"b\"\n    baseA.createDirectory()\n    baseAA.writeUtf8(\"aa\")\n    fileSystem.createSymlink(baseB, baseA)\n\n    val sequence = fileSystem.listRecursively(base, followSymlinks = false)\n    assertEquals(listOf(baseA, baseAA, baseB), sequence.toList())\n  }\n\n  @Test\n  fun listRecursivelyOnSymlink() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAA = baseA / \"a\"\n    val baseB = base / \"b\"\n    val baseBA = baseB / \"a\"\n\n    baseA.createDirectory()\n    baseAA.writeUtf8(\"aa\")\n    fileSystem.createSymlink(baseB, baseA)\n\n    val sequence = fileSystem.listRecursively(baseB, followSymlinks = false)\n    assertEquals(listOf(baseBA), sequence.toList())\n  }\n\n  @Test\n  fun listRecursiveWithSpecialCharacterNamedFiles() {\n    val baseA = base / \"ä\"\n    val baseASuperSaiyan = baseA / \"超サイヤ人\"\n    val baseB = base / \"ß\"\n    val baseBIliad = baseB / \"Ἰλιάς\"\n\n    baseA.createDirectory()\n    baseASuperSaiyan.writeUtf8(\"カカロットよ！\")\n    baseB.createDirectory()\n    baseBIliad.writeUtf8(\"μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος\")\n\n    val sequence = fileSystem.listRecursively(base)\n    assertEquals(listOf(baseB, baseBIliad, baseA, baseASuperSaiyan), sequence.toList())\n  }\n\n  @Test\n  fun listRecursiveOnSymlinkWithSpecialCharacterNamedFiles() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"ä\"\n    val baseASuperSaiyan = baseA / \"超サイヤ人\"\n    val baseB = base / \"ß\"\n    val baseBSuperSaiyan = baseB / \"超サイヤ人\"\n\n    baseA.createDirectory()\n    baseASuperSaiyan.writeUtf8(\"aa\")\n    fileSystem.createSymlink(baseB, baseA)\n\n    val sequence = fileSystem.listRecursively(baseB, followSymlinks = false)\n    assertEquals(listOf(baseBSuperSaiyan), sequence.toList())\n  }\n\n  @Test\n  fun listRecursivelyOnSymlinkCycleThrows() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAB = baseA / \"b\"\n    val baseAC = baseA / \"c\"\n\n    baseA.createDirectory()\n    baseAB.writeUtf8(\"ab\")\n    fileSystem.createSymlink(baseAC, baseA)\n\n    val iterator = fileSystem.listRecursively(base, followSymlinks = true).iterator()\n    assertEquals(baseA, iterator.next())\n    assertEquals(baseAB, iterator.next())\n    assertEquals(baseAC, iterator.next())\n    val exception = assertFailsWith<IOException> {\n      iterator.next() // This would fail because 'c' refers to a path we've already visited.\n    }\n    assertEquals(\"symlink cycle at $baseAC\", exception.message)\n  }\n\n  @Test\n  fun listRecursivelyDoesNotFollowRelativeSymlink() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAA = baseA / \"a\"\n    val baseB = base / \"b\"\n    baseA.createDirectory()\n    baseAA.writeUtf8(\"aa\")\n    fileSystem.createSymlink(baseB, \".\".toPath()) // Symlink to enclosing directory!\n\n    val iterator = fileSystem.listRecursively(base, followSymlinks = true).iterator()\n    assertEquals(baseA, iterator.next())\n    assertEquals(baseAA, iterator.next())\n    assertEquals(baseB, iterator.next())\n    val exception = assertFailsWith<IOException> {\n      iterator.next()\n    }\n    assertEquals(\"symlink cycle at $baseB\", exception.message)\n  }\n\n  @Test\n  fun fileSourceNoSuchDirectory() {\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.source(base / \"no-such-directory\" / \"file\")\n    }\n  }\n\n  @Test\n  fun fileSource() {\n    val path = base / \"file-source\"\n    path.writeUtf8(\"hello, world!\")\n\n    val source = fileSystem.source(path)\n    val buffer = Buffer()\n    assertTrue(source.read(buffer, 100L) == 13L)\n    assertEquals(-1L, source.read(buffer, 100L))\n    assertEquals(\"hello, world!\", buffer.readUtf8())\n    source.close()\n  }\n\n  @Test\n  fun readPath() {\n    val path = base / \"read-path\"\n    val string = \"hello, read with a Path\"\n    path.writeUtf8(string)\n\n    val result = fileSystem.read(path) {\n      assertEquals(\"hello\", readUtf8(5))\n      assertEquals(\", read with \", readUtf8(12))\n      assertEquals(\"a Path\", readUtf8())\n      return@read \"success\"\n    }\n    assertEquals(\"success\", result)\n  }\n\n  @Test\n  fun fileSink() {\n    val path = base / \"file-sink\"\n    val sink = fileSystem.sink(path)\n    val buffer = Buffer().writeUtf8(\"hello, world!\")\n    sink.write(buffer, buffer.size)\n    sink.close()\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(0, buffer.size)\n    assertEquals(\"hello, world!\", path.readUtf8())\n  }\n\n  @Test\n  fun fileSinkWithSpecialCharacterNamedFiles() {\n    val path = base / \"Ἰλιάς\"\n    val sink = fileSystem.sink(path)\n    val buffer = Buffer().writeUtf8(\"μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος\")\n    sink.write(buffer, buffer.size)\n    sink.close()\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(0, buffer.size)\n    assertEquals(\"μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος\", path.readUtf8())\n  }\n\n  @Test\n  fun fileSinkMustCreate() {\n    val path = base / \"file-sink\"\n    val sink = fileSystem.sink(path, mustCreate = true)\n    val buffer = Buffer().writeUtf8(\"hello, world!\")\n    sink.write(buffer, buffer.size)\n    sink.close()\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(0, buffer.size)\n    assertEquals(\"hello, world!\", path.readUtf8())\n  }\n\n  @Test\n  fun fileSinkMustCreateThrowsIfAlreadyExists() {\n    val path = base / \"file-sink\"\n    path.writeUtf8(\"First!\")\n    assertFailsWith<IOException> {\n      fileSystem.sink(path, mustCreate = true)\n    }\n  }\n\n  /**\n   * Write a file by concatenating three mechanisms, then read it in its entirety using three other\n   * mechanisms. This is attempting to defend against unwanted use of Windows text mode.\n   *\n   * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=msvc-160\n   */\n  @Test\n  fun fileSinkSpecialCharacters() {\n    val path = base / \"file-sink-special-characters\"\n    val content = \"[ctrl-z: \\u001A][newline: \\n][crlf: \\r\\n]\".encodeUtf8()\n\n    fileSystem.write(path) {\n      writeUtf8(\"FileSystem.write()\\n\")\n      write(content)\n    }\n\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.sink(fileOffset = handle.size()).buffer().use { sink ->\n        sink.writeUtf8(\"FileSystem.openReadWrite()\\n\")\n        sink.write(content)\n      }\n    }\n\n    fileSystem.appendingSink(path).buffer().use { sink ->\n      sink.writeUtf8(\"FileSystem.appendingSink()\\n\")\n      sink.write(content)\n    }\n\n    fileSystem.read(path) {\n      assertEquals(\"FileSystem.write()\", readUtf8LineStrict())\n      assertEquals(content, readByteString(content.size.toLong()))\n      assertEquals(\"FileSystem.openReadWrite()\", readUtf8LineStrict())\n      assertEquals(content, readByteString(content.size.toLong()))\n      assertEquals(\"FileSystem.appendingSink()\", readUtf8LineStrict())\n      assertEquals(content, readByteString(content.size.toLong()))\n      assertTrue(exhausted())\n    }\n\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.source().buffer().use { source ->\n        assertEquals(\"FileSystem.write()\", source.readUtf8LineStrict())\n        assertEquals(content, source.readByteString(content.size.toLong()))\n        assertEquals(\"FileSystem.openReadWrite()\", source.readUtf8LineStrict())\n        assertEquals(content, source.readByteString(content.size.toLong()))\n        assertEquals(\"FileSystem.appendingSink()\", source.readUtf8LineStrict())\n        assertEquals(content, source.readByteString(content.size.toLong()))\n        assertTrue(source.exhausted())\n      }\n    }\n\n    fileSystem.openReadOnly(path).use { handle ->\n      handle.source().buffer().use { source ->\n        assertEquals(\"FileSystem.write()\", source.readUtf8LineStrict())\n        assertEquals(content, source.readByteString(content.size.toLong()))\n        assertEquals(\"FileSystem.openReadWrite()\", source.readUtf8LineStrict())\n        assertEquals(content, source.readByteString(content.size.toLong()))\n        assertEquals(\"FileSystem.appendingSink()\", source.readUtf8LineStrict())\n        assertEquals(content, source.readByteString(content.size.toLong()))\n        assertTrue(source.exhausted())\n      }\n    }\n  }\n\n  @Test\n  fun writePath() {\n    val path = base / \"write-path\"\n    val content = fileSystem.write(path) {\n      val string = \"hello, write with a Path\"\n      writeUtf8(string)\n      return@write string\n    }\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(content, path.readUtf8())\n  }\n\n  @Test\n  fun writePathMustCreate() {\n    val path = base / \"write-path\"\n    val content = fileSystem.write(path, mustCreate = true) {\n      val string = \"hello, write with a Path\"\n      writeUtf8(string)\n      return@write string\n    }\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(content, path.readUtf8())\n  }\n\n  @Test\n  fun writePathMustCreateThrowsIfAlreadyExists() {\n    val path = base / \"write-path\"\n    path.writeUtf8(\"First!\")\n    assertFailsWith<IOException> {\n      fileSystem.write(path, mustCreate = true) {}\n    }\n  }\n\n  @Test\n  fun appendingSinkAppendsToExistingFile() {\n    val path = base / \"appending-sink-appends-to-existing-file\"\n    path.writeUtf8(\"hello, world!\\n\")\n    val sink = fileSystem.appendingSink(path)\n    val buffer = Buffer().writeUtf8(\"this is added later!\")\n    sink.write(buffer, buffer.size)\n    sink.close()\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(\"hello, world!\\nthis is added later!\", path.readUtf8())\n  }\n\n  @Test\n  fun appendingSinkDoesNotImpactExistingFile() {\n    if (fileSystem.isFakeFileSystem && !fileSystem.allowReadsWhileWriting) return\n\n    val path = base / \"appending-sink-does-not-impact-existing-file\"\n    path.writeUtf8(\"hello, world!\\n\")\n    val sink = fileSystem.appendingSink(path)\n    assertEquals(\"hello, world!\\n\", path.readUtf8())\n    sink.close()\n    assertEquals(\"hello, world!\\n\", path.readUtf8())\n  }\n\n  @Test\n  fun appendingSinkCreatesNewFile() {\n    val path = base / \"appending-sink-creates-new-file\"\n    val sink = fileSystem.appendingSink(path)\n    val buffer = Buffer().writeUtf8(\"this is all there is!\")\n    sink.write(buffer, buffer.size)\n    sink.close()\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(\"this is all there is!\", path.readUtf8())\n  }\n\n  @Test\n  fun appendingSinkExistingFileMustExist() {\n    val path = base / \"appending-sink-creates-new-file\"\n    path.writeUtf8(\"Hey, \")\n\n    val sink = fileSystem.appendingSink(path, mustExist = true)\n    val buffer = Buffer().writeUtf8(\"this is all there is!\")\n    sink.write(buffer, buffer.size)\n    sink.close()\n    assertTrue(path in fileSystem.list(base))\n    assertEquals(\"Hey, this is all there is!\", path.readUtf8())\n  }\n\n  @Test\n  fun appendingSinkMustExistThrowsIfAbsent() {\n    val path = base / \"appending-sink-creates-new-file\"\n    assertFailsWith<IOException> {\n      fileSystem.appendingSink(path, mustExist = true)\n    }\n  }\n\n  @Test\n  fun fileSinkFlush() {\n    if (fileSystem.isFakeFileSystem && !fileSystem.allowReadsWhileWriting) return\n\n    val path = base / \"file-sink\"\n    val sink = fileSystem.sink(path)\n\n    val buffer = Buffer().writeUtf8(\"hello,\")\n    sink.write(buffer, buffer.size)\n    sink.flush()\n    assertEquals(\"hello,\", path.readUtf8())\n\n    buffer.writeUtf8(\" world!\")\n    sink.write(buffer, buffer.size)\n    sink.close()\n    assertEquals(\"hello, world!\", path.readUtf8())\n  }\n\n  @Test\n  fun fileSinkNoSuchDirectory() {\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.sink(base / \"no-such-directory\" / \"file\")\n    }\n  }\n\n  @Test\n  fun createDirectory() {\n    val path = base / \"create-directory\"\n    fileSystem.createDirectory(path)\n    assertTrue(path in fileSystem.list(base))\n  }\n\n  @Test\n  fun createDirectoryMustCreate() {\n    val path = base / \"create-directory\"\n    fileSystem.createDirectory(path, mustCreate = true)\n    assertTrue(path in fileSystem.list(base))\n  }\n\n  @Test\n  fun createDirectoryAlreadyExists() {\n    val path = base / \"already-exists\"\n    fileSystem.createDirectory(path)\n    fileSystem.createDirectory(path)\n  }\n\n  @Test\n  fun createDirectoryAlreadyExistsMustCreateThrows() {\n    val path = base / \"already-exists\"\n    fileSystem.createDirectory(path)\n    val exception = assertFailsWith<IOException> {\n      fileSystem.createDirectory(path, mustCreate = true)\n    }\n    assertTrue(exception !is FileNotFoundException)\n  }\n\n  @Test\n  fun createDirectoryParentDirectoryDoesNotExist() {\n    val path = base / \"no-such-directory\" / \"created\"\n    assertFailsWith<IOException> {\n      fileSystem.createDirectory(path)\n    }\n  }\n\n  @Test\n  fun createDirectoriesSingle() {\n    val path = base / \"create-directories-single\"\n    fileSystem.createDirectories(path)\n    assertTrue(path in fileSystem.list(base))\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesAlreadyExists() {\n    val path = base / \"already-exists\"\n    fileSystem.createDirectory(path)\n    fileSystem.createDirectories(path)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesAlreadyExistsMustCreateThrows() {\n    val path = base / \"already-exists\"\n    fileSystem.createDirectory(path)\n    val exception = assertFailsWith<IOException> {\n      fileSystem.createDirectories(path, mustCreate = true)\n    }\n    assertTrue(exception !is FileNotFoundException)\n    assertTrue(fileSystem.metadata(path).isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesParentDirectoryDoesNotExist() {\n    fileSystem.createDirectories(base / \"a\" / \"b\" / \"c\")\n    assertTrue(base / \"a\" in fileSystem.list(base))\n    assertTrue(base / \"a\" / \"b\" in fileSystem.list(base / \"a\"))\n    assertTrue(base / \"a\" / \"b\" / \"c\" in fileSystem.list(base / \"a\" / \"b\"))\n    assertTrue(fileSystem.metadata(base / \"a\" / \"b\" / \"c\").isDirectory)\n  }\n\n  @Test\n  fun createDirectoriesParentIsFile() {\n    val file = base / \"simple-file\"\n    file.writeUtf8(\"just a file\")\n    assertFailsWith<IOException> {\n      fileSystem.createDirectories(file / \"child\")\n    }\n  }\n\n  @Test\n  fun atomicMoveFile() {\n    val source = base / \"source\"\n    source.writeUtf8(\"hello, world!\")\n    val target = base / \"target\"\n    fileSystem.atomicMove(source, target)\n    assertEquals(\"hello, world!\", target.readUtf8())\n    assertTrue(source !in fileSystem.list(base))\n    assertTrue(target in fileSystem.list(base))\n  }\n\n  @Test\n  fun atomicMoveDirectory() {\n    val source = base / \"source\"\n    fileSystem.createDirectory(source)\n    val target = base / \"target\"\n    fileSystem.atomicMove(source, target)\n    assertTrue(source !in fileSystem.list(base))\n    assertTrue(target in fileSystem.list(base))\n  }\n\n  @Test\n  fun atomicMoveSourceIsTarget() {\n    val source = base / \"source\"\n    source.writeUtf8(\"hello, world!\")\n    fileSystem.atomicMove(source, source)\n    assertEquals(\"hello, world!\", source.readUtf8())\n    assertTrue(source in fileSystem.list(base))\n  }\n\n  @Test\n  fun atomicMoveClobberExistingFile() {\n    // `java.io` on Windows doesn't allow file renaming if the target already exists.\n    if (isJvmFileSystemOnWindows()) return\n\n    val source = base / \"source\"\n    source.writeUtf8(\"hello, world!\")\n    val target = base / \"target\"\n    target.writeUtf8(\"this file will be clobbered!\")\n    fileSystem.atomicMove(source, target)\n    assertEquals(\"hello, world!\", target.readUtf8())\n    assertTrue(source !in fileSystem.list(base))\n    assertTrue(target in fileSystem.list(base))\n  }\n\n  @Test\n  fun atomicMoveSourceDoesNotExist() {\n    val source = base / \"source\"\n    val target = base / \"target\"\n    if (fileSystem::class.simpleName == \"JvmSystemFileSystem\") {\n      assertFailsWith<IOException> {\n        fileSystem.atomicMove(source, target)\n      }\n    } else {\n      assertFailsWith<FileNotFoundException> {\n        fileSystem.atomicMove(source, target)\n      }\n    }\n  }\n\n  @Test\n  fun atomicMoveSourceIsFileAndTargetIsDirectory() {\n    val source = base / \"source\"\n    source.writeUtf8(\"hello, world!\")\n    val target = base / \"target\"\n    fileSystem.createDirectory(target)\n\n    if (allowAtomicMoveFromFileToDirectory) {\n      fileSystem.atomicMove(source, target)\n      assertEquals(\"hello, world!\", target.readUtf8())\n    } else {\n      val exception = assertFailsWith<IOException> {\n        fileSystem.atomicMove(source, target)\n      }\n      assertTrue(exception !is FileNotFoundException)\n    }\n  }\n\n  @Test\n  fun atomicMoveSourceIsDirectoryAndTargetIsFile() {\n    // `java.io` on Windows doesn't allow file renaming if the target already exists.\n    if (isJvmFileSystemOnWindows()) return\n\n    val source = base / \"source\"\n    fileSystem.createDirectory(source)\n    val target = base / \"target\"\n    target.writeUtf8(\"hello, world!\")\n    try {\n      fileSystem.atomicMove(source, target)\n      assertTrue(allowClobberingEmptyDirectories)\n    } catch (e: IOException) {\n      assertFalse(allowClobberingEmptyDirectories)\n    }\n  }\n\n  @Test\n  fun copyFile() {\n    val source = base / \"source\"\n    source.writeUtf8(\"hello, world!\")\n    val target = base / \"target\"\n    fileSystem.copy(source, target)\n    assertTrue(target in fileSystem.list(base))\n    assertEquals(\"hello, world!\", source.readUtf8())\n    assertEquals(\"hello, world!\", target.readUtf8())\n  }\n\n  @Test\n  fun copySourceDoesNotExist() {\n    val source = base / \"source\"\n    val target = base / \"target\"\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.copy(source, target)\n    }\n    assertFalse(target in fileSystem.list(base))\n  }\n\n  @Test\n  fun copyTargetIsClobbered() {\n    val source = base / \"source\"\n    source.writeUtf8(\"hello, world!\")\n    val target = base / \"target\"\n    target.writeUtf8(\"this file will be clobbered!\")\n    fileSystem.copy(source, target)\n    assertTrue(target in fileSystem.list(base))\n    assertEquals(\"hello, world!\", target.readUtf8())\n  }\n\n  @Test\n  fun deleteFile() {\n    val path = base / \"delete-file\"\n    path.writeUtf8(\"delete me\")\n    fileSystem.delete(path)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteFileMustExist() {\n    val path = base / \"delete-file\"\n    path.writeUtf8(\"delete me\")\n    fileSystem.delete(path, mustExist = true)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteEmptyDirectory() {\n    val path = base / \"delete-empty-directory\"\n    fileSystem.createDirectory(path)\n    fileSystem.delete(path)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteEmptyDirectoryMustExist() {\n    val path = base / \"delete-empty-directory\"\n    fileSystem.createDirectory(path)\n    fileSystem.delete(path, mustExist = true)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteDoesNotExist() {\n    val path = base / \"no-such-file\"\n    fileSystem.delete(path)\n  }\n\n  @Test\n  fun deleteFailsOnNoSuchFileIfMustExist() {\n    val path = base / \"no-such-file\"\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.delete(path, mustExist = true)\n    }\n  }\n\n  @Test\n  fun deleteFailsOnNonEmptyDirectory() {\n    val path = base / \"non-empty-directory\"\n    fileSystem.createDirectory(path)\n    (path / \"file.txt\").writeUtf8(\"inside directory\")\n    val exception = assertFailsWith<IOException> {\n      fileSystem.delete(path)\n    }\n    assertTrue(exception !is FileNotFoundException)\n  }\n\n  @Test\n  fun deleteFailsOnNonEmptyDirectoryMustExist() {\n    val path = base / \"non-empty-directory\"\n    fileSystem.createDirectory(path)\n    (path / \"file.txt\").writeUtf8(\"inside directory\")\n    val exception = assertFailsWith<IOException> {\n      fileSystem.delete(path, mustExist = true)\n    }\n    assertTrue(exception !is FileNotFoundException)\n  }\n\n  @Test\n  fun deleteRecursivelyFile() {\n    val path = base / \"delete-recursively-file\"\n    path.writeUtf8(\"delete me\")\n    fileSystem.deleteRecursively(path)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyFileMustExist() {\n    val path = base / \"delete-recursively-file\"\n    path.writeUtf8(\"delete me\")\n    fileSystem.deleteRecursively(path, mustExist = true)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyEmptyDirectory() {\n    val path = base / \"delete-recursively-empty-directory\"\n    fileSystem.createDirectory(path)\n    fileSystem.deleteRecursively(path)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyEmptyDirectoryMustExist() {\n    val path = base / \"delete-recursively-empty-directory\"\n    fileSystem.createDirectory(path)\n    fileSystem.deleteRecursively(path, mustExist = true)\n    assertTrue(path !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyNoSuchFile() {\n    val path = base / \"no-such-file\"\n    fileSystem.deleteRecursively(path)\n  }\n\n  @Test\n  fun deleteRecursivelyMustExistFailsOnNoSuchFile() {\n    val path = base / \"no-such-file\"\n    assertFailsWith<IOException> {\n      fileSystem.deleteRecursively(path, mustExist = true)\n    }\n  }\n\n  @Test\n  fun deleteRecursivelyNonEmptyDirectory() {\n    val path = base / \"delete-recursively-non-empty-directory\"\n    fileSystem.createDirectory(path)\n    (path / \"file.txt\").writeUtf8(\"inside directory\")\n    fileSystem.deleteRecursively(path)\n    assertTrue(path !in fileSystem.list(base))\n    assertTrue((path / \"file.txt\") !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyNonEmptyDirectoryMustExist() {\n    val path = base / \"delete-recursively-non-empty-directory\"\n    fileSystem.createDirectory(path)\n    (path / \"file.txt\").writeUtf8(\"inside directory\")\n    fileSystem.deleteRecursively(path, mustExist = true)\n    assertTrue(path !in fileSystem.list(base))\n    assertTrue((path / \"file.txt\") !in fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyDeepHierarchy() {\n    fileSystem.createDirectory(base / \"a\")\n    fileSystem.createDirectory(base / \"a\" / \"b\")\n    fileSystem.createDirectory(base / \"a\" / \"b\" / \"c\")\n    (base / \"a\" / \"b\" / \"c\" / \"d.txt\").writeUtf8(\"inside deep hierarchy\")\n    fileSystem.deleteRecursively(base / \"a\")\n    assertEquals(listOf(), fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyDeepHierarchyMustExist() {\n    fileSystem.createDirectory(base / \"a\")\n    fileSystem.createDirectory(base / \"a\" / \"b\")\n    fileSystem.createDirectory(base / \"a\" / \"b\" / \"c\")\n    (base / \"a\" / \"b\" / \"c\" / \"d.txt\").writeUtf8(\"inside deep hierarchy\")\n    fileSystem.deleteRecursively(base / \"a\", mustExist = true)\n    assertEquals(listOf(), fileSystem.list(base))\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkToFileDeletesOnlyThatSymlink() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseB = base / \"b\"\n    baseB.writeUtf8(\"b\")\n    fileSystem.createSymlink(baseA, baseB)\n    fileSystem.deleteRecursively(baseA)\n    assertEquals(\"b\", baseB.readUtf8())\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkToFileDeletesOnlyThatSymlinkMustExist() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseB = base / \"b\"\n    baseB.writeUtf8(\"b\")\n    fileSystem.createSymlink(baseA, baseB)\n    fileSystem.deleteRecursively(baseA, mustExist = true)\n    assertEquals(\"b\", baseB.readUtf8())\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkToDirectoryDeletesOnlyThatSymlink() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseB = base / \"b\"\n    val baseBC = base / \"b\" / \"c\"\n    fileSystem.createDirectory(baseB)\n    baseBC.writeUtf8(\"c\")\n    fileSystem.createSymlink(baseA, baseB)\n    fileSystem.deleteRecursively(baseA)\n    assertEquals(\"c\", baseBC.readUtf8())\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkToDirectoryDeletesOnlyThatSymlinkMustExist() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseB = base / \"b\"\n    val baseBC = base / \"b\" / \"c\"\n    fileSystem.createDirectory(baseB)\n    baseBC.writeUtf8(\"c\")\n    fileSystem.createSymlink(baseA, baseB)\n    fileSystem.deleteRecursively(baseA, mustExist = true)\n    assertEquals(\"c\", baseBC.readUtf8())\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkCycleSucceeds() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAB = baseA / \"b\"\n    val baseAC = baseA / \"c\"\n\n    baseA.createDirectory()\n    baseAB.writeUtf8(\"ab\")\n    fileSystem.createSymlink(baseAC, baseA)\n\n    fileSystem.deleteRecursively(base)\n    assertFalse(fileSystem.exists(base))\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkCycleSucceedsMustExist() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAB = baseA / \"b\"\n    val baseAC = baseA / \"c\"\n\n    baseA.createDirectory()\n    baseAB.writeUtf8(\"ab\")\n    fileSystem.createSymlink(baseAC, baseA)\n\n    fileSystem.deleteRecursively(base, mustExist = true)\n    assertFalse(fileSystem.exists(base))\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkToEnclosingDirectorySucceeds() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    fileSystem.createSymlink(baseA, \".\".toPath())\n\n    fileSystem.deleteRecursively(baseA)\n    assertFalse(fileSystem.exists(baseA))\n    assertTrue(fileSystem.exists(base))\n  }\n\n  @Test\n  fun deleteRecursivelyOnSymlinkToEnclosingDirectorySucceedsMustExist() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    fileSystem.createSymlink(baseA, \".\".toPath())\n\n    fileSystem.deleteRecursively(baseA, mustExist = true)\n    assertFalse(fileSystem.exists(baseA))\n    assertTrue(fileSystem.exists(base))\n  }\n\n  @Test\n  fun fileMetadata() {\n    val minTime = clock.now()\n    val path = base / \"file-metadata\"\n    path.writeUtf8(\"hello, world!\")\n    val maxTime = clock.now()\n\n    val metadata = fileSystem.metadata(path)\n    assertTrue(metadata.isRegularFile)\n    assertFalse(metadata.isDirectory)\n    assertEquals(13, metadata.size)\n    assertInRange(metadata.createdAt, minTime, maxTime)\n    assertInRange(metadata.lastModifiedAt, minTime, maxTime)\n    assertInRange(metadata.lastAccessedAt, minTime, maxTime)\n  }\n\n  /** https://github.com/square/okio/issues/1755 */\n  @Test\n  fun fileMetadataTimestampsAreDistinct() {\n    if (fileSystem.isFakeFileSystem) return\n    if (fileSystem is ForwardingFileSystem) return\n    if (isJimFileSystem()) return\n    if (!fileSystemHasGoodMetadata) return\n\n    // These timestamps are hardcoded in the following Gradle tasks:\n    //   :okio-testing-support:touchAbstractFileSystemTestFilesCreatedAt\n    //   :okio-testing-support:touchAbstractFileSystemTestFilesModifiedAt\n    val createdAt = fromIso8601String(\"2026-01-01T01:01:01Z\")\n    val lastModifiedAt = fromIso8601String(\"2026-02-02T02:02:02Z\")\n\n    val path = okioRoot / \"okio-testing-support\" / \"build/AbstractFileSystemTestFiles/metadata.txt\"\n    val metadata = fileSystem.metadata(path)\n    assertTrue(metadata.isRegularFile)\n    assertInRange(metadata.createdAt, createdAt, createdAt)\n    assertInRange(metadata.lastModifiedAt, lastModifiedAt, lastModifiedAt)\n  }\n\n  @Test\n  fun directoryMetadata() {\n    val minTime = clock.now()\n    val path = base / \"directory-metadata\"\n    fileSystem.createDirectory(path)\n    val maxTime = clock.now()\n\n    val metadata = fileSystem.metadata(path)\n    assertFalse(metadata.isRegularFile)\n    assertTrue(metadata.isDirectory)\n    // Note that the size check is omitted; we'd expect null but the JVM returns values like 64.\n    assertInRange(metadata.createdAt, minTime, maxTime)\n    assertInRange(metadata.lastModifiedAt, minTime, maxTime)\n    assertInRange(metadata.lastAccessedAt, minTime, maxTime)\n  }\n\n  @Test\n  fun fileMetadataWithSpecialCharacterNamedFiles() {\n    val minTime = clock.now()\n    val path = base / \"超サイヤ人\"\n    path.writeUtf8(\"カカロットよ！\")\n    val maxTime = clock.now()\n\n    val metadata = fileSystem.metadata(path)\n    assertTrue(metadata.isRegularFile)\n    assertFalse(metadata.isDirectory)\n    assertEquals(21, metadata.size)\n    assertInRange(metadata.createdAt, minTime, maxTime)\n    assertInRange(metadata.lastModifiedAt, minTime, maxTime)\n    assertInRange(metadata.lastAccessedAt, minTime, maxTime)\n  }\n\n  @Test\n  fun directoryMetadataWithSpecialCharacterNamedFiles() {\n    val minTime = clock.now()\n    val path = base / \"Ἰλιάς\"\n    fileSystem.createDirectory(path)\n    val maxTime = clock.now()\n\n    val metadata = fileSystem.metadata(path)\n    assertFalse(metadata.isRegularFile)\n    assertTrue(metadata.isDirectory)\n    // Note that the size check is omitted; we'd expect null but the JVM returns values like 64.\n    assertInRange(metadata.createdAt, minTime, maxTime)\n    assertInRange(metadata.lastModifiedAt, minTime, maxTime)\n    assertInRange(metadata.lastAccessedAt, minTime, maxTime)\n  }\n\n  @Test\n  fun absentMetadataOrNull() {\n    val path = base / \"no-such-file\"\n    assertNull(fileSystem.metadataOrNull(path))\n  }\n\n  @Test\n  fun absentParentDirectoryMetadataOrNull() {\n    val path = base / \"no-such-directory\" / \"no-such-file\"\n    assertNull(fileSystem.metadataOrNull(path))\n  }\n\n  @Test\n  fun parentDirectoryIsFileMetadataOrNull() {\n    val parent = base / \"regular-file\"\n    val path = parent / \"no-such-file\"\n    parent.writeUtf8(\"just a regular file\")\n    // This returns null on Windows and throws IOException on other platforms.\n    try {\n      assertNull(fileSystem.metadataOrNull(path))\n    } catch (e: IOException) {\n      // Also okay.\n    }\n  }\n\n  @Test\n  @Ignore\n  fun inaccessibleMetadata() {\n    // TODO(swankjesse): configure a test directory in CI that exists, but that this process doesn't\n    //     have permission to read metadata of. Perhaps a file in another user's /home directory?\n  }\n\n  @Test\n  fun absentMetadata() {\n    val path = base / \"no-such-file\"\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.metadata(path)\n    }\n  }\n\n  @Test\n  fun fileExists() {\n    val path = base / \"file-exists\"\n    assertFalse(fileSystem.exists(path))\n    path.writeUtf8(\"hello, world!\")\n    assertTrue(fileSystem.exists(path))\n  }\n\n  @Test\n  fun directoryExists() {\n    val path = base / \"directory-exists\"\n    assertFalse(fileSystem.exists(path))\n    fileSystem.createDirectory(path)\n    assertTrue(fileSystem.exists(path))\n  }\n\n  @Test\n  fun deleteOpenForWritingFailsOnWindows() {\n    val file = base / \"file.txt\"\n    expectIOExceptionOnWindows(exceptJs = true) {\n      fileSystem.sink(file).use {\n        fileSystem.delete(file)\n      }\n    }\n  }\n\n  @Test\n  fun deleteOpenForReadingFailsOnWindows() {\n    val file = base / \"file.txt\"\n    file.writeUtf8(\"abc\")\n    expectIOExceptionOnWindows(exceptJs = true) {\n      fileSystem.source(file).use {\n        fileSystem.delete(file)\n      }\n    }\n  }\n\n  @Test\n  fun renameSourceIsOpenFailsOnWindows() {\n    val from = base / \"from.txt\"\n    val to = base / \"to.txt\"\n    from.writeUtf8(\"source file\")\n    to.writeUtf8(\"target file\")\n    expectIOExceptionOnWindows(exceptJs = true) {\n      fileSystem.source(from).use {\n        fileSystem.atomicMove(from, to)\n      }\n    }\n  }\n\n  @Test\n  fun renameTargetIsOpenFailsOnWindows() {\n    val from = base / \"from.txt\"\n    val to = base / \"to.txt\"\n    from.writeUtf8(\"source file\")\n    to.writeUtf8(\"target file\")\n\n    val expectCrash = !allowRenameWhenTargetIsOpen\n    try {\n      fileSystem.source(to).use {\n        fileSystem.atomicMove(from, to)\n      }\n      assertFalse(expectCrash)\n    } catch (_: IOException) {\n      assertTrue(expectCrash)\n    }\n  }\n\n  @Test\n  fun deleteContentsOfParentOfFileOpenForReadingFailsOnWindows() {\n    val parentA = (base / \"a\")\n    fileSystem.createDirectory(parentA)\n    val parentAB = parentA / \"b\"\n    fileSystem.createDirectory(parentAB)\n    val parentABC = parentAB / \"c\"\n    fileSystem.createDirectory(parentABC)\n    val file = parentABC / \"file.txt\"\n    file.writeUtf8(\"child file\")\n    expectIOExceptionOnWindows {\n      fileSystem.source(file).use {\n        fileSystem.delete(file)\n        fileSystem.delete(parentABC)\n        fileSystem.delete(parentAB)\n        fileSystem.delete(parentA)\n      }\n    }\n  }\n\n  @Test fun fileHandleWriteAndRead() {\n    val path = base / \"file-handle-write-and-read\"\n    fileSystem.openReadWrite(path).use { handle ->\n\n      handle.sink().buffer().use { sink ->\n        sink.writeUtf8(\"abcdefghijklmnop\")\n      }\n\n      handle.source().buffer().use { source ->\n        assertEquals(\"abcde\", source.readUtf8(5))\n        assertEquals(\"fghijklmnop\", source.readUtf8())\n      }\n    }\n  }\n\n  @Test fun fileHandleWriteAndOverwrite() {\n    val path = base / \"file-handle-write-and-overwrite\"\n    fileSystem.openReadWrite(path).use { handle ->\n\n      handle.sink().buffer().use { sink ->\n        sink.writeUtf8(\"abcdefghij\")\n      }\n\n      handle.sink(fileOffset = handle.size() - 3).buffer().use { sink ->\n        sink.writeUtf8(\"HIJKLMNOP\")\n      }\n\n      handle.source().buffer().use { source ->\n        assertEquals(\"abcdefgHIJKLMNOP\", source.readUtf8())\n      }\n    }\n  }\n\n  @Test fun fileHandleWriteBeyondEnd() {\n    val path = base / \"file-handle-write-beyond-end\"\n    fileSystem.openReadWrite(path).use { handle ->\n\n      handle.sink(fileOffset = 10).buffer().use { sink ->\n        sink.writeUtf8(\"klmnop\")\n      }\n\n      handle.source().buffer().use { source ->\n        assertEquals(\"00000000000000000000\", source.readByteString(10).hex())\n        assertEquals(\"klmnop\", source.readUtf8())\n      }\n    }\n  }\n\n  @Test fun fileHandleResizeSmaller() {\n    val path = base / \"file-handle-resize-smaller\"\n    fileSystem.openReadWrite(path).use { handle ->\n\n      handle.sink().buffer().use { sink ->\n        sink.writeUtf8(\"abcdefghijklmnop\")\n      }\n\n      handle.resize(10)\n\n      handle.source().buffer().use { source ->\n        assertEquals(\"abcdefghij\", source.readUtf8())\n      }\n    }\n  }\n\n  @Test fun fileHandleResizeLarger() {\n    val path = base / \"file-handle-resize-larger\"\n    fileSystem.openReadWrite(path).use { handle ->\n\n      handle.sink().buffer().use { sink ->\n        sink.writeUtf8(\"abcde\")\n      }\n\n      handle.resize(15)\n\n      handle.source().buffer().use { source ->\n        assertEquals(\"abcde\", source.readUtf8(5))\n        assertEquals(\"00000000000000000000\", source.readByteString().hex())\n      }\n    }\n  }\n\n  @Test fun fileHandleFlush() {\n    if (windowsLimitations) return // Open for reading and writing simultaneously.\n\n    val path = base / \"file-handle-flush\"\n    fileSystem.openReadWrite(path).use { handleA ->\n      handleA.sink().buffer().use { sink ->\n        sink.writeUtf8(\"abcde\")\n      }\n      handleA.flush()\n\n      fileSystem.openReadWrite(path).use { handleB ->\n        handleB.source().buffer().use { source ->\n          assertEquals(\"abcde\", source.readUtf8())\n        }\n      }\n    }\n  }\n\n  @Test fun fileHandleLargeBufferedWriteAndRead() {\n    if (isBrowser()) return // This test errors on browsers in CI.\n\n    val data = randomBytes(1024 * 1024 * 8)\n\n    val path = base / \"file-handle-large-buffered-write-and-read\"\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.sink().buffer().use { sink ->\n        sink.write(data)\n      }\n    }\n\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.source().buffer().use { source ->\n        assertEquals(data, source.readByteString())\n      }\n    }\n  }\n\n  @Test fun fileHandleLargeArrayWriteAndRead() {\n    if (isBrowser()) return // This test errors on browsers in CI.\n\n    val path = base / \"file-handle-large-array-write-and-read\"\n\n    val writtenBytes = randomBytes(1024 * 1024 * 8)\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.write(0, writtenBytes.toByteArray(), 0, writtenBytes.size)\n    }\n\n    val readBytes = fileSystem.openReadWrite(path).use { handle ->\n      val byteArray = ByteArray(writtenBytes.size)\n      handle.read(0, byteArray, 0, byteArray.size)\n      return@use byteArray.toByteString(0, byteArray.size) // Parameters necessary for issue 910.\n    }\n\n    assertEquals(writtenBytes, readBytes)\n  }\n\n  @Test fun fileHandleEmptyArrayWriteAndRead() {\n    val path = base / \"file-handle-empty-array-write-and-read\"\n\n    val writtenBytes = ByteArray(0)\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.write(0, writtenBytes, 0, writtenBytes.size)\n    }\n\n    val readBytes = fileSystem.openReadWrite(path).use { handle ->\n      val byteArray = ByteArray(writtenBytes.size)\n      handle.read(0, byteArray, 0, byteArray.size)\n      return@use byteArray\n    }\n\n    assertContentEquals(writtenBytes, readBytes)\n  }\n\n  @Test fun fileHandleSinkPosition() {\n    val path = base / \"file-handle-sink-position\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.sink().use { sink ->\n        sink.write(Buffer().writeUtf8(\"abcde\"), 5)\n        assertEquals(5, handle.position(sink))\n        sink.write(Buffer().writeUtf8(\"fghijklmno\"), 10)\n        assertEquals(15, handle.position(sink))\n      }\n\n      handle.sink(200).use { sink ->\n        sink.write(Buffer().writeUtf8(\"abcde\"), 5)\n        assertEquals(205, handle.position(sink))\n        sink.write(Buffer().writeUtf8(\"fghijklmno\"), 10)\n        assertEquals(215, handle.position(sink))\n      }\n    }\n  }\n\n  @Test fun fileHandleBufferedSinkPosition() {\n    val path = base / \"file-handle-buffered-sink-position\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.sink().buffer().use { sink ->\n        sink.writeUtf8(\"abcde\")\n        assertEquals(5, handle.position(sink))\n        sink.writeUtf8(\"fghijklmno\")\n        assertEquals(15, handle.position(sink))\n      }\n\n      handle.sink(200).buffer().use { sink ->\n        sink.writeUtf8(\"abcde\")\n        assertEquals(205, handle.position(sink))\n        sink.writeUtf8(\"fghijklmno\")\n        assertEquals(215, handle.position(sink))\n      }\n    }\n  }\n\n  @Test fun fileHandleSinkReposition() {\n    val path = base / \"file-handle-sink-reposition\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.sink().use { sink ->\n        sink.write(Buffer().writeUtf8(\"abcdefghij\"), 10)\n        handle.reposition(sink, 5)\n        assertEquals(5, handle.position(sink))\n        sink.write(Buffer().writeUtf8(\"KLM\"), 3)\n        assertEquals(8, handle.position(sink))\n\n        handle.reposition(sink, 200)\n        sink.write(Buffer().writeUtf8(\"ABCDEFGHIJ\"), 10)\n        handle.reposition(sink, 205)\n        assertEquals(205, handle.position(sink))\n        sink.write(Buffer().writeUtf8(\"klm\"), 3)\n        assertEquals(208, handle.position(sink))\n      }\n\n      Buffer().also {\n        handle.read(fileOffset = 0, sink = it, byteCount = 10)\n        assertEquals(\"abcdeKLMij\", it.readUtf8())\n      }\n\n      Buffer().also {\n        handle.read(fileOffset = 200, sink = it, byteCount = 15)\n        assertEquals(\"ABCDEklmIJ\", it.readUtf8())\n      }\n    }\n  }\n\n  @Test fun fileHandleBufferedSinkReposition() {\n    val path = base / \"file-handle-buffered-sink-reposition\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.sink().buffer().use { sink ->\n        sink.write(Buffer().writeUtf8(\"abcdefghij\"), 10)\n        handle.reposition(sink, 5)\n        assertEquals(5, handle.position(sink))\n        sink.write(Buffer().writeUtf8(\"KLM\"), 3)\n        assertEquals(8, handle.position(sink))\n\n        handle.reposition(sink, 200)\n        sink.write(Buffer().writeUtf8(\"ABCDEFGHIJ\"), 10)\n        handle.reposition(sink, 205)\n        assertEquals(205, handle.position(sink))\n        sink.write(Buffer().writeUtf8(\"klm\"), 3)\n        assertEquals(208, handle.position(sink))\n      }\n\n      Buffer().also {\n        handle.read(fileOffset = 0, sink = it, byteCount = 10)\n        assertEquals(\"abcdeKLMij\", it.readUtf8())\n      }\n\n      Buffer().also {\n        handle.read(fileOffset = 200, sink = it, byteCount = 15)\n        assertEquals(\"ABCDEklmIJ\", it.readUtf8())\n      }\n    }\n  }\n\n  @Test fun fileHandleSourceHappyPath() {\n    val path = base / \"file-handle-source\"\n    fileSystem.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n\n    fileSystem.openReadOnly(path).use { handle ->\n      assertEquals(16L, handle.size())\n      val buffer = Buffer()\n\n      handle.source().use { source ->\n        assertEquals(0L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(\"abcd\", buffer.readUtf8())\n        assertEquals(4L, handle.position(source))\n      }\n\n      handle.source(fileOffset = 8L).use { source ->\n        assertEquals(8L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(\"ijkl\", buffer.readUtf8())\n        assertEquals(12L, handle.position(source))\n      }\n\n      handle.source(fileOffset = 16L).use { source ->\n        assertEquals(16L, handle.position(source))\n        assertEquals(-1L, source.read(buffer, 4L))\n        assertEquals(\"\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n    }\n  }\n\n  @Test fun fileHandleSourceReposition() {\n    val path = base / \"file-handle-source-reposition\"\n    fileSystem.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n\n    fileSystem.openReadOnly(path).use { handle ->\n      assertEquals(16L, handle.size())\n      val buffer = Buffer()\n\n      handle.source().use { source ->\n        handle.reposition(source, 12L)\n        assertEquals(12L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(\"mnop\", buffer.readUtf8())\n        assertEquals(-1L, source.read(buffer, 4L))\n        assertEquals(\"\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n\n        handle.reposition(source, 0L)\n        assertEquals(0L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(\"abcd\", buffer.readUtf8())\n        assertEquals(4L, handle.position(source))\n\n        handle.reposition(source, 8L)\n        assertEquals(8L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(\"ijkl\", buffer.readUtf8())\n        assertEquals(12L, handle.position(source))\n\n        handle.reposition(source, 16L)\n        assertEquals(16L, handle.position(source))\n        assertEquals(-1L, source.read(buffer, 4L))\n        assertEquals(\"\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n    }\n  }\n\n  @Test fun fileHandleBufferedSourceReposition() {\n    val path = base / \"file-handle-buffered-source-reposition\"\n    fileSystem.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n\n    fileSystem.openReadOnly(path).use { handle ->\n      assertEquals(16L, handle.size())\n      val buffer = Buffer()\n\n      handle.source().buffer().use { source ->\n        handle.reposition(source, 12L)\n        assertEquals(0L, source.buffer.size)\n        assertEquals(12L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(0L, source.buffer.size)\n        assertEquals(\"mnop\", buffer.readUtf8())\n        assertEquals(-1L, source.read(buffer, 4L))\n        assertEquals(\"\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n\n        handle.reposition(source, 0L)\n        assertEquals(0L, source.buffer.size)\n        assertEquals(0L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(12L, source.buffer.size) // Buffered bytes accumulated.\n        assertEquals(\"abcd\", buffer.readUtf8())\n        assertEquals(4L, handle.position(source))\n\n        handle.reposition(source, 8L)\n        assertEquals(8L, source.buffer.size) // Buffered bytes preserved.\n        assertEquals(8L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(4L, source.buffer.size)\n        assertEquals(\"ijkl\", buffer.readUtf8())\n        assertEquals(12L, handle.position(source))\n\n        handle.reposition(source, 16L)\n        assertEquals(0L, source.buffer.size)\n        assertEquals(16L, handle.position(source))\n        assertEquals(-1L, source.read(buffer, 4L))\n        assertEquals(0L, source.buffer.size)\n        assertEquals(\"\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n    }\n  }\n\n  @Test fun fileHandleSourceSeekBackwards() {\n    val path = base / \"file-handle-source-backwards\"\n    fileSystem.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n    fileSystem.openReadOnly(path).use { handle ->\n      assertEquals(16L, handle.size())\n      val buffer = Buffer()\n\n      handle.source().use { source ->\n        assertEquals(0L, handle.position(source))\n        assertEquals(16L, source.read(buffer, 16L))\n        assertEquals(\"abcdefghijklmnop\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n\n      handle.source(0L).use { source ->\n        assertEquals(0L, handle.position(source))\n        assertEquals(16L, source.read(buffer, 16L))\n        assertEquals(\"abcdefghijklmnop\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n    }\n  }\n\n  @Test fun bufferedFileHandleSourceHappyPath() {\n    val path = base / \"file-handle-source\"\n    fileSystem.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n\n    fileSystem.openReadOnly(path).use { handle ->\n      assertEquals(16L, handle.size())\n      val buffer = Buffer()\n\n      handle.source().buffer().use { source ->\n        assertEquals(0L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(\"abcd\", buffer.readUtf8())\n        assertEquals(4L, handle.position(source))\n      }\n\n      handle.source(fileOffset = 8L).buffer().use { source ->\n        assertEquals(8L, handle.position(source))\n        assertEquals(4L, source.read(buffer, 4L))\n        assertEquals(\"ijkl\", buffer.readUtf8())\n        assertEquals(12L, handle.position(source))\n      }\n\n      handle.source(fileOffset = 16L).buffer().use { source ->\n        assertEquals(16L, handle.position(source))\n        assertEquals(-1L, source.read(buffer, 4L))\n        assertEquals(\"\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n    }\n  }\n\n  @Test fun bufferedFileHandleSourceSeekBackwards() {\n    val path = base / \"file-handle-source-backwards\"\n    fileSystem.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n    fileSystem.openReadOnly(path).use { handle ->\n      assertEquals(16L, handle.size())\n      val buffer = Buffer()\n\n      handle.source().buffer().use { source ->\n        assertEquals(0L, handle.position(source))\n        assertEquals(16L, source.read(buffer, 16L))\n        assertEquals(\"abcdefghijklmnop\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n\n      handle.source(0L).buffer().use { source ->\n        assertEquals(0L, handle.position(source))\n        assertEquals(16L, source.read(buffer, 16L))\n        assertEquals(\"abcdefghijklmnop\", buffer.readUtf8())\n        assertEquals(16L, handle.position(source))\n      }\n    }\n  }\n\n  @Test fun openReadOnlyThrowsOnAttemptToWrite() {\n    val path = base / \"file-handle-source\"\n    fileSystem.write(path) {\n      writeUtf8(\"abcdefghijklmnop\")\n    }\n\n    fileSystem.openReadOnly(path).use { handle ->\n      try {\n        handle.sink()\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n\n      try {\n        handle.flush()\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n\n      try {\n        handle.resize(0L)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n\n      try {\n        handle.write(0L, Buffer().writeUtf8(\"hello\"), 5L)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n    }\n  }\n\n  @Test fun openReadOnlyFailsOnAbsentFile() {\n    val path = base / \"file-handle-source\"\n\n    try {\n      fileSystem.openReadOnly(path)\n      fail()\n    } catch (_: IOException) {\n    }\n  }\n\n  @Test fun openReadWriteCreatesAbsentFile() {\n    val path = base / \"file-handle-source\"\n\n    fileSystem.openReadWrite(path).use {\n    }\n\n    assertEquals(\"\", path.readUtf8())\n  }\n\n  @Test fun openReadWriteCreatesAbsentFileMustCreate() {\n    val path = base / \"file-handle-source\"\n\n    fileSystem.openReadWrite(path, mustCreate = true).use {\n    }\n\n    assertEquals(\"\", path.readUtf8())\n  }\n\n  @Test fun openReadWriteMustCreateThrowsIfAlreadyExists() {\n    val path = base / \"file-handle-source\"\n    path.writeUtf8(\"First!\")\n\n    assertFailsWith<IOException> {\n      fileSystem.openReadWrite(path, mustCreate = true).use {}\n    }\n  }\n\n  @Test fun openReadWriteMustExist() {\n    val path = base / \"file-handle-source\"\n    path.writeUtf8(\"one\")\n\n    fileSystem.openReadWrite(path, mustExist = true).use { handle ->\n      handle.write(3L, Buffer().writeUtf8(\" two\"), 4L)\n    }\n\n    assertEquals(\"one two\", path.readUtf8())\n  }\n\n  @Test fun openReadWriteMustExistThrowsIfAbsent() {\n    val path = base / \"file-handle-source\"\n\n    assertFailsWith<IOException> {\n      fileSystem.openReadWrite(path, mustExist = true).use {}\n    }\n  }\n\n  @Test fun openReadWriteThrowsIfBothMustCreateAndMustExist() {\n    val path = base / \"file-handle-source\"\n\n    assertFailsWith<IllegalArgumentException> {\n      fileSystem.openReadWrite(path, mustCreate = true, mustExist = true).use {}\n    }\n  }\n\n  @Test fun sinkPositionFailsAfterClose() {\n    val path = base / \"sink-position-fails-after-close\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      val sink = handle.sink()\n      sink.close()\n      try {\n        handle.position(sink)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n      try {\n        handle.position(sink.buffer())\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n    }\n  }\n\n  @Test fun sinkRepositionFailsAfterClose() {\n    val path = base / \"sink-reposition-fails-after-close\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      val sink = handle.sink()\n      sink.close()\n      try {\n        handle.reposition(sink, 1L)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n      try {\n        handle.reposition(sink.buffer(), 1L)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n    }\n  }\n\n  @Test fun sourcePositionFailsAfterClose() {\n    val path = base / \"source-position-fails-after-close\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      val source = handle.source()\n      source.close()\n      try {\n        handle.position(source)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n      try {\n        handle.position(source.buffer())\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n    }\n  }\n\n  @Test fun sourceRepositionFailsAfterClose() {\n    val path = base / \"source-reposition-fails-after-close\"\n\n    fileSystem.openReadWrite(path).use { handle ->\n      val source = handle.source()\n      source.close()\n      try {\n        handle.reposition(source, 1L)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n      try {\n        handle.reposition(source.buffer(), 1L)\n        fail()\n      } catch (_: IllegalStateException) {\n      }\n    }\n  }\n\n  @Test fun sizeFailsAfterClose() {\n    val path = base / \"size-fails-after-close\"\n\n    val handle = fileSystem.openReadWrite(path)\n    handle.close()\n    try {\n      handle.size()\n      fail()\n    } catch (_: IllegalStateException) {\n    }\n  }\n\n  @Test\n  fun absoluteSymlinkMetadata() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n\n    val minTime = clock.now()\n    fileSystem.createSymlink(source, target)\n    val maxTime = clock.now()\n\n    val sourceMetadata = fileSystem.metadata(source)\n    // Okio's WasiFileSystem only creates relative symlinks.\n    assertEquals(\n      when {\n        isWasiFileSystem -> target.relativeTo(source.parent!!)\n        else -> target\n      },\n      sourceMetadata.symlinkTarget,\n    )\n    assertInRange(sourceMetadata.createdAt, minTime, maxTime)\n  }\n\n  @Test\n  fun relativeSymlinkMetadata() {\n    if (!supportsSymlink()) return\n\n    val target = \"symlink-target\".toPath()\n    val source = base / \"symlink-source\"\n\n    val minTime = clock.now()\n    fileSystem.createSymlink(source, target)\n    val maxTime = clock.now()\n\n    val sourceMetadata = fileSystem.metadata(source)\n    assertEquals(target, sourceMetadata.symlinkTarget)\n    assertInRange(sourceMetadata.createdAt, minTime, maxTime)\n  }\n\n  @Test\n  fun createSymlinkSourceAlreadyExists() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    source.writeUtf8(\"hello\")\n    val exception = assertFailsWith<IOException> {\n      fileSystem.createSymlink(source, target)\n    }\n    assertTrue(exception !is FileNotFoundException)\n  }\n\n  @Test\n  fun createSymlinkParentDirectoryDoesNotExist() {\n    if (!supportsSymlink()) return\n\n    val source = base / \"no-such-directory\" / \"source\"\n    val target = base / \"target\"\n    val e = assertFailsWith<IOException> {\n      fileSystem.createSymlink(source, target)\n    }\n    assertTrue(e !is FileNotFoundException)\n  }\n\n  @Test\n  fun openSymlinkSource() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    fileSystem.createSymlink(source, target)\n    target.writeUtf8(\"I am the target file\")\n    val sourceContent = fileSystem.source(source).buffer().use { it.readUtf8() }\n    assertEquals(\"I am the target file\", sourceContent)\n  }\n\n  @Test\n  fun openSymlinkSink() {\n    if (!supportsSymlink()) return\n    if (isJimFileSystem()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    fileSystem.createSymlink(source, target)\n    fileSystem.sink(source).buffer().use {\n      it.writeUtf8(\"This writes to the the source file\")\n    }\n    assertEquals(\"This writes to the the source file\", target.readUtf8())\n  }\n\n  @Test\n  fun openFileWithDirectorySymlink() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAA = base / \"a\" / \"a\"\n    val baseB = base / \"b\"\n    val baseBA = base / \"b\" / \"a\"\n    fileSystem.createDirectory(baseA)\n    baseAA.writeUtf8(\"aa\")\n    fileSystem.createSymlink(baseB, baseA)\n    assertEquals(\"aa\", baseAA.readUtf8())\n    assertEquals(\"aa\", baseBA.readUtf8())\n  }\n\n  @Test\n  fun openSymlinkFileHandle() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    fileSystem.createSymlink(source, target)\n    target.writeUtf8(\"I am the target file\")\n    val sourceContent = fileSystem.openReadOnly(source).use { fileHandle ->\n      fileHandle.source().buffer().use { it.readUtf8() }\n    }\n    assertEquals(\"I am the target file\", sourceContent)\n  }\n\n  @Test\n  fun listSymlinkDirectory() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAA = base / \"a\" / \"a\"\n    val baseAB = base / \"a\" / \"b\"\n    val baseB = base / \"b\"\n    val baseBA = base / \"b\" / \"a\"\n    val baseBB = base / \"b\" / \"b\"\n    fileSystem.createDirectory(baseA)\n    baseAA.writeUtf8(\"aa\")\n    baseAB.writeUtf8(\"ab\")\n    fileSystem.createSymlink(baseB, baseA)\n    assertEquals(listOf(baseBA, baseBB), fileSystem.list(baseB))\n  }\n\n  @Test\n  fun symlinkFileLastAccessedAt() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    target.writeUtf8(\"a\")\n    fileSystem.createSymlink(source, target)\n    tryAdvanceTime()\n    val minTime = clock.now()\n    assertEquals(\"a\", source.readUtf8())\n    val maxTime = clock.now()\n    assertInRange(fileSystem.metadata(source).lastAccessedAt, minTime, maxTime)\n  }\n\n  @Test\n  fun symlinkDirectoryLastAccessedAt() {\n    if (!supportsSymlink()) return\n\n    val baseA = base / \"a\"\n    val baseAA = base / \"a\" / \"a\"\n    val baseB = base / \"b\"\n    val baseBA = base / \"b\" / \"a\"\n    fileSystem.createDirectory(baseA)\n    baseAA.writeUtf8(\"aa\")\n    fileSystem.createSymlink(baseB, baseA)\n    tryAdvanceTime()\n    val minTime = clock.now()\n    assertEquals(\"aa\", baseBA.readUtf8())\n    val maxTime = clock.now()\n    assertInRange(fileSystem.metadata(baseB).lastAccessedAt, minTime, maxTime)\n  }\n\n  @Test\n  fun deleteSymlinkDoesntDeleteTargetFile() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source = base / \"symlink-source\"\n    target.writeUtf8(\"I am the target file\")\n    fileSystem.createSymlink(source, target)\n    fileSystem.delete(source)\n    assertEquals(\"I am the target file\", target.readUtf8())\n  }\n\n  @Test\n  fun moveSymlinkDoesntMoveTargetFile() {\n    if (!supportsSymlink()) return\n\n    val target = base / \"symlink-target\"\n    val source1 = base / \"symlink-source-1\"\n    val source2 = base / \"symlink-source-2\"\n    target.writeUtf8(\"I am the target file\")\n    fileSystem.createSymlink(source1, target)\n    fileSystem.atomicMove(source1, source2)\n    assertEquals(\"I am the target file\", target.readUtf8())\n    assertEquals(\"I am the target file\", source2.readUtf8())\n    // Okio's WasiFileSystem only creates relative symlinks.\n    assertEquals(\n      when {\n        isWasiFileSystem -> target.relativeTo(source1.parent!!)\n        else -> target\n      },\n      fileSystem.metadata(source2).symlinkTarget,\n    )\n  }\n\n  @Test\n  fun symlinkCanBeRelative() {\n    if (!supportsSymlink()) return\n\n    val relativeTarget = \"symlink-target\".toPath()\n    val absoluteTarget = base / relativeTarget\n    val source = base / \"symlink-source\"\n    absoluteTarget.writeUtf8(\"I am the target file\")\n    fileSystem.createSymlink(source, relativeTarget)\n    assertEquals(\"I am the target file\", source.readUtf8())\n  }\n\n  @Test\n  fun symlinkCanBeRelativeWithDotDots() {\n    if (!supportsSymlink()) return\n\n    val relativeTarget = \"../b/symlink-target\".toPath()\n    val absoluteTarget = base / \"b\" / \"symlink-target\"\n    val absoluteSource = base / \"a\" / \"symlink-source\"\n    fileSystem.createDirectory(absoluteSource.parent!!)\n    fileSystem.createDirectory(absoluteTarget.parent!!)\n    absoluteTarget.writeUtf8(\"I am the target file\")\n    fileSystem.createSymlink(absoluteSource, relativeTarget)\n    assertEquals(\"I am the target file\", absoluteSource.readUtf8())\n  }\n\n  @Test\n  fun followingRecursiveSymlinksIsOkay() {\n    if (!supportsSymlink()) return\n\n    val pathA = base / \"symlink-a\"\n    val pathB = base / \"symlink-b\"\n    val pathC = base / \"symlink-c\"\n    val target = base / \"symlink-target\"\n    fileSystem.createSymlink(pathA, pathB)\n    fileSystem.createSymlink(pathB, pathC)\n    fileSystem.createSymlink(pathC, target)\n    target.writeUtf8(\"I am the target file\")\n    assertEquals(\"I am the target file\", pathC.readUtf8())\n    assertEquals(\"I am the target file\", pathB.readUtf8())\n    assertEquals(\"I am the target file\", pathA.readUtf8())\n  }\n\n  @Test\n  fun symlinkCycle() {\n    if (!supportsSymlink()) return\n\n    val pathA = base / \"symlink-a\"\n    val pathB = base / \"symlink-b\"\n    fileSystem.createSymlink(pathA, pathB)\n    fileSystem.createSymlink(pathB, pathA)\n    assertFailsWith<IOException> {\n      pathB.writeUtf8(\"This should not work\")\n    }\n    assertFailsWith<IOException> {\n      pathB.readUtf8()\n    }\n  }\n\n  @Test\n  fun readAfterFileSystemClose() {\n    val path = base / \"file\"\n\n    path.writeUtf8(\"hello, world!\")\n\n    when (closeBehavior) {\n      CloseBehavior.Closes -> {\n        fileSystem.close()\n\n        assertFailsWith<IllegalStateException> {\n          fileSystem.canonicalize(path)\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.exists(path)\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.metadata(path)\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.openReadOnly(path)\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.source(path)\n        }\n      }\n\n      CloseBehavior.DoesNothing -> {\n        fileSystem.close()\n        fileSystem.canonicalize(path)\n        fileSystem.exists(path)\n        fileSystem.metadata(path)\n        fileSystem.openReadOnly(path).use {\n        }\n        fileSystem.source(path).use {\n        }\n      }\n\n      CloseBehavior.Unsupported -> {\n        assertFailsWith<UnsupportedOperationException> {\n          fileSystem.close()\n        }\n      }\n    }\n  }\n\n  @Test\n  fun writeAfterFileSystemClose() {\n    val path = base / \"file\"\n\n    when (closeBehavior) {\n      CloseBehavior.Closes -> {\n        fileSystem.close()\n\n        assertFailsWith<IllegalStateException> {\n          fileSystem.appendingSink(path)\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.atomicMove(path, base / \"file2\")\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.createDirectory(base / \"directory\")\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.delete(path)\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.openReadWrite(path)\n        }\n        assertFailsWith<IllegalStateException> {\n          fileSystem.sink(path)\n        }\n        if (supportsSymlink()) {\n          assertFailsWith<IllegalStateException> {\n            fileSystem.createSymlink(base / \"symlink\", base)\n          }\n        }\n      }\n\n      CloseBehavior.DoesNothing -> {\n        fileSystem.close()\n\n        fileSystem.appendingSink(path).use {\n        }\n        fileSystem.atomicMove(path, base / \"file2\")\n        fileSystem.createDirectory(base / \"directory\")\n        fileSystem.delete(path)\n        fileSystem.sink(path).use {\n        }\n        fileSystem.openReadWrite(path).use {\n        }\n        if (supportsSymlink()) {\n          fileSystem.createSymlink(base / \"symlink\", base)\n        }\n      }\n\n      CloseBehavior.Unsupported -> {\n        assertFailsWith<UnsupportedOperationException> {\n          fileSystem.close()\n        }\n      }\n    }\n  }\n\n  protected fun supportsSymlink(): Boolean {\n    if (fileSystem.isFakeFileSystem) return fileSystem.allowSymlinks\n    if (windowsLimitations) return false\n    return when (fileSystem::class.simpleName) {\n      \"JvmSystemFileSystem\",\n      -> false\n      else -> true\n    }\n  }\n\n  private fun expectIOExceptionOnWindows(\n    exceptJs: Boolean = false,\n    block: () -> Unit,\n  ) {\n    val expectCrash = windowsLimitations && (!isNodeJsFileSystem || !exceptJs)\n    try {\n      block()\n      assertFalse(expectCrash)\n    } catch (_: IOException) {\n      assertTrue(expectCrash)\n    }\n  }\n\n  fun Path.readUtf8(): String {\n    return fileSystem.source(this).buffer().use {\n      it.readUtf8()\n    }\n  }\n\n  fun Path.writeUtf8(string: String) {\n    fileSystem.sink(this).buffer().use {\n      it.writeUtf8(string)\n    }\n  }\n\n  fun Path.createDirectory() {\n    fileSystem.createDirectory(this)\n  }\n\n  /**\n   * Returns the earliest file system time that could be recorded for an event occurring at this\n   * instant. This truncates fractional seconds because most host file systems do not use precise\n   * timestamps for file metadata.\n   *\n   * It also pads the result by 200 milliseconds because the host and file system may use different\n   * clocks, allowing the time on the CPU to drift ahead of the time on the file system.\n   */\n  private fun Instant.minFileSystemTime(): Instant {\n    val paddedInstant = minus(200.milliseconds)\n    return Instant.fromEpochSeconds(paddedInstant.epochSeconds)\n  }\n\n  /**\n   * Returns the latest file system time that could be recorded for an event occurring at this\n   * instant. This adds 2 seconds and truncates fractional seconds because file systems may defer\n   * assigning the timestamp.\n   *\n   * It also pads the result by 200 milliseconds because the host and file system may use different\n   * clocks, allowing the time on the CPU to drift behind the time on the file system.\n   *\n   * https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times\n   */\n  private fun Instant.maxFileSystemTime(): Instant {\n    val paddedInstant = plus(200.milliseconds)\n    return Instant.fromEpochSeconds(paddedInstant.plus(2.seconds).epochSeconds)\n  }\n\n  /**\n   * Attempt to advance the clock so that any already-issued timestamps will not collide with\n   * timestamps yet to be issued.\n   */\n  private fun tryAdvanceTime() {\n    if (clock is FakeClock) clock.sleep(1.minutes)\n  }\n\n  private fun assertInRange(sampled: Instant?, minTime: Instant, maxTime: Instant) {\n    if (sampled == null) return\n    val minFsTime = minTime.minFileSystemTime()\n    val maxFsTime = maxTime.maxFileSystemTime()\n    assertTrue(\"expected $sampled in $minFsTime..$maxFsTime (relaxed from $minTime..$maxTime)\") {\n      sampled in minFsTime..maxFsTime\n    }\n  }\n\n  private fun isJvmFileSystemOnWindows(): Boolean {\n    return windowsLimitations && fileSystem::class.simpleName == \"JvmSystemFileSystem\"\n  }\n\n  private fun isJimFileSystem(): Boolean {\n    return \"JimfsFileSystem\" in fileSystem.toString()\n  }\n\n  private fun isNodeJsFileSystemOnWindows(): Boolean {\n    return windowsLimitations && fileSystem::class.simpleName == \"NodeJsFileSystem\"\n  }\n}\n"
  },
  {
    "path": "okio-testing-support/src/commonMain/kotlin/okio/CloseBehavior.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio\n\nenum class CloseBehavior {\n  Closes,\n  DoesNothing,\n  Unsupported,\n}\n"
  },
  {
    "path": "okio-testing-support/src/commonMain/kotlin/okio/FakeClock.kt",
    "content": "/*\n * Copyright (C) 2020 Square, Inc.\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 */\npackage okio\n\nimport kotlin.time.Clock\nimport kotlin.time.Duration\nimport kotlin.time.Instant\n\nclass FakeClock : Clock {\n  var time = Instant.fromEpochSeconds(1609459200L) // 2021-01-01T00:00:00Z\n\n  override fun now() = time\n\n  fun sleep(duration: Duration) {\n    time = time.plus(duration)\n  }\n}\n"
  },
  {
    "path": "okio-testing-support/src/commonMain/kotlin/okio/TestDirectory.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.TestFunction\nimport app.cash.burst.TestInterceptor\n\n/**\n * A temporary directory on [fileSystem] that's usable for the current test.\n */\nclass TestDirectory(\n  val fileSystem: FileSystem,\n  val temporaryDirectory: Path = FileSystem.SYSTEM_TEMPORARY_DIRECTORY,\n) : TestInterceptor {\n  lateinit var path: Path\n    private set\n\n  override fun intercept(testFunction: TestFunction) {\n    path = temporaryDirectory / \"${testFunction.functionName}-${randomToken(16)}\"\n    fileSystem.createDirectories(path)\n    testFunction()\n  }\n}\n"
  },
  {
    "path": "okio-testing-support/src/commonMain/kotlin/okio/TestingCommon.kt",
    "content": "/*\n * Copyright (C) 2019 Square, Inc.\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 */\npackage okio\n\nimport kotlin.random.Random\nimport kotlin.test.assertEquals\nimport kotlin.time.Instant\nimport okio.ByteString.Companion.toByteString\nimport okio.Path.Companion.toPath\n\nfun Char.repeat(count: Int): String {\n  return toString().repeat(count)\n}\n\nfun assertArrayEquals(a: ByteArray, b: ByteArray) {\n  assertEquals(a.contentToString(), b.contentToString())\n}\n\nfun randomBytes(length: Int, seed: Int = 0): ByteString {\n  val random = Random(seed)\n  val randomBytes = ByteArray(length)\n  random.nextBytes(randomBytes)\n  return ByteString.of(*randomBytes)\n}\n\nfun randomToken(length: Int) = Random.nextBytes(length).toByteString(0, length).hex()\n\nexpect fun isBrowser(): Boolean\n\n/**\n * Returns true if the host file system probably exposes metadata like file creation time.\n *\n * The file system that GitHub actions gives us doesn't do anything when we `touch` a file.\n */\nval fileSystemHasGoodMetadata: Boolean\n  get() = getEnv(\"GITHUB_WORKSPACE\") == null\n\nval FileMetadata.createdAt: Instant?\n  get() {\n    val createdAt = createdAtMillis ?: return null\n    return Instant.fromEpochMilliseconds(createdAt)\n  }\n\nval FileMetadata.lastModifiedAt: Instant?\n  get() {\n    val lastModifiedAt = lastModifiedAtMillis ?: return null\n    return Instant.fromEpochMilliseconds(lastModifiedAt)\n  }\n\nval FileMetadata.lastAccessedAt: Instant?\n  get() {\n    val lastAccessedAt = lastAccessedAtMillis ?: return null\n    return Instant.fromEpochMilliseconds(lastAccessedAt)\n  }\n\nfun fromIso8601String(iso8601String: String): Instant =\n  Instant.fromEpochMilliseconds(Instant.parse(iso8601String).toEpochMilliseconds())\n\nexpect val FileSystem.isFakeFileSystem: Boolean\n\nexpect val FileSystem.allowSymlinks: Boolean\n\nexpect val FileSystem.allowReadsWhileWriting: Boolean\n\nexpect var FileSystem.workingDirectory: Path\n\nexpect fun getEnv(name: String): String?\n\nval okioRoot: Path by lazy {\n  getEnv(\"OKIO_ROOT\")!!.toPath()\n}\n"
  },
  {
    "path": "okio-testing-support/src/commonMain/resources/go/NOTICE",
    "content": "The files in this directory are copied from Go:\nhttps://go.dev/\n\nThese files are subject to the 3-Clause BSD License:\nhttps://github.com/golang/go/blob/master/LICENSE\n"
  },
  {
    "path": "okio-testing-support/src/jsMain/kotlin/okio/TestingJs.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nactual fun isBrowser(): Boolean {\n  return js(\"\"\"(globalThis.window || null)\"\"\") != null\n}\n\nactual fun getEnv(name: String): String? =\n  js(\"globalThis.process.env[name]\") as String?\n"
  },
  {
    "path": "okio-testing-support/src/jvmMain/kotlin/okio/TestExecutor.kt",
    "content": "/*\n * Copyright (C) 2025 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.TestFunction\nimport app.cash.burst.TestInterceptor\nimport java.util.concurrent.Executors\nimport java.util.concurrent.Future\nimport java.util.concurrent.ScheduledExecutorService\nimport java.util.concurrent.ScheduledFuture\nimport java.util.concurrent.ThreadFactory\nimport java.util.concurrent.TimeUnit\nimport kotlin.time.Duration\n\n/**\n * Manages a `ExecutorService` and shuts it down after the test.\n */\nclass TestExecutor(\n  private val corePoolSize: Int = 0,\n) : TestInterceptor {\n  lateinit var executorService: ScheduledExecutorService\n    private set\n\n  fun <T> submit(task: () -> T): Future<T> = executorService.submit<T>(task)\n\n  fun <T> schedule(delay: Duration, command: () -> T): ScheduledFuture<T> =\n    executorService.schedule(command, delay.inWholeNanoseconds, TimeUnit.NANOSECONDS)\n\n  override fun intercept(testFunction: TestFunction) {\n    executorService = when {\n      isLoom -> Executors.newScheduledThreadPool(corePoolSize, newVirtualThreadFactory())\n      else -> Executors.newScheduledThreadPool(corePoolSize)\n    }\n    try {\n      testFunction()\n    } finally {\n      executorService.shutdown()\n    }\n  }\n\n  private companion object {\n    val isLoom = System.getProperty(\"loomEnabled\").toBoolean()\n\n    fun newVirtualThreadFactory(): ThreadFactory {\n      val threadBuilder = Thread::class.java.getMethod(\"ofVirtual\").invoke(null)\n      return Class.forName(\"java.lang.Thread\\$Builder\").getMethod(\"factory\")\n        .invoke(threadBuilder) as ThreadFactory\n    }\n  }\n}\n"
  },
  {
    "path": "okio-testing-support/src/jvmMain/kotlin/okio/TestingJvm.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nactual fun isBrowser() = false\n\nactual fun getEnv(name: String): String? = System.getenv(name)\n"
  },
  {
    "path": "okio-testing-support/src/nativeMain/kotlin/okio/TestingNative.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\npackage okio\n\nimport kotlinx.cinterop.ExperimentalForeignApi\nimport kotlinx.cinterop.toKString\nimport platform.posix.getenv\n\nactual fun isBrowser() = false\n\n@OptIn(ExperimentalForeignApi::class)\nactual fun getEnv(name: String): String? = getenv(name)?.toKString()\n"
  },
  {
    "path": "okio-testing-support/src/nonWasmMain/kotlin/okio/TestingNonWasm.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport okio.fakefilesystem.FakeFileSystem\n\nactual val FileSystem.isFakeFileSystem: Boolean\n  get() = this is FakeFileSystem\n\nactual val FileSystem.allowSymlinks: Boolean\n  get() = (this as? FakeFileSystem)?.allowSymlinks == true\n\nactual val FileSystem.allowReadsWhileWriting: Boolean\n  get() = (this as? FakeFileSystem)?.allowReadsWhileWriting == true\n\nactual var FileSystem.workingDirectory: Path\n  get() {\n    return when (this) {\n      is FakeFileSystem -> workingDirectory\n      is ForwardingFileSystem -> delegate.workingDirectory\n      else -> error(\"cannot get working directory: $this\")\n    }\n  }\n  set(value) {\n    when (this) {\n      is FakeFileSystem -> workingDirectory = value\n      is ForwardingFileSystem -> delegate.workingDirectory = value\n      else -> error(\"cannot set working directory: $this\")\n    }\n  }\n"
  },
  {
    "path": "okio-testing-support/src/wasmJsMain/kotlin/okio/WasiEnvWasmJs.kt",
    "content": "/*\n * Copyright (C) 2026 Square, Inc.\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 */\npackage okio\n\nactual fun getEnv(name: String): String? = error(\"unexpected call\")\n"
  },
  {
    "path": "okio-testing-support/src/wasmMain/kotlin/okio/TestingWasm.kt",
    "content": "/*\n * Copyright (C) 2021 Square, Inc.\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 */\n@file:OptIn(ExperimentalTime::class)\n\npackage okio\n\nimport kotlin.time.ExperimentalTime\n\nactual fun isBrowser() = false\n\nactual val FileSystem.isFakeFileSystem: Boolean\n  get() = false\n\nactual val FileSystem.allowSymlinks: Boolean\n  get() = error(\"unexpected call\")\n\nactual val FileSystem.allowReadsWhileWriting: Boolean\n  get() = error(\"unexpected call\")\n\nactual var FileSystem.workingDirectory: Path\n  get() = error(\"unexpected call\")\n  set(_) = error(\"unexpected call\")\n"
  },
  {
    "path": "okio-testing-support/src/wasmWasiMain/kotlin/okio/WasiClock.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport kotlin.time.Clock\nimport kotlin.time.Instant\nimport kotlin.wasm.unsafe.UnsafeWasmMemoryApi\nimport kotlin.wasm.unsafe.withScopedMemoryAllocator\nimport okio.internal.preview1.clock_time_get\nimport okio.internal.preview1.clockid_realtime\n\nobject WasiClock : Clock {\n  @OptIn(UnsafeWasmMemoryApi::class)\n  override fun now(): Instant {\n    withScopedMemoryAllocator { allocator ->\n      val returnPointer = allocator.allocate(8) // timestamp is u64.\n      val errno = clock_time_get(\n        id = clockid_realtime,\n        precision = 1_000_000_000L, // 1-second precision.\n        returnPointer.address.toInt(),\n      )\n      if (errno != 0) throw IllegalStateException(\"failed to get now: $errno\")\n\n      val nanos = returnPointer.loadLong()\n      val seconds = nanos / 1_000_000_000L\n      return Instant.fromEpochSeconds(\n        epochSeconds = seconds,\n        nanosecondAdjustment = (nanos - seconds * 1_000_000_000L).toInt(),\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "okio-testing-support/src/wasmWasiMain/kotlin/okio/WasiEnv.kt",
    "content": "/*\n * Copyright (C) 2026 Square, Inc.\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 */\n@file:Suppress(\n  \"INVISIBLE_REFERENCE\",\n)\n\npackage okio\n\nimport kotlin.wasm.unsafe.Pointer\nimport kotlin.wasm.unsafe.UnsafeWasmMemoryApi\nimport kotlin.wasm.unsafe.withScopedMemoryAllocator\nimport okio.internal.ErrnoException\nimport okio.internal.preview1.environ_get\nimport okio.internal.preview1.environ_sizes_get\nimport okio.internal.readString\n\n@OptIn(UnsafeWasmMemoryApi::class)\nval env: Map<String, String> by lazy {\n  withScopedMemoryAllocator { allocator ->\n    val entryCountPointer = allocator.allocate(4)\n    val byteCountPointer = allocator.allocate(4)\n    val sizesGetErrno = environ_sizes_get(\n      returnEntryCountPointer = entryCountPointer.address.toInt(),\n      returnByteCountPointer = byteCountPointer.address.toInt(),\n    )\n    if (sizesGetErrno != 0) throw ErrnoException(sizesGetErrno.toShort())\n\n    val entryCount = entryCountPointer.loadInt()\n    val byteCount = byteCountPointer.loadInt()\n\n    val entryPointersPointer = allocator.allocate(entryCount * 4)\n    val entryBytesPointer = allocator.allocate(byteCount)\n    val getErrno = environ_get(\n      entryPointersPointer.address.toInt(),\n      entryBytesPointer.address.toInt(),\n    )\n    if (getErrno != 0) throw ErrnoException(getErrno.toShort())\n\n    buildMap {\n      for (i in 0 until entryCount) {\n        val entryPointer = Pointer((entryPointersPointer + i * 4).loadInt().toUInt())\n        val entryString = entryPointer.readNullTerminated()\n        val eq = entryString.indexOf('=')\n        if (eq != -1) {\n          put(entryString.take(eq), entryString.substring(eq + 1))\n        }\n      }\n    }\n  }\n}\n\n@OptIn(UnsafeWasmMemoryApi::class)\ninternal fun Pointer.readNullTerminated(): String {\n  var byteCount = 0\n  while ((this + byteCount).loadByte().toInt() != 0) {\n    byteCount++\n  }\n  return readString(byteCount)\n}\n\nactual fun getEnv(name: String) = env[name]\n"
  },
  {
    "path": "okio-testing-support/src/wasmWasiMain/kotlin/okio/internal/preview1/Clockid.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\ninternal typealias clockid = Int\n\n/**\n * The clock measuring real time. Time value zero corresponds with\n * 1970-01-01T00:00:00Z.\n */\ninternal val clockid_realtime = 0\n\n/**\n * The store-wide monotonic clock, which is defined as a clock measuring\n * real time, whose value cannot be adjusted and which cannot have negative\n * clock jumps. The epoch of this clock is undefined. The absolute time\n * value of this clock therefore has no meaning.\n */\ninternal val clockid_monotonic = 1\n\n/**\n * The CPU-time clock associated with the current process.\n */\ninternal val clockid_process_cputime_id = 2\n\n/**\n * The CPU-time clock associated with the current thread.\n */\ninternal val clockid_thread_cputime_id = 3\n"
  },
  {
    "path": "okio-testing-support/src/wasmWasiMain/kotlin/okio/internal/preview1/Preview1Clock.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\nimport kotlin.wasm.WasmImport\n\n/**\n * clock_time_get(id: clockid, precision: timestamp) -> Result<timestamp, errno>\n *\n * Return the time value of a clock.\n * Note: This is similar to `clock_gettime` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"clock_time_get\")\ninternal external fun clock_time_get(\n  id: clockid,\n  precision: Long,\n  returnPointer: Int,\n): Int // should be Short??\n"
  },
  {
    "path": "okio-testing-support/src/wasmWasiMain/kotlin/okio/internal/preview1/Preview1Env.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\n\npackage okio.internal.preview1\n\n/**\n * environ_sizes_get() -> Result<(size, size), errno>\n *\n * Return environment variable data sizes.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"environ_sizes_get\")\ninternal external fun environ_sizes_get(\n  returnEntryCountPointer: Int,\n  returnByteCountPointer: Int,\n): Int // should be Short??\n\n/**\n * environ_get(environ: Pointer<Pointer<u8>>, environ_buf: Pointer<u8>) -> Result<(), errno>\n *\n * Read environment variable data.\n * The sizes of the buffers should match that returned by [`environ_sizes_get`](#environ_sizes_get).\n * Key/value pairs are expected to be joined with `=`s, and terminated with `\\0`s.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"environ_get\")\ninternal external fun environ_get(\n  environ: Int,\n  environ_buf: Int,\n): Int // should be Short??\n"
  },
  {
    "path": "okio-wasifilesystem/README.md",
    "content": "WASI FileSystem\n===============\n\n⚠️ This is a work in progress ⚠️\n\nThis module implements Okio's FileSystem API using the [WebAssembly System Interface (WASI)][wasi].\n\nIt currently uses the WASI [preview1] APIs and is tested on NodeJS with the\n`--experimental-wasi-unstable-preview1` option.\n\n[wasi]: https://wasi.dev/\n[preview1]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\n"
  },
  {
    "path": "okio-wasifilesystem/build.gradle.kts",
    "content": "import com.vanniktech.maven.publish.JavadocJar.Empty\nimport com.vanniktech.maven.publish.KotlinMultiplatform\nimport com.vanniktech.maven.publish.MavenPublishBaseExtension\n\nplugins {\n  kotlin(\"multiplatform\")\n  // TODO: Restore Dokka once this issue is resolved.\n  //     https://github.com/Kotlin/dokka/issues/3038\n  // id(\"org.jetbrains.dokka\")\n  id(\"app.cash.burst\")\n  id(\"com.vanniktech.maven.publish.base\")\n  id(\"build-support\")\n  id(\"binary-compatibility-validator\")\n}\n\nkotlin {\n  configureOrCreateWasmPlatform(\n    js = false,\n    wasi = true,\n  )\n  sourceSets {\n    all {\n      languageSettings.optIn(\"kotlin.wasm.unsafe.UnsafeWasmMemoryApi\")\n    }\n    val wasmWasiMain by getting {\n      dependencies {\n        implementation(projects.okio)\n      }\n    }\n    val wasmWasiTest by getting {\n      dependencies {\n        implementation(projects.okioTestingSupport)\n        implementation(libs.kotlin.test)\n      }\n    }\n  }\n}\n\nconfigure<MavenPublishBaseExtension> {\n  // TODO: switch from 'Empty' to 'Dokka' once this issue is resolved.\n  //     https://github.com/Kotlin/dokka/issues/3038\n  configure(\n    KotlinMultiplatform(javadocJar = Empty()),\n  )\n}\n\n/**\n * Inspired by runner.mjs in kowasm, this rewrites the JavaScript bootstrap script to set up WASI.\n *\n * See also:\n *  * https://github.com/kowasm/kowasm\n *  * https://github.com/nodejs/node/blob/main/doc/api/wasi.md\n *\n * This task overwrites the output of `compileTestDevelopmentExecutableKotlinWasmWasi` and must run\n * after that task. It must also run before the WASM test execution tasks that read this script.\n *\n * Note that this includes which file paths are exposed to the WASI sandbox.\n */\nval injectWasiInit by tasks.creating {\n  dependsOn(\"compileTestDevelopmentExecutableKotlinWasmWasi\")\n  val moduleName = \"${rootProject.name}-${project.name}-test\"\n\n  val entryPointMjs = File(\n    buildDir,\n    \"compileSync/wasmWasi/test/testDevelopmentExecutable/kotlin/$moduleName.mjs\"\n  )\n\n  outputs.file(entryPointMjs)\n\n  doLast {\n    val base = File(System.getProperty(\"java.io.tmpdir\"), \"okio-wasifilesystem-test\")\n    val baseA = File(base, \"a\")\n    val baseB = File(base, \"b\")\n    val okio = rootDir\n    base.mkdirs()\n    baseA.mkdirs()\n    baseB.mkdirs()\n\n    entryPointMjs.writeText(\n      \"\"\"\n      import { WASI } from 'wasi';\n      import { argv, env } from 'node:process';\n\n      var wasiEnv = Object.assign({}, env);\n      wasiEnv['OKIO_ROOT'] = '/okio';\n      wasiEnv['WasiTest.testEnv.empty'] = '';\n      wasiEnv['WasiTest.testEnv.nonempty'] = 'hello';\n\n      const wasi = new WASI({\n        version: 'preview1',\n        args: argv,\n        preopens: {\n          '/tmp': '$base',\n          '/a': '$baseA',\n          '/b': '$baseB',\n          '/okio': '$okio'\n        },\n        env: wasiEnv,\n      });\n\n      const fs = await import('node:fs');\n      const url = await import('node:url');\n      const wasmBuffer = fs.readFileSync(url.fileURLToPath(import.meta.resolve('./$moduleName.wasm')));\n      const wasmModule = new WebAssembly.Module(wasmBuffer);\n      const wasmInstance = new WebAssembly.Instance(wasmModule, wasi.getImportObject());\n\n      wasi.initialize(wasmInstance);\n\n      const exports = wasmInstance.exports\n\n      export const {\n        memory,\n        _initialize,\n        startUnitTests\n      } = exports\n      \"\"\".trimIndent()\n    )\n  }\n}\ntasks.named(\"wasmWasiNodeTest\").configure {\n  dependsOn(injectWasiInit)\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/FileSink.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport kotlin.wasm.unsafe.withScopedMemoryAllocator\nimport okio.internal.ErrnoException\nimport okio.internal.fdClose\nimport okio.internal.preview1.fd\nimport okio.internal.preview1.fd_sync\nimport okio.internal.preview1.fd_write\nimport okio.internal.preview1.size\nimport okio.internal.write\n\ninternal class FileSink(\n  private val fd: fd,\n) : Sink {\n  private var closed = false\n  private val cursor = Buffer.UnsafeCursor()\n\n  override fun write(source: Buffer, byteCount: Long) {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    require(source.size >= byteCount) { \"source.size=${source.size} < byteCount=$byteCount\" }\n    check(!closed) { \"closed\" }\n\n    var bytesRemaining = byteCount\n    source.readAndWriteUnsafe(cursor)\n    try {\n      while (bytesRemaining > 0L) {\n        check(cursor.next() != -1)\n\n        val count = minOf(bytesRemaining, cursor.end.toLong() - cursor.start).toInt()\n        if (fdWrite(cursor.data!!, cursor.start, count) != count) {\n          throw IOException(\"write failed\")\n        }\n        bytesRemaining -= count\n      }\n    } finally {\n      cursor.close()\n      source.skip(byteCount)\n    }\n  }\n\n  private fun fdWrite(data: ByteArray, offset: Int, count: Int): size {\n    withScopedMemoryAllocator { allocator ->\n      val dataPointer = allocator.write(data, offset, count)\n\n      val iovec = allocator.allocate(8)\n      iovec.storeInt(dataPointer.address.toInt())\n      (iovec + 4).storeInt(count)\n\n      val returnPointer = allocator.allocate(4) // `size` is u32, 4 bytes.\n      val errno = fd_write(\n        fd = fd,\n        iovs = iovec.address.toInt(),\n        iovsSize = 1,\n        returnPointer = returnPointer.address.toInt(),\n      )\n      if (errno != 0) throw ErrnoException(errno.toShort())\n\n      return returnPointer.loadInt()\n    }\n  }\n\n  override fun flush() {\n    val errno = fd_sync(fd)\n    if (errno != 0) throw ErrnoException(errno.toShort())\n  }\n\n  override fun timeout() = Timeout.NONE\n\n  override fun close() {\n    if (closed) return\n    closed = true\n    fdClose(fd)\n  }\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/FileSource.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport kotlin.wasm.unsafe.withScopedMemoryAllocator\nimport okio.internal.ErrnoException\nimport okio.internal.fdClose\nimport okio.internal.preview1.fd\nimport okio.internal.preview1.fd_read\nimport okio.internal.preview1.size\nimport okio.internal.read\n\ninternal class FileSource(\n  private val fd: fd,\n) : Source {\n  private val unsafeCursor = Buffer.UnsafeCursor()\n  private var closed = false\n\n  override fun read(sink: Buffer, byteCount: Long): Long {\n    require(byteCount >= 0L) { \"byteCount < 0: $byteCount\" }\n    check(!closed) { \"closed\" }\n    val sinkInitialSize = sink.size\n\n    // Request a writable segment in `sink`. We request at least 1024 bytes, unless the request is\n    // for smaller than that, in which case we request only that many bytes.\n    val cursor = sink.readAndWriteUnsafe(unsafeCursor)\n    val addedCapacityCount = cursor.expandBuffer(minByteCount = minOf(byteCount, 1024L).toInt())\n\n    // Now that we have a writable segment, figure out how many bytes to read. This is the smaller\n    // of the user's requested byte count, and the segment's writable capacity.\n    val attemptCount = minOf(byteCount, addedCapacityCount).toInt()\n\n    // Copy bytes from the file to the segment.\n    val bytesRead = fdRead(cursor.data!!, cursor.start, attemptCount)\n\n    // Remove new capacity that was added but not used.\n    cursor.resizeBuffer(sinkInitialSize + bytesRead)\n    cursor.close()\n\n    return when {\n      bytesRead == attemptCount -> bytesRead.toLong()\n      else -> if (bytesRead == 0) -1L else bytesRead.toLong()\n    }\n  }\n\n  private fun fdRead(data: ByteArray, offset: Int, count: Int): size {\n    withScopedMemoryAllocator { allocator ->\n      val dataPointer = allocator.allocate(count)\n\n      val iovec = allocator.allocate(8)\n      iovec.storeInt(dataPointer.address.toInt())\n      (iovec + 4).storeInt(count)\n\n      val returnPointer = allocator.allocate(4) // `size` is u32, 4 bytes.\n      val errno = fd_read(\n        fd = fd,\n        iovs = iovec.address.toInt(),\n        iovsSize = 1,\n        returnPointer = returnPointer.address.toInt(),\n      )\n      if (errno != 0) throw ErrnoException(errno.toShort())\n\n      val byteCount = returnPointer.loadInt()\n      if (byteCount != -1) {\n        dataPointer.read(data, offset, byteCount)\n      }\n\n      return byteCount\n    }\n  }\n\n  override fun timeout(): Timeout = Timeout.NONE\n\n  override fun close() {\n    if (closed) return\n    closed = true\n    fdClose(fd)\n  }\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/WasiFileHandle.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport kotlin.wasm.unsafe.Pointer\nimport kotlin.wasm.unsafe.withScopedMemoryAllocator\nimport okio.internal.ErrnoException\nimport okio.internal.fdClose\nimport okio.internal.preview1.fd\nimport okio.internal.preview1.fd_filestat_get\nimport okio.internal.preview1.fd_filestat_set_size\nimport okio.internal.preview1.fd_pread\nimport okio.internal.preview1.fd_pwrite\nimport okio.internal.preview1.fd_sync\nimport okio.internal.read\nimport okio.internal.write\n\ninternal class WasiFileHandle(\n  private val fd: fd,\n  readWrite: Boolean,\n) : FileHandle(readWrite) {\n  override fun protectedSize(): Long {\n    withScopedMemoryAllocator { allocator ->\n      val returnPointer: Pointer = allocator.allocate(64) // filestat is 64 bytes.\n      val errno = fd_filestat_get(fd, returnPointer.address.toInt())\n      if (errno != 0) throw ErrnoException(errno.toShort())\n\n      return (returnPointer + 32).loadLong()\n    }\n  }\n\n  override fun protectedRead(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ): Int {\n    withScopedMemoryAllocator { allocator ->\n      val dataPointer = allocator.allocate(byteCount)\n\n      val iovec = allocator.allocate(8)\n      iovec.storeInt(dataPointer.address.toInt())\n      (iovec + 4).storeInt(byteCount)\n\n      val returnPointer = allocator.allocate(4) // `size` is u32, 4 bytes.\n      val errno = fd_pread(\n        fd = fd,\n        iovs = iovec.address.toInt(),\n        iovsSize = 1,\n        offset = fileOffset,\n        returnPointer = returnPointer.address.toInt(),\n      )\n      if (errno != 0) throw ErrnoException(errno.toShort())\n\n      val readByteCount = returnPointer.loadInt()\n      if (byteCount != -1) {\n        dataPointer.read(array, arrayOffset, readByteCount)\n      }\n\n      if (readByteCount == 0) return -1\n      return readByteCount\n    }\n  }\n\n  override fun protectedWrite(\n    fileOffset: Long,\n    array: ByteArray,\n    arrayOffset: Int,\n    byteCount: Int,\n  ) {\n    withScopedMemoryAllocator { allocator ->\n      val dataPointer = allocator.write(array, arrayOffset, byteCount)\n\n      val iovec = allocator.allocate(8)\n      iovec.storeInt(dataPointer.address.toInt())\n      (iovec + 4).storeInt(byteCount)\n\n      val returnPointer = allocator.allocate(4) // `size` is u32, 4 bytes.\n      val errno = fd_pwrite(\n        fd = fd,\n        iovs = iovec.address.toInt(),\n        iovsSize = 1,\n        offset = fileOffset,\n        returnPointer = returnPointer.address.toInt(),\n      )\n      if (errno != 0) throw ErrnoException(errno.toShort())\n\n      val writtenByteCount = returnPointer.loadInt()\n      if (writtenByteCount != byteCount) {\n        throw IOException(\"expected $byteCount but was $writtenByteCount\")\n      }\n    }\n  }\n\n  override fun protectedFlush() {\n    val errno = fd_sync(fd)\n    if (errno != 0) throw ErrnoException(errno.toShort())\n  }\n\n  override fun protectedResize(size: Long) {\n    val errno = fd_filestat_set_size(fd, size)\n    if (errno != 0) throw ErrnoException(errno.toShort())\n  }\n\n  override fun protectedClose() {\n    fdClose(fd)\n  }\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/WasiFileSystem.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport kotlin.wasm.unsafe.Pointer\nimport kotlin.wasm.unsafe.withScopedMemoryAllocator\nimport okio.Path.Companion.toPath\nimport okio.internal.ErrnoException\nimport okio.internal.fdClose\nimport okio.internal.preview1.Errno\nimport okio.internal.preview1.dirnamelen\nimport okio.internal.preview1.fd\nimport okio.internal.preview1.fd_prestat_dir_name\nimport okio.internal.preview1.fd_prestat_get\nimport okio.internal.preview1.fd_readdir\nimport okio.internal.preview1.fdflags\nimport okio.internal.preview1.fdflags_append\nimport okio.internal.preview1.filetype\nimport okio.internal.preview1.filetype_directory\nimport okio.internal.preview1.filetype_regular_file\nimport okio.internal.preview1.filetype_symbolic_link\nimport okio.internal.preview1.oflag_creat\nimport okio.internal.preview1.oflag_directory\nimport okio.internal.preview1.oflag_excl\nimport okio.internal.preview1.oflag_trunc\nimport okio.internal.preview1.oflags\nimport okio.internal.preview1.path_create_directory\nimport okio.internal.preview1.path_filestat_get\nimport okio.internal.preview1.path_open\nimport okio.internal.preview1.path_readlink\nimport okio.internal.preview1.path_remove_directory\nimport okio.internal.preview1.path_rename\nimport okio.internal.preview1.path_symlink\nimport okio.internal.preview1.path_unlink_file\nimport okio.internal.preview1.right_fd_filestat_get\nimport okio.internal.preview1.right_fd_filestat_set_size\nimport okio.internal.preview1.right_fd_read\nimport okio.internal.preview1.right_fd_readdir\nimport okio.internal.preview1.right_fd_seek\nimport okio.internal.preview1.right_fd_sync\nimport okio.internal.preview1.right_fd_write\nimport okio.internal.preview1.rights\nimport okio.internal.readString\nimport okio.internal.write\n\n/**\n * Use [WASI] to implement the Okio file system interface.\n *\n * [WASI]: https://wasi.dev/\n */\nobject WasiFileSystem : FileSystem() {\n  private val preopens: List<Preopen> = buildList {\n    // File descriptor of the first preopen in the `WASI` instance's configured `preopens` property.\n    // This is 3 by default, assuming `stdin` is 0, `stdout` is 1, and `stderr` is 2. Other preopens\n    // are assigned sequentially starting at this value.\n    val firstPreopen = 3\n\n    withScopedMemoryAllocator { allocator ->\n      val bufSize = 2048\n      val bufPointer = allocator.allocate(bufSize)\n\n      for (fd in firstPreopen..Int.MAX_VALUE) {\n        val getReturnPointer = allocator.allocate(12)\n\n        val getErrno = fd_prestat_get(fd, getReturnPointer.address.toInt())\n        if (getErrno == Errno.badf.ordinal) break // No more preopens.\n        if (getErrno != 0) throw ErrnoException(getErrno.toShort())\n\n        val size = (getReturnPointer + 4).loadInt()\n        require(size + 1 < bufSize) { \"unexpected preopen size: $size\" }\n        val dirNameErrno = fd_prestat_dir_name(fd, bufPointer.address.toInt(), size + 1)\n        if (dirNameErrno != 0) throw ErrnoException(dirNameErrno.toShort())\n        val dirName = bufPointer.readString(size)\n        val dirNamePath = dirName.toPath()\n        add(Preopen(dirNamePath, dirNamePath.segmentsBytes, fd))\n      }\n    }\n  }\n\n  private val relativePathPreopen: Preopen = preopens.firstOrNull()\n    ?: throw IllegalStateException(\"no preopens\")\n\n  override fun canonicalize(path: Path): Path {\n    val absolutePath = when {\n      path.isAbsolute -> path\n      else -> relativePathPreopen.path.resolve(path, normalize = true)\n    }\n\n    // There's no APIs in preview1 to canonicalize a path. We give it a best effort by resolving\n    // all symlinks, but this could result in a relative path.\n    val result = resolveSymlinks(absolutePath, 0).normalized()\n\n    check(result.isAbsolute) {\n      \"Canonicalize $path returned non-absolute path: $result\"\n    }\n\n    return result\n  }\n\n  private fun resolveSymlinks(\n    path: Path,\n    recurseCount: Int = 0,\n  ): Path {\n    // 40 is chosen for consistency with the Linux kernel (which previously used 8).\n    if (recurseCount > 40) throw IOException(\"symlink cycle?\")\n\n    val parent = path.parent\n    val resolvedParent = when {\n      parent != null -> resolveSymlinks(parent, recurseCount + 1)\n      else -> null\n    }\n    val pathWithResolvedParent = when {\n      resolvedParent != null -> resolvedParent.resolve(path.name)\n      else -> path\n    }\n\n    val symlinkTarget = metadata(pathWithResolvedParent).symlinkTarget\n      ?: return pathWithResolvedParent\n\n    val resolvedSymlinkTarget = when {\n      symlinkTarget.isAbsolute -> symlinkTarget\n      resolvedParent != null -> resolvedParent.resolve(symlinkTarget)\n      else -> symlinkTarget\n    }\n\n    return resolveSymlinks(resolvedSymlinkTarget, recurseCount + 1)\n  }\n\n  override fun metadataOrNull(path: Path): FileMetadata? {\n    withScopedMemoryAllocator { allocator ->\n      val returnPointer = allocator.allocate(64)\n      val preopen = preopenForPath(path) ?: return null\n      val (pathAddress, pathSize) = allocator.write(path.toString())\n\n      val errno = path_filestat_get(\n        fd = preopen.fd,\n        flags = 0,\n        path = pathAddress.address.toInt(),\n        pathSize = pathSize,\n        returnPointer = returnPointer.address.toInt(),\n      )\n\n      when (errno) {\n        // 'notcapable' means our preopens don't cover this path. This will happen for paths\n        // like '/' that are an ancestor of our preopens.\n        Errno.notcapable.ordinal -> return FileMetadata(isDirectory = true)\n        Errno.noent.ordinal -> return null\n      }\n\n      if (errno != 0) throw ErrnoException(errno.toShort())\n\n      // Skip device, offset 0.\n      // Skip ino, offset 8.\n      val filetype: filetype = (returnPointer + 16).loadByte()\n      // Skip nlink, offset 24.\n      val filesize: Long = (returnPointer + 32).loadLong()\n      val atim: Long = (returnPointer + 40).loadLong() // Access time, Nanoseconds.\n      val mtim: Long = (returnPointer + 48).loadLong() // Modification time, Nanoseconds.\n      val ctim: Long = (returnPointer + 56).loadLong() // Status change time, Nanoseconds.\n\n      val symlinkTarget: Path? = when (filetype) {\n        filetype_symbolic_link -> {\n          val bufLen = filesize.toInt() + 1\n          val bufPointer = allocator.allocate(bufLen)\n          val readlinkReturnPointer = allocator.allocate(4) // `size` is u32, 4 bytes.\n          val readlinkErrno = path_readlink(\n            fd = preopen.fd,\n            path = pathAddress.address.toInt(),\n            pathSize = pathSize,\n            buf = bufPointer.address.toInt(),\n            buf_len = bufLen,\n            returnPointer = readlinkReturnPointer.address.toInt(),\n          )\n          if (readlinkErrno != 0) throw ErrnoException(readlinkErrno.toShort())\n          val symlinkSize = readlinkReturnPointer.loadInt()\n          val symlink = bufPointer.readString(symlinkSize)\n          symlink.toPath()\n        }\n\n        else -> null\n      }\n\n      return FileMetadata(\n        isRegularFile = filetype == filetype_regular_file,\n        isDirectory = filetype == filetype_directory,\n        symlinkTarget = symlinkTarget,\n        size = filesize,\n        createdAtMillis = ctim / 1_000_000L, // Nanos to millis.\n        lastModifiedAtMillis = mtim / 1_000_000L, // Nanos to millis.\n        lastAccessedAtMillis = atim / 1_000_000L, // Nanos to millis.\n      )\n    }\n  }\n\n  override fun list(dir: Path): List<Path> {\n    val fd = pathOpen(\n      path = dir,\n      oflags = oflag_directory,\n      rightsBase = right_fd_readdir,\n    )\n    try {\n      return list(dir, fd)\n    } finally {\n      fdClose(fd)\n    }\n  }\n\n  override fun listOrNull(dir: Path): List<Path>? {\n    // TODO: stop using exceptions for flow control.\n    try {\n      return list(dir)\n    } catch (e: FileNotFoundException) {\n      return null\n    } catch (e: ErrnoException) {\n      if (e.errno == Errno.notdir) return null\n      throw e\n    }\n  }\n\n  private fun list(dir: Path, fd: fd): List<Path> {\n    withScopedMemoryAllocator { allocator ->\n      // In theory, fd_readdir uses a 'cookie' field to page through results. In practice the\n      // NodeJS implementation doesn't honor the cookie and directories with large file names\n      // don't progress. Instead, just grow the buffer until the entire directory fits.\n      var bufSize = 2048\n      var bufPointer = allocator.allocate(bufSize)\n      val returnPointer = allocator.allocate(4) // `size` is u32, 4 bytes.\n      var pageSize: Int\n      while (true) {\n        val errno = fd_readdir(\n          fd = fd,\n          buf = bufPointer.address.toInt(),\n          buf_len = bufSize,\n          cookie = 0L, // Don't bother with dircookie, it doesn't work for large file names.\n          returnPointer = returnPointer.address.toInt(),\n        )\n\n        if (errno != 0) throw ErrnoException(errno.toShort())\n        pageSize = returnPointer.loadInt()\n\n        if (pageSize < bufSize) break\n\n        bufSize *= 4\n        bufPointer = allocator.allocate(bufSize)\n      }\n\n      // Parse dirent records from the buffer.\n      var pos = bufPointer\n      val limit = bufPointer + pageSize\n      val result = mutableListOf<Path>()\n      while (pos.address < limit.address) {\n        pos += 8 // Skip dircookie.\n        pos += 8 // Skip inode.\n        val d_namelen: dirnamelen = pos.loadInt()\n        pos += 4 // Consume d_namelen.\n        pos += 4 // Skip d_type.\n\n        val name = pos.readString(d_namelen)\n        pos += d_namelen\n\n        result += dir / name\n      }\n\n      result.sort()\n      return result\n    }\n  }\n\n  override fun openReadOnly(file: Path): FileHandle {\n    val rightsBase = right_fd_filestat_get or\n      right_fd_read or\n      right_fd_seek or\n      right_fd_sync\n    val fd = pathOpen(\n      path = file,\n      oflags = 0,\n      rightsBase = rightsBase,\n    )\n    return WasiFileHandle(fd, readWrite = false)\n  }\n\n  override fun openReadWrite(file: Path, mustCreate: Boolean, mustExist: Boolean): FileHandle {\n    val oflags = when {\n      mustCreate && mustExist -> {\n        throw IllegalArgumentException(\"Cannot require mustCreate and mustExist at the same time.\")\n      }\n      mustCreate -> oflag_creat or oflag_excl\n      mustExist -> 0\n      else -> oflag_creat\n    }\n    val rightsBase = right_fd_filestat_get or\n      right_fd_filestat_set_size or\n      right_fd_read or\n      right_fd_seek or\n      right_fd_sync or\n      right_fd_write\n    val fd = pathOpen(\n      path = file,\n      oflags = oflags,\n      rightsBase = rightsBase,\n    )\n    return WasiFileHandle(fd, readWrite = true)\n  }\n\n  override fun source(file: Path): Source {\n    return FileSource(\n      fd = pathOpen(\n        path = file,\n        oflags = 0,\n        rightsBase = right_fd_read,\n      ),\n    )\n  }\n\n  override fun sink(file: Path, mustCreate: Boolean): Sink {\n    val oflags = when {\n      mustCreate -> oflag_creat or oflag_excl or oflag_trunc\n      else -> oflag_creat or oflag_trunc\n    }\n\n    return FileSink(\n      fd = pathOpen(\n        path = file,\n        oflags = oflags,\n        rightsBase = right_fd_write or right_fd_sync,\n      ),\n    )\n  }\n\n  override fun appendingSink(file: Path, mustExist: Boolean): Sink {\n    val oflags = when {\n      mustExist -> 0\n      else -> oflag_creat\n    }\n\n    return FileSink(\n      fd = pathOpen(\n        path = file,\n        oflags = oflags,\n        rightsBase = right_fd_write,\n        fdflags = fdflags_append,\n      ),\n    )\n  }\n\n  override fun createDirectory(dir: Path, mustCreate: Boolean) {\n    withScopedMemoryAllocator { allocator ->\n      val (pathAddress, pathSize) = allocator.write(dir.toString())\n\n      val errno = path_create_directory(\n        fd = preopenForPath(dir)?.fd ?: throw FileNotFoundException(\"no preopen: $dir\"),\n        path = pathAddress.address.toInt(),\n        pathSize = pathSize,\n      )\n      if (errno == Errno.exist.ordinal) {\n        if (mustCreate) throw IOException(\"already exists: $dir\")\n        return\n      }\n\n      if (errno != 0) throw ErrnoException(errno.toShort())\n    }\n  }\n\n  override fun atomicMove(source: Path, target: Path) {\n    withScopedMemoryAllocator { allocator ->\n      val (sourcePathAddress, sourcePathSize) = allocator.write(source.toString())\n      val (targetPathAddress, targetPathSize) = allocator.write(target.toString())\n\n      val errno = path_rename(\n        fd = preopenForPath(source)?.fd ?: throw FileNotFoundException(\"no preopen: $source\"),\n        old_path = sourcePathAddress.address.toInt(),\n        old_pathSize = sourcePathSize,\n        new_fd = preopenForPath(target)?.fd ?: throw FileNotFoundException(\"no preopen: $target\"),\n        new_path = targetPathAddress.address.toInt(),\n        new_pathSize = targetPathSize,\n      )\n      if (errno == Errno.noent.ordinal) {\n        throw FileNotFoundException(\"no such file: $source\")\n      }\n\n      if (errno != 0) throw ErrnoException(errno.toShort())\n    }\n  }\n\n  override fun delete(path: Path, mustExist: Boolean) {\n    withScopedMemoryAllocator { allocator ->\n      val (pathAddress, pathSize) = allocator.write(path.toString())\n      val preopenFd = preopenForPath(path) ?: throw FileNotFoundException(\"no preopen: $path\")\n\n      var errno = path_unlink_file(\n        fd = preopenFd.fd,\n        path = pathAddress.address.toInt(),\n        pathSize = pathSize,\n      )\n      // If unlink failed, try remove_directory.\n      when (errno) {\n        Errno.noent.ordinal -> {\n          if (mustExist) throw FileNotFoundException(\"no such file: $path\")\n          return // Nothing to delete.\n        }\n\n        Errno.perm.ordinal,\n        Errno.isdir.ordinal,\n        -> {\n          errno = path_remove_directory(\n            fd = preopenFd.fd,\n            path = pathAddress.address.toInt(),\n            pathSize = pathSize,\n          )\n        }\n      }\n      if (errno != 0) throw ErrnoException(errno.toShort())\n    }\n  }\n\n  override fun createSymlink(source: Path, target: Path) {\n    withScopedMemoryAllocator { allocator ->\n      val sourcePreopen = preopenForPath(source)\n        ?: throw FileNotFoundException(\"no preopen: $source\")\n\n      // Always create symlinks relative to their source. Absolute symlinks are trouble because the\n      // absolute paths used by WASI are different from the absolute paths on the host file system.\n      val sourceParent = source.parent\n        ?: throw IOException(\"unexpected symlink source: $source\")\n      val targetRelative = when {\n        target.isRelative -> target\n        else -> target.relativeTo(sourceParent)\n      }\n\n      val (sourcePathAddress, sourcePathSize) = allocator.write(source.toString())\n      val (targetPathAddress, targetPathSize) = allocator.write(targetRelative.toString())\n\n      val errno = path_symlink(\n        old_path = targetPathAddress.address.toInt(),\n        old_pathSize = targetPathSize,\n        fd = sourcePreopen.fd,\n        new_path = sourcePathAddress.address.toInt(),\n        new_pathSize = sourcePathSize,\n      )\n      if (errno != 0) throw ErrnoException(errno.toShort())\n    }\n  }\n\n  private fun pathOpen(\n    path: Path,\n    oflags: oflags,\n    rightsBase: rights,\n    fdflags: fdflags = 0,\n  ): fd {\n    withScopedMemoryAllocator { allocator ->\n      val preopenFd = preopenForPath(path) ?: throw FileNotFoundException(\"no preopen: $path\")\n      val (pathAddress, pathSize) = allocator.write(path.toString())\n\n      val returnPointer: Pointer = allocator.allocate(4) // fd is u32.\n      val errno = path_open(\n        fd = preopenFd.fd,\n        dirflags = 0,\n        path = pathAddress.address.toInt(),\n        pathSize = pathSize,\n        oflags = oflags,\n        fs_rights_base = rightsBase,\n        fs_rights_inheriting = 0,\n        fdflags = fdflags,\n        returnPointer = returnPointer.address.toInt(),\n      )\n      if (errno == Errno.noent.ordinal) {\n        throw FileNotFoundException(\"no such file: $path\")\n      }\n      if (errno != 0) throw ErrnoException(errno.toShort())\n      return returnPointer.loadInt()\n    }\n  }\n\n  /**\n   * Returns the preopen whose path is either an ancestor of [path], or whose path [path] is an\n   * ancestor of.\n   *\n   * If [path] is an ancestor of our preopen, then operating on the path will ultimately fail with a\n   * `notcapable` errno.\n   */\n  private fun preopenForPath(path: Path): Preopen? {\n    if (path.isRelative) return relativePathPreopen\n\n    val pathSegmentsBytes = path.segmentsBytes\n\n    return preopens.firstOrNull { preopen ->\n      val commonSize = minOf(pathSegmentsBytes.size, preopen.segmentsBytes.size)\n      preopen.segmentsBytes.subList(0, commonSize) == pathSegmentsBytes.subList(0, commonSize)\n    }\n  }\n\n  override fun toString() = \"okio.WasiFileSystem\"\n\n  private class Preopen(\n    val path: Path,\n    val segmentsBytes: List<ByteString>,\n    val fd: fd,\n  )\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/ErrnoException.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio.internal\n\nimport okio.IOException\nimport okio.internal.preview1.Errno\nimport okio.internal.preview1.errno\n\nclass ErrnoException(\n  val errno: Errno,\n) : IOException(errno.name) {\n  constructor(errno: errno) : this(Errno.entries[errno.toInt()])\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/Wasi.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio.internal\n\nimport kotlin.wasm.unsafe.MemoryAllocator\nimport kotlin.wasm.unsafe.Pointer\nimport okio.internal.preview1.fd\nimport okio.internal.preview1.fd_close\nimport okio.internal.preview1.size\n\ninternal fun fdClose(fd: fd) {\n  val errno = fd_close(fd = fd)\n  if (errno != 0) throw ErrnoException(errno.toShort())\n}\n\ninternal fun Pointer.readString(byteCount: Int): String {\n  if (byteCount == 0) return \"\"\n\n  // Drop the last byte if it's 0. At least in NodeJS' implementation, strings are returned with\n  // a trailing NUL byte.\n  val lastByte = (this + byteCount - 1).loadByte()\n  val byteArray = when {\n    lastByte.toInt() == 0 -> readByteArray(byteCount - 1)\n    else -> readByteArray(byteCount)\n  }\n\n  return byteArray.decodeToString()\n}\n\nprivate fun Pointer.readByteArray(byteCount: Int): ByteArray {\n  val result = ByteArray(byteCount)\n  read(result, 0, byteCount)\n  return result\n}\n\ninternal fun Pointer.read(\n  sink: ByteArray,\n  offset: Int,\n  count: Int,\n): ByteArray {\n  for (i in 0 until count) {\n    sink[offset + i] = (this + i).loadByte()\n  }\n  return sink\n}\n\ninternal fun MemoryAllocator.write(\n  string: String,\n): Pair<Pointer, size> {\n  val bytes = string.encodeToByteArray()\n\n  // Append a trailing NUL byte. This shouldn't be necessary, but it reduces crashes in practice,\n  // at least on NodeJS 20.0. https://github.com/WebAssembly/WASI/issues/492\n  val result = allocate(bytes.size + 1)\n  var pos = result\n  for (element in bytes) {\n    pos.storeByte(element)\n    pos += 1\n  }\n  pos.storeByte(0)\n  return result to bytes.size\n}\n\ninternal fun MemoryAllocator.write(\n  byteArray: ByteArray,\n  offset: Int = 0,\n  count: Int = byteArray.size - offset,\n): Pointer {\n  val result = allocate(count)\n  var pos = result\n  for (b in offset until (offset + count)) {\n    pos.storeByte(byteArray[b])\n    pos += 1\n  }\n  return result\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/preview1/Errno.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\n@Suppress(\"ktlint:enum-entry-name-case\")\nenum class Errno {\n  /** `success`: No error occurred. System call completed successfully. */\n  success,\n\n  /** `2big`: Argument list too long. */\n  toobig,\n\n  /** `acces`: Permission denied. */\n  acces,\n\n  /** `addrinuse`: Address in use. */\n  addrinuse,\n\n  /** `addrnotavail`: Address not available. */\n  addrnotavail,\n\n  /** `afnosupport`: Address family not supported. */\n  afnosupport,\n\n  /** `again`: Resource unavailable, or operation would block. */\n  again,\n\n  /** `already`: Connection already in progress. */\n  already,\n\n  /** `badf`: Bad file descriptor. */\n  badf,\n\n  /** `badmsg`: Bad message. */\n  badmsg,\n\n  /** `busy`: Device or resource busy. */\n  busy,\n\n  /** `canceled`: Operation canceled. */\n  canceled,\n\n  /** `child`: No child processes. */\n  child,\n\n  /** `connaborted`: Connection aborted. */\n  connaborted,\n\n  /** `connrefused`: Connection refused. */\n  connrefused,\n\n  /** `connreset`: Connection reset. */\n  connreset,\n\n  /** `deadlk`: Resource deadlock would occur. */\n  deadlk,\n\n  /** `destaddrreq`: Destination address required. */\n  destaddrreq,\n\n  /** `dom`: Mathematics argument out of domain of function. */\n  dom,\n\n  /** `dquot`: Reserved. */\n  dquot,\n\n  /** `exist`: File exists. */\n  exist,\n\n  /** `fault`: Bad address. */\n  fault,\n\n  /** `fbig`: File too large. */\n  fbig,\n\n  /** `hostunreach`: Host is unreachable. */\n  hostunreach,\n\n  /** `idrm`: Identifier removed. */\n  idrm,\n\n  /** `ilseq`: Illegal byte sequence. */\n  ilseq,\n\n  /** `inprogress`: Operation in progress. */\n  inprogress,\n\n  /** `intr`: Interrupted function. */\n  intr,\n\n  /** `inval`: Invalid argument. */\n  inval,\n\n  /** `io`: I/O error. */\n  io,\n\n  /** `isconn`: Socket is connected. */\n  isconn,\n\n  /** `isdir`: Is a directory. */\n  isdir,\n\n  /** `loop`: Too many levels of symbolic links. */\n  loop,\n\n  /** `mfile`: File descriptor value too large. */\n  mfile,\n\n  /** `mlink`: Too many links. */\n  mlink,\n\n  /** `msgsize`: Message too large. */\n  msgsize,\n\n  /** `multihop`: Reserved. */\n  multihop,\n\n  /** `nametoolong`: Filename too long. */\n  nametoolong,\n\n  /** `netdown`: Network is down. */\n  netdown,\n\n  /** `netreset`: Connection aborted by network. */\n  netreset,\n\n  /** `netunreach`: Network unreachable. */\n  netunreach,\n\n  /** `nfile`: Too many files open in system. */\n  nfile,\n\n  /** `nobufs`: No buffer space available. */\n  nobufs,\n\n  /** `nodev`: No such device. */\n  nodev,\n\n  /** `noent`: No such file or directory. */\n  noent,\n\n  /** `noexec`: Executable file format error. */\n  noexec,\n\n  /** `nolck`: No locks available. */\n  nolck,\n\n  /** `nolink`: Reserved. */\n  nolink,\n\n  /** `nomem`: Not enough space. */\n  nomem,\n\n  /** `nomsg`: No message of the desired type. */\n  nomsg,\n\n  /** `noprotoopt`: Protocol not available. */\n  noprotoopt,\n\n  /** `nospc`: No space left on device. */\n  nospc,\n\n  /** `nosys`: Function not supported. */\n  nosys,\n\n  /** `notconn`: The socket is not connected. */\n  notconn,\n\n  /** `notdir`: Not a directory or a symbolic link to a directory. */\n  notdir,\n\n  /** `notempty`: Directory not empty. */\n  notempty,\n\n  /** `notrecoverable`: State not recoverable. */\n  notrecoverable,\n\n  /** `notsock`: Not a socket. */\n  notsock,\n\n  /** `notsup`: Not supported, or operation not supported on socket. */\n  notsup,\n\n  /** `notty`: Inappropriate I/O control operation. */\n  notty,\n\n  /** `nxio`: No such device or address. */\n  nxio,\n\n  /** `overflow`: Value too large to be stored in data type. */\n  overflow,\n\n  /** `ownerdead`: Previous owner died. */\n  ownerdead,\n\n  /** `perm`: Operation not permitted. */\n  perm,\n\n  /** `pipe`: Broken pipe. */\n  pipe,\n\n  /** `proto`: Protocol error. */\n  proto,\n\n  /** `protonosupport`: Protocol not supported. */\n  protonosupport,\n\n  /** `prototype`: Protocol wrong type for socket. */\n  prototype_,\n\n  /** `range`: Result too large. */\n  range,\n\n  /** `rofs`: Read-only file system. */\n  rofs,\n\n  /** `spipe`: Invalid seek. */\n  spipe,\n\n  /** `srch`: No such process. */\n  srch,\n\n  /** `stale`: Reserved. */\n  stale,\n\n  /** `timedout`: Connection timed out. */\n  timedout,\n\n  /** `txtbsy`: Text file busy. */\n  txtbsy,\n\n  /** `xdev`: Cross-device link. */\n  xdev,\n\n  /** `notcapable`: Extension: Capabilities insufficient. */\n  notcapable,\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/preview1/Fdflags.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\n/**\n * `fdflags: Record`.\n *\n * File descriptor flags.\n */\ntypealias fdflags = Short\n\n/** Data written to the file is always appended to the file's end. */\nval fdflags_append: Short = (1 shl 0).toShort()\n\n/** Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. */\nval fdflags_dsync: Short = (1 shl 1).toShort()\n\n/** Non-blocking mode. */\nval fdflags_nonblock: Short = (1 shl 2).toShort()\n\n/** Synchronized read I/O operations. */\nval fdflags_rsync: Short = (1 shl 3).toShort()\n\n/** Write according to synchronized I/O file integrity completion. In addition to synchronizing the data stored in the file, the implementation may also synchronously update the file's metadata. */\nval fdflags_sync: Short = (1 shl 4).toShort()\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/preview1/Filetype.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\n/**\n * `Variant`.\n *\n * The type of a file descriptor or file.\n */\ntypealias filetype = Byte\n\n/** The type of the file descriptor or file is unknown or is different from any of the other types specified. */\nval filetype_unknown: filetype = 0\n\n/** The file descriptor or file refers to a block device inode. */\nval filetype_block_device: filetype = 1\n\n/** The file descriptor or file refers to a character device inode. */\nval filetype_character_device: filetype = 2\n\n/** The file descriptor or file refers to a directory inode. */\nval filetype_directory: filetype = 3\n\n/** The file descriptor or file refers to a regular file inode. */\nval filetype_regular_file: filetype = 4\n\n/** The file descriptor or file refers to a datagram socket. */\nval filetype_socket_dgram: filetype = 5\n\n/** The file descriptor or file refers to a byte-stream socket. */\nval filetype_socket_stream: filetype = 6\n\n/** The file refers to a symbolic link inode. */\nval filetype_symbolic_link: filetype = 7\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/preview1/LookupFlags.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\n/**\n * `lookupflags: Record`.\n *\n * Flags determining the method of how paths are resolved.\n *\n * Bit0:\n * symlink_follow:\n */\ntypealias lookupflags = Int\n\n/** As long as the resolved path corresponds to a symbolic link, it is expanded. */\nval lookupflags_symlink_follow = 1 shl 0\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/preview1/OFlags.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\n/**\n * `oflags: `Record`.\n *\n * Open flags used by path_open.\n */\ntypealias oflags = Int\n\n/** Create file if it does not exist. */\nval oflag_creat = 1 shl 0\n\n/** Fail if not a directory. */\nval oflag_directory = 1 shl 1\n\n/** Fail if file already exists. */\nval oflag_excl = 1 shl 2\n\n/** Truncate file to size 0. */\nval oflag_trunc = 1 shl 3\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/preview1/Preview1.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\n/** `u32`. */\ntypealias size = Int\n\n/**\n * `Handle`.\n *\n * A file descriptor handle.\n */\ntypealias fd = Int\n\n/**\n * `u64`.\n *\n * A reference to the offset of a directory entry.\n *\n * The value 0 signifies the start of the directory.\n */\ntypealias dircookie = Long\n\n/**\n * `Variant`.\n *\n * Error codes returned by functions. Not all of these error codes are returned by the functions\n * provided by this API; some are used in higher-level library layers, and others are provided\n * merely for alignment with POSIX.\n */\ntypealias errno = Short\n\n/**\n * `u64`.\n *\n * File serial number that is unique within its file system.\n */\ntypealias inode = Long\n\n/**\n * `u32`.\n *\n * The type for the [`dirent::d_namlen`](#dirent.d_namlen) field of [`dirent`](#dirent) struct.\n */\ntypealias dirnamelen = Int\n\n/**\n * `Pointer<u8>`.\n */\ntypealias PointerU8 = Int\n\n/**\n * path_create_directory(fd: fd, path: string) -> Result<(), errno>\n *\n * Create a directory.\n * Note: This is similar to `mkdirat` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_create_directory\")\ninternal external fun path_create_directory(\n  fd: fd,\n  path: PointerU8,\n  pathSize: size,\n): Int // should be Short??\n\n/**\n * path_filestat_get(fd: fd, flags: lookupflags, path: string) -> Result<filestat, errno>\n *\n * Return the attributes of a file or directory.\n * Note: This is similar to `stat` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_filestat_get\")\ninternal external fun path_filestat_get(\n  fd: fd,\n  flags: lookupflags,\n  path: PointerU8,\n  pathSize: size,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * path_open(fd: fd, dirflags: lookupflags, path: string, oflags: oflags, fs_rights_base: rights, fs_rights_inheriting: rights, fdflags: fdflags) -> Result<fd, errno>\n *\n * Open a file or directory.\n * The returned file descriptor is not guaranteed to be the lowest-numbered\n * file descriptor not currently open; it is randomized to prevent\n * applications from depending on making assumptions about indexes, since this\n * is error-prone in multi-threaded contexts. The returned file descriptor is\n * guaranteed to be less than 2**31.\n * Note: This is similar to `openat` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_open\")\ninternal external fun path_open(\n  fd: fd,\n  dirflags: lookupflags,\n  path: PointerU8,\n  pathSize: size,\n  oflags: oflags,\n  fs_rights_base: rights,\n  fs_rights_inheriting: rights,\n  fdflags: fdflags,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * path_readlink(fd: fd, path: string, buf: Pointer<u8>, buf_len: size) -> Result<size, errno>\n *\n * Read the contents of a symbolic link.\n * Note: This is similar to `readlinkat` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_readlink\")\ninternal external fun path_readlink(\n  fd: fd,\n  path: PointerU8,\n  pathSize: size,\n  buf: PointerU8,\n  buf_len: size,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * path_remove_directory(fd: fd, path: string) -> Result<(), errno>\n *\n * Remove a directory.\n * Return [`errno::notempty`](#errno.notempty) if the directory is not empty.\n * Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_remove_directory\")\ninternal external fun path_remove_directory(\n  fd: fd,\n  path: PointerU8,\n  pathSize: size,\n): Int // should be Short??\n\n/**\n * path_rename(fd: fd, old_path: string, new_fd: fd, new_path: string) -> Result<(), errno>\n *\n * Rename a file or directory.\n * Note: This is similar to `renameat` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_rename\")\ninternal external fun path_rename(\n  fd: fd,\n  old_path: PointerU8,\n  old_pathSize: size,\n  new_fd: fd,\n  new_path: PointerU8,\n  new_pathSize: size,\n): Int // should be Short??\n\n/**\n * path_symlink(old_path: string, fd: fd, new_path: string) -> Result<(), errno>\n *\n * Create a symbolic link.\n * Note: This is similar to `symlinkat` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_symlink\")\ninternal external fun path_symlink(\n  old_path: PointerU8,\n  old_pathSize: size,\n  fd: fd,\n  new_path: PointerU8,\n  new_pathSize: size,\n): Int // should be Short??\n\n/**\n * path_unlink_file(fd: fd, path: string) -> Result<(), errno>\n *\n * Unlink a file.\n * Return [`errno::isdir`](#errno.isdir) if the path refers to a directory.\n * Note: This is similar to `unlinkat(fd, path, 0)` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"path_unlink_file\")\ninternal external fun path_unlink_file(\n  fd: fd,\n  path: PointerU8,\n  pathSize: size,\n): Int // should be Short??\n\n/**\n * fd_close(fd: fd) -> Result<(), errno>\n *\n * Close a file descriptor.\n * Note: This is similar to `close` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_close\")\ninternal external fun fd_close(\n  fd: fd,\n): Int // should be Short??\n\n/**\n * fd_filestat_get(fd: fd) -> Result<filestat, errno>\n *\n * Return the attributes of an open file.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_filestat_get\")\ninternal external fun fd_filestat_get(\n  fd: fd,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * fd_pread(fd: fd, iovs: iovec_array, offset: filesize) -> Result<size, errno>\n *\n * Read from a file descriptor.\n * Note: This is similar to `readv` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_pread\")\ninternal external fun fd_pread(\n  fd: fd,\n  iovs: PointerU8,\n  iovsSize: size,\n  offset: Long,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * fd_prestat_dir_name(fd: fd, path: Pointer<u8>, path_len: size) -> Result<(), errno>\n *\n * Return a description of the given preopened file descriptor.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_prestat_dir_name\")\ninternal external fun fd_prestat_dir_name(\n  fd: fd,\n  path: PointerU8,\n  pathSize: size,\n): Int // should be Short??\n\n/**\n * fd_prestat_get(fd: fd) -> Result<prestat, errno>\n *\n * Return a description of the given preopened file descriptor.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_prestat_get\")\ninternal external fun fd_prestat_get(\n  fd: fd,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * fd_pwrite(fd: fd, iovs: ciovec_array, offset: filesize) -> Result<size, errno>`\n *\n * Write to a file descriptor, without using and updating the file descriptor's offset.\n * Note: This is similar to `pwritev` in Linux (and other Unix-es).\n *\n * Like Linux (and other Unix-es), any calls of `pwrite` (and other\n * functions to read or write) for a regular file by other threads in the\n * WASI process should not be interleaved while `pwrite` is executed.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_pwrite\")\ninternal external fun fd_pwrite(\n  fd: fd,\n  iovs: PointerU8,\n  iovsSize: size,\n  offset: Long,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * fd_read(fd: fd, iovs: iovec_array) -> Result<size, errno>\n *\n * Read from a file descriptor.\n * Note: This is similar to `readv` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_read\")\ninternal external fun fd_read(\n  fd: fd,\n  iovs: PointerU8,\n  iovsSize: size,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * fd_readdir(fd: fd, buf: Pointer<u8>, buf_len: size, cookie: dircookie) -> Result<size, errno>\n *\n * Read directory entries from a directory.\n * When successful, the contents of the output buffer consist of a sequence of\n * directory entries. Each directory entry consists of a [`dirent`](#dirent) object,\n * followed by [`dirent::d_namlen`](#dirent.d_namlen) bytes holding the name of the directory\n * entry.\n * This function fills the output buffer as much as possible, potentially\n * truncating the last directory entry. This allows the caller to grow its\n * read buffer size in case it's too small to fit a single large directory\n * entry, or skip the oversized directory entry.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_readdir\")\ninternal external fun fd_readdir(\n  fd: fd,\n  buf: PointerU8,\n  buf_len: size,\n  cookie: dircookie,\n  returnPointer: PointerU8,\n): Int // should be Short??\n\n/**\n * fd_filestat_set_size(fd: fd, size: filesize) -> Result<(), errno>\n *\n * Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros.\n * Note: This is similar to `ftruncate` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_filestat_set_size\")\ninternal external fun fd_filestat_set_size(\n  fd: fd,\n  size: Long,\n): Int // should be Short??\n\n/**\n * fd_sync(fd: fd) -> Result<(), errno>\n *\n * Synchronize the data and metadata of a file to disk.\n * Note: This is similar to `fsync` in POSIX.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_sync\")\ninternal external fun fd_sync(\n  fd: fd,\n): Int // should be Short??\n\n/**\n * fd_write(fd: fd, iovs: ciovec_array) -> Result<size, errno>\n *\n * Write to a file descriptor.\n * Note: This is similar to `writev` in POSIX.\n *\n * Like POSIX, any calls of `write` (and other functions to read or write)\n * for a regular file by other threads in the WASI process should not be\n * interleaved while `write` is executed.\n */\n@WasmImport(\"wasi_snapshot_preview1\", \"fd_write\")\ninternal external fun fd_write(\n  fd: fd,\n  iovs: PointerU8,\n  iovsSize: size,\n  returnPointer: PointerU8,\n): Int // should be Short??\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiMain/kotlin/okio/internal/preview1/Rights.kt",
    "content": "// Copyright 2019-2023 the Contributors to the WASI Specification\n// This file is adapted from the WASI preview1 spec here:\n// https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md\npackage okio.internal.preview1\n\n/** `rights: Record`. */\ntypealias rights = Long\n\n/**\n * The right to invoke [`fd_datasync`](#fd_datasync)0\n * If [`path_open`](#path_open) is set, includes the right to invoke\n * [`path_open`](#path_open) with [`fdflags::dsync`](#fdflags.dsync).\n */\nval right_fd_datasync = 1L shl 0\n\n/**\n * The right to invoke [`fd_read`](#fd_read) and [`sock_recv`](#sock_recv).\n * If [`rights::fd_seek`](#rights.fd_seek) is set, includes the right to invoke [`fd_pread`](#fd_pread).\n */\nval right_fd_read = 1L shl 1\n\n/** The right to invoke [`fd_seek`](#fd_seek). This flag implies [`rights::fd_tell`](#rights.fd_tell). */\nval right_fd_seek = 1L shl 2\n\n/** The right to invoke [`fd_fdstat_set_flags`](#fd_fdstat_set_flags). */\nval right_fd_fdstat_set_flags = 1L shl 3\n\n/**\n * The right to invoke [`fd_sync`](#fd_sync).\n * If [`path_open`](#path_open) is set, includes the right to invoke\n * [`path_open`](#path_open) with [`fdflags::rsync`](#fdflags.rsync) and [`fdflags::dsync`](#fdflags.dsync).\n */\nval right_fd_sync = 1L shl 4\n\n/**\n * The right to invoke [`fd_seek`](#fd_seek) in such a way that the file offset\n * remains unaltered (i.e., [`whence::cur`](#whence.cur) with offset zero), or to\n * invoke [`fd_tell`](#fd_tell).\n */\nval right_fd_tell = 1L shl 5\n\n/**\n * The right to invoke [`fd_write`](#fd_write) and [`sock_send`](#sock_send).\n * If [`rights::fd_seek`](#rights.fd_seek) is set, includes the right to invoke [`fd_pwrite`](#fd_pwrite).\n */\nval right_fd_write = 1L shl 6\n\n/** The right to invoke [`fd_advise`](#fd_advise). */\nval right_fd_advise = 1L shl 7\n\n/** The right to invoke [`fd_allocate`](#fd_allocate). */\nval right_fd_allocate = 1L shl 8\n\n/** The right to invoke [`path_create_directory`](#path_create_directory). */\nval right_path_create_directory = 1L shl 9\n\n/** If [`path_open`](#path_open) is set, the right to invoke [`path_open`](#path_open) with [`oflags::creat`](#oflags.creat). */\nval right_path_create_file = 1L shl 10\n\n/**\n * The right to invoke [`path_link`](#path_link) with the file descriptor as the\n * source directory.\n */\nval right_path_link_source = 1L shl 11\n\n/** The right to invoke [`path_link`](#path_link) with the file descriptor as the target directory.\n */\nval right_path_link_target = 1L shl 12\n\n/** The right to invoke [`path_open`](#path_open). */\nval right_path_open = 1L shl 13\n\n/** The right to invoke [`fd_readdir`](#fd_readdir). */\nval right_fd_readdir = 1L shl 14\n\n/** The right to invoke [`path_readlink`](#path_readlink). */\nval right_path_readlink = 1L shl 15\n\n/** The right to invoke [`path_rename`](#path_rename) with the file descriptor as the source directory. */\nval right_path_rename_source = 1L shl 16\n\n/** The right to invoke [`path_rename`](#path_rename) with the file descriptor as the target directory. */\nval right_path_rename_target = 1L shl 17\n\n/** The right to invoke [`path_filestat_get`](#path_filestat_get). */\nval right_path_filestat_get = 1L shl 18\n\n/**\n * The right to change a file's size.\n * If [`path_open`](#path_open) is set, includes the right to invoke [`path_open`](#path_open) with [`oflags::trunc`](#oflags.trunc).\n * Note: there is no function named `path_filestat_set_size`. This follows POSIX design,\n * which only has `ftruncate` and does not provide `ftruncateat`.\n * While such function would be desirable from the API design perspective, there are virtually\n * no use cases for it since no code written for POSIX systems would use it.\n * Moreover, implementing it would require multiple syscalls, leading to inferior performance.\n */\nval right_path_filestat_set_size = 1L shl 19\n\n/** The right to invoke [`path_filestat_set_times`](#path_filestat_set_times). */\nval right_path_filestat_set_times = 1L shl 20\n\n/** The right to invoke [`fd_filestat_get`](#fd_filestat_get). */\nval right_fd_filestat_get = 1L shl 21\n\n/** The right to invoke [`fd_filestat_set_size`](#fd_filestat_set_size). */\nval right_fd_filestat_set_size = 1L shl 22\n\n/** The right to invoke [`fd_filestat_set_times`](#fd_filestat_set_times). */\nval right_fd_filestat_set_times = 1L shl 23\n\n/** The right to invoke [`path_symlink`](#path_symlink). */\nval right_path_symlink = 1L shl 24\n\n/** The right to invoke [`path_remove_directory`](#path_remove_directory). */\nval right_path_remove_directory = 1L shl 25\n\n/** The right to invoke [`path_unlink_file`](#path_unlink_file). */\nval right_path_unlink_file = 1L shl 26\n\n/**\n * If [`rights::fd_read`](#rights.fd_read) is set, includes the right to invoke [`poll_oneoff`](#poll_oneoff) to subscribe to [`eventtype::fd_read`](#eventtype.fd_read).\n * If [`rights::fd_write`](#rights.fd_write) is set, includes the right to invoke [`poll_oneoff`](#poll_oneoff) to subscribe to [`eventtype::fd_write`](#eventtype.fd_write).\n */\nval right_poll_fd_readwrite = 1L shl 27\n\n/** The right to invoke [`sock_shutdown`](#sock_shutdown). */\nval right_sock_shutdown = 1L shl 28\n\n/** The right to invoke [`sock_accept`](#sock_accept). */\nval right_sock_accept = 1L shl 29\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiTest/kotlin/okio/WasiFileSystemPreopensTest.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertNull\nimport okio.Path.Companion.toPath\n\n/**\n * Confirm the [WasiFileSystem] can operate on different preopened directories independently.\n *\n * This tracks the `preopens` attribute in `.mjs` script in `okio-wasifilesystem/build.gradle.kts`.\n */\nclass WasiFileSystemPreopensTest {\n  private val fileSystem = WasiFileSystem\n\n  @InterceptTest\n  private val testDirectoryA = TestDirectory(fileSystem, \"/a\".toPath())\n  private val baseA: Path get() = testDirectoryA.path\n\n  @InterceptTest\n  private val testDirectoryB = TestDirectory(fileSystem, \"/b\".toPath())\n  private val baseB: Path get() = testDirectoryB.path\n\n  @Test\n  fun operateOnPreopens() {\n    fileSystem.write(baseA / \"a.txt\") {\n      writeUtf8(\"hello world a\")\n    }\n    fileSystem.write(baseB / \"b.txt\") {\n      writeUtf8(\"bello burld\")\n    }\n    assertEquals(\n      \"hello world a\".length.toLong(),\n      fileSystem.metadata(baseA / \"a.txt\").size,\n    )\n    assertEquals(\n      \"bello burld\".length.toLong(),\n      fileSystem.metadata(baseB / \"b.txt\").size,\n    )\n  }\n\n  @Test\n  fun operateAcrossPreopens() {\n    fileSystem.write(baseA / \"a.txt\") {\n      writeUtf8(\"hello world\")\n    }\n\n    fileSystem.atomicMove(baseA / \"a.txt\", baseB / \"b.txt\")\n\n    assertEquals(\n      \"hello world\",\n      fileSystem.read(baseB / \"b.txt\") {\n        readUtf8()\n      },\n    )\n  }\n\n  @Test\n  fun cannotOperateOutsideOfPreopens() {\n    val noPreopen = \"/c/absent\".toPath()\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.createDirectory(noPreopen)\n    }\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.sink(noPreopen)\n    }\n    assertNull(fileSystem.metadataOrNull(noPreopen))\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.metadata(noPreopen)\n    }\n    assertNull(fileSystem.listOrNull(noPreopen))\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.list(noPreopen)\n    }\n  }\n}\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiTest/kotlin/okio/WasiFileSystemTest.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport okio.Path.Companion.toPath\n\nclass WasiFileSystemTest : AbstractFileSystemTest(\n  clock = WasiClock,\n  fileSystem = WasiFileSystem,\n  windowsLimitations = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowClobberingEmptyDirectories = Path.DIRECTORY_SEPARATOR == \"\\\\\",\n  allowAtomicMoveFromFileToDirectory = false,\n  temporaryDirectory = \"/tmp\".toPath(),\n  closeBehavior = CloseBehavior.DoesNothing,\n)\n"
  },
  {
    "path": "okio-wasifilesystem/src/wasmWasiTest/kotlin/okio/WasiTest.kt",
    "content": "/*\n * Copyright (C) 2023 Square, Inc.\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 */\npackage okio\n\nimport app.cash.burst.InterceptTest\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertFailsWith\nimport kotlin.test.assertTrue\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.Path.Companion.toPath\n\nclass WasiTest {\n  private val fileSystem = WasiFileSystem\n\n  @InterceptTest\n  private val testDirectory = TestDirectory(fileSystem, \"/tmp\".toPath())\n  private val base: Path get() = testDirectory.path\n\n  @Test\n  fun createDirectory() {\n    fileSystem.createDirectory(base / \"child\")\n  }\n\n  @Test\n  fun canonicalizeAbsolutePathNoSymlinks() {\n    val path = base / \"regular_file.txt\"\n    fileSystem.write(path) {\n      writeUtf8(\"hello\")\n    }\n    assertEquals(\n      path,\n      fileSystem.canonicalize(path),\n    )\n  }\n\n  @Test\n  fun canonicalizeAbsolutePathWithSymlinksInFiles() {\n    val target = base / \"target\"\n    val source = base / \"source\"\n    fileSystem.write(target) {\n      writeUtf8(\"hello\")\n    }\n    fileSystem.createSymlink(source, \"target\".toPath())\n    assertEquals(\n      target,\n      fileSystem.canonicalize(source),\n    )\n  }\n\n  @Test\n  fun canonicalizeAbsolutePathWithSymlinksInDirectories() {\n    val target = base / \"target\"\n    val source = base / \"source\"\n    fileSystem.createDirectory(target)\n    fileSystem.write(target / \"file.txt\") {\n      writeUtf8(\"hello\")\n    }\n    fileSystem.createSymlink(source, \"target\".toPath())\n    assertEquals(\n      target / \"file.txt\",\n      fileSystem.canonicalize(source / \"file.txt\"),\n    )\n  }\n\n  @Test\n  fun canonicalizeAbsolutePathWithSymlinkCycle() {\n    fileSystem.createSymlink(base / \"rock\", \"scissors\".toPath())\n    fileSystem.createSymlink(base / \"scissors\", \"paper\".toPath())\n    fileSystem.createSymlink(base / \"paper\", \"rock\".toPath())\n    val e = assertFailsWith<IOException> {\n      fileSystem.canonicalize(base / \"rock\")\n    }\n    assertEquals(\"symlink cycle?\", e.message)\n  }\n\n  @Test\n  fun writeAndReadEmptyFile() {\n    writeAndReadFile(ByteString.EMPTY, base / \"empty.txt\")\n  }\n\n  @Test\n  fun writeAndReadShortFile() {\n    writeAndReadFile(\"hello\\n\".encodeUtf8(), base / \"hello.txt\")\n  }\n\n  private fun writeAndReadFile(content: ByteString, fileName: Path) {\n    fileSystem.write(fileName) {\n      write(content)\n    }\n    assertEquals(\n      content,\n      fileSystem.read(fileName) {\n        readByteString()\n      },\n    )\n  }\n\n  @Test\n  fun writeAndReadLongFile() {\n    val fileName = base / \"5m_bytes.txt\"\n    fileSystem.write(fileName) {\n      for (i in 0L until 1_000_000L) {\n        writeByte(i.toInt())\n        writeByte(0)\n        writeByte(0)\n        writeByte(0)\n        writeByte(0)\n      }\n    }\n    fileSystem.read(fileName) {\n      for (i in 0L until 1_000_000L) {\n        assertEquals(i.toByte(), readByte())\n        assertEquals(0, readByte())\n        assertEquals(0, readByte())\n        assertEquals(0, readByte())\n        assertEquals(0, readByte())\n      }\n      assertTrue(exhausted())\n    }\n  }\n\n  @Test\n  fun appendToFile() {\n    val fileName = base / \"append.txt\"\n    fileSystem.write(fileName) {\n      writeUtf8(\"hello\")\n    }\n    fileSystem.appendingSink(fileName).buffer().use {\n      it.writeUtf8(\" world\")\n    }\n    assertEquals(\n      \"hello world\",\n      fileSystem.read(fileName) {\n        readUtf8()\n      },\n    )\n  }\n\n  @Test\n  fun listDirectory() {\n    fileSystem.write(base / \"a\") {\n      writeUtf8(\"this file has a 1-byte file name\")\n    }\n    fileSystem.write(base / \"a.txt\") {\n      writeUtf8(\"this file has a 5-byte file name\")\n    }\n\n    assertEquals(\n      listOf(\n        base / \"a\",\n        base / \"a.txt\",\n      ),\n      fileSystem.list(base).sorted(),\n    )\n  }\n\n  @Test\n  fun deleteFile() {\n    fileSystem.write(base / \"a\") {\n    }\n    fileSystem.write(base / \"b\") {\n    }\n    fileSystem.write(base / \"c\") {\n    }\n    fileSystem.delete(base / \"b\")\n\n    assertEquals(\n      listOf(\n        base / \"a\",\n        base / \"c\",\n      ),\n      fileSystem.list(base).sorted(),\n    )\n  }\n\n  @Test\n  fun deleteDirectory() {\n    fileSystem.createDirectory(base / \"a\")\n    fileSystem.createDirectory(base / \"b\")\n    fileSystem.createDirectory(base / \"c\")\n    fileSystem.delete(base / \"b\")\n\n    assertEquals(\n      listOf(\n        base / \"a\",\n        base / \"c\",\n      ),\n      fileSystem.list(base).sorted(),\n    )\n  }\n\n  @Test\n  fun createSymlink() {\n    val targetPath = base / \"target\"\n    val sourcePath = base / \"source\"\n    fileSystem.write(targetPath) {\n      writeUtf8(\"this is the target file's contents\")\n    }\n    fileSystem.createSymlink(sourcePath, \"target\".toPath())\n\n    assertEquals(\n      \"this is the target file's contents\",\n      fileSystem.read(sourcePath) {\n        readUtf8()\n      },\n    )\n  }\n\n  @Test\n  fun rename() {\n    val targetPath = base / \"target\"\n    val sourcePath = base / \"source\"\n    fileSystem.write(sourcePath) {\n      writeUtf8(\"this is the file's contents\")\n    }\n    fileSystem.atomicMove(sourcePath, targetPath)\n\n    assertEquals(\n      \"this is the file's contents\",\n      fileSystem.read(targetPath) {\n        readUtf8()\n      },\n    )\n    assertEquals(\n      listOf(targetPath),\n      fileSystem.list(base),\n    )\n  }\n\n  @Test\n  fun fileMetadata() {\n    val regularFile = base / \"regularFile\"\n    val directory = base / \"directory\"\n    val symlink = base / \"symlink\"\n    fileSystem.write(regularFile) {\n      writeUtf8(\"this is a regular file\")\n    }\n    fileSystem.createDirectory(directory)\n    fileSystem.createSymlink(symlink, \"regularFile\".toPath())\n\n    val regularFileMetadata = fileSystem.metadata(regularFile)\n    assertEquals(true, regularFileMetadata.isRegularFile)\n    assertEquals(false, regularFileMetadata.isDirectory)\n    assertEquals(null, regularFileMetadata.symlinkTarget)\n    assertEquals(22L, regularFileMetadata.size)\n\n    val directoryMetadata = fileSystem.metadata(directory)\n    assertEquals(false, directoryMetadata.isRegularFile)\n    assertEquals(true, directoryMetadata.isDirectory)\n    assertEquals(null, directoryMetadata.symlinkTarget)\n    // Note: no assertions about directory size.\n\n    val symlinkMetadata = fileSystem.metadata(symlink)\n    assertEquals(false, symlinkMetadata.isRegularFile)\n    assertEquals(false, symlinkMetadata.isDirectory)\n    assertEquals(\"regularFile\".toPath(), symlinkMetadata.symlinkTarget)\n    assertEquals(\"regularFile\".length.toLong(), symlinkMetadata.size)\n  }\n\n  @Test\n  fun absentMetadata() {\n    assertEquals(null, fileSystem.metadataOrNull(base / \"no-such-file\"))\n    assertFailsWith<FileNotFoundException> {\n      fileSystem.metadata(base / \"no-such-file\")\n    }\n  }\n\n  @Test\n  fun fileHandleRead() {\n    val path = base / \"file.txt\"\n    fileSystem.write(path) {\n      writeUtf8(\"this is a file about dogs and cats\")\n    }\n    fileSystem.openReadOnly(path).use { handle ->\n      val sink = Buffer()\n      handle.read(21L, sink, 4L)\n\n      assertEquals(\n        \"dogs\",\n        sink.readUtf8(),\n      )\n    }\n  }\n\n  @Test\n  fun fileHandleWrite() {\n    val path = base / \"file.txt\"\n    fileSystem.write(path) {\n      writeUtf8(\"this is a file about cats and cats\")\n    }\n    fileSystem.openReadWrite(path).use { handle ->\n      val source = Buffer().writeUtf8(\"dogs\")\n      handle.write(21L, source, 4L)\n\n      assertEquals(\n        \"this is a file about dogs and cats\",\n        fileSystem.read(path) {\n          readUtf8()\n        },\n      )\n    }\n  }\n\n  @Test\n  fun fileHandleGetSize() {\n    val path = base / \"file.txt\"\n    fileSystem.write(path) {\n      writeUtf8(\"this is a file about dogs and cats\")\n    }\n    fileSystem.openReadOnly(path).use { handle ->\n      assertEquals(\n        34L,\n        handle.size(),\n      )\n    }\n  }\n\n  @Test\n  fun fileHandleResize() {\n    val path = base / \"file.txt\"\n    fileSystem.write(path) {\n      writeUtf8(\"this is a file about dogs and cats\")\n    }\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.resize(25L)\n\n      assertEquals(\n        \"this is a file about dogs\",\n        fileSystem.read(path) {\n          readUtf8()\n        },\n      )\n    }\n  }\n\n  @Test\n  fun fileHandleFlush() {\n    val path = base / \"file.txt\"\n    fileSystem.openReadWrite(path).use { handle ->\n      handle.sink().buffer().use {\n        it.writeUtf8(\"hello\")\n      }\n      handle.flush()\n\n      assertEquals(\n        \"hello\",\n        fileSystem.read(path) {\n          readUtf8()\n        },\n      )\n    }\n  }\n\n  @Test\n  fun fileSinkFlush() {\n    val path = base / \"file.txt\"\n    fileSystem.write(path) {\n      writeUtf8(\"hello\")\n      flush()\n\n      assertEquals(\n        \"hello\",\n        fileSystem.read(path) {\n          readUtf8()\n        },\n      )\n    }\n  }\n\n  /**\n   * Confirm environment variables are correctly decoded. (These are hardcoded in the test Wasi\n   * config.)\n   */\n  @Test\n  fun testEnv() {\n    assertEquals(\"\", env[\"WasiTest.testEnv.empty\"])\n    assertEquals(\"hello\", env[\"WasiTest.testEnv.nonempty\"])\n    assertEquals(\"/okio\".toPath(), okioRoot)\n  }\n}\n"
  },
  {
    "path": "samples/build.gradle.kts",
    "content": "plugins {\n  kotlin(\"multiplatform\")\n  id(\"com.gradleup.tapmoc\")\n}\n\nkotlin {\n  jvm {\n    binaries {\n      executable {\n        mainClass.set(System.getProperty(\"mainClass\"))\n      }\n    }\n  }\n  sourceSets {\n    commonMain {\n      dependencies {\n        implementation(projects.okio)\n      }\n    }\n    val jvmTest by getting {\n      dependencies {\n        implementation(libs.test.assertk)\n        implementation(libs.test.junit)\n      }\n    }\n  }\n}\n\ntapmoc {\n  java(8)\n  kotlin(project.getVersionByName(\"kotlinCoreLibrariesVersion\"))\n  checkDependencies()\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/BitmapEncoder.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport okio.BufferedSink;\nimport okio.FileSystem;\nimport okio.Okio;\nimport okio.Path;\n\npublic final class BitmapEncoder {\n  static final class Bitmap {\n    private final int[][] pixels;\n\n    Bitmap(int[][] pixels) {\n      this.pixels = pixels;\n    }\n\n    int width() {\n      return pixels[0].length;\n    }\n\n    int height() {\n      return pixels.length;\n    }\n\n    int red(int x, int y) {\n      return (pixels[y][x] & 0xff0000) >> 16;\n    }\n\n    int green(int x, int y) {\n      return (pixels[y][x] & 0xff00) >> 8;\n    }\n\n    int blue(int x, int y) {\n      return (pixels[y][x] & 0xff);\n    }\n  }\n\n  /**\n   * Returns a bitmap that lights up red subpixels at the bottom, green subpixels on the right, and\n   * blue subpixels in bottom-right.\n   */\n  Bitmap generateGradient() {\n    int[][] pixels = new int[1080][1920];\n    for (int y = 0; y < 1080; y++) {\n      for (int x = 0; x < 1920; x++) {\n        int r = (int) (y / 1080f * 255);\n        int g = (int) (x / 1920f * 255);\n        int b = (int) ((Math.hypot(x, y) / Math.hypot(1080, 1920)) * 255);\n        pixels[y][x] = r << 16 | g << 8 | b;\n      }\n    }\n    return new Bitmap(pixels);\n  }\n\n  void encode(Bitmap bitmap, FileSystem fileSystem, Path path) throws IOException {\n    try (BufferedSink sink = Okio.buffer(fileSystem.sink(path))) {\n      encode(bitmap, sink);\n    }\n  }\n\n  /** https://en.wikipedia.org/wiki/BMP_file_format */\n  void encode(Bitmap bitmap, BufferedSink sink) throws IOException {\n    int height = bitmap.height();\n    int width = bitmap.width();\n\n    int bytesPerPixel = 3;\n    int rowByteCountWithoutPadding = (bytesPerPixel * width);\n    int rowByteCount = ((rowByteCountWithoutPadding + 3) / 4) * 4;\n    int pixelDataSize = rowByteCount * height;\n    int bmpHeaderSize = 14;\n    int dibHeaderSize = 40;\n\n    // BMP Header\n    sink.writeUtf8(\"BM\"); // ID.\n    sink.writeIntLe(bmpHeaderSize + dibHeaderSize + pixelDataSize); // File size.\n    sink.writeShortLe(0); // Unused.\n    sink.writeShortLe(0); // Unused.\n    sink.writeIntLe(bmpHeaderSize + dibHeaderSize); // Offset of pixel data.\n\n    // DIB Header\n    sink.writeIntLe(dibHeaderSize);\n    sink.writeIntLe(width);\n    sink.writeIntLe(height);\n    sink.writeShortLe(1);  // Color plane count.\n    sink.writeShortLe(bytesPerPixel * Byte.SIZE);\n    sink.writeIntLe(0);    // No compression.\n    sink.writeIntLe(16);   // Size of bitmap data including padding.\n    sink.writeIntLe(2835); // Horizontal print resolution in pixels/meter. (72 dpi).\n    sink.writeIntLe(2835); // Vertical print resolution in pixels/meter. (72 dpi).\n    sink.writeIntLe(0);    // Palette color count.\n    sink.writeIntLe(0);    // 0 important colors.\n\n    // Pixel data.\n    for (int y = height - 1; y >= 0; y--) {\n      for (int x = 0; x < width; x++) {\n        sink.writeByte(bitmap.blue(x, y));\n        sink.writeByte(bitmap.green(x, y));\n        sink.writeByte(bitmap.red(x, y));\n      }\n\n      // Padding for 4-byte alignment.\n      for (int p = rowByteCountWithoutPadding; p < rowByteCount; p++) {\n        sink.writeByte(0);\n      }\n    }\n  }\n\n  public static void main(String[] args) throws Exception {\n    BitmapEncoder encoder = new BitmapEncoder();\n    Bitmap bitmap = encoder.generateGradient();\n    encoder.encode(bitmap, FileSystem.SYSTEM, Path.get(\"gradient.bmp\"));\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/ByteChannelSink.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.nio.channels.WritableByteChannel;\nimport okio.Buffer;\nimport okio.Sink;\nimport okio.Timeout;\n\n/**\n * Creates a Sink around a WritableByteChannel and efficiently writes data using an UnsafeCursor.\n *\n * <p>This is a basic example showing another use for the UnsafeCursor. Using the\n * {@link ByteBuffer#wrap(byte[], int, int) ByteBuffer.wrap()} along with access to Buffer segments,\n * a WritableByteChannel can be given direct access to Buffer data without having to copy the data.\n */\nfinal class ByteChannelSink implements Sink {\n  private final WritableByteChannel channel;\n  private final Timeout timeout;\n\n  private final Buffer.UnsafeCursor cursor = new Buffer.UnsafeCursor();\n\n  ByteChannelSink(WritableByteChannel channel, Timeout timeout) {\n    this.channel = channel;\n    this.timeout = timeout;\n  }\n\n  @Override public void write(Buffer source, long byteCount) throws IOException {\n    if (!channel.isOpen()) throw new IllegalStateException(\"closed\");\n    if (byteCount == 0) return;\n\n    long remaining = byteCount;\n    while (remaining > 0) {\n      timeout.throwIfReached();\n\n      try (Buffer.UnsafeCursor ignored = source.readUnsafe(cursor)) {\n        cursor.seek(0);\n        int length = (int) Math.min(cursor.end - cursor.start, remaining);\n        int written = channel.write(ByteBuffer.wrap(cursor.data, cursor.start, length));\n        remaining -= written;\n        source.skip(written);\n      }\n    }\n  }\n\n  @Override public void flush() {}\n\n  @Override public Timeout timeout() {\n    return timeout;\n  }\n\n  @Override public void close() throws IOException {\n    channel.close();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/ByteChannelSource.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.nio.channels.ReadableByteChannel;\nimport okio.Buffer;\nimport okio.Source;\nimport okio.Timeout;\n\n/**\n * Creates a Source around a ReadableByteChannel and efficiently reads data using an UnsafeCursor.\n *\n * <p>This is a basic example showing another use for the UnsafeCursor. Using the\n * {@link ByteBuffer#wrap(byte[], int, int) ByteBuffer.wrap()} along with access to Buffer segments,\n * a ReadableByteChannel can be given direct access to Buffer data without having to copy the data.\n */\nfinal class ByteChannelSource implements Source {\n  private final ReadableByteChannel channel;\n  private final Timeout timeout;\n\n  private final Buffer.UnsafeCursor cursor = new Buffer.UnsafeCursor();\n\n  ByteChannelSource(ReadableByteChannel channel, Timeout timeout) {\n    this.channel = channel;\n    this.timeout = timeout;\n  }\n\n  @Override public long read(Buffer sink, long byteCount) throws IOException {\n    if (!channel.isOpen()) throw new IllegalStateException(\"closed\");\n\n    try (Buffer.UnsafeCursor ignored = sink.readAndWriteUnsafe(cursor)) {\n      timeout.throwIfReached();\n      long oldSize = sink.size();\n      int length = (int) Math.min(8192, byteCount);\n\n      cursor.expandBuffer(length);\n      int read = channel.read(ByteBuffer.wrap(cursor.data, cursor.start, length));\n      if (read == -1) {\n        cursor.resizeBuffer(oldSize);\n        return -1;\n      } else {\n        cursor.resizeBuffer(oldSize + read);\n        return read;\n      }\n    }\n  }\n\n  @Override public Timeout timeout() {\n    return timeout;\n  }\n\n  @Override public void close() throws IOException {\n    channel.close();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/ExploreCharsets.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport okio.ByteString;\nimport okio.Utf8;\n\npublic final class ExploreCharsets {\n  public void run() throws Exception {\n    dumpStringData(\"Café \\uD83C\\uDF69\"); // NFC: é is one code point.\n    dumpStringData(\"Café \\uD83C\\uDF69\"); // NFD: e is one code point, its accent is another.\n  }\n\n  public void dumpStringData(String s) throws IOException {\n    System.out.println(\"                       \" + s);\n    System.out.println(\"        String.length: \" + s.length());\n    System.out.println(\"String.codePointCount: \" + s.codePointCount(0, s.length()));\n    System.out.println(\"            Utf8.size: \" + Utf8.size(s));\n    System.out.println(\"          UTF-8 bytes: \" + ByteString.encodeUtf8(s).hex());\n    System.out.println();\n  }\n\n  public static void main(String... args) throws Exception {\n    new ExploreCharsets().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/FileChannelSink.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.nio.channels.FileChannel;\nimport java.nio.channels.ReadableByteChannel;\nimport okio.Buffer;\nimport okio.Sink;\nimport okio.Timeout;\n\n/**\n * Special Sink for a FileChannel to take advantage of the\n * {@link FileChannel#transferFrom(ReadableByteChannel, long, long) transfer} method available.\n */\nfinal class FileChannelSink implements Sink {\n  private final FileChannel channel;\n  private final Timeout timeout;\n\n  private long position;\n\n  FileChannelSink(FileChannel channel, Timeout timeout) throws IOException {\n    this.channel = channel;\n    this.timeout = timeout;\n\n    this.position = channel.position();\n  }\n\n  @Override public void write(Buffer source, long byteCount) throws IOException {\n    if (!channel.isOpen()) throw new IllegalStateException(\"closed\");\n    if (byteCount == 0) return;\n\n    long remaining = byteCount;\n    while (remaining > 0) {\n      long written = channel.transferFrom(source, position, remaining);\n      position += written;\n      remaining -= written;\n    }\n  }\n\n  @Override public void flush() throws IOException {\n    // Cannot alter meta data through this Sink\n    channel.force(false);\n  }\n\n  @Override public Timeout timeout() {\n    return timeout;\n  }\n\n  @Override public void close() throws IOException {\n    channel.close();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/FileChannelSource.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.nio.channels.FileChannel;\nimport java.nio.channels.WritableByteChannel;\nimport okio.Buffer;\nimport okio.Source;\nimport okio.Timeout;\n\n/**\n * Special Source for a FileChannel to take advantage of the\n * {@link FileChannel#transferTo(long, long, WritableByteChannel) transfer} method available.\n */\nfinal class FileChannelSource implements Source {\n  private final FileChannel channel;\n  private final Timeout timeout;\n\n  private long position;\n\n  FileChannelSource(FileChannel channel, Timeout timeout) throws IOException {\n    this.channel = channel;\n    this.timeout = timeout;\n\n    this.position = channel.position();\n  }\n\n  @Override public long read(Buffer sink, long byteCount) throws IOException {\n    if (!channel.isOpen()) throw new IllegalStateException(\"closed\");\n    if (position == channel.size()) return -1L;\n\n    long read = channel.transferTo(position, byteCount, sink);\n    position += read;\n    return read;\n  }\n\n  @Override public Timeout timeout() {\n    return timeout;\n  }\n\n  @Override public void close() throws IOException {\n    channel.close();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/GoldenValue.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.io.Serializable;\nimport okio.Buffer;\nimport okio.ByteString;\n\npublic final class GoldenValue {\n  public void run() throws Exception {\n    Point point = new Point(8.0, 15.0);\n    ByteString pointBytes = serialize(point);\n    System.out.println(pointBytes.base64());\n\n    ByteString goldenBytes = ByteString.decodeBase64(\"rO0ABXNyAB5va2lvLnNhbXBsZ\"\n        + \"XMuR29sZGVuVmFsdWUkUG9pbnTdUW8rMji1IwIAAkQAAXhEAAF5eHBAIAAAAAAAAEAuA\"\n        + \"AAAAAAA\");\n    Point decoded = (Point) deserialize(goldenBytes);\n    assertEquals(point, decoded);\n  }\n\n  private ByteString serialize(Object o) throws IOException {\n    Buffer buffer = new Buffer();\n    try (ObjectOutputStream objectOut = new ObjectOutputStream(buffer.outputStream())) {\n      objectOut.writeObject(o);\n    }\n    return buffer.readByteString();\n  }\n\n  private Object deserialize(ByteString byteString) throws IOException, ClassNotFoundException {\n    Buffer buffer = new Buffer();\n    buffer.write(byteString);\n    try (ObjectInputStream objectIn = new ObjectInputStream(buffer.inputStream())) {\n      Object result = objectIn.readObject();\n      if (objectIn.read() != -1) throw new IOException(\"Unconsumed bytes in stream\");\n      return result;\n    }\n  }\n\n  static final class Point implements Serializable {\n    double x;\n    double y;\n\n    Point(double x, double y) {\n      this.x = x;\n      this.y = y;\n    }\n  }\n\n  private void assertEquals(Point a, Point b) {\n    if (a.x != b.x || a.y != b.y) throw new AssertionError();\n  }\n\n  public static void main(String... args) throws Exception {\n    new GoldenValue().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/Hashing.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.BufferedSource;\nimport okio.ByteString;\nimport okio.FileSystem;\nimport okio.HashingSink;\nimport okio.HashingSource;\nimport okio.Okio;\nimport okio.Path;\nimport okio.Source;\n\npublic final class Hashing {\n  public void run() throws Exception {\n    Path path = Path.get(\"../README.md\");\n\n    System.out.println(\"ByteString\");\n    ByteString byteString = readByteString(path);\n    System.out.println(\"       md5: \" + byteString.md5().hex());\n    System.out.println(\"      sha1: \" + byteString.sha1().hex());\n    System.out.println(\"    sha256: \" + byteString.sha256().hex());\n    System.out.println(\"    sha512: \" + byteString.sha512().hex());\n    System.out.println();\n\n    System.out.println(\"Buffer\");\n    Buffer buffer = readBuffer(path);\n    System.out.println(\"       md5: \" + buffer.md5().hex());\n    System.out.println(\"      sha1: \" + buffer.sha1().hex());\n    System.out.println(\"    sha256: \" + buffer.sha256().hex());\n    System.out.println(\"    sha512: \" + buffer.sha512().hex());\n    System.out.println();\n\n    System.out.println(\"HashingSource\");\n    try (HashingSource hashingSource = HashingSource.sha256(FileSystem.SYSTEM.source(path));\n         BufferedSource source = Okio.buffer(hashingSource)) {\n      source.readAll(Okio.blackhole());\n      System.out.println(\"    sha256: \" + hashingSource.hash().hex());\n    }\n    System.out.println();\n\n    System.out.println(\"HashingSink\");\n    try (HashingSink hashingSink = HashingSink.sha256(Okio.blackhole());\n         BufferedSink sink = Okio.buffer(hashingSink);\n         Source source = FileSystem.SYSTEM.source(path)) {\n      sink.writeAll(source);\n      sink.close(); // Emit anything buffered.\n      System.out.println(\"    sha256: \" + hashingSink.hash().hex());\n    }\n    System.out.println();\n\n    System.out.println(\"HMAC\");\n    ByteString secret = ByteString.decodeHex(\"7065616e7574627574746572\");\n    System.out.println(\"hmacSha256: \" + byteString.hmacSha256(secret).hex());\n    System.out.println();\n  }\n\n  public ByteString readByteString(Path path) throws IOException {\n    try (BufferedSource source = Okio.buffer(FileSystem.SYSTEM.source(path))) {\n      return source.readByteString();\n    }\n  }\n\n  public Buffer readBuffer(Path path) throws IOException {\n    try (Source source = FileSystem.SYSTEM.source(path)) {\n      Buffer buffer = new Buffer();\n      buffer.writeAll(source);\n      return buffer;\n    }\n  }\n\n  public static void main(String[] args) throws Exception {\n    new Hashing().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/Interceptors.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.util.Random;\nimport okio.Buffer;\nimport okio.ForwardingSink;\nimport okio.ForwardingSource;\nimport okio.Sink;\nimport okio.Source;\n\n/**\n * Demonstrates use of the {@link Buffer.UnsafeCursor} class. While other\n * samples might demonstrate real use cases, this sample hopes to show the\n * basics of using an {@link Buffer.UnsafeCursor}:\n * <ul>\n *   <li>Efficient reuse of a single cursor instance.</li>\n *   <li>Guaranteed release of an attached cursor.</li>\n *   <li>Safe traversal of the data in a Buffer.</li>\n * </ul>\n *\n * <p>This sample implements a\n * <a href=\"https://en.wikipedia.org/wiki/Cipher_disk\">circular cipher</a> by\n * creating a Source which will intercept all bytes written to the wire and\n * decrease their value by a specific amount. Then create a Sink which will\n * intercept all bytes read from the wire and increase their value by that same\n * specific amount. This creates an incredibly insecure way of encrypting data\n * written to the wire but demonstrates the power of the\n * {@link Buffer.UnsafeCursor} class for efficient operations on the bytes\n * being written and read.\n */\npublic final class Interceptors {\n  public void run() throws Exception {\n    final byte cipher = (byte) (new Random().nextInt(256) - 128);\n    System.out.println(\"Cipher   : \" + cipher);\n\n    Buffer wire = new Buffer();\n\n    // Create a Sink which will intercept and negatively rotate each byte by `cipher`\n    Sink sink = new InterceptingSink(wire) {\n      @Override\n      protected void intercept(byte[] data, int offset, int length) {\n        for (int i = offset, end = offset + length; i < end; i++) {\n          data[i] -= cipher;\n        }\n      }\n    };\n\n    // Create a Source which will intercept and positively rotate each byte by `cipher`\n    Source source = new InterceptingSource(wire) {\n      @Override\n      protected void intercept(byte[] data, int offset, int length) {\n        for (int i = offset, end = offset + length; i < end; i++) {\n          data[i] += cipher;\n        }\n      }\n    };\n\n    Buffer transmit = new Buffer();\n    transmit.writeUtf8(\"This is not really a secure message\");\n    System.out.println(\"Transmit : \" + transmit);\n\n    sink.write(transmit, transmit.size());\n    System.out.println(\"Wire     : \" + wire);\n\n    Buffer receive = new Buffer();\n    source.read(receive, Long.MAX_VALUE);\n    System.out.println(\"Receive  : \" + receive);\n  }\n\n  abstract class InterceptingSource extends ForwardingSource {\n\n    private final Buffer.UnsafeCursor cursor = new Buffer.UnsafeCursor();\n\n    InterceptingSource(Source source) {\n      super(source);\n    }\n\n    @Override\n    public long read(Buffer sink, long byteCount) throws IOException {\n      if (byteCount < 0) throw new IllegalArgumentException(\"byteCount < 0: \" + byteCount);\n      if (byteCount == 0) return 0;\n\n      long result = super.read(sink, byteCount);\n      if (result == -1L) return result;\n\n      sink.readUnsafe(cursor);\n      try {\n        long remaining = result;\n        for (int length = cursor.seek(sink.size() - result);\n             remaining > 0 && length > 0;\n             length = cursor.next()) {\n          int toIntercept = (int) Math.min(length, remaining);\n          intercept(cursor.data, cursor.start, toIntercept);\n          remaining -= toIntercept;\n        }\n      } finally {\n        cursor.close();\n      }\n\n      return result;\n    }\n\n    protected abstract void intercept(byte[] data, int offset, int length) throws IOException;\n  }\n\n\n  abstract class InterceptingSink extends ForwardingSink {\n\n    private final Buffer.UnsafeCursor cursor = new Buffer.UnsafeCursor();\n\n    InterceptingSink(Sink delegate) {\n      super(delegate);\n    }\n\n    @Override\n    public void write(Buffer source, long byteCount) throws IOException {\n      if (byteCount < 0) throw new IllegalArgumentException(\"byteCount < 0: \" + byteCount);\n      if (source.size() < byteCount) {\n        throw new IllegalArgumentException(\"size=\" + source.size() + \" byteCount=\" + byteCount);\n      }\n      if (byteCount == 0) return;\n\n      source.readUnsafe(cursor);\n      try {\n        long remaining = byteCount;\n        for (int length = cursor.seek(0);\n             remaining > 0 && length > 0;\n             length = cursor.next()) {\n          int toIntercept = (int) Math.min(length, remaining);\n          intercept(cursor.data, cursor.start, toIntercept);\n          remaining -= toIntercept;\n        }\n      } finally {\n        cursor.close();\n      }\n\n      super.write(source, byteCount);\n    }\n\n    protected abstract void intercept(byte[] data, int offset, int length) throws IOException;\n  }\n\n  public static void main(String... args) throws Exception {\n    new Interceptors().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/Randoms.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.util.Random;\nimport okio.Buffer;\nimport okio.BufferedSource;\nimport okio.Okio;\nimport okio.Source;\nimport okio.Timeout;\n\npublic final class Randoms {\n  public void run() throws IOException, InterruptedException {\n    Random random = new Random(3782615686L);\n    BufferedSource source = Okio.buffer(new RandomSource(random, 5));\n    System.out.println(source.readUtf8());\n  }\n\n  static final class RandomSource implements Source {\n    private final Random random;\n    private long bytesLeft;\n\n    RandomSource(Random random, long bytesLeft) {\n      this.random = random;\n      this.bytesLeft = bytesLeft;\n    }\n\n    @Override public long read(Buffer sink, long byteCount) throws IOException {\n      if (bytesLeft == -1L) throw new IllegalStateException(\"closed\");\n      if (bytesLeft == 0L) return -1L;\n      if (byteCount > Integer.MAX_VALUE) byteCount = Integer.MAX_VALUE;\n      if (byteCount > bytesLeft) byteCount = bytesLeft;\n\n      // Random is most efficient when computing 32 bits of randomness. Start with that.\n      int ints = (int) (byteCount / 4);\n      for (int i = 0; i < ints; i++) {\n        sink.writeInt(random.nextInt());\n      }\n\n      // If we need 1, 2, or 3 bytes more, keep going. We'll discard 24, 16 or 8 random bits!\n      int bytes = (int) (byteCount - ints * 4);\n      if (bytes > 0) {\n        int bits = random.nextInt();\n        for (int i = 0; i < bytes; i++) {\n          sink.writeByte(bits & 0xff);\n          bits >>>= 8;\n        }\n      }\n\n      bytesLeft -= byteCount;\n      return byteCount;\n    }\n\n    @Override public Timeout timeout() {\n      return Timeout.NONE;\n    }\n\n    @Override public void close() throws IOException {\n      bytesLeft = -1L;\n    }\n  }\n\n  public static void main(String... args) throws Exception {\n    new Randoms().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/ReadFileLineByLine.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport okio.BufferedSource;\nimport okio.FileSystem;\nimport okio.Okio;\nimport okio.Path;\nimport okio.Source;\n\npublic final class ReadFileLineByLine {\n  public void run() throws Exception {\n    readLines(Path.get(\"../README.md\"));\n  }\n\n  public void readLines(Path path) throws IOException {\n    try (Source fileSource = FileSystem.SYSTEM.source(path);\n         BufferedSource bufferedFileSource = Okio.buffer(fileSource)) {\n\n      while (true) {\n        String line = bufferedFileSource.readUtf8Line();\n        if (line == null) break;\n\n        if (line.contains(\"square\")) {\n          System.out.println(line);\n        }\n      }\n\n    }\n  }\n\n  public static void main(String... args) throws Exception {\n    new ReadFileLineByLine().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/ReadFileLineByLine.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport okio.FileSystem\nimport okio.IOException\nimport okio.Path\nimport okio.Path.Companion.toPath\nimport okio.buffer\n\n@Throws(IOException::class)\nfun readLines(path: Path) {\n  FileSystem.SYSTEM.source(path).use { fileSource ->\n    fileSource.buffer().use { bufferedFileSource ->\n      while (true) {\n        val line = bufferedFileSource.readUtf8Line() ?: break\n        if (\"square\" in line) {\n          println(line)\n        }\n      }\n    }\n  }\n}\n\nfun main() {\n  readLines(\"../README.md\".toPath())\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/ReadJavaIoFileLineByLine.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.File;\nimport java.io.IOException;\nimport okio.BufferedSource;\nimport okio.Okio;\nimport okio.Source;\n\npublic final class ReadJavaIoFileLineByLine {\n  public void run() throws Exception {\n    readLines(new File(\"../README.md\"));\n  }\n\n  public void readLines(File file) throws IOException {\n    try (Source fileSource = Okio.source(file);\n         BufferedSource bufferedFileSource = Okio.buffer(fileSource)) {\n\n      while (true) {\n        String line = bufferedFileSource.readUtf8Line();\n        if (line == null) break;\n\n        if (line.contains(\"square\")) {\n          System.out.println(line);\n        }\n      }\n\n    }\n  }\n\n  public static void main(String... args) throws Exception {\n    new ReadJavaIoFileLineByLine().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/SocksProxyServer.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.ProtocolException;\nimport java.net.Proxy;\nimport java.net.ServerSocket;\nimport java.net.Socket;\nimport java.net.URL;\nimport java.net.URLConnection;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.BufferedSource;\nimport okio.Okio;\nimport okio.Sink;\nimport okio.Source;\n\n/**\n * A partial implementation of SOCKS Protocol Version 5.\n * See <a href=\"https://www.ietf.org/rfc/rfc1928.txt\">RFC 1928</a>.\n */\npublic final class SocksProxyServer {\n  private static final int VERSION_5 = 5;\n  private static final int METHOD_NO_AUTHENTICATION_REQUIRED = 0;\n  private static final int ADDRESS_TYPE_IPV4 = 1;\n  private static final int ADDRESS_TYPE_DOMAIN_NAME = 3;\n  private static final int COMMAND_CONNECT = 1;\n  private static final int REPLY_SUCCEEDED = 0;\n\n  private final ExecutorService executor = Executors.newCachedThreadPool();\n  private ServerSocket serverSocket;\n  private final Set<Socket> openSockets =\n      Collections.newSetFromMap(new ConcurrentHashMap<>());\n\n  public void start() throws IOException {\n    serverSocket = new ServerSocket(0);\n    executor.execute(this::acceptSockets);\n  }\n\n  public void shutdown() throws IOException {\n    serverSocket.close();\n    executor.shutdown();\n  }\n\n  public Proxy proxy() {\n    return new Proxy(Proxy.Type.SOCKS,\n        InetSocketAddress.createUnresolved(\"localhost\", serverSocket.getLocalPort()));\n  }\n\n  private void acceptSockets() {\n    try {\n      while (true) {\n        final Socket from = serverSocket.accept();\n        openSockets.add(from);\n        executor.execute(() -> handleSocket(from));\n      }\n    } catch (IOException e) {\n      System.out.println(\"shutting down: \" + e);\n    } finally {\n      for (Socket socket : openSockets) {\n        closeQuietly(socket);\n      }\n    }\n  }\n\n  private void handleSocket(final Socket fromSocket) {\n    try {\n      final BufferedSource fromSource = Okio.buffer(Okio.source(fromSocket));\n      final BufferedSink fromSink = Okio.buffer(Okio.sink(fromSocket));\n\n      // Read the hello.\n      int socksVersion = fromSource.readByte() & 0xff;\n      if (socksVersion != VERSION_5) throw new ProtocolException();\n      int methodCount = fromSource.readByte() & 0xff;\n      boolean foundSupportedMethod = false;\n      for (int i = 0; i < methodCount; i++) {\n        int method = fromSource.readByte() & 0xff;\n        foundSupportedMethod |= method == METHOD_NO_AUTHENTICATION_REQUIRED;\n      }\n      if (!foundSupportedMethod) throw new ProtocolException();\n\n      // Respond to hello.\n      fromSink.writeByte(VERSION_5)\n          .writeByte(METHOD_NO_AUTHENTICATION_REQUIRED)\n          .emit();\n\n      // Read a command.\n      int version = fromSource.readByte() & 0xff;\n      int command = fromSource.readByte() & 0xff;\n      int reserved = fromSource.readByte() & 0xff;\n      if (version != VERSION_5 || command != COMMAND_CONNECT || reserved != 0) {\n        throw new ProtocolException();\n      }\n\n      // Read an address.\n      int addressType = fromSource.readByte() & 0xff;\n      InetAddress inetAddress;\n      if (addressType == ADDRESS_TYPE_IPV4) {\n        inetAddress = InetAddress.getByAddress(fromSource.readByteArray(4L));\n      } else if (addressType == ADDRESS_TYPE_DOMAIN_NAME){\n        int domainNameLength = fromSource.readByte() & 0xff;\n        inetAddress = InetAddress.getByName(fromSource.readUtf8(domainNameLength));\n      } else {\n        throw new ProtocolException();\n      }\n      int port = fromSource.readShort() & 0xffff;\n\n      // Connect to the caller's specified host.\n      final Socket toSocket = new Socket(inetAddress, port);\n      openSockets.add(toSocket);\n      byte[] localAddress = toSocket.getLocalAddress().getAddress();\n      if (localAddress.length != 4) throw new ProtocolException();\n\n      // Write the reply.\n      fromSink.writeByte(VERSION_5)\n          .writeByte(REPLY_SUCCEEDED)\n          .writeByte(0)\n          .writeByte(ADDRESS_TYPE_IPV4)\n          .write(localAddress)\n          .writeShort(toSocket.getLocalPort())\n          .emit();\n\n      // Connect sources to sinks in both directions.\n      final Sink toSink = Okio.sink(toSocket);\n      executor.execute(() -> transfer(fromSocket, fromSource, toSink));\n      final Source toSource = Okio.source(toSocket);\n      executor.execute(() -> transfer(toSocket, toSource, fromSink));\n    } catch (IOException e) {\n      closeQuietly(fromSocket);\n      openSockets.remove(fromSocket);\n      System.out.println(\"connect failed for \" + fromSocket + \": \" + e);\n    }\n  }\n\n  /**\n   * Read data from {@code source} and write it to {@code sink}. This doesn't use {@link\n   * BufferedSink#writeAll} because that method doesn't flush aggressively and we need that.\n   */\n  private void transfer(Socket sourceSocket, Source source, Sink sink) {\n    try {\n      Buffer buffer = new Buffer();\n      for (long byteCount; (byteCount = source.read(buffer, 8192L)) != -1; ) {\n        sink.write(buffer, byteCount);\n        sink.flush();\n      }\n    } catch (IOException e) {\n      System.out.println(\"transfer failed from \" + sourceSocket + \": \" + e);\n    } finally {\n      closeQuietly(sink);\n      closeQuietly(source);\n      closeQuietly(sourceSocket);\n      openSockets.remove(sourceSocket);\n    }\n  }\n\n  private void closeQuietly(Closeable c) {\n    try {\n      c.close();\n    } catch (IOException ignored) {\n    }\n  }\n\n  public static void main(String[] args) throws IOException {\n    SocksProxyServer proxyServer = new SocksProxyServer();\n    proxyServer.start();\n\n    URL url = new URL(\"https://publicobject.com/helloworld.txt\");\n    URLConnection connection = url.openConnection(proxyServer.proxy());\n    try (BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()))) {\n      for (String line; (line = source.readUtf8Line()) != null; ) {\n        System.out.println(line);\n      }\n    }\n\n    proxyServer.shutdown();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/SourceMarker.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport okio.Buffer;\nimport okio.BufferedSource;\nimport okio.ForwardingSource;\nimport okio.Okio;\nimport okio.Source;\n\n/**\n * Builds a buffered source that can rewind to a marked position earlier in the stream.\n *\n * <p>Mark potential positions to rewind back to with {@link #mark}; rewind back to these positions\n * with {@link #reset}. Both operations apply to the position in the {@linkplain #source() buffered\n * source}; resetting will impact the buffer.\n *\n * <p>When marking it is necessary to specify how much data to retain. Once you advance above this\n * limit, the mark is discarded and resetting is not permitted. This may be used to lookahead a\n * fixed number of bytes without loading an entire stream into memory. To reset an arbitrary\n * number of bytes use {@code mark(Long#MAX_VALUE)}.\n */\npublic final class SourceMarker {\n\n  /*\n   * This class wraps the underlying source in a MarkSource to support mark and reset. It creates a\n   * BufferedSource for the caller so that it can track its offsets and manipulate its buffer.\n   */\n\n  /**\n   * The offset into the underlying source. To compute the user's offset start with this and\n   * subtract userBuffer.size().\n   */\n  long offset;\n\n  /** The offset of the earliest mark, or -1 for no mark. */\n  long mark = -1L;\n\n  /** The offset of the latest readLimit, or -1 for no mark. */\n  long limit = -1L;\n\n  boolean closed;\n\n  final MarkSource markSource;\n  final BufferedSource userSource;\n\n  /** A copy of the underlying source's data beginning at {@code mark}. */\n  final Buffer markBuffer;\n\n  /** Just the userSource's buffer. */\n  final Buffer userBuffer;\n\n  public SourceMarker(Source source) {\n    this.markSource = new MarkSource(source);\n    this.markBuffer = new Buffer();\n    this.userSource = Okio.buffer(markSource);\n    this.userBuffer = userSource.getBuffer();\n  }\n\n  public BufferedSource source() {\n    return userSource;\n  }\n\n  /**\n   * Marks the current position in the stream as one to potentially return back to. Returns the\n   * offset of this position. Call {@link #reset(long)} with this position to return to it later. It\n   * is an error to call {@link #reset(long)} after consuming more than {@code readLimit} bytes from\n   * {@linkplain #source() the source}.\n   */\n  public long mark(long readLimit) throws IOException {\n    if (readLimit < 0L) {\n      throw new IllegalArgumentException(\"readLimit < 0: \" + readLimit);\n    }\n\n    if (closed) {\n      throw new IllegalStateException(\"closed\");\n    }\n\n    // Mark the current position in the buffered source.\n    long userOffset = offset - userBuffer.size();\n\n    // If this is a new mark promote userBuffer data into the markBuffer.\n    if (mark == -1L) {\n      markBuffer.writeAll(userBuffer);\n      mark = userOffset;\n      offset = userOffset;\n    }\n\n    // Grow the limit if necessary.\n    long newMarkBufferLimit = userOffset + readLimit;\n    if (newMarkBufferLimit < 0) newMarkBufferLimit = Long.MAX_VALUE; // Long overflow!\n    limit = Math.max(limit, newMarkBufferLimit);\n\n    return userOffset;\n  }\n\n  /** Resets {@linkplain #source() the source} to {@code userOffset}. */\n  public void reset(long userOffset) throws IOException {\n    if (closed) {\n      throw new IllegalStateException(\"closed\");\n    }\n\n    if (userOffset < mark // userOffset is before mark.\n        || userOffset > limit // userOffset is beyond limit.\n        || userOffset > mark + markBuffer.size() // userOffset is in the future.\n        || offset - userBuffer.size() > limit) { // Stream advanced beyond limit.\n      throw new IOException(\"cannot reset to \" + userOffset + \": out of range\");\n    }\n\n    // Clear userBuffer to cause data at 'offset' to be returned by the next read.\n    offset = userOffset;\n    userBuffer.clear();\n  }\n\n  final class MarkSource extends ForwardingSource {\n    MarkSource(Source source) {\n      super(source);\n    }\n\n    @Override public long read(Buffer sink, long byteCount) throws IOException {\n      if (closed) {\n        throw new IllegalStateException(\"closed\");\n      }\n\n      // If there's no mark, go to the underlying source.\n      if (mark == -1L) {\n        long result = super.read(sink, byteCount);\n        if (result == -1L) return -1L;\n        offset += result;\n        return result;\n      }\n\n      // If we can read from markBuffer, do that.\n      if (offset < mark + markBuffer.size()) {\n        long posInBuffer = offset - mark;\n        long result = Math.min(byteCount, markBuffer.size() - posInBuffer);\n        markBuffer.copyTo(sink, posInBuffer, result);\n        offset += result;\n        return result;\n      }\n\n      // If we can write to markBuffer, do that.\n      if (offset < limit) {\n        long byteCountBeforeLimit = limit - (mark + markBuffer.size());\n        long result = super.read(markBuffer, Math.min(byteCount, byteCountBeforeLimit));\n        if (result == -1L) return -1L;\n        markBuffer.copyTo(sink, markBuffer.size() - result, result);\n        offset += result;\n        return result;\n      }\n\n      // Attempt to read past the limit. Data will not be saved.\n      long result = super.read(sink, byteCount);\n      if (result == -1L) return -1L;\n\n      // We read past the limit. Discard marked data.\n      markBuffer.clear();\n      mark = -1L;\n      limit = -1L;\n      return result;\n    }\n\n    @Override public void close() throws IOException {\n      if (closed) return;\n\n      closed = true;\n      markBuffer.clear();\n      super.close();\n    }\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/WriteFile.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.IOException;\nimport java.util.Map;\nimport okio.BufferedSink;\nimport okio.FileSystem;\nimport okio.Okio;\nimport okio.Path;\nimport okio.Sink;\n\npublic final class WriteFile {\n  public void run() throws Exception {\n    writeEnv(Path.get(\"env.txt\"));\n  }\n\n  public void writeEnv(Path path) throws IOException {\n    try (Sink fileSink = FileSystem.SYSTEM.sink(path);\n         BufferedSink bufferedSink = Okio.buffer(fileSink)) {\n\n      for (Map.Entry<String, String> entry : System.getenv().entrySet()) {\n        bufferedSink.writeUtf8(entry.getKey());\n        bufferedSink.writeUtf8(\"=\");\n        bufferedSink.writeUtf8(entry.getValue());\n        bufferedSink.writeUtf8(\"\\n\");\n      }\n\n    }\n  }\n\n  public static void main(String... args) throws Exception {\n    new WriteFile().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/java/okio/samples/WriteJavaIoFile.java",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.Map;\nimport okio.BufferedSink;\nimport okio.Okio;\nimport okio.Sink;\n\npublic final class WriteJavaIoFile {\n  public void run() throws Exception {\n    writeEnv(new File(\"env.txt\"));\n  }\n\n  public void writeEnv(File file) throws IOException {\n    try (Sink fileSink = Okio.sink(file);\n         BufferedSink bufferedSink = Okio.buffer(fileSink)) {\n\n      for (Map.Entry<String, String> entry : System.getenv().entrySet()) {\n        bufferedSink.writeUtf8(entry.getKey());\n        bufferedSink.writeUtf8(\"=\");\n        bufferedSink.writeUtf8(entry.getValue());\n        bufferedSink.writeUtf8(\"\\n\");\n      }\n\n    }\n  }\n\n  public static void main(String... args) throws Exception {\n    new WriteFile().run();\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/BitmapEncoder.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport kotlin.math.hypot\nimport okio.BufferedSink\nimport okio.FileSystem\nimport okio.IOException\nimport okio.Path\nimport okio.Path.Companion.toPath\n\nclass KotlinBitmapEncoder {\n  class Bitmap(\n    private val pixels: Array<IntArray>,\n  ) {\n    val width: Int = pixels[0].size\n    val height: Int = pixels.size\n\n    fun red(x: Int, y: Int): Int = pixels[y][x] and 0xff0000 shr 16\n\n    fun green(x: Int, y: Int): Int = pixels[y][x] and 0xff00 shr 8\n\n    fun blue(x: Int, y: Int): Int = pixels[y][x] and 0xff\n  }\n\n  /**\n   * Returns a bitmap that lights up red subpixels at the bottom, green subpixels on the right, and\n   * blue subpixels in bottom-right.\n   */\n  fun generateGradient(): Bitmap {\n    val pixels = Array(1080) { IntArray(1920) }\n    for (y in 0 until 1080) {\n      for (x in 0 until 1920) {\n        val r = (y / 1080f * 255).toInt()\n        val g = (x / 1920f * 255).toInt()\n        val b = (hypot(x.toDouble(), y.toDouble()) / hypot(1080.0, 1920.0) * 255).toInt()\n        pixels[y][x] = r shl 16 or (g shl 8) or b\n      }\n    }\n    return Bitmap(pixels)\n  }\n\n  @Throws(IOException::class)\n  fun encode(bitmap: Bitmap, fileSystem: FileSystem, path: Path) {\n    fileSystem.write(path) { encode(bitmap, this) }\n  }\n\n  /** https://en.wikipedia.org/wiki/BMP_file_format  */\n  @Throws(IOException::class)\n  fun encode(bitmap: Bitmap, sink: BufferedSink) {\n    val height = bitmap.height\n    val width = bitmap.width\n    val bytesPerPixel = 3\n    val rowByteCountWithoutPadding = bytesPerPixel * width\n    val rowByteCount = (rowByteCountWithoutPadding + 3) / 4 * 4\n    val pixelDataSize = rowByteCount * height\n    val bmpHeaderSize = 14\n    val dibHeaderSize = 40\n\n    // BMP Header\n    sink.writeUtf8(\"BM\") // ID.\n    sink.writeIntLe(bmpHeaderSize + dibHeaderSize + pixelDataSize) // File size.\n    sink.writeShortLe(0) // Unused.\n    sink.writeShortLe(0) // Unused.\n    sink.writeIntLe(bmpHeaderSize + dibHeaderSize) // Offset of pixel data.\n\n    // DIB Header\n    sink.writeIntLe(dibHeaderSize)\n    sink.writeIntLe(width)\n    sink.writeIntLe(height)\n    sink.writeShortLe(1) // Color plane count.\n    sink.writeShortLe(bytesPerPixel * Byte.SIZE_BITS)\n    sink.writeIntLe(0) // No compression.\n    sink.writeIntLe(16) // Size of bitmap data including padding.\n    sink.writeIntLe(2835) // Horizontal print resolution in pixels/meter. (72 dpi).\n    sink.writeIntLe(2835) // Vertical print resolution in pixels/meter. (72 dpi).\n    sink.writeIntLe(0) // Palette color count.\n    sink.writeIntLe(0) // 0 important colors.\n\n    // Pixel data.\n    for (y in height - 1 downTo 0) {\n      for (x in 0 until width) {\n        sink.writeByte(bitmap.blue(x, y))\n        sink.writeByte(bitmap.green(x, y))\n        sink.writeByte(bitmap.red(x, y))\n      }\n\n      // Padding for 4-byte alignment.\n      for (p in rowByteCountWithoutPadding until rowByteCount) {\n        sink.writeByte(0)\n      }\n    }\n  }\n}\n\nfun main() {\n  val encoder = KotlinBitmapEncoder()\n  val bitmap = encoder.generateGradient()\n  encoder.encode(bitmap, FileSystem.SYSTEM, \"gradient.bmp\".toPath())\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/ExploreCharsets.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport java.io.IOException\nimport okio.ByteString.Companion.encodeUtf8\nimport okio.utf8Size\n\n@Throws(IOException::class)\nfun dumpStringData(s: String) {\n  println(\"                       \" + s)\n  println(\"        String.length: \" + s.length)\n  println(\"String.codePointCount: \" + s.codePointCount(0, s.length))\n  println(\"            Utf8.size: \" + s.utf8Size())\n  println(\"          UTF-8 bytes: \" + s.encodeUtf8().hex())\n  println()\n}\n\nfun main() {\n  dumpStringData(\"Café \\uD83C\\uDF69\") // NFC: é is one code point.\n  dumpStringData(\"Café \\uD83C\\uDF69\") // NFD: e is one code point, its accent is another.\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/GoldenValue.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport java.io.IOException\nimport java.io.ObjectInputStream\nimport java.io.ObjectOutputStream\nimport java.io.Serializable\nimport okio.Buffer\nimport okio.ByteString\nimport okio.ByteString.Companion.decodeBase64\n\nclass KotlinGoldenValue {\n  fun run() {\n    val point = Point(8.0, 15.0)\n    val pointBytes = serialize(point)\n    println(pointBytes.base64())\n    val goldenBytes = (\n      \"rO0ABXNyACRva2lvLnNhbXBsZXMuS290bGluR29sZGVuVmFsdWUkUG9pbnRF9yaY7cJ9EwIAA\" +\n        \"kQAAXhEAAF5eHBAIAAAAAAAAEAuAAAAAAAA\"\n      ).decodeBase64()!!\n    val decoded = deserialize(goldenBytes) as Point\n    assertEquals(point, decoded)\n  }\n\n  @Throws(IOException::class)\n  private fun serialize(o: Any?): ByteString {\n    val buffer = Buffer()\n    ObjectOutputStream(buffer.outputStream()).use { objectOut ->\n      objectOut.writeObject(o)\n    }\n    return buffer.readByteString()\n  }\n\n  @Throws(IOException::class, ClassNotFoundException::class)\n  private fun deserialize(byteString: ByteString): Any? {\n    val buffer = Buffer()\n    buffer.write(byteString)\n    ObjectInputStream(buffer.inputStream()).use { objectIn ->\n      val result = objectIn.readObject()\n      if (objectIn.read() != -1) throw IOException(\"Unconsumed bytes in stream\")\n      return result\n    }\n  }\n\n  internal class Point(var x: Double, var y: Double) : Serializable\n\n  private fun assertEquals(\n    a: Point,\n    b: Point,\n  ) {\n    if (a.x != b.x || a.y != b.y) throw AssertionError()\n  }\n}\n\nfun main() {\n  KotlinGoldenValue().run()\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/Hashing.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport java.io.IOException\nimport okio.Buffer\nimport okio.ByteString\nimport okio.ByteString.Companion.decodeHex\nimport okio.FileSystem\nimport okio.HashingSink.Companion.sha256\nimport okio.HashingSource.Companion.sha256\nimport okio.Path\nimport okio.Path.Companion.toPath\nimport okio.blackholeSink\nimport okio.buffer\n\nclass KotlinHashing {\n  fun run() {\n    val path = \"../README.md\".toPath()\n\n    println(\"ByteString\")\n    val byteString = readByteString(path)\n    println(\"       md5: \" + byteString.md5().hex())\n    println(\"      sha1: \" + byteString.sha1().hex())\n    println(\"    sha256: \" + byteString.sha256().hex())\n    println(\"    sha512: \" + byteString.sha512().hex())\n    println()\n\n    println(\"Buffer\")\n    val buffer = readBuffer(path)\n    println(\"       md5: \" + buffer.md5().hex())\n    println(\"      sha1: \" + buffer.sha1().hex())\n    println(\"    sha256: \" + buffer.sha256().hex())\n    println(\"    sha512: \" + buffer.sha512().hex())\n    println()\n\n    println(\"HashingSource\")\n    sha256(FileSystem.SYSTEM.source(path)).use { hashingSource ->\n      hashingSource.buffer().use { source ->\n        source.readAll(blackholeSink())\n        println(\"    sha256: \" + hashingSource.hash.hex())\n      }\n    }\n    println()\n\n    println(\"HashingSink\")\n    sha256(blackholeSink()).use { hashingSink ->\n      hashingSink.buffer().use { sink ->\n        FileSystem.SYSTEM.source(path).use { source ->\n          sink.writeAll(source)\n          sink.close() // Emit anything buffered.\n          println(\"    sha256: \" + hashingSink.hash.hex())\n        }\n      }\n    }\n    println()\n\n    println(\"HMAC\")\n    val secret = \"7065616e7574627574746572\".decodeHex()\n    println(\"hmacSha256: \" + byteString.hmacSha256(secret).hex())\n    println()\n  }\n\n  @Throws(IOException::class)\n  fun readByteString(path: Path): ByteString {\n    return FileSystem.SYSTEM.read(path) { readByteString() }\n  }\n\n  @Throws(IOException::class)\n  fun readBuffer(path: Path): Buffer {\n    FileSystem.SYSTEM.read(path) {\n      val result = Buffer()\n      readAll(result)\n      return result\n    }\n  }\n}\n\nfun main() {\n  KotlinHashing().run()\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/ReadJavaIoFileLineByLine.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport java.io.File\nimport java.io.IOException\nimport okio.buffer\nimport okio.source\n\n@Throws(IOException::class)\nfun readLines(file: File) {\n  file.source().use { fileSource ->\n    fileSource.buffer().use { bufferedFileSource ->\n      while (true) {\n        val line = bufferedFileSource.readUtf8Line() ?: break\n        if (\"square\" in line) {\n          println(line)\n        }\n      }\n    }\n  }\n}\n\nfun main() {\n  readLines(File(\"../README.md\"))\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/SocksProxyServer.kt",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\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 */\npackage okio.samples\n\nimport java.io.IOException\nimport java.net.InetAddress\nimport java.net.InetSocketAddress\nimport java.net.ProtocolException\nimport java.net.Proxy\nimport java.net.ServerSocket\nimport java.net.Socket\nimport java.net.URL\nimport java.util.Collections\nimport java.util.concurrent.ConcurrentHashMap\nimport java.util.concurrent.Executors\nimport okio.Buffer\nimport okio.BufferedSink\nimport okio.Sink\nimport okio.Source\nimport okio.buffer\nimport okio.sink\nimport okio.source\n\nprivate const val VERSION_5 = 5\nprivate const val METHOD_NO_AUTHENTICATION_REQUIRED = 0\nprivate const val ADDRESS_TYPE_IPV4 = 1\nprivate const val ADDRESS_TYPE_DOMAIN_NAME = 3\nprivate const val COMMAND_CONNECT = 1\nprivate const val REPLY_SUCCEEDED = 0\n\n/**\n * A partial implementation of SOCKS Protocol Version 5.\n * See [RFC 1928](https://www.ietf.org/rfc/rfc1928.txt).\n */\nclass KotlinSocksProxyServer {\n  private val executor = Executors.newCachedThreadPool()\n  private lateinit var serverSocket: ServerSocket\n  private val openSockets: MutableSet<Socket> = Collections.newSetFromMap(ConcurrentHashMap())\n\n  @Throws(IOException::class)\n  fun start() {\n    serverSocket = ServerSocket(0)\n    executor.execute { acceptSockets() }\n  }\n\n  @Throws(IOException::class)\n  fun shutdown() {\n    serverSocket.close()\n    executor.shutdown()\n  }\n\n  fun proxy(): Proxy = Proxy(\n    Proxy.Type.SOCKS,\n    InetSocketAddress.createUnresolved(\"localhost\", serverSocket.localPort),\n  )\n\n  private fun acceptSockets() {\n    try {\n      while (true) {\n        val from = serverSocket.accept()\n        openSockets.add(from)\n        executor.execute { handleSocket(from) }\n      }\n    } catch (e: IOException) {\n      println(\"shutting down: $e\")\n    } finally {\n      for (socket in openSockets) {\n        socket.close()\n      }\n    }\n  }\n\n  private fun handleSocket(fromSocket: Socket) {\n    try {\n      val fromSource = fromSocket.source().buffer()\n      val fromSink = fromSocket.sink().buffer()\n\n      // Read the hello.\n      val socksVersion = fromSource.readByte().toInt() and 0xff\n      if (socksVersion != VERSION_5) throw ProtocolException()\n      val methodCount = fromSource.readByte().toInt() and 0xff\n      var foundSupportedMethod = false\n      for (i in 0 until methodCount) {\n        val method: Int = fromSource.readByte().toInt() and 0xff\n        foundSupportedMethod = foundSupportedMethod or (method == METHOD_NO_AUTHENTICATION_REQUIRED)\n      }\n      if (!foundSupportedMethod) throw ProtocolException()\n\n      // Respond to hello.\n      fromSink.writeByte(VERSION_5)\n        .writeByte(METHOD_NO_AUTHENTICATION_REQUIRED)\n        .emit()\n\n      // Read a command.\n      val version = fromSource.readByte().toInt() and 0xff\n      val command = fromSource.readByte().toInt() and 0xff\n      val reserved = fromSource.readByte().toInt() and 0xff\n      if (version != VERSION_5 || command != COMMAND_CONNECT || reserved != 0) {\n        throw ProtocolException()\n      }\n\n      // Read an address.\n      val addressType = fromSource.readByte().toInt() and 0xff\n      val inetAddress = when (addressType) {\n        ADDRESS_TYPE_IPV4 -> InetAddress.getByAddress(fromSource.readByteArray(4L))\n        ADDRESS_TYPE_DOMAIN_NAME -> {\n          val domainNameLength: Int = fromSource.readByte().toInt() and 0xff\n          InetAddress.getByName(fromSource.readUtf8(domainNameLength.toLong()))\n        }\n        else -> throw ProtocolException()\n      }\n      val port = fromSource.readShort().toInt() and 0xffff\n\n      // Connect to the caller's specified host.\n      val toSocket = Socket(inetAddress, port)\n      openSockets.add(toSocket)\n      val localAddress = toSocket.localAddress.address\n      if (localAddress.size != 4) throw ProtocolException()\n\n      // Write the reply.\n      fromSink.writeByte(VERSION_5)\n        .writeByte(REPLY_SUCCEEDED)\n        .writeByte(0)\n        .writeByte(ADDRESS_TYPE_IPV4)\n        .write(localAddress)\n        .writeShort(toSocket.localPort)\n        .emit()\n\n      // Connect sources to sinks in both directions.\n      val toSink = toSocket.sink()\n      executor.execute { transfer(fromSocket, fromSource, toSink) }\n      val toSource = toSocket.source()\n      executor.execute { transfer(toSocket, toSource, fromSink) }\n    } catch (e: IOException) {\n      fromSocket.close()\n      openSockets.remove(fromSocket)\n      println(\"connect failed for $fromSocket: $e\")\n    }\n  }\n\n  /**\n   * Read data from `source` and write it to `sink`. This doesn't use [BufferedSink.writeAll]\n   * because that method doesn't flush aggressively and we need that.\n   */\n  private fun transfer(sourceSocket: Socket, source: Source, sink: Sink) {\n    try {\n      val buffer = Buffer()\n      var byteCount: Long\n      while (source.read(buffer, 8192L).also { byteCount = it } != -1L) {\n        sink.write(buffer, byteCount)\n        sink.flush()\n      }\n    } catch (e: IOException) {\n      println(\"transfer failed from $sourceSocket: $e\")\n    } finally {\n      sink.close()\n      source.close()\n      sourceSocket.close()\n      openSockets.remove(sourceSocket)\n    }\n  }\n}\n\nfun main() {\n  val proxyServer = KotlinSocksProxyServer()\n  proxyServer.start()\n\n  val url = URL(\"https://publicobject.com/helloworld.txt\")\n  val connection = url.openConnection(proxyServer.proxy())\n  connection.getInputStream().source().buffer().use { source ->\n    generateSequence { source.readUtf8Line() }\n      .forEach(::println)\n  }\n\n  proxyServer.shutdown()\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/TeeSink.kt",
    "content": "/*\n * Copyright (C) 2024 Square, Inc.\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 */\npackage okio.samples\n\nimport okio.Buffer\nimport okio.FileSystem\nimport okio.Path.Companion.toPath\nimport okio.Sink\nimport okio.Timeout\nimport okio.buffer\nimport okio.sink\n\n/**\n * A sink that writes all input to both [sinkA] and [sinkB].\n */\nclass TeeSink(\n  private val sinkA: Sink,\n  private val sinkB: Sink,\n) : Sink {\n  private val timeout = Timeout()\n\n  override fun write(source: Buffer, byteCount: Long) {\n    // Writing to sink mutates source. Work around that.\n    sinkA.timeout().intersectWith(timeout) {\n      val buffer = Buffer()\n      source.copyTo(buffer, byteCount = byteCount)\n      sinkA.write(buffer, byteCount)\n    }\n\n    sinkB.timeout().intersectWith(timeout) {\n      sinkB.write(source, byteCount)\n    }\n  }\n\n  override fun flush() {\n    sinkA.flush()\n    sinkB.flush()\n  }\n\n  override fun close() {\n    try {\n      sinkA.close()\n    } catch (tA: Throwable) {\n      try {\n        sinkB.close()\n      } catch (tB: Throwable) {\n        tA.addSuppressed(tB)\n      }\n      throw tA\n    }\n\n    sinkB.close()\n  }\n\n  override fun timeout() = sinkA.timeout()\n}\n\nfun main() {\n  val a = System.out.sink()\n  val b = FileSystem.SYSTEM.sink(\"tee.txt\".toPath())\n\n  TeeSink(a, b).buffer().use { teeSink ->\n    teeSink.writeUtf8(\"hello\\n\")\n    teeSink.flush()\n    teeSink.writeUtf8(\"world!\")\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/WriteFile.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport okio.FileSystem\nimport okio.IOException\nimport okio.Path\nimport okio.Path.Companion.toPath\nimport okio.buffer\n\n@Throws(IOException::class)\nfun writeEnv(path: Path) {\n  FileSystem.SYSTEM.sink(path).buffer().use { sink ->\n    for ((key, value) in System.getenv()) {\n      sink.writeUtf8(key)\n      sink.writeUtf8(\"=\")\n      sink.writeUtf8(value)\n      sink.writeUtf8(\"\\n\")\n    }\n  }\n}\n\nfun main() {\n  writeEnv(\"env.txt\".toPath())\n}\n"
  },
  {
    "path": "samples/src/jvmMain/kotlin/okio/samples/WriteJavaIoFile.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport java.io.File\nimport java.io.IOException\nimport okio.buffer\nimport okio.sink\n\n@Throws(IOException::class)\nfun writeEnv(file: File) {\n  file.sink().buffer().use { sink ->\n    for ((key, value) in System.getenv()) {\n      sink.writeUtf8(key)\n      sink.writeUtf8(\"=\")\n      sink.writeUtf8(value)\n      sink.writeUtf8(\"\\n\")\n    }\n  }\n}\n\nfun main() {\n  writeEnv(File(\"env.txt\"))\n}\n"
  },
  {
    "path": "samples/src/jvmTest/java/okio/samples/ChannelsTest.kt",
    "content": "/*\n * Copyright (C) 2018 Square, Inc.\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 */\npackage okio.samples\n\nimport assertk.assertThat\nimport assertk.assertions.isEqualTo\nimport java.nio.channels.FileChannel\nimport java.nio.channels.ReadableByteChannel\nimport java.nio.file.Files\nimport java.nio.file.StandardOpenOption\nimport java.util.EnumSet\nimport okio.Buffer\nimport okio.Timeout\nimport okio.buffer\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertTrue\nimport org.junit.Rule\nimport org.junit.Test\nimport org.junit.rules.TemporaryFolder\n\nclass ChannelsTest {\n  @JvmField\n  @Rule\n  var temporaryFolder = TemporaryFolder()\n\n  @Test\n  fun testReadChannel() {\n    val channel: ReadableByteChannel = Buffer().writeUtf8(quote)\n\n    val buffer = Buffer()\n    val source = ByteChannelSource(channel, Timeout.NONE)\n    source.read(buffer, 75)\n\n    assertThat(buffer.readUtf8())\n      .isEqualTo(\"John, the kind of control you're attempting simply is... it's not possible.\")\n  }\n\n  @Test\n  fun testReadChannelFully() {\n    val channel: ReadableByteChannel = Buffer().writeUtf8(quote)\n\n    val source = ByteChannelSource(channel, Timeout.NONE).buffer()\n    assertThat(source.readUtf8())\n      .isEqualTo(quote)\n  }\n\n  @Test\n  fun testWriteChannel() {\n    val channel = Buffer()\n\n    val sink = ByteChannelSink(channel, Timeout.NONE)\n    sink.write(Buffer().writeUtf8(quote), 75)\n\n    assertThat(channel.readUtf8())\n      .isEqualTo(\"John, the kind of control you're attempting simply is... it's not possible.\")\n  }\n\n  @Test\n  fun testReadWriteFile() {\n    val path = temporaryFolder.newFile().toPath()\n\n    val sink = FileChannelSink(FileChannel.open(path, w), Timeout.NONE)\n    sink.write(Buffer().writeUtf8(quote), 317)\n    sink.close()\n    assertTrue(Files.exists(path))\n    assertEquals(quote.length.toLong(), Files.size(path))\n\n    val buffer = Buffer()\n    val source = FileChannelSource(FileChannel.open(path, r), Timeout.NONE)\n\n    source.read(buffer, 44)\n    assertThat(buffer.readUtf8())\n      .isEqualTo(\"John, the kind of control you're attempting \")\n\n    source.read(buffer, 31)\n    assertThat(buffer.readUtf8())\n      .isEqualTo(\"simply is... it's not possible.\")\n  }\n\n  @Test\n  fun testAppend() {\n    val path = temporaryFolder.newFile().toPath()\n    val buffer = Buffer().writeUtf8(quote)\n\n    FileChannelSink(FileChannel.open(path, w), Timeout.NONE).use { sink ->\n      sink.write(buffer, 75)\n    }\n    assertTrue(Files.exists(path))\n    assertEquals(75, Files.size(path))\n\n    FileChannelSource(FileChannel.open(path, r), Timeout.NONE).buffer().use { source ->\n      assertThat(source.readUtf8())\n        .isEqualTo(\"John, the kind of control you're attempting simply is... it's not possible.\")\n    }\n\n    FileChannelSink(FileChannel.open(path, append), Timeout.NONE).use { sink ->\n      sink.write(buffer, buffer.size)\n    }\n    assertTrue(Files.exists(path))\n    assertEquals(quote.length.toLong(), Files.size(path))\n\n    FileChannelSource(FileChannel.open(path, r), Timeout.NONE).buffer().use { source ->\n      assertThat(source.readUtf8())\n        .isEqualTo(quote)\n    }\n  }\n\n  companion object {\n    private val quote =\n      \"John, the kind of control you're attempting simply is... it's not \" +\n        \"possible. If there is one thing the history of evolution has \" +\n        \"taught us it's that life will not be contained. Life breaks \" +\n        \"free, it expands to new territories and crashes through \" +\n        \"barriers, painfully, maybe even dangerously, but, uh... well, \" +\n        \"there it is.\"\n\n    private val r = EnumSet.of(\n      StandardOpenOption.READ,\n    )\n    private val w = EnumSet.of(\n      StandardOpenOption.WRITE,\n    )\n    private val append = EnumSet.of(\n      StandardOpenOption.WRITE,\n      StandardOpenOption.APPEND,\n    )\n  }\n}\n"
  },
  {
    "path": "samples/src/jvmTest/java/okio/samples/SourceMarkerTest.kt",
    "content": "/*\n * Copyright (C) 2013 Square, Inc.\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 */\npackage okio.samples\n\nimport assertk.assertThat\nimport assertk.assertions.hasMessage\nimport assertk.assertions.isEqualTo\nimport java.io.IOException\nimport java.util.Arrays\nimport okio.Buffer\nimport org.junit.Assert.fail\nimport org.junit.Test\n\nclass SourceMarkerTest {\n  @Test\n  fun test() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    assertThat(source.readUtf8(3)).isEqualTo(\"ABC\")\n    val pos3 = marker.mark(7) // DEFGHIJ\n    assertThat(source.readUtf8(4)).isEqualTo(\"DEFG\")\n    val pos7 = marker.mark(5) // HIJKL\n    assertThat(source.readUtf8(4)).isEqualTo(\"HIJK\")\n    marker.reset(pos7) // Back to 'H'\n    assertThat(source.readUtf8(3)).isEqualTo(\"HIJ\")\n    marker.reset(pos3) // Back to 'D'\n    assertThat(source.readUtf8(7)).isEqualTo(\"DEFGHIJ\")\n    marker.reset(pos7) // Back to 'H' again.\n    assertThat(source.readUtf8(6)).isEqualTo(\"HIJKLM\")\n    try {\n      marker.reset(pos7)\n      fail()\n    } catch (expected: IOException) {\n      assertThat(expected)\n        .hasMessage(\"cannot reset to 7: out of range\")\n    }\n    try {\n      marker.reset(pos3)\n      fail()\n    } catch (expected: IOException) {\n      assertThat(expected)\n        .hasMessage(\"cannot reset to 3: out of range\")\n    }\n  }\n\n  @Test\n  fun exceedLimitTest() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    assertThat(source.readUtf8(3)).isEqualTo(\"ABC\")\n    val pos3 = marker.mark(Long.MAX_VALUE) // D...\n    assertThat(source.readUtf8(4)).isEqualTo(\"DEFG\")\n    val pos7 = marker.mark(5) // H...\n    assertThat(source.readUtf8(4)).isEqualTo(\"HIJK\")\n    marker.reset(pos7) // Back to 'H'\n    assertThat(source.readUtf8(3)).isEqualTo(\"HIJ\")\n    marker.reset(pos3) // Back to 'D'\n    assertThat(source.readUtf8(7)).isEqualTo(\"DEFGHIJ\")\n    marker.reset(pos7) // Back to 'H' again.\n    assertThat(source.readUtf8(6)).isEqualTo(\"HIJKLM\")\n\n    marker.reset(pos7) // Back to 'H' again despite the original limit being exceeded\n    assertThat(source.readUtf8(2)).isEqualTo(\"HI\") // confirm we're really back at H\n\n    marker.reset(pos3) // Back to 'D' again despite the original limit being exceeded\n    assertThat(source.readUtf8(2))\n      .isEqualTo(\"DE\") // confirm that we're really back at D\n  }\n\n  @Test\n  fun markAndLimitSmallerThanUserBuffer() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    // Load 5 bytes into the user buffer, then mark 0..3 and confirm that resetting from 4 fails.\n    source.require(5)\n    val pos0 = marker.mark(3)\n    assertThat(source.readUtf8(3)).isEqualTo(\"ABC\")\n    marker.reset(pos0)\n    assertThat(source.readUtf8(4)).isEqualTo(\"ABCD\")\n    try {\n      marker.reset(pos0)\n      fail()\n    } catch (expected: IOException) {\n      assertThat(expected).hasMessage(\"cannot reset to 0: out of range\")\n    }\n  }\n\n  @Test\n  fun resetTooLow() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    source.skip(3)\n    marker.mark(3)\n    source.skip(2)\n    try {\n      marker.reset(2)\n      fail()\n    } catch (expected: IOException) {\n      assertThat(expected).hasMessage(\"cannot reset to 2: out of range\")\n    }\n  }\n\n  @Test\n  fun resetTooHigh() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    marker.mark(3)\n    source.skip(6)\n    try {\n      marker.reset(4)\n      fail()\n    } catch (expected: IOException) {\n      assertThat(expected).hasMessage(\"cannot reset to 4: out of range\")\n    }\n  }\n\n  @Test\n  fun resetUnread() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n\n    marker.mark(3)\n    try {\n      marker.reset(2)\n      fail()\n    } catch (expected: IOException) {\n      assertThat(expected).hasMessage(\"cannot reset to 2: out of range\")\n    }\n  }\n\n  @Test\n  fun markNothingBuffered() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    val pos0 = marker.mark(5)\n    assertThat(source.readUtf8(4)).isEqualTo(\"ABCD\")\n    marker.reset(pos0)\n    assertThat(source.readUtf8(6)).isEqualTo(\"ABCDEF\")\n  }\n\n  @Test\n  fun mark0() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    val pos0 = marker.mark(0)\n    marker.reset(pos0)\n    assertThat(source.readUtf8(3)).isEqualTo(\"ABC\")\n  }\n\n  @Test\n  fun markNegative() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n\n    try {\n      marker.mark(-1L)\n      fail()\n    } catch (expected: IllegalArgumentException) {\n      assertThat(expected).hasMessage(\"readLimit < 0: -1\")\n    }\n  }\n\n  @Test\n  fun resetAfterEof() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDE\"))\n    val source = marker.source()\n\n    val pos0 = marker.mark(5)\n    assertThat(source.readUtf8()).isEqualTo(\"ABCDE\")\n    marker.reset(pos0)\n    assertThat(source.readUtf8(3)).isEqualTo(\"ABC\")\n  }\n\n  @Test\n  fun closeThenMark() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    source.close()\n    try {\n      marker.mark(5)\n      fail()\n    } catch (expected: IllegalStateException) {\n      assertThat(expected).hasMessage(\"closed\")\n    }\n  }\n\n  @Test\n  fun closeThenReset() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    val pos0 = marker.mark(5)\n    source.close()\n    try {\n      marker.reset(pos0)\n      fail()\n    } catch (expected: IllegalStateException) {\n      assertThat(expected).hasMessage(\"closed\")\n    }\n  }\n\n  @Test\n  fun closeThenRead() {\n    val marker = SourceMarker(Buffer().writeUtf8(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n    val source = marker.source()\n\n    source.close()\n    try {\n      source.readUtf8(3)\n      fail()\n    } catch (expected: IllegalStateException) {\n      assertThat(expected).hasMessage(\"closed\")\n    }\n  }\n\n  @Test\n  fun multipleSegments() {\n    val `as` = repeat('a', 10000)\n    val bs = repeat('b', 10000)\n    val cs = repeat('c', 10000)\n    val ds = repeat('d', 10000)\n\n    val marker = SourceMarker(Buffer().writeUtf8(`as` + bs + cs + ds))\n    val source = marker.source()\n\n    assertThat(source.readUtf8(10000)).isEqualTo(`as`)\n    val pos10k = marker.mark(15000)\n    assertThat(source.readUtf8(10000)).isEqualTo(bs)\n    val pos20k = marker.mark(15000)\n    assertThat(source.readUtf8(10000)).isEqualTo(cs)\n    marker.reset(pos20k)\n    marker.reset(pos10k)\n    assertThat(source.readUtf8(30000)).isEqualTo(bs + cs + ds)\n  }\n\n  private fun repeat(c: Char, count: Int): String {\n    val array = CharArray(count)\n    Arrays.fill(array, c)\n    return String(array)\n  }\n}\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "rootProject.name = \"okio-parent\"\n\nincludeBuild(\"build-support\")\n\ninclude(\":okio\")\ninclude(\":okio-assetfilesystem\")\ninclude(\":okio-bom\")\ninclude(\":okio-fakefilesystem\")\nif (System.getProperty(\"kjs\", \"true\").toBoolean()) {\n  include(\":okio-nodefilesystem\")\n}\ninclude(\":okio-testing-support\")\ninclude(\":okio:jvm:jmh\")\nif (System.getProperty(\"kwasm\", \"true\").toBoolean()) {\n  include(\":okio-wasifilesystem\")\n}\ninclude(\":samples\")\n\n// The Android test module doesn't work in IntelliJ. Use Android Studio or the command line.\nif (System.getProperties().containsKey(\"android.injected.invoked.from.ide\") ||\n  System.getenv(\"ANDROID_HOME\") != null) {\n  include(\":android-test\")\n}\n\nenableFeaturePreview(\"TYPESAFE_PROJECT_ACCESSORS\")\n"
  }
]