[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*.rs]\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nindent_style = space\nindent_size = 4\ntab_width = 4\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text eol=lf\n\n# Denote all files that are truly binary and should not be modified.\n*.png binary\n*.jpg binary\n*.gif binary\n*.svg binary\n"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "# Rocket Community Code of Conduct\n\nLike the technical community as a whole, the Rocket project, its teams, and its\ncommunity are made up of a mixture of professionals and volunteers from all over\nthe world, working on every aspect of the mission. Diversity is one of our huge\nstrengths, but it can also lead to communication issues and unhappiness. To that\nend, we have a few ground rules that we ask people to adhere to. This code\napplies equally to everyone in our community: maintainers, contributors, team\nleads, mentors, those seeking help and guidance, and so on.\n\nThis isn’t an exhaustive list of things that you can’t do. Rather, take it in\nthe spirit in which it’s intended - a guide to make it easier to enrich all of\nus and the technical communities in which we participate.\n\n_If you believe someone is violating the code of conduct, we ask that you report\nit by emailing community@rwf2.org._\n\n- **Be friendly. Be Kind. Be patient.**\n\n- **Be welcoming.** We strive to be a community that welcomes and supports\n  everyone, of all backgrounds and identities. This includes, but is not limited\n  to members of any race, ethnicity, culture, national origin, color,\n  immigration status, social and economic class, educational level, sex, sexual\n  orientation, gender identity and expression, age, size, family status,\n  political belief, religion, and mental and physical ability.\n\n- **Be considerate.** Your work will be used by other people, and you in turn\n  will depend on the work of others. Any decision you take will affect users and\n  colleagues, and you should take those consequences into account when making\n  decisions. Remember that we're a global community, so you might not be\n  communicating in someone else's primary language.\n\n- **Be respectful.** We won't all agree all the time, but disagreement isn't an\n  excuse for poor behavior or poor manners. While frustrations may occasionally\n  arise, we cannot allow those frustrations to turn into personal attacks.\n  Remember that a community where people feel uncomfortable or threatened is not\n  a productive one. Be respectful, not just to fellow community members, but to\n  individuals outside the community as well.\n\n- **Be careful in the words that you choose.** We are a community of\n  professionals, and we conduct ourselves professionally. Do not insult or put\n  down other participants. Harassment and other exclusionary behavior aren't\n  acceptable. This includes, but is not limited to:\n  - Violent threats or language directed against another person.\n  - Discriminatory jokes and language.\n  - Posting sexually explicit or violent material.\n  - Posting (or threatening to post) other people's personally identifying\n    information (\"doxing\").\n  - Personal insults, especially those using racist or sexist terms.\n  - Unwelcome sexual attention.\n  - Advocating for, or encouraging, any of the above behavior.\n  - Repeated harassment of others. In general, if someone asks you to stop, then\n    stop.\n\n- **Be understanding.** Disagreements, both social and technical, happen all the\n  time. It is important that we resolve differing views constructively. When we\n  disagree, try to understand why. Our community consists of people from a wide\n  range of backgrounds. Different people have different perspectives on issues.\n  Being unable to understand why someone holds a viewpoint doesn’t mean that\n  they’re wrong. Don’t forget that it is human to err; blame accomplishes\n  nothing. Instead, focus on helping to resolve issues and learning from\n  mistakes.\n\n_This code of conduct applies to all spaces managed by Rocket or the Rocket Web\nFramework Foundation including issues and discussions on GitHub, Matrix, and any\nother forums which the community uses for communication._\n\n_This Code of Conduct is adapted from the [Django Code of Conduct]. Original text\nfrom the [Speak Up! project]._\n\n[Django Code of Conduct]: https://www.djangoproject.com/conduct/\n[Speak Up! project]: http://web.archive.org/web/20141109123859/http://speakup.io/coc.html\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: rwf2\nopen_collective: rwf2\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: Bug Report\ndescription: Report a functionality issue that deviates from the documentation.\nlabels: [\"triage\"]\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        **Thanks for taking the time to fill out this bug report!** Your report\n        helps make Rocket better.\n\n\n        Please only report issues related to _functionality_ that deviates from\n        published specification or reasonable expectation. Do not report issues\n        with documentation, infrastructure, or anything unrelated to functional\n        correctness here.\n  - type: input\n    attributes:\n      label: Rocket Version\n      description: >\n        Enter the exact version of Rocket (x.y.z) or git shorthash (8d9dfce) you're using.\n\n\n        Please ensure you're using the latest release before reporting a bug.\n      placeholder: \"ex: 0.5.0\"\n    validations:\n      required: true\n  - type: input\n    attributes:\n      label: Operating System\n      description: Which operating system and version are you running?\n      placeholder: \"examples: macOS 13.6.2, Arch Linux 4.16.13\"\n    validations:\n      required: true\n  - type: input\n    attributes:\n      label: Rust Toolchain Version\n      description: Which version of `rustc` are you using? (`rustc --version`)\n      placeholder: \"ex: rustc 1.74.0 (79e9716c9 2023-11-13)\"\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: What happened?\n      description: Provide a brief overview of what went wrong.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Test Case\n      description: >\n        Provide a Rocket application that elicits the bug. Ideally the program\n        contains a `#[test]` case using Rocket's\n        [`local`](https://api.rocket.rs/v0.5/rocket/local/index.html) testing\n        module.\n      placeholder: >\n        #[macro_use] extern crate rocket;\n\n\n        #[launch]\n\n        fn rocket() -> _ {\n            rocket::build()\n        }\n\n\n        #[test]\n\n        fn failing_test() {\n            use rocket::local::blocking::Client;\n\n            let client = Client::tracked(rocket()).unwrap();\n            let response = client.get(\"/\").dispatch();\n            assert!(response.status().class().is_success());\n        }\n      render: rust\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Log Output\n      description: >\n        Please provide the complete log output captured with\n        `ROCKET_LOG_LEVEL=debug` when the test case is run.\n      placeholder: >\n        ❯ ROCKET_LOG_LEVEL=debug cargo test\n\n        running 1 test\n\n        test failing_test ... FAILED\n\n        failures:\n\n\n        ---- failing_test stdout ----\n\n        -- configuration trace information --\n           >> \"address\" parameter source: rocket::Config::default()\n           >> \"port\" parameter source: rocket::Config::default()\n           >> \"workers\" parameter source: rocket::Config::default()\n           >> \"max_blocking\" parameter source: rocket::Config::default()\n           >> \"keep_alive\" parameter source: rocket::Config::default()\n           >> \"ident\" parameter source: rocket::Config::default()\n           >> \"ip_header\" parameter source: rocket::Config::default()\n           >> \"limits\" parameter source: rocket::Config::default()\n           >> \"temp_dir\" parameter source: rocket::Config::default()\n           >> \"log_level\" parameter source: `ROCKET_` environment variable(s)\n           >> \"shutdown\" parameter source: rocket::Config::default()\n           >> \"cli_colors\" parameter source: rocket::Config::default()\n        🔧 Configured for debug.\n           >> address: 127.0.0.1\n           >> port: 8000\n           [...]\n      render: shell\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Additional Context\n      description: >\n        Feel free to provide any additional context for your bug report.\n  - type: checkboxes\n    attributes:\n      label: System Checks\n      description: \"Please confirm all of the following:\"\n      options:\n        - label: My bug report relates to functionality.\n          required: true\n        - label: I have tested against the latest Rocket release or a recent git commit.\n          required: true\n        - label: I have tested against the latest stable `rustc` toolchain.\n          required: true\n        - label: I was unable to find this issue previously reported.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: FAQ\n    url: https://rocket.rs/guide/faq/\n    about: Please see our FAQ for answers to common questions.\n  - name: Questions\n    url: https://github.com/rwf2/Rocket/discussions/new?category=questions\n    about: For other questions or help, please use GitHub discussions.\n  - name: Feedback\n    url: https://github.com/rwf2/Rocket/discussions/new/choose\n    about: For general chat or feedback, please use GitHub discussions.\n  - name: Chat\n    url: https://chat.mozilla.org/#/room/#rocket:mozilla.org\n    about: Chat with us live on rocket:mozilla.org on Matrix.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/doc-problem.yml",
    "content": "name: Documentation Problem\ndescription: Report an issue with or suggest documentation.\nlabels: [\"docs\"]\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        **Thanks for taking the time to report a documentation issue!**\n\n\n        Documentation problems include everything from typos to missing or\n        incorrect technical details in any of the following:\n          - [Rocket's Website](https://rocket.rs/)\n          - [The Rocket Programming Guide](https://rocket.rs/guide/)\n          - [API Docs](https://api.rocket.rs)\n          - [Content on GitHub](https://github.com/rwf2/Rocket)\n\n        If we've written it, we want to know how it can be improved.\n  - type: dropdown\n    validations:\n      required: true\n    attributes:\n      label: What kind of documentation problem are you reporting?\n      multiple: true\n      options:\n        - Typo (PRs welcome!)\n        - Unclear Docs\n        - Undocumented Feature\n        - Broken Links\n        - Rendering Issue\n        - Grammar Issue\n        - Technical Problem\n        - Other\n  - type: input\n    validations:\n      required: true\n    attributes:\n      label: Where is the issue found?\n      description: Please provide a direct link to the documentation.\n      placeholder: \"ex: https://rocket.rs/v0.5/guide/requests/#multiple-segments\"\n  - type: textarea\n    validations:\n      required: true\n    attributes:\n      label: What's wrong?\n      description: >\n        Please describe what's wrong with the documentation.\n  - type: checkboxes\n    attributes:\n      label: System Checks\n      description: \"Please confirm all of the following:\"\n      options:\n        - label: I confirmed that the issue still exists on `master` on GitHub.\n          required: true\n        - label: I was unable to find a previous report of this problem.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "content": "name: Feature Request\ndescription: Propose a change that introduces new functionality.\nlabels: [\"request\"]\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        **Thanks for taking the time to request a feature!** Your request helps\n        make Rocket better.\n\n\n        Please note that Rocket is designed to have a small but pluggable core.\n        Feature requests that can be implemented outside of Rocket _are\n        typically declined._ In your request, please make a strong case for why\n        this feature can't or shouldn't be implemented outside of Rocket.\n  - type: textarea\n    attributes:\n      label: What's missing?\n      description: >\n        Provide a brief overview of the functionality that's missing in Rocket\n        today, which problem(s) that functionality would solve for you, and what\n        the functionality would enable you to do.\n      placeholder: >\n        example: I frequently want to do X, but Rocket makes it hard. It would\n        be nice if Rocket...\n\n        example: I want to do X but Rocket makes it impossible because...\n\n        example: Feature Z exists, but it has these N drawbacks: [..]. What if...\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Ideal Solution\n      description: >\n        If you already have an idea of how this feature can be implemented,\n        please describe it here. Hypothetical code examples are particularly\n        useful.\n  - type: textarea\n    attributes:\n      label: Why can't this be implemented outside of Rocket?\n      description: >\n        Please make a strong case for why this feature can't or shouldn't be\n        implemented outside of Rocket. We are likely to decline feature requests\n        that can exist outside of Rocket without compromise.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Are there workarounds usable today?\n      description: >\n        If the functionality being requested can be achieved today, please detail\n        how here.\n  - type: textarea\n    attributes:\n      label: Alternative Solutions\n      description: >\n        If you have other ideas about how this feature can be implemented, let\n        us know.\n  - type: textarea\n    attributes:\n      label: Additional Context\n      description: >\n        Feel free to provide any additional context for your request.\n  - type: checkboxes\n    attributes:\n      label: System Checks\n      description: \"Please confirm all of the following:\"\n      options:\n        - label: I do not believe that this feature can or should be implemented outside of Rocket.\n          required: true\n        - label: I was unable to find a previous request for this feature.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/suggestion.yml",
    "content": "name: Suggestion\ndescription: Suggest a change or improvement to existing functionality.\nlabels: [\"suggestion\"]\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        **Thanks for taking the time to make a suggestion!**\n  - type: input\n    validations:\n      required: true\n    attributes:\n      label: API Docs to Existing Functionality\n      description: Please provide a direct link to the API docs for the\n        functionality you'd like to change.\n      placeholder: \"ex: https://api.rocket.rs/v0.5/rocket/trait.Sentinel.html\"\n  - type: textarea\n    validations:\n      required: true\n    attributes:\n      label: Problems with Existing Functionality\n      description: Please let us know what you think is wrong with the existing functionality.\n      placeholder: >\n        example: Sentinels don't allow me to access `Foo`, but I'd like to because...\n\n        example: Feature Z exists, but it has these drawbacks. What if...\n  - type: textarea\n    validations:\n      required: true\n    attributes:\n      label: Suggested Changes\n      description: >\n        How do you propose the existing functionality be changed? Code examples\n        are particular useful.\n  - type: textarea\n    validations:\n      required: true\n    attributes:\n      label: Alternatives Considered\n      description: >\n        Instead of making a change to Rocket, please describe alternative\n        solutions using existing features or new features you've considered.\n  - type: textarea\n    attributes:\n      label: Additional Context\n      description: Feel free to provide any additional context for your suggestion.\n  - type: checkboxes\n    attributes:\n      label: System Checks\n      description: \"Please confirm all of the following:\"\n      options:\n        - label: >\n            I do not believe that this suggestion can or should be implemented\n            outside of Rocket.\n          required: true\n        - label: I was unable to find a previous suggestion for this change.\n          required: true\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non: [push, pull_request]\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  test:\n    name: \"${{ matrix.platform.name }} ${{ matrix.test.name }} (${{ matrix.platform.toolchain }})\"\n    runs-on: ${{ matrix.platform.distro }}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        platform:\n          - { name: Linux, distro: ubuntu-latest, toolchain: stable }\n          - { name: Windows, distro: windows-latest, toolchain: stable }\n          - { name: macOS, distro: macOS-latest, toolchain: stable }\n          - { name: Linux, distro: ubuntu-latest, toolchain: nightly }\n        test:\n          - { name: Debug }\n          - { name: Examples, flag: \"--examples\" }\n          - { name: Contrib, flag: \"--contrib\" }\n        include:\n          # Additional tests on Linux/stable.\n          - platform: { name: Linux, distro: ubuntu-latest, toolchain: stable }\n            test: { name: Core, flag: \"--core\" }\n          - platform: { name: Linux, distro: ubuntu-latest, toolchain: stable }\n            test: { name: Release, flag: \"--release\" }\n          - platform: { name: Linux, distro: ubuntu-latest, toolchain: stable }\n            test: { name: Testbench, flag: \"--testbench\" }\n          - platform: { name: Linux, distro: ubuntu-latest, toolchain: stable }\n            test: { name: UI, flag: \"--ui\" }\n            fallible: true\n          # Allow tests on nightly to fail.\n          - platform: { toolchain: nightly }\n            fallible: true\n          # Use the bigger 'C:/' from the \"Switch Disk\" step\n          - platform: { name: Windows }\n            working-directory:\n              \"C:\\\\a\\\\${{ github.event.repository.name }}\\\\${{ github.event.repository.name }}\"\n\n    steps:\n      - name: Checkout Sources\n        uses: actions/checkout@v4\n\n      - name: Free Disk Space (Linux)\n        if: matrix.platform.name == 'Linux'\n        run: |\n            echo \"Freeing up disk space on Linux CI\"\n            df -h\n            sudo rm -rf /usr/share/dotnet/\n            sudo rm -rf /opt/ghc\n            sudo rm -rf /usr/local/share/boost\n            sudo rm -rf /usr/local/graalvm/\n            sudo rm -rf /usr/local/.ghcup/\n            sudo rm -rf /usr/local/share/powershell\n            sudo rm -rf /usr/local/share/chromium\n            sudo rm -rf /usr/local/lib/android\n            sudo rm -rf /usr/local/lib/node_modules\n            sudo rm -rf \"$AGENT_TOOLSDIRECTORY\"\n            sudo docker image prune --all --force\n            df -h\n\n      - name: Install Native Dependencies (macOS)\n        if: matrix.platform.name == 'macOS'\n        run: |\n            brew install mysql-client@8.4 libpq sqlite coreutils\n            brew link --force --overwrite mysql-client@8.4\n            brew link --force --overwrite libpq\n            echo \"/usr/local/opt/mysql-client/bin\" >> \"$GITHUB_PATH\"\n\n      # vcpkg --triplet x64-windows install libmysql libpq sqlite3 openssl\n      # + vcpkg/installed/vcpkg (in particular, the status file)\n      - name: Install Native Dependencies (Windows)\n        if: matrix.platform.name == 'Windows'\n        run: |\n          curl -fsLS -o vcpkg.7z https://blob.rocket.rs/vcpkg-2024-08-16.7z\n          7z x vcpkg.7z -y -bb0\n          xcopy .\\vcpkg $env:VCPKG_INSTALLATION_ROOT /s /e /h /y /q\n          vcpkg integrate install\n          echo \"VCPKGRS_DYNAMIC=1\" >> \"$env:GITHUB_ENV\"\n          echo \"VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT\" >> \"$env:GITHUB_ENV\"\n          echo \"$env:VCPKG_INSTALLATION_ROOT\\installed\\x64-windows\\lib\" >> \"$env:GITHUB_PATH\"\n          echo \"MYSQLCLIENT_VERSION=8.0.39\" >> \"$env:GITHUB_ENV\"\n\n      - name: Install NASM (Windows)\n        if: matrix.platform.name == 'Windows'\n        uses: ilammy/setup-nasm@v1\n\n      - name: Install Native Dependencies (Linux)\n        if: matrix.platform.name == 'Linux'\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y libmysqlclient-dev libpq-dev libsqlite3-dev\n\n      - name: Install Rust\n        uses: dtolnay/rust-toolchain@master\n        id: toolchain\n        with:\n          toolchain: ${{ matrix.platform.toolchain }}\n          components: rust-src\n\n      - name: Cache Example Workspace\n        if: matrix.test.name == 'Examples'\n        uses: Swatinem/rust-cache@v2\n        with:\n          workspaces: examples\n          key: ${{ matrix.test.name }}-${{ steps.toolchain.outputs.cachekey }}\n\n      - name: Cache Root Workspace\n        if: matrix.test.name != 'Examples'\n        uses: Swatinem/rust-cache@v2\n        with:\n          key: ${{ matrix.test.name }}-${{ steps.toolchain.outputs.cachekey }}\n\n      # Don't run out of disk space on Windows. C: has much much space than D:.\n      - name: Switch Disk (Windows)\n        if: matrix.platform.name == 'Windows'\n        run: |\n          Get-PSDrive\n          cp D:\\a C:\\ -Recurse\n          Get-PSDrive\n\n      - name: Run Tests\n        continue-on-error: ${{ matrix.fallible || false }}\n        working-directory: ${{ matrix.working-directory || github.workspace }}\n        run: ./scripts/test.sh ${{ matrix.test.flag || '' }} -q\n        shell: bash\n"
  },
  {
    "path": ".github/workflows/trigger.yaml",
    "content": "name: Trigger\non: [push]\njobs:\n  trigger:\n    name: api.rocket.rs\n    runs-on: ubuntu-latest\n    if: github.repository == 'rwf2/Rocket'\n    steps:\n      - uses: actions/github-script@v7\n        with:\n          github-token: ${{ secrets.API_DOCS_DEPLOY_TOKEN }}\n          script: |\n            github.rest.actions.createWorkflowDispatch({\n              owner: 'rwf2',\n              repo: 'api.rocket.rs',\n              workflow_id: 'deploy.yaml',\n              ref: 'master'\n            })\n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled files\n*.o\n*.so\n*.rlib\n*.dll\n\n# Executables\n*.exe\n\n# Generated by Cargo\ntarget\n\n# Generated databases\ndb.sqlite\ndb.sqlite-shm\ndb.sqlite-wal\n\n# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries\n# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html\nCargo.lock\n\n# Cargo config directory\n.cargo/\n\n# The upload script, for now.\nscripts/upload-docs.sh\nscripts/redirect.html\n\n# Backup files.\n*.bak\n\n# Uploads in pastebin example.\nexamples/pastebin/upload/*\n"
  },
  {
    "path": ".rustfmt.toml",
    "content": "disable_all_formatting = true\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Version 0.5.1 (May 22, 2024)\n\nThis release contains the following crate updates:\n\n  - `rocket` `0.5.1`\n  - `rocket_db_pools` `0.2.0`\n  - `rocket_dyn_templates` `0.2.0`\n  - `rocket_ws` `0.1.1`\n\n## [`rocket`](https://api.rocket.rs/v0.5/rocket/) `0.5.1`\n\n  * The following `char` and `std::ops::Range` types now implement `FromForm`:\n\n    - `char`\n    - `Range<T: FromForm>` with `start` and `end` fields\n    - `RangeFrom<T: FromForm>` with `start` field\n    - `RangeTo<T: FromForm>` with `end` field\n    - `RangeToInclusive<T: FromForm>` with `end` field\n\n  * `[T; N]`, `Vec<T>`, and `[u8]` can now be passed to `uri!`.\n\n  * The guide now includes a [deploying section].\n\n  * The `FromForm` derive now properly records errors involving entire forms.\n\n  * `FromForm` derive can now be used in code emitted by `macro_rules!` macros.\n\n  * **(fix [#2668] via [52de9a])** [`TempFile`] now ensures it flushes before\n    being persisted.\n\n## [`rocket_db_pools`](https://api.rocket.rs/v0.5/rocket_db_pools/) `0.2.0`\n\n  * SQLite extensions are now supported in `sqlx_sqlite`.\n\n    Use a database configuration option of `extensions` to specify extensions:\n\n    ```toml\n    [default.databases.db_name]\n    url = \"db.sqlite\"\n    # This option is only supported by the `sqlx_sqlite` driver.\n    extensions = [\"memvfs\", \"rot13\"]\n    ```\n\n  * (**breaking**) `deadpool` was updated to `0.13`.\n\n  * (**breaking**) The [`Config`](https://api.rocket.rs/v0.5/rocket_db_pools/struct.Config)\n    structure has a new `extensions` field.\n\n## [`rocket_dyn_templates`](https://api.rocket.rs/v0.5/rocket_dyn_templates/) `0.2.0`\n\n  * Support for `minijinja` `2.0` templates was introduced.\n\n    Templates with an extension of `.j2` are recognized and rendered with\n    Minijinja.\n\n  * **(breaking)** `handlebars` was updated to `5.1`.\n\n## [`rocket_ws`](https://api.rocket.rs/v0.5/rocket_ws/) `0.1.1`\n\n  * Introduced [`WebSocket::accept_key()`] method.\n\n  * `tungstenite` was updated to `0.21`.\n\n## General Changes\n\n  * The `rust-version` for all crates was updated to `1.64`.\n\n    This reflects the correct MSRV required to build `rocket` `0.5.0`.\n\n  * License files are now present in all published crates.\n\n[52de9a]: https://github.com/rwf2/Rocket/commit/52de9a\n[#2668]: https://github.com/rwf2/Rocket/pull/2668\n[deploying section]: https://rocket.rs/guide/v0.5/deploying/\n[`WebSocket::accept_key()`]: https://api.rocket.rs/v0.5/rocket_ws/struct.WebSocket#method.accept_key\n\n# Version 0.5.0 (Nov 17, 2023)\n\n## Major Features and Improvements\n\nThis release introduces the following major features and improvements:\n\n  * Support for [compilation on Rust's stable] release channel.\n  * A rewritten, fully asynchronous core with support for [`async`/`await`].\n  * WebSocket support via [`rocket_ws`].\n  * [Feature-complete forms support] including multipart, collections, [ad-hoc validation], and\n    [context](https://rocket.rs/v0.5/guide/requests/#context).\n  * [Sentinels]: automatic verification of application state at start-up to prevent runtime errors.\n  * [Graceful shutdown] with configurable signaling, grace periods, [notification], and\n    [shutdown fairings].\n  * An entirely new, flexible and robust [configuration system] based on [Figment].\n  * Typed [asynchronous streams] and [Server-Sent Events] with generator syntax.\n  * Asynchronous database pooling support via [`rocket_db_pools`].\n  * Support for [mutual TLS] and client [`Certificate`]s.\n  * Automatic support for HTTP/2 including `h2` ALPN.\n  * Graduation of `json`, `msgpack`, and `uuid` `rocket_contrib` [features into core].\n  * An automatically enabled [`Shield`]: security and privacy headers for all responses.\n  * Type-system enforced [incoming data limits] to mitigate memory-based DoS attacks.\n  * Compile-time URI literals via a fully revamped [`uri!`] macro.\n  * [Request connection upgrade APIs] with support for raw I/O with the client.\n  * Full support for [UTF-8 characters] in routes and catchers.\n  * Precise detection of missing managed state, databases, and templating with [sentinels].\n  * Typed [build phases] with strict application-level guarantees.\n  * [Ignorable segments]: wildcard route matching with no typing restrictions.\n  * First-class [support for `serde`] for built-in guards and types.\n  * New application launch attributes:\n    [`#[launch]`](https://api.rocket.rs/v0.5/rocket/attr.launch.html) and\n    [`#[rocket::main]`](https://api.rocket.rs/v0.5/rocket/attr.main.html).\n  * [Default catchers] via `#[catch(default)]`, which handle _any_ status code.\n  * [Catcher scoping] to narrow the scope of a catcher to a URI prefix.\n  * Built-in libraries and support for [asynchronous testing].\n  * A [`TempFile`] data and form guard for automatic uploading to a temporary file.\n  * A [`Capped<T>`] data and form guard which enables detecting truncation due to data limits.\n  * Support for dynamic and static prefixing and suffixing of route URIs in [`uri!`].\n  * Support for custom config profiles and [automatic typed config extraction].\n  * Rewritten, zero-copy, RFC compliant URI parsers with support for URI-[`Reference`]s.\n  * Multi-segment parameters (`<param..>`) which match _zero_ segments.\n  * A [`local_cache!`] macro for request-local storage of non-uniquely typed values.\n  * A [`CookieJar`] without \"one-at-a-time\" limitations.\n  * [Singleton fairings] with replacement and guaranteed uniqueness.\n  * [Data limit declaration in SI units]: \"2 MiB\", `2.mebibytes()`.\n  * Optimistic responding even when data is left unread or limits are exceeded.\n  * Fully decoded borrowed strings as dynamic parameters, form and data guards.\n  * Borrowed byte slices as data and form guards.\n  * Fail-fast behavior for [misconfigured secrets], file serving paths.\n  * Support for generics and custom generic bounds in\n    [`#[derive(Responder)]`](https://api.rocket.rs/v0.5/rocket/derive.Responder.html).\n  * [Default ranking colors], which prevent more routing collisions automatically.\n  * Improved error logging with suggestions when common errors are detected.\n  * Completely rewritten examples including a new real-time [`chat`] application.\n\n## Support for Rust Stable\n\nAs a result of support for Rust stable (Rust 2021 Edition and beyond),\n`#![feature(..)]` crate attributes are no longer required to use Rocket. The\ncomplete canonical example with a single `hello` route becomes:\n\n```rust\n#[macro_use] extern crate rocket;\n\n#[get(\"/<name>/<age>\")]\nfn hello(name: &str, age: u8) -> String {\n    format!(\"Hello, {} year old named {}!\", age, name)\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/hello\", routes![hello])\n}\n```\n\n<details>\n  <summary>See a <code>diff</code> of the changes from v0.4.</summary>\n\n```diff\n- #![feature(proc_macro_hygiene, decl_macro)]\n-\n #[macro_use] extern crate rocket;\n\n #[get(\"/<name>/<age>\")]\n- fn hello(name: String, age: u8) -> String {\n+ fn hello(name: &str, age: u8) -> String {\n     format!(\"Hello, {} year old named {}!\", age, name)\n}\n\n- fn main() {\n-     rocket::ignite().mount(\"/hello\", routes![hello]).launch();\n- }\n+ #[launch]\n+ fn rocket() -> _ {\n+     rocket::build().mount(\"/hello\", routes![hello])\n+ }\n```\n\n</details>\n\n## Breaking Changes\n\nThis release includes many breaking changes. For a walkthrough guide on handling these changes, see\nthe [v0.4 to v0.5 migration guide]. The most significant changes are listed below.\n\n### Silent Changes\n\nThese changes are invisible to the compiler and will _not_ yield errors or warnings at compile-time.\nWe **strongly** advise all application authors to review this list carefully.\n\n  * Blocking I/O (long running compute, synchronous `sleep()`, `Mutex`, `RwLock`, etc.) may prevent\n    the server from making progress and should be avoided, replaced with an `async` variant, or\n    performed in a worker thread. This is a consequence of Rust's cooperative `async` multitasking.\n    For details, see the new [multitasking] section of the guide.\n  * `ROCKET_ENV` is now `ROCKET_PROFILE`. A warning is emitted a launch time if the former is set.\n  * The default profile for debug builds is now `debug`, not `dev`.\n  * The default profile for release builds is now `release`, not `prod`.\n  * `ROCKET_LOG` is now `ROCKET_LOG_LEVEL`. A warning is emitted a launch time if the former is set.\n  * `ROCKET_ADDRESS` accepts only IP addresses, no longer resolves hostnames like `localhost`.\n  * `ROCKET_CLI_COLORS` accepts booleans `true`, `false` in place of strings `\"on\"`, `\"off\"`.\n  * It is a launch-time error if `secrets` is enabled in non-`debug` profiles without a configured\n    `secret_key`.\n  * A misconfigured `template_dir` is reported as an error at launch time.\n  * [`FileServer::new()`] fails immediately if the provided directory does not exist.\n  * Catcher collisions result in a launch failure as opposed to a warning.\n  * Default ranks now range from `-12` to `-1`. There is no breaking change if only code generated\n    routes are used. Manually configured routes with negative ranks may collide or be considered in\n    a different order than before.\n  * The order of execution of path and query guards relative to each other is now unspecified.\n  * URIs beginning with `:` are properly recognized as invalid and rejected.\n  * URI normalization now normalizes the query part as well.\n  * The `Segments` iterator now returns percent-decoded `&str`s.\n  * Forms are now parsed leniently by the [`Form` guard]. Use [`Strict`] for the previous behavior.\n  * The `Option<T>` form guard defaults to `None` instead of the default value for `T`.\n  * When data limits are exceeded, a `413 Payload Too Large` status is returned to the client.\n  * The default catcher now returns JSON when the client indicates preference via the `Accept`\n    header.\n  * Empty boolean form values parse as `true`: the query string `?f` is the same as `?f=true`.\n  * [`Created<R>`] does not automatically send an `ETag` header if `R: Hash`. Use\n    [`Created::tagged_body`] instead.\n  * `FileServer` now forwards when a file is not found instead of failing with `404 Not Found`.\n  * [`Shield`] is enabled by default. You may need to disable or change policies if your application\n    depends on typically insecure browser features or if you wish to opt-in to different policies\n    than the defaults.\n  * [`CookieJar`] `get()`s do not return cookies added during request handling. See\n    [`CookieJar`#pending].\n  * `Hash` `impl`s for `MediaType` and `ContentType` no longer consider media type parameters.\n  * When requested, the `FromForm` implementations of `Vec` and `Map`s are now properly lenient.\n  * To agree with browsers, the `[` and `]` characters are now accepted in URI paths.\n  * The `[` and `]` characters are no longer encoded by [`uri!`].\n  * The `Secure` cookie flag is set by default for all cookies when serving over TLS.\n  * Removal cookies have `SameSite` set to `Lax` by default.\n  * [`MediaType::JavaScript`] is now `text/javascript`.\n\n### Contrib Graduation\n\nThe `rocket_contrib` crate is deprecated and the functionality moved to other `rocket` crates. The\n[contrib deprecation upgrade guide] provides a walkthrough on migrating. The relevant changes are:\n\n  * Several features previously in `rocket_contrib` were merged into `rocket` itself:\n    - `json`, `msgpack`, and `uuid` are now [features of `rocket`].\n    - Moved `rocket_contrib::json` to [`rocket::serde::json`].\n    - Moved `rocket_contrib::msgpack` to [`rocket::serde::msgpack`].\n    - Moved `rocket_contrib::uuid` to [`rocket::serde::uuid`].\n    - Moved `rocket_contrib::helmet` to [`rocket::shield`]. [`Shield`] is enabled by default.\n    - Moved `rocket_contrib::serve` to [`rocket::fs`], `StaticFiles` to [`rocket::fs::FileServer`].\n    - Removed the now unnecessary `Uuid` and `JsonValue` wrapper types.\n    - Removed headers in `Shield` that are no longer respected by browsers.\n  * The remaining features from `rocket_contrib` are now provided by separate crates:\n    - Replaced `rocket_contrib::templates` with [`rocket_dyn_templates`].\n    - Replaced `rocket_contrib::databases` with [`rocket_sync_db_pools`] and [`rocket_db_pools`].\n    - These crates are versioned and released independently of `rocket`.\n    - `rocket_contrib::databases::DbError` is now `rocket_sync_db_pools::Error`.\n    - Removed `redis`, `mongodb`, and `mysql` integrations which have upstream `async` drivers.\n    - The [`#[database]`](https://api.rocket.rs/v0.5/rocket_sync_db_pools/attr.database.html)\n      attribute generates an [`async run()`] method instead of `Deref` implementations.\n\n### General\n\nThe following breaking changes apply broadly and are likely to cause compile-time errors.\n\n  * [`Rocket`] is now generic over a [phase] marker:\n    - APIs operate on `Rocket<Build>`, `Rocket<Ignite>`, `Rocket<Orbit>`, or `Rocket<P: Phase>` as\n      needed.\n    - The phase marker statically enforces state transitions in `Build`, `Ignite`, `Orbit` order.\n    - `rocket::ignite()` is now [`rocket::build()`] and returns a `Rocket<Build>`.\n    - [`Rocket::ignite()`] transitions to the `Ignite` phase. This is run automatically on launch as\n      needed.\n    - Ignition finalizes configuration, runs `ignite` fairings, and verifies [sentinels].\n    - [`Rocket::launch()`] transitions into the `Orbit` phase and starts the server.\n    - Methods like [`Request::rocket()`] that refer to a live Rocket instance return an\n      `&Rocket<Orbit>`.\n  * [Fairings] have been reorganized and restructured for `async`:\n    - Replaced `attach` fairings with `ignite` fairings. Unlike `attach` fairings, which ran\n      immediately at the time of attachment, `ignite` fairings are run when transitioning into the\n      `Ignite` phase.\n    - Replaced `launch` fairings with `liftoff` fairings. `liftoff` fairings are always run, even in\n      local clients, after the server begins listening and the concrete port is known.\n  * Introduced a new [configuration system] based on [Figment]:\n    - The concept of \"environments\" is replaced with \"profiles\".\n    - `ROCKET_ENV` is superseded by `ROCKET_PROFILE`.\n    - `ROCKET_LOG` is superseded by `ROCKET_LOG_LEVEL`.\n    - Profile names can now be arbitrarily chosen. The `dev`, `stage`, and `prod` profiles carry no\n      special meaning.\n    - The `debug` and `release` profiles are the default profiles for the debug and release\n      compilation profiles.\n    - A new specially recognized `default` profile specifies defaults for all profiles.\n    - The `global` profile has highest precedence, followed by the selected profile, followed by\n      `default`.\n    - Added support for limits specified in SI units: \"1 MiB\".\n    - Renamed `LoggingLevel` to [`LogLevel`].\n    - Inlined error variants into the [`Error`] structure.\n    - Changed the type of `workers` to `usize` from `u16`.\n    - Changed accepted values for `keep_alive`: it is disabled with `0`, not `false` or `off`.\n    - Disabled the `secrets` feature (for private cookies) by default.\n    - Removed APIs related to \"extras\". Typed values can be extracted from the configured `Figment`.\n    - Removed `ConfigBuilder`: all fields of [`Config`] are public with constructors for each field\n      type.\n  * Many functions, traits, and trait bounds have been modified for `async`:\n    - [`FromRequest`], [`Fairing`], [`catcher::Handler`], [`route::Handler`], and [`FromData`] use\n      `#[async_trait]`.\n    - [`NamedFile::open`] is now an `async` function.\n    - Added [`Request::local_cache_async()`] for use in async request guards.\n    - Unsized `Response` bodies must be [`AsyncRead`] instead of `Read`.\n    - Automatically sized `Response` bodies must be [`AsyncSeek`] instead of `Seek`.\n    - The `local` module is split into two: [`rocket::local::asynchronous`] and\n      [`rocket::local::blocking`].\n  * Functionality and features requiring Rust nightly were removed:\n    - Removed the `Try` implementation on [`Outcome`] which allowed using `?` with `Outcome`s. The\n      recommended replacement is the [`rocket::outcome::try_outcome!`] macro or the various\n      combinator functions on `Outcome`.\n    - [`Result<T, E>` implements `Responder`] only when both `T` and `E` implement `Responder`. The\n      new [`Debug`] wrapping responder replaces `Result<T: Responder, E: Debug>`.\n    - APIs which used the `!` type to now use [`std::convert::Infallible`].\n  * [`IntoOutcome`] was overhauled to supplant methods now removed in `Outcome`.\n    - `IntoOutcome::into_outcome()` is now `or_error()`.\n    - `IntoOutcome` is implemented for all `Outcome` type aliases.\n    - `Outcome::forward()` requires specifying a status code.\n    - `Outcome::from()` and `Outcome::from_or_forward()` were removed.\n  * [`Rocket::register()`] now takes a base path to scope catchers under as its first argument.\n  * `ErrorKind::Collision` has been renamed to [`ErrorKind::Collisions`].\n  * TLS config values are only available when the `tls` feature is enabled.\n  * [`MediaType::with_params()`] and [`ContentType::with_params()`] are now builder methods.\n  * Content-Type [`content`] responder type names are now prefixed with `Raw`.\n  * The `content::Plain` responder is now called `content::RawText`.\n  * The `content::Custom<T>` responder was removed in favor of [`(ContentType, T)`].\n  * Removed `CookieJar::get_private_pending()` in favor of [`CookieJar::get_pending()`].\n  * The [`local_cache!`] macro accepts fewer types. Use [`local_cache_once!`] as appropriate.\n  * [`Rocket::launch()`] allows `Rocket` recovery by returning the instance after shutdown.\n  * `ErrorKind::Runtime` was removed; [`ErrorKind::Shutdown`] was added.\n  * `Outcome::Failure` was renamed to [`Outcome::Error`].\n\n### Routing and URIs\n\n  * In `#[route(GET, path = \"...\")]`, `path` is now `uri`: `#[route(GET, uri = \"...\")]`.\n  * Multi-segment paths (`/<p..>`) now match _zero_ or more segments.\n  * Codegen improvements preclude identically named routes and modules in the same namespace.\n  * A route URI like (`/<a>/<p..>`) now collides with (`/<a>`), requires a `rank` to resolve.\n  * All catcher related types and traits moved to [`rocket::catcher`].\n  * All route related types and traits moved to [`rocket::route`].\n  * URI formatting types and traits moved to [`rocket::http::uri::fmt`].\n  * `T` no longer converts to `Option<T>` or `Result<T, _>` for [`uri!`] query parameters.\n  * For optional query parameters, [`uri!`] requires using a wrapped value or `_`.\n  * `&RawStr` no longer implements `FromParam`: use `&str` instead.\n  * Percent-decoding is performed before calling `FromParam` implementations.\n  * `RawStr::url_decode()` and `RawStr::url_decode_lossy()` allocate as necessary, return `Cow`.\n  * `RawStr::from_str()` was replaced with `RawStr::new()`.\n  * `Origin::segments()` was replaced with `Origin.path().segments()`.\n  * `Origin::path()` and `Origin::query()` return `&RawStr` instead of `&str`.\n  * The type of `Route::name` is now `Option<Cow<'static, str>>`.\n  * `Route::set_uri` was replaced with [`Route::map_base()`].\n  * The `Route::uri` field is now of type [`RouteUri`].\n  * `Route::base` was removed in favor of `Route.uri().base()`.\n  * [Route `Forward` outcomes] are now associated with a `Status`.\n  * The status codes used when built-in guards forward were changed:\n    - Route parameter `FromParam` errors now forward as 422.\n    - Query parameter errors now forward as 422.\n    - Incorrect form content-type errors forwards as 413.\n    - `&Host`, `&Accept`, `&ContentType`, `IpAddr`, and `SocketAddr` all forward\n      with a 500.\n\n### Data and Forms\n\n  * `Data` now has a lifetime generic: `Data<'r>`.\n  * [`Data::open()`] indelibly requires a data limit.\n  * Removed `FromDataSimple`. Use [`FromData`] and [`local_cache!`] or [`local_cache_once!`].\n  * All [`DataStream`] APIs require limits and return [`Capped<T>`] types.\n  * Form types and traits were moved from `rocket::request` to [`rocket::form`].\n  * Removed `FromQuery`. Dynamic query parameters (`#[get(\"/?<param>\")]`) use [`FromForm`] instead.\n  * Replaced `FromFormValue` with [`FromFormField`]. All `T: FromFormField` implement `FromForm`.\n  * Form field values are percent-decoded before calling [`FromFormField`] implementations.\n  * Renamed the `#[form(field = ...)]` attribute to `#[field(name = ...)]`.\n  * [Custom form errors] must now specify an associated `Status`.\n\n### Request Guards\n\n  * Renamed `Cookies` to [`CookieJar`]. Its methods take `&self`.\n  * Renamed `Flash.name` to `Flash.kind`, `Flash.msg` to `Flash.message`.\n  * Replaced `Request::get_param()` with `Request::param()`.\n  * Replaced `Request::get_segments()` to `Request::segments()`.\n  * Replaced `Request::get_query_value()` with `Request::query_value()`.\n  * Replaced `Segments::into_path_buf()` with `Segments::to_path_buf()`.\n  * Replaced `Segments` and `QuerySegments` with [`Segments<Path>` and `Segments<Query>`].\n  * [`Flash`] constructors now take `Into<String>` instead of `AsRef<str>`.\n  * The `State<'_, T>` request guard is now `&State<T>`.\n  * Removed a lifetime from [`FromRequest`]: `FromRequest<'r>`.\n  * Removed a lifetime from [`FlashMessage`]: `FlashMessage<'_>`.\n  * Removed all `State` reexports except [`rocket::State`].\n\n### Responders\n\n  * Moved `NamedFile` to `rocket::fs::NamedFile`\n  * Replaced `Content` with `content::Custom`.\n  * `Response::body` and `Response::body_mut` are now infallible methods.\n  * Renamed `ResponseBuilder` to `Builder`.\n  * Removed direct `Response` body reading methods. Use methods on `r.body_mut()` instead.\n  * Removed inaccurate \"chunked body\" types and variants.\n  * Removed `Responder` `impl` for `Response`. Prefer custom responders with `#[derive(Responder)]`.\n  * Removed the unused reason phrase from `Status`.\n  * The types of responders in [`response::status`] were unified to all be of\n    the form `Status<R>(R)`.\n\n## General Improvements\n\nIn addition to new features and changes, Rocket saw the following improvements:\n\n### General\n\n  * Added support for [raw identifiers] in the `FromForm` derive, `#[route]` macros, and `uri!`.\n  * Added support for uncased derived form fields: `#[field(name = uncased(...))]`.\n  * Added support for [default form field values]: `#[field(default = expr())]`.\n  * Added support for multiple `#[field]` attributes on struct fields.\n  * Added support for base16-encoded (a.k.a. hex-encoded) secret keys.\n  * Added [`Config::ident`] for configuring or removing the global `Server` header.\n  * Added [`Rocket::figment()`] and [`Rocket::catchers()`].\n  * Added [`LocalRequest::json()`] and [`LocalResponse::json()`].\n  * Added [`LocalRequest::msgpack()`] and [`LocalResponse::msgpack()`].\n  * Added support for `use m::route; routes![route]` instead of needing `routes![m::route]`.\n  * Added support for [hierarchical data limits]: a limit of `a/b/c` falls back to `a/b` then `a`.\n  * Added [`LocalRequest::inner_mut()`]. `LocalRequest` implements `DerefMut` to `Request`.\n  * Added support for ECDSA and EdDSA TLS keys.\n  * Added associated constants in `Config` for all config parameter names.\n  * Added `ErrorKind::Config` to represent errors in configuration at runtime.\n  * Added `rocket::fairing::Result` type alias, returned by `Fairing::on_ignite()`.\n  * All guard failures are logged at runtime.\n  * `Rocket::mount()` now accepts a base value of any type that implements `TryInto<Origin<'_>>`.\n  * The default error catcher's HTML has been compacted.\n  * The default error catcher returns JSON if requested by the client.\n  * Panics in routes or catchers are caught and forwarded to `500` error catcher.\n  * A detailed warning is emitted if a route or catcher panics.\n  * Emoji characters are no longer output on Windows.\n  * Fixed [`Error`] to not panic if a panic is already in progress.\n  * Introduced [`Reference`] and [`Asterisk`] URI types.\n  * Added support to [`UriDisplayQuery`] for C-like enums.\n  * The [`UriDisplayQuery`] derive now recognizes the `#[field]` attribute for field renaming.\n  * `Client` method builders accept `TryInto<Origin>` allowing a `uri!()` to be used directly.\n  * [`Rocket`] is now `#[must_use]`.\n  * Support for HTTP/2 can be disabled by disabling the default `http2` crate feature.\n  * Added [`rocket::execute()`] for executing Rocket's `launch()` future.\n  * Added the [`context!`] macro to [`rocket_dyn_templates`] for ad-hoc template contexts.\n  * The `time` crate is re-exported from the crate root.\n  * The `FromForm`, `Responder`, and `UriDisplay` derives now fully support generics.\n  * Added helper functions to `serde` submodules.\n  * The [`Shield`] HSTS preload header now includes `includeSubdomains`.\n  * Logging ignores `write!` errors if `stdout` disappears, preventing panics.\n  * Added [`Client::terminate()`] to run graceful shutdown in testing.\n  * Shutdown now terminates the `async` runtime, never the process.\n  * Added a [`local_cache_once!`] macro for request-local storage.\n  * Final launch messages are now _always_ logged, irrespective of profile.\n  * Only functions that return `Rocket<Build>` are now `#[must_use]`, not all `Rocket<P>`.\n  * Fixed mismatched form field names in errors under certain conditions in [`FromForm`] derive.\n  * The [`FromForm`] derive now collects _all_ errors that occur.\n  * Data pools are now gracefully shutdown in [`rocket_sync_db_pools`].\n  * Added [`Metadata::render()`] in [`rocket_dyn_templates`] for direct template rendering.\n  * Rocket salvages more information from malformed requests for error catchers.\n  * The `cookie` `secure` feature is now properly conditionally enabled.\n  * Data before encapsulation boundaries in TLS keys is allowed and ignored.\n  * Support for TLS keys in SEC1 format was added.\n  * Rocket now warns when a known secret key is configured.\n  * A panic that could occur on shutdown in `rocket_sync_db_pools` was fixed.\n  * Added a [`max_blocking`] configuration parameter to control number of blocking threads.\n  * Added an [`ip_header`] \"real IP\" header configuration parameter.\n  * A [`pool()`] method is emitted by [`rocket_sync_db_pools`] for code-generated pools.\n  * Data guards are now eligible [sentinels].\n  * Raw binary form field data can be retrieved using the `&[u8]` form guard.\n  * Added [`TempFile::open()`] to stream `TempFile` data.\n  * mTLS certificates can be set on local requests with [`LocalRequest::identity()`].\n  * Added [`Error::pretty_print()`] for pretty-printing errors like Rocket.\n  * Warnings are logged when data limits are reached.\n  * A warning is emitted when `String` is used as a route parameter.\n  * Configuration provenance information is logged under the `debug` log level.\n  * Logging of `Outcome`s now includes the relevant status code.\n  * `Span::mixed_site()` is used in codegen to reduce errant `clippy` warnings.\n\n### HTTP\n\n  * Added support for HTTP/2, enabled by default via the `http2` crate feature.\n  * Added a `const` constructor for `MediaType`.\n  * Introduced [`RawStrBuf`], an owned `RawStr`.\n  * Added many new \"pattern\" methods to [`RawStr`].\n  * Added [`RawStr::percent_encode()`] and [`RawStr::strip()`].\n  * Added support for unencoded query characters in URIs that are frequently sent by browsers.\n  * Introduced [`Host`] and [`&Host`] request guards.\n  * Added [`RawStr::percent_encode_bytes()`].\n  * `NODELAY` is now enabled on all connections by default.\n  * The TLS implementation handles handshakes off the main task, improving DoS resistance.\n\n### Known Media Types\n\n  * Added AVIF: `image/avif`.\n  * Added `EventStream`: `text/event-stream`.\n  * Added `Markdown`: `text/markdown`.\n  * Added `MP3`: `audio/mpeg`.\n  * Added `CBZ`: `application/vnd.comicbook+zip`, extension `.cbz`.\n  * Added `CBR`: `application/vnd.comicbook-rar`, extension `.cbr`.\n  * Added `RAR`: `application/vnd.rar`, extension `.rar`.\n  * Added `EPUB`: `application/epub+zip`, extension `.epub`.\n  * Added `OPF`: `application/oebps-package+xml`, extension `.opf`.\n  * Added `XHTML`: `application/xhtml+xml`, extension `.xhtml`.\n  * Added `Text` as an alias for the `Plain` media type.\n  * Added `Bytes` as an alias for the `Binary` media type.\n  * Added `.mjs` as known JavaScript extension.\n  * Added '.exe', '.iso', '.dmg' as known extensions.\n\n### Request\n\n  * Added support for all UTF-8 characters in route paths.\n  * Added support for percent-encoded `:` in socket or IP address values in [`FromFormValue`].\n  * Added [`Request::rocket()`] to access the active `Rocket` instance.\n  * `Request::uri()` now returns an `&Origin<'r>` instead of `&Origin<'_>`.\n  * `Request::accept()`, `Request::content_type()` reflect changes to `Accept`, `Content-Type`.\n  * `Json<T>`, `MsgPack<T>` accept `T: Deserialize`, not only `T: DeserializeOwned`.\n  * Diesel SQLite connections in `rocket_sync_db_pools` use better defaults.\n  * The default number of workers for synchronous database pools is now `workers * 4`.\n  * Added [`Request::host()`] to retrieve the client-requested host.\n\n### Response\n\n  * Added [`Template::try_custom()`] for fallible template engine customization.\n  * Manually registered templates can now be rendered with `Template::render()`.\n  * Added support for the `X-DNS-Prefetch-Control` header to `Shield`.\n  * Added support for manually-set `expires` values for private cookies.\n  * Added support for type generics and custom generic bounds to\n    [`#[derive(Responder)]`](https://api.rocket.rs/v0.5/rocket/derive.Responder.html).\n  * The `Server` header is only set if one isn't already set.\n  * Accurate `Content-Length` headers are sent even for partially read `Body`s.\n  * [`Redirect`] now accepts a `TryFrom<Reference>`, allowing fragment parts.\n\n### Trait Implementations\n\n  * Implemented `Clone` for `State`.\n  * Implemented `Copy` and `Clone` for `fairing::Info`.\n  * Implemented `Debug` for `Rocket` and `Client`.\n  * Implemented `Default` for `Status` (returns `Status::Ok`).\n  * Implemented `PartialEq`, `Eq`, `Hash`, `PartialOrd`, and `Ord` for `Status`.\n  * Implemented `Eq`, `Hash`, and `PartialEq<&str>` for `Origin`.\n  * Implemented `PartialEq<Cow<'_, RawStr>>>` for `RawStr`.\n  * Implemented `std::error::Error` for `Error`.\n  * Implemented `Deref` and `DerefMut` for `LocalRequest` (to `Request`).\n  * Implemented `DerefMut` for `Form`, `LenientForm`.\n  * Implemented `From<T>` for `Json<T>`, `MsgPack<T>`.\n  * Implemented `TryFrom<String>` and `TryFrom<&str>` for `Origin`.\n  * Implemented `TryFrom<Uri>` for each of the specific URI variants.\n  * Implemented `FromRequest` for `&Config`.\n  * Implemented `FromRequest` for `IpAddr`.\n  * Implemented `FromParam` for `PathBuf`\n  * Implemented `FromParam`, `FromData`, and `FromForm` for `&str`.\n  * Implemented `FromForm` for `Json<T>`, `MsgPack<T>`.\n  * Implemented `FromFormField` for `Cow` and `Capped<Cow>>`\n  * Implemented `Responder` for `tokio::fs::File`.\n  * Implemented `Responder` for `(ContentType, R) where R: Responder`.\n  * Implemented `Responder` for `(Status, R) where R: Responder` which overrides `R`'s status.\n  * Implemented `Responder` for `std::io::Error` (behaves as `Debug<std::io::Error>`).\n  * Implemented `Responder` for `Either<T, E>`, equivalently to `Result<T, E>`.\n  * Implemented `Serialize` for `Flash`.\n  * Implemented `Serialize`, `Deserialize`, `UriDisplay` and `FromUriParam` for `uuid::Uuid`\n  * Implemented `Serialize`, `Deserialize` for `RawStr`.\n  * Implemented `Serialize`, `Deserialize` for all URI types.\n  * Implemented `Responder` for `Arc<T>`, `Box<T>` where `T: Responder`.\n  * Implemented `Serialize` and `Deserialize` for [`Method`].\n  * Implemented `Eq` for [`MediaType`] and [`ContentType`].\n  * Implemented `Responder` for `Box<T: Responder + Sized>`.\n  * Implemented `FromForm` for `Arc<T>`.\n  * Implemented `Fairing` for `Arc<dyn Fairing>`.\n  * Implemented `Serialize` and `Deserialize` for `Status`.\n\n### Dependency Changes\n\n  * `serde` was introduced (`1.0`).\n  * `futures` was introduced (`0.3`).\n  * `binascii` was introduced (`0.1`).\n  * `ref-cast` was introduced (`1.0`).\n  * `atomic` was introduced (`0.5`).\n  * `parking_lot` was introduced (`0.11`).\n  * `ubtye` was introduced (`0.10`).\n  * `figment` was introduced (`0.10`).\n  * `rand` was introduced (`0.8`).\n  * `either` was introduced (`1.0`).\n  * `pin-project-lite` was introduced (`0.2`).\n  * `indexmap` was introduced (`2.0`).\n  * `tempfile` was introduced (`3.0`).\n  * `async-trait` was introduced (`0.1`).\n  * `async-stream` was introduced (`0.3`).\n  * `multer` was introduced (`2.0`).\n  * `tokio` was introduced (`1.6.1`).\n  * `tokio-util` was introduced (`0.6`).\n  * `tokio-stream` was introduced (`0.1.6`).\n  * `bytes` was introduced (`1.0`).\n  * `normpath` was introduced (`1`).\n  * `state` was updated to `0.6`.\n  * `rmp-serde` was updated to `0.15`.\n  * `uuid` was updated to `0.8`.\n  * `tera` was updated to `1.10`.\n  * `postgres` was updated to `0.19`.\n  * `rusqlite` was updated to `0.25`.\n  * `r2d2_sqlite` was updated to `0.18`.\n  * `time` was updated to `0.3`.\n  * `handlebars` was updated to `4.0`.\n  * `memcache` was updated to `0.16`.\n  * `rustls` was updated to `0.21`.\n  * `tokio-rustls` was updated to `0.24`.\n  * `syn` was updated to `2`.\n  * `diesel` was updated to `2.0`.\n  * `sqlx` was updated to `0.7`.\n  * `notify` was updated to `6`.\n  * `criterion` was updated to `0.4`.\n  * `cookie` was updated to `0.18`.\n  * `yansi` was updated to `1.0`.\n  * `atty` was removed.\n\n## Infrastructure\n\nThe following changes were made to the project's infrastructure:\n\n  * Rocket now uses the 2021 edition of Rust.\n  * Added a [v0.4 to v0.5 migration guide] and [FAQ] to Rocket's website.\n  * Added visible `use` statements to examples in the guide.\n  * Split examples into a separate workspace for easier testing.\n  * Updated documentation for all changes.\n  * Fixed many typos, errors, and broken links throughout documentation and examples.\n  * Improved the general robustness of macros, and the quality and frequency of error messages.\n  * Benchmarks now use `criterion` and datasets extracted from real-world projects.\n  * Fixed the SPDX license expressions in `Cargo.toml` files.\n  * Added support to `test.sh` for a `+` flag (e.g. `+stable`) to pass to `cargo`.\n  * Added support to `test.sh` for extra flags to be passed on to `cargo`.\n  * UI tests are now allowed to fail by the CI to avoid false negatives.\n  * The GitHub CI workflow was updated to use maintained actions.\n  * The CI now frees disk space before proceeding to avoid out-of-disk errors.\n  * All workspaces now use `resolver = 2`.\n\n[phase]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#phases\n[`async`/`await`]: https://rocket.rs/v0.5/guide/overview/#async-routes\n[compilation on Rust's stable]: https://rocket.rs/v0.5/guide/getting-started/#installing-rust\n[Feature-complete forms support]: https://rocket.rs/v0.5/guide/requests/#forms\n[configuration system]: https://rocket.rs/v0.5/guide/configuration/#configuration\n[graceful shutdown]: https://api.rocket.rs/v0.5/rocket/config/struct.Shutdown.html#summary\n[asynchronous testing]: https://rocket.rs/v0.5/guide/testing/#asynchronous-testing\n[UTF-8 characters]: https://rocket.rs/v0.5/guide/requests/#static-parameters\n[ignorable segments]: https://rocket.rs/v0.5/guide/requests/#ignored-segments\n[Catcher scoping]: https://rocket.rs/v0.5/guide/requests/#scoping\n[ad-hoc validation]: https://rocket.rs/v0.5/guide/requests#ad-hoc-validation\n[incoming data limits]: https://rocket.rs/v0.5/guide/requests/#streaming\n[build phases]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#phases\n[Singleton fairings]: https://api.rocket.rs/v0.5/rocket/fairing/trait.Fairing.html#singletons\n[features into core]: https://api.rocket.rs/v0.5/rocket/index.html#features\n[features of `rocket`]: https://api.rocket.rs/v0.5/rocket/index.html#features\n[Data limit declaration in SI units]: https://api.rocket.rs/v0.5/rocket/data/struct.ByteUnit.html\n[support for `serde`]: https://api.rocket.rs/v0.5/rocket/serde/index.html\n[automatic typed config extraction]: https://api.rocket.rs/v0.5/rocket/fairing/struct.AdHoc.html#method.config\n[misconfigured secrets]: https://api.rocket.rs/v0.5/rocket/config/struct.SecretKey.html\n[default ranking colors]: https://rocket.rs/v0.5/guide/requests/#default-ranking\n[`chat`]: https://github.com/rwf2/Rocket/tree/v0.5/examples/chat\n[`Form` guard]: https://api.rocket.rs/v0.5/rocket/form/struct.Form.html\n[`Strict`]: https://api.rocket.rs/v0.5/rocket/form/struct.Strict.html\n[`CookieJar`#pending]: https://api.rocket.rs/v0.5/rocket/http/struct.CookieJar.html#pending\n[`rocket::serde::json`]: https://api.rocket.rs/v0.5/rocket/serde/json/index.html\n[`rocket::serde::msgpack`]: https://api.rocket.rs/v0.5/rocket/serde/msgpack/index.html\n[`rocket::serde::uuid`]: https://api.rocket.rs/v0.5/rocket/serde/uuid/index.html\n[`rocket::shield`]: https://api.rocket.rs/v0.5/rocket/shield/index.html\n[`rocket::fs`]: https://api.rocket.rs/v0.5/rocket/fs/index.html\n[`async run()`]: https://api.rocket.rs/v0.5/rocket_sync_db_pools/index.html#handlers\n[`LocalRequest::json()`]: https://api.rocket.rs/v0.5/rocket/local/blocking/struct.LocalRequest.html#method.json\n[`LocalRequest::msgpack()`]: https://api.rocket.rs/v0.5/rocket/local/blocking/struct.LocalRequest.html#method.msgpack\n[`LocalResponse::json()`]: https://api.rocket.rs/v0.5/rocket/local/blocking/struct.LocalResponse.html#method.json\n[`LocalResponse::msgpack()`]: https://api.rocket.rs/v0.5/rocket/local/blocking/struct.LocalResponse.html#method.msgpack\n[hierarchical data limits]: https://api.rocket.rs/v0.5/rocket/data/struct.Limits.html#hierarchy\n[default form field values]: https://rocket.rs/v0.5/guide/requests/#defaults\n[`Config::ident`]: https://api.rocket.rs/rocket/struct.Config.html#structfield.ident\n[`tokio`]: https://tokio.rs/\n[Figment]: https://docs.rs/figment/0.10/figment/\n[`TempFile`]: https://api.rocket.rs/v0.5/rocket/fs/enum.TempFile.html\n[`Contextual`]: https://rocket.rs/v0.5/guide/requests/#context\n[`Capped<T>`]: https://api.rocket.rs/v0.5/rocket/data/struct.Capped.html\n[default catchers]: https://rocket.rs/v0.5/guide/requests/#default-catchers\n[URI types]: https://api.rocket.rs/v0.5/rocket/http/uri/index.html\n[`uri!`]: https://api.rocket.rs/v0.5/rocket/macro.uri.html\n[`Reference`]: https://api.rocket.rs/v0.5/rocket/http/uri/struct.Reference.html\n[`Asterisk`]: https://api.rocket.rs/v0.5/rocket/http/uri/struct.Asterisk.html\n[`Redirect`]: https://api.rocket.rs/v0.5/rocket/response/struct.Redirect.html\n[`UriDisplayQuery`]: https://api.rocket.rs/v0.5/rocket/derive.UriDisplayQuery.html\n[`Shield`]: https://api.rocket.rs/v0.5/rocket/shield/struct.Shield.html\n[Sentinels]: https://api.rocket.rs/v0.5/rocket/trait.Sentinel.html\n[`local_cache!`]: https://api.rocket.rs/v0.5/rocket/request/macro.local_cache.html\n[`local_cache_once!`]: https://api.rocket.rs/v0.5/rocket/request/macro.local_cache_once.html\n[`CookieJar`]: https://api.rocket.rs/v0.5/rocket/http/struct.CookieJar.html\n[asynchronous streams]: https://rocket.rs/v0.5/guide/responses/#async-streams\n[Server-Sent Events]: https://api.rocket.rs/v0.5/rocket/response/stream/struct.EventStream.html\n[`fs::relative!`]: https://api.rocket.rs/v0.5/rocket/fs/macro.relative.html\n[notification]: https://api.rocket.rs/v0.5/rocket/struct.Shutdown.html\n[`Rocket`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html\n[`rocket::build()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.build\n[`Rocket::ignite()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.ignite\n[`Rocket::launch()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.launch\n[`Request::rocket()`]: https://api.rocket.rs/v0.5/rocket/request/struct.Request.html#method.rocket\n[Fairings]: https://rocket.rs/v0.5/guide/fairings/\n[configuration system]: https://rocket.rs/v0.5/guide/configuration/\n[`Poolable`]: https://api.rocket.rs/v0.5/rocket_sync_db_pools/trait.Poolable.html\n[`Config`]: https://api.rocket.rs/v0.5/rocket/struct.Config.html\n[`Error`]: https://api.rocket.rs/v0.5/rocket/struct.Error.html\n[`LogLevel`]: https://api.rocket.rs/v0.5/rocket/config/enum.LogLevel.html\n[`Rocket::register()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.register\n[`NamedFile::open`]: https://api.rocket.rs/v0.5/rocket/fs/struct.NamedFile.html#method.open\n[`Request::local_cache_async()`]: https://api.rocket.rs/v0.5/rocket/request/struct.Request.html#method.local_cache_async\n[`FromRequest`]: https://api.rocket.rs/v0.5/rocket/request/trait.FromRequest.html\n[`Fairing`]: https://api.rocket.rs/v0.5/rocket/fairing/trait.Fairing.html\n[`catcher::Handler`]: https://api.rocket.rs/v0.5/rocket/catcher/trait.Handler.html\n[`route::Handler`]: https://api.rocket.rs/v0.5/rocket/route/trait.Handler.html\n[`FromData`]: https://api.rocket.rs/v0.5/rocket/data/trait.FromData.html\n[`AsyncRead`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncRead.html\n[`AsyncSeek`]: https://docs.rs/tokio/1/tokio/io/trait.AsyncSeek.html\n[`rocket::local::asynchronous`]: https://api.rocket.rs/v0.5/rocket/local/asynchronous/index.html\n[`rocket::local::blocking`]: https://api.rocket.rs/v0.5/rocket/local/blocking/index.html\n[`Outcome`]: https://api.rocket.rs/v0.5/rocket/outcome/enum.Outcome.html\n[`rocket::outcome::try_outcome!`]: https://api.rocket.rs/v0.5/rocket/outcome/macro.try_outcome.html\n[`Result<T, E>` implements `Responder`]: https://api.rocket.rs/v0.5/rocket/response/trait.Responder.html#provided-implementations\n[`Debug`]: https://api.rocket.rs/v0.5/rocket/response/struct.Debug.html\n[`std::convert::Infallible`]: https://doc.rust-lang.org/stable/std/convert/enum.Infallible.html\n[`ErrorKind::Collisions`]: https://api.rocket.rs/v0.5/rocket/error/enum.ErrorKind.html#variant.Collisions\n[`rocket::http::uri::fmt`]: https://api.rocket.rs/v0.5/rocket/http/uri/fmt/index.html\n[`Data::open()`]: https://api.rocket.rs/v0.5/rocket/data/struct.Data.html#method.open\n[`DataStream`]: https://api.rocket.rs/v0.5/rocket/data/struct.DataStream.html\n[`rocket::form`]: https://api.rocket.rs/v0.5/rocket/form/index.html\n[`FromFormField`]: https://api.rocket.rs/v0.5/rocket/form/trait.FromFormField.html\n[`FromForm`]: https://api.rocket.rs/v0.5/rocket/form/trait.FromForm.html\n[`FlashMessage`]: https://api.rocket.rs/v0.5/rocket/request/type.FlashMessage.html\n[`Flash`]: https://api.rocket.rs/v0.5/rocket/response/struct.Flash.html\n[`rocket::State`]: https://api.rocket.rs/v0.5/rocket/struct.State.html\n[`Segments<Path>` and `Segments<Query>`]: https://api.rocket.rs/v0.5/rocket/http/uri/struct.Segments.html\n[`Route::map_base()`]: https://api.rocket.rs/v0.5/rocket/route/struct.Route.html#method.map_base\n[`uuid` support]: https://api.rocket.rs/v0.5/rocket/serde/uuid/index.html\n[`json`]: https://api.rocket.rs/v0.5/rocket/serde/json/index.html\n[`msgpack`]: https://api.rocket.rs/v0.5/rocket/serde/msgpack/index.html\n[`rocket::serde::json::json!`]: https://api.rocket.rs/v0.5/rocket/serde/json/macro.json.html\n[`rocket::shield::Shield`]: https://api.rocket.rs/v0.5/rocket/shield/struct.Shield.html\n[`rocket::fs::FileServer`]: https://api.rocket.rs/v0.5/rocket/fs/struct.FileServer.html\n[`rocket_dyn_templates`]: https://api.rocket.rs/v0.5/rocket_dyn_templates/index.html\n[`rocket_sync_db_pools`]: https://api.rocket.rs/v0.5/rocket_sync_db_pools/index.html\n[multitasking]: https://rocket.rs/v0.5/guide/overview/#multitasking\n[`Created<R>`]: https://api.rocket.rs/v0.5/rocket/response/status/struct.Created.html\n[`Created::tagged_body`]: https://api.rocket.rs/v0.5/rocket/response/status/struct.Created.html#method.tagged_body\n[raw identifiers]: https://doc.rust-lang.org/1.51.0/book/appendix-01-keywords.html#raw-identifiers\n[`Rocket::config()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.config\n[`Rocket::figment()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.figment\n[`Rocket::state()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.state\n[`Rocket::catchers()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.catchers\n[`LocalRequest::inner_mut()`]: https://api.rocket.rs/v0.5/rocket/local/blocking/struct.LocalRequest.html#method.inner_mut\n[`RawStrBuf`]: https://api.rocket.rs/v0.5/rocket/http/struct.RawStrBuf.html\n[`RawStr`]: https://api.rocket.rs/v0.5/rocket/http/struct.RawStr.html\n[`RawStr::percent_encode()`]: https://api.rocket.rs/v0.5/rocket/http/struct.RawStr.html#method.percent_encode\n[`RawStr::percent_encode_bytes()`]: https://api.rocket.rs/v0.5/rocket/http/struct.RawStr.html#method.percent_encode_bytes\n[`RawStr::strip()`]: https://api.rocket.rs/v0.5/rocket/http/struct.RawStr.html#method.strip_prefix\n[`rocket::catcher`]: https://api.rocket.rs/v0.5/rocket/catcher/index.html\n[`rocket::route`]: https://api.rocket.rs/v0.5/rocket/route/index.html\n[`Segments::prefix_of()`]: https://api.rocket.rs/v0.5/rocket/http/uri/struct.Segments.html#method.prefix_of\n[`Template::try_custom()`]: https://api.rocket.rs/v0.5/rocket_dyn_templates/struct.Template.html#method.try_custom\n[`Template::custom`]: https://api.rocket.rs/v0.5/rocket_dyn_templates/struct.Template.html#method.custom\n[`FileServer::new()`]: https://api.rocket.rs/v0.5/rocket/fs/struct.FileServer.html#method.new\n[`content`]: https://api.rocket.rs/v0.5/rocket/response/content/index.html\n[`rocket_db_pools`]: https://api.rocket.rs/v0.5/rocket_db_pools/index.html\n[mutual TLS]: https://rocket.rs/v0.5/guide/configuration/#mutual-tls\n[`Certificate`]: https://api.rocket.rs/v0.5/rocket/mtls/struct.Certificate.html\n[`MediaType::with_params()`]: https://api.rocket.rs/v0.5/rocket/http/struct.MediaType.html#method.with_params\n[`ContentType::with_params()`]: https://api.rocket.rs/v0.5/rocket/http/struct.ContentType.html#method.with_params\n[`Host`]: https://api.rocket.rs/v0.5/rocket/http/uri/struct.Host.html\n[`&Host`]: https://api.rocket.rs/v0.5/rocket/http/uri/struct.Host.html\n[`Request::host()`]: https://api.rocket.rs/v0.5/rocket/request/struct.Request.html#method.host\n[`context!`]: https://api.rocket.rs/v0.5/rocket_dyn_templates/macro.context.html\n[`MediaType`]: https://api.rocket.rs/v0.5/rocket/http/struct.MediaType.html\n[`ContentType`]: https://api.rocket.rs/v0.5/rocket/http/struct.ContentType.html\n[`Method`]: https://api.rocket.rs/v0.5/rocket/http/enum.Method.html\n[`(ContentType, T)`]: https://api.rocket.rs/v0.5/rocket/response/content/index.html#usage\n[v0.4 to v0.5 migration guide]: https://rocket.rs/v0.5/guide/upgrading/\n[contrib deprecation upgrade guide]: https://rocket.rs/v0.5/guide/upgrading/#contrib-deprecation\n[FAQ]: https://rocket.rs/v0.5/guide/faq/\n[`Rocket::launch()`]: https://api.rocket.rs/v0.5/rocket/struct.Rocket.html#method.launch\n[`ErrorKind::Shutdown`]: https://api.rocket.rs/v0.5/rocket/error/enum.ErrorKind.html#variant.Shutdown\n[shutdown fairings]: https://api.rocket.rs/v0.5/rocket/fairing/trait.Fairing.html#shutdown\n[`Client::terminate()`]: https://api.rocket.rs/v0.5/rocket/local/blocking/struct.Client.html#method.terminate\n[`rocket::execute()`]: https://api.rocket.rs/v0.5/rocket/fn.execute.html\n[`CookieJar::get_pending()`]: https://api.rocket.rs/v0.5/rocket/http/struct.CookieJar.html#method.get_pending\n[`Metadata::render()`]: https://api.rocket.rs/v0.5/rocket_dyn_templates/struct.Metadata.html#method.render\n[`pool()`]: https://api.rocket.rs/v0.5/rocket_sync_db_pools/example/struct.ExampleDb.html#method.pool\n[`Request::client_ip()`]: https://api.rocket.rs/v0.5/rocket/request/struct.Request.html#method.client_ip\n[`max_blocking`]: https://api.rocket.rs/v0.5/rocket/struct.Config.html#structfield.max_blocking\n[`ip_header`]: https://api.rocket.rs/v0.5/rocket/struct.Config.html#structfield.ip_header\n[`LocalRequest::identity()`]: https://api.rocket.rs/v0.5/rocket/local/blocking/struct.LocalRequest.html#method.identity\n[`TempFile::open()`]: https://api.rocket.rs/v0.5/rocket/fs/enum.TempFile.html#method.open\n[`Error::pretty_print()`]: https://api.rocket.rs/v0.5/rocket/struct.Error.html#method.pretty_print\n[Request connection upgrade APIs]: https://api.rocket.rs/v0.5/rocket/struct.Response.html#upgrading\n[`rocket_ws`]: https://api.rocket.rs/v0.5/rocket_ws/\n[registering]: https://api.rocket.rs/v0.5/rocket/response/struct.Response.html#method.add_upgrade\n[`IoHandler`]: https://api.rocket.rs/v0.5/rocket/data/trait.IoHandler.html\n[`response::status`]: https://api.rocket.rs/v0.5/rocket/response/status/index.html\n[Custom form errors]: https://api.rocket.rs/v0.5/rocket/form/error/enum.ErrorKind.html#variant.Custom\n[`request::Outcome`]: https://api.rocket.rs/v0.5/rocket/request/type.Outcome.html#variant.Forward\n[Route `Forward` outcomes]: https://api.rocket.rs/v0.5/rocket/request/type.Outcome.html#variant.Forward\n[`Outcome::Error`]: https://api.rocket.rs/v0.5/rocket/outcome/enum.Outcome.html#variant.Error\n[`IntoOutcome`]: https://api.rocket.rs/v0.5/rocket/outcome/trait.IntoOutcome.html\n[`MediaType::JavaScript`]: https://api.rocket.rs/v0.5/rocket/http/struct.MediaType.html#associatedconstant.JavaScript\n[`TempFile::open()`]: https://api.rocket.rs/v0.5/rocket/fs/enum.TempFile.html#method.open\n[`Error::pretty_print()`]: https://api.rocket.rs/v0.5/rocket/struct.Error.html#method.pretty_print\n[`RouteUri`]: https://api.rocket.rs/v0.5/rocket/route/struct.RouteUri.html\n\n# Version 0.4.10 (May 21, 2021)\n\n## Core\n\n  * [[`3276b8`]] Removed `unsafe` in `Origin::parse_owned()`, fixing a soundness\n    issue.\n\n[`3276b8`]: https://github.com/rwf2/Rocket/commit/3276b8\n\n# Version 0.4.9 (May 19, 2021)\n\n## Core\n\n  * [[`#1645`], [`f2a56f`]] Fixed `Try` `impl FromResidual<Result> for Outcome`.\n\n[`#1645`]: https://github.com/rwf2/Rocket/issues/1645\n[`f2a56f`]: https://github.com/rwf2/Rocket/commit/f2a56f\n\n# Version 0.4.8 (May 18, 2021)\n\n## Core\n\n  * [[`#1548`], [`93e88b0`]] Fixed an issue that prevented compilation under\n    Windows Subsystem for Linux v1.\n  * Updated `Outcome` `Try` implementation to v2 in latest nightly.\n  * Minimum required `rustc` is `1.54.0-nightly (2021-05-18)`.\n\n## Internal\n\n  * Updated `base64` dependency to `0.13`.\n\n[`#1548`]: https://github.com/rwf2/Rocket/issues/1548\n[`93e88b0`]: https://github.com/rwf2/Rocket/commit/93e88b0\n\n# Version 0.4.7 (Feb 09, 2021)\n\n## Core\n\n  * [[#1534], [`2059a6`]] Fixed a low-severity, minimal impact soundness issue\n    in `uri::Formatter`.\n\n[#1534]: https://github.com/rwf2/Rocket/issues/1534\n[`2059a6`]: https://github.com/rwf2/Rocket/commit/2059a6\n\n# Version 0.4.6 (Nov 09, 2020)\n\n## Core\n\n  * [[`86bd7c`]] Added default and configurable read/write timeouts:\n    `read_timeout` and `write_timeout`.\n  * [[`c24a96`]] Added the `sse` feature, which [enables flushing] by returning\n    `io::ErrorKind::WouldBlock`.\n\n## Docs\n\n  * Fixed broken doc links in `contrib`.\n  * Fixed database library versions in `contrib` docs.\n\n## Internal\n\n  * Updated source code for Rust 2018.\n  * UI tests now use `trybuild` instead of `compiletest-rs`.\n\n[`86bd7c`]: https://github.com/rwf2/Rocket/commit/86bd7c\n[`c24a96`]: https://github.com/rwf2/Rocket/commit/c24a96\n[enables flushing]: https://api.rocket.rs/v0.4/rocket/response/struct.Stream.html#buffering-and-blocking\n\n# Version 0.4.5 (May 30, 2020)\n\n## Core\n\n  * [[#1312], [`89150f`]] Fixed a low-severity, minimal impact soundness issue in\n    `LocalRequest::clone()`.\n  * [[#1263], [`376f74`]] Fixed a cookie serialization issue that led to\n    incorrect cookie deserialization in certain cases.\n  * Removed dependency on `ring` for private cookies and thus Rocket, by\n    default.\n  * Added [`Origin::map_path()`] for manipulating `Origin` paths.\n  * Added [`handler::Outcome::from_or_forward()`].\n  * Added [`Options::NormalizeDirs`] option to `StaticFiles`.\n  * Improved accessibility of default error HTML.\n\n## Docs\n\n  * Fixed various typos.\n\n[#1312]: https://github.com/rwf2/Rocket/issues/1312\n[`89150f`]: https://github.com/rwf2/Rocket/commit/89150f\n[#1263]: https://github.com/rwf2/Rocket/issues/1263\n[`376f74`]: https://github.com/rwf2/Rocket/commit/376f74\n[`Origin::map_path()`]: https://api.rocket.rs/v0.4/rocket/http/uri/struct.Origin.html#method.map_path\n[`handler::Outcome::from_or_forward()`]: https://api.rocket.rs/v0.4/rocket/handler/type.Outcome.html#method.from_or_forward\n[`Options::NormalizeDirs`]: https://api.rocket.rs/v0.4/rocket_contrib/serve/struct.Options.html#associatedconstant.NormalizeDirs\n\n# Version 0.4.4 (Mar 09, 2020)\n\n## Core\n\n  * Removed use of unsupported `cfg(debug_assertions)` in `Cargo.toml`, allowing\n    for builds on latest nightlies.\n\n## Docs\n\n  * Fixed various broken links.\n\n# Version 0.4.3 (Feb 29, 2020)\n\n## Core\n\n  * Added a new [`Debug`] `500` `Responder` that `Debug`-prints its contents on\n    response.\n  * Specialization on `Result` was deprecated. [`Debug`] can be used in place of\n    non-`Responder` errors.\n  * Fixed an issue that resulted in cookies not being set on error responses.\n  * Various `Debug` implementations on Rocket types now respect formatting\n    options.\n  * Added `Responder`s for various HTTP status codes: [`NoContent`],\n    [`Unauthorized`], [`Forbidden`], and [`Conflict`].\n  * `FromParam` is implemented for `NonZero` core types.\n\n## Codegen\n\n  * Docs for Rocket-generated macros are now hidden.\n  * Generated code now works even when prelude imports like `Some`, `Ok`, and\n    `Err` are shadowed.\n  * Error messages referring to responder types in routes now point to the type\n    correctly.\n\n## Docs\n\n  * All code examples in the guide are now tested and guaranteed to compile.\n  * All macros are documented in the `core` crate; `rocket_codegen` makes no\n    appearances.\n\n## Infrastructure\n\n  * CI was moved from Travis to Azure Pipelines; Windows support is tested.\n  * Rocket's chat moved to [Matrix] and [Freenode].\n\n[`Debug`]: https://api.rocket.rs/v0.4/rocket/response/struct.Debug.html\n[`NoContent`]: https://api.rocket.rs/v0.4/rocket/response/status/struct.NoContent.html\n[`Unauthorized`]: https://api.rocket.rs/v0.4/rocket/response/status/struct.Unauthorized.html\n[`Forbidden`]: https://api.rocket.rs/v0.4/rocket/response/status/struct.Forbidden.html\n[`Conflict`]: https://api.rocket.rs/v0.4/rocket/response/status/struct.Conflict.html\n[Matrix]: https://chat.mozilla.org/#/room/#rocket:mozilla.org\n[Freenode]: https://kiwiirc.com/client/chat.freenode.net/#rocket\n\n# Version 0.4.2 (Jun 28, 2019)\n\n## Core\n\n  * Replaced use of `FnBox` with `Box<dyn FnOnce>`.\n  * Removed the stable feature gates `try_from` and `transpose_result`.\n  * Derive macros are reexported alongside their respective traits.\n  * Minimum required `rustc` is `1.35.0-nightly (2019-04-05)`.\n\n## Codegen\n\n  * `JsonValue` now implements `FromIterator`.\n  * `non_snake_case` errors are silenced in generated code.\n  * Minimum required `rustc` is `1.33.0-nightly (2019-01-03)`.\n\n## Contrib\n\n  * Allow setting custom ranks on `StaticFiles` via [`StaticFiles::rank()`].\n  * `MsgPack` correctly sets a MessagePack Content-Type on responses.\n\n## Docs\n\n  * Fixed typos across rustdocs and guide.\n  * Documented library versions in contrib database documentation.\n\n## Infrastructure\n\n  * Updated internal dependencies to their latest versions.\n\n[`StaticFiles::rank()`]: https://api.rocket.rs/v0.4/rocket_contrib/serve/struct.StaticFiles.html#method.rank\n\n# Version 0.4.1 (May 11, 2019)\n\n## Core\n\n  * Rocket's default `Server` HTTP header no longer overrides a user-set header.\n  * Fixed encoding and decoding of certain URI characters.\n\n## Codegen\n\n  * Compiler diagnostic information is more reliably produced.\n\n## Contrib\n\n  * Database pool types now implement `DerefMut`.\n  * Added support for memcache connection pools.\n  * Stopped depending on default features from core.\n\n## Docs\n\n  * Fixed many typos across the rustdocs and guide.\n  * Added guide documentation on mounting more than one route at once.\n\n## Infrastructure\n\n  * Testing no longer requires \"bootstrapping\".\n  * Removed deprecated `isatty` dependency in favor of `atty`.\n\n# Version 0.4.0 (Dec 06, 2018)\n\n## New Features\n\nThis release includes the following new features:\n\n  * Introduced [Typed URIs].\n  * Introduced [ORM agnostic database support].\n  * Introduced [Request-Local State].\n  * Introduced mountable static-file serving via [`StaticFiles`].\n  * Introduced automatic [live template reloading].\n  * Introduced custom stateful handlers via [`Handler`].\n  * Introduced [transforming] data guards via [`FromData::transform()`].\n  * Introduced revamped [query string handling].\n  * Introduced the [`SpaceHelmet`] security and privacy headers fairing.\n  * Private cookies are gated behind a `private-cookies` default feature.\n  * Added [derive for `FromFormValue`].\n  * Added [derive for `Responder`].\n  * Added [`Template::custom()`] for customizing templating engines including\n    registering filters and helpers.\n  * Cookies are automatically tracked and propagated by [`Client`].\n  * Private cookies can be added to local requests with\n    [`LocalRequest::private_cookie()`].\n  * Release builds default to the `production` environment.\n  * Keep-alive can be configured via the `keep_alive` configuration parameter.\n  * Allow CLI colors and emoji to be disabled with `ROCKET_CLI_COLORS=off`.\n  * Route `format` accepts [shorthands] such as `json` and `html`.\n  * Implemented [`Responder` for `Status`].\n  * Added [`Response::cookies()`] for retrieving response cookies.\n  * All logging is disabled when `log` is set to `off`.\n  * Added [`Metadata`] guard for retrieving templating information.\n  * The [`Uri`] type parses URIs according to RFC 7230 into one of [`Origin`],\n    [`Absolute`], or [`Authority`].\n  * Added [`Outcome::and_then()`], [`Outcome::failure_then()`], and\n    [`Outcome::forward_then()`].\n  * Implemented `Responder` for `&[u8]`.\n  * Any `T: Into<Vec<Route>>` can be [`mount()`]ed.\n  * [Default rankings] range from -6 to -1, differentiating on static query\n    strings.\n  * Added [`Request::get_query_value()`] for retrieving a query value by key.\n  * Applications can launch without a working directory.\n  * Added [`State::from()`] for constructing `State` values.\n\n[`SpaceHelmet`]: https://api.rocket.rs/v0.4/rocket_contrib/helmet/index.html\n[`State::from()`]: https://api.rocket.rs/v0.4/rocket/struct.State.html#method.from\n[Typed URIs]: https://rocket.rs/v0.4/guide/responses/#typed-uris\n[ORM agnostic database support]: https://rocket.rs/v0.4/guide/state/#databases\n[`Template::custom()`]: https://api.rocket.rs/v0.4/rocket_contrib/templates/struct.Template.html#method.custom\n[`LocalRequest::private_cookie()`]: https://api.rocket.rs/v0.4/rocket/local/struct.LocalRequest.html#method.private_cookie\n[`LocalRequest`]: https://api.rocket.rs/v0.4/rocket/local/struct.LocalRequest.html\n[shorthands]: https://api.rocket.rs/v0.4/rocket/http/struct.ContentType.html#method.parse_flexible\n[derive for `FromFormValue`]: https://api.rocket.rs/v0.4/rocket_codegen/derive.FromFormValue.html\n[derive for `Responder`]: https://api.rocket.rs/v0.4/rocket_codegen/derive.Responder.html\n[`Response::cookies()`]: https://api.rocket.rs/v0.4/rocket/struct.Response.html#method.cookies\n[`Client`]: https://api.rocket.rs/v0.4/rocket/local/struct.Client.html\n[Request-Local State]: https://rocket.rs/v0.4/guide/state/#request-local-state\n[`Metadata`]: https://api.rocket.rs/v0.4/rocket_contrib/templates/struct.Metadata.html\n[`Uri`]: https://api.rocket.rs/v0.4/rocket/http/uri/enum.Uri.html\n[`Origin`]: https://api.rocket.rs/v0.4/rocket/http/uri/struct.Origin.html\n[`Absolute`]: https://api.rocket.rs/v0.4/rocket/http/uri/struct.Absolute.html\n[`Authority`]: https://api.rocket.rs/v0.4/rocket/http/uri/struct.Authority.html\n[`Outcome::and_then()`]: https://api.rocket.rs/v0.4/rocket/enum.Outcome.html#method.and_then\n[`Outcome::forward_then()`]: https://api.rocket.rs/v0.4/rocket/enum.Outcome.html#method.forward_then\n[`Outcome::failure_then()`]: https://api.rocket.rs/v0.4/rocket/enum.Outcome.html#method.failure_then\n[`StaticFiles`]: https://api.rocket.rs/v0.4/rocket_contrib/serve/struct.StaticFiles.html\n[live template reloading]: https://rocket.rs/v0.4/guide/responses/#live-reloading\n[`Handler`]: https://api.rocket.rs/v0.4/rocket/trait.Handler.html\n[`mount()`]: https://api.rocket.rs/v0.4/rocket/struct.Rocket.html#method.mount\n[`FromData::transform()`]: https://api.rocket.rs/v0.4/rocket/data/trait.FromData.html#tymethod.transform\n[transforming]: https://api.rocket.rs/v0.4/rocket/data/trait.FromData.html#transforming\n[query string handling]: https://rocket.rs/v0.4/guide/requests/#query-strings\n[Default rankings]: https://rocket.rs/v0.4/guide/requests/#default-ranking\n[`Request::get_query_value()`]: https://api.rocket.rs/v0.4/rocket/struct.Request.html#method.get_query_value\n[`Responder` for `Status`]: https://rocket.rs/v0.4/guide/responses/#status\n\n## Codegen Rewrite\n\nThe [`rocket_codegen`] crate has been entirely rewritten using to-be-stable\nprocedural macro APIs. We expect nightly breakages to drop dramatically, likely\nto zero, as a result. The new prelude import for Rocket applications is:\n\n```diff\n- #![feature(plugin)]\n- #![plugin(rocket_codegen)]\n+ #![feature(proc_macro_hygiene, decl_macro)]\n\n- extern crate rocket;\n+ #[macro_use] extern crate rocket;\n```\n\nThe [`rocket_codegen`] crate should **_not_** be a direct dependency. Remove it\nfrom your `Cargo.toml`:\n\n```diff\n[dependencies]\n- rocket = \"0.3\"\n+ rocket = \"0.4\"\n- rocket_codegen = \"0.3\"\n```\n\n[`rocket_codegen`]: https://api.rocket.rs/v0.4/rocket_codegen/index.html\n\n## Breaking Changes\n\nThis release includes many breaking changes. These changes are listed below\nalong with a short note about how to handle the breaking change in existing\napplications when applicable.\n\n  * **Route and catcher attributes respect function privacy.**\n\n    To mount a route or register a catcher outside of the module it is declared,\n    ensure that the handler function is marked `pub` or `crate`.\n\n  * **Query handling syntax has been completely revamped.**\n\n    A query parameter of `<param>` is now `<param..>`. Consider whether your\n    application benefits from the revamped [query string handling].\n\n  * **The `#[error]` attribute and `errors!` macro were removed.**\n\n    Use `#[catch]` and `catchers!` instead.\n\n  * **`Rocket::catch()` was renamed to [`Rocket::register()`].**\n\n    Change calls of the form `.catch(errors![..])` to\n    `.register(catchers![..])`.\n\n  * **The `#[catch]` attribute only accepts functions with 0 or 1 argument.**\n\n    Ensure the argument to the catcher, if any, is of type `&Request`.\n\n  * **[`json!`] returns a [`JsonValue`], no longer needs wrapping.**\n\n    Change instances of `Json(json!(..))` to `json!` and change the\n    corresponding type to `JsonValue`.\n\n  * **All environments default to port 8000.**\n\n    Manually configure a port of `80` for the `stage` and `production`\n    environments for the previous behavior.\n\n  * **Release builds default to the production environment.**\n\n    Manually set the environment to `debug` with `ROCKET_ENV=debug` for the\n    previous behavior.\n\n  * **[`Form`] and [`LenientForm`] lost a lifetime parameter, `get()` method.**\n\n    Change a type of `Form<'a, T<'a>>` to `Form<T>` or `Form<T<'a>>`. `Form<T>`\n    and `LenientForm<T>` now implement `Deref<Target = T>`, allowing for calls\n    to `.get()` to be removed.\n\n  * **[`ring`] was updated to 0.13.**\n\n    Ensure all transitive dependencies to `ring` refer to version `0.13`.\n\n  * **`Uri` was largely replaced by [`Origin`].**\n\n    In general, replace the type `Uri` with `Origin`. The `base` and `uri`\n    fields of [`Route`] are now of type [`Origin`]. The `&Uri` guard is now\n    `&Origin`. [`Request::uri()`] now returns an [`Origin`].\n\n  * **All items in [`rocket_contrib`] are namespaced behind modules.**\n\n    * `Json` is now `json::Json`\n    * `MsgPack` is now `msgpack::MsgPack`\n    * `MsgPackError` is now `msgpack::Error`\n    * `Template` is now `templates::Template`\n    * `UUID` is now `uuid::Uuid`\n    * `Value` is replaced by `json::JsonValue`\n\n  * **TLS certificates require the `subjectAltName` extension.**\n\n    Ensure that your TLS certificates contain the `subjectAltName` extension\n    with a value set to your domain.\n\n  * **Route paths, mount points, and [`LocalRequest`] URIs are strictly\n    checked.**\n\n    Ensure your mount points are absolute paths with no parameters, ensure your\n    route paths are absolute paths with proper parameter syntax, and ensure that\n    paths passed to `LocalRequest` are valid.\n\n  * **[`Template::show()`] takes an `&Rocket`, doesn't accept a `root`.**\n\n    Use [`client.rocket()`] to get a reference to an instance of `Rocket` when\n    testing. Use [`Template::render()`] in routes.\n\n  * **[`Request::remote()`] returns the _actual_ remote IP, doesn't rewrite.**\n\n    Use [`Request::real_ip()`] or [`Request::client_ip()`] to retrieve the IP\n    address from the \"X-Real-IP\" header if it is present.\n\n  * **[`Bind`] variant was added to [`LaunchErrorKind`].**\n\n    Ensure matches on `LaunchErrorKind` include or ignore the `Bind` variant.\n\n  * **Cookies are automatically tracked and propagated by [`Client`].**\n\n    For the previous behavior, construct a `Client` with\n    [`Client::untracked()`].\n\n  * **`UUID` was renamed to [`Uuid`].**\n\n    Use `Uuid` instead of `UUID`.\n\n  * **`LocalRequest::cloned_dispatch()` was removed.**\n\n    Chain calls to `.clone().dispatch()` for the previous behavior.\n\n  * **[`Redirect`] constructors take a generic type of `T:\n    TryInto<Uri<'static>>`.**\n\n    A call to a `Redirect` constructor with a non-`'static` `&str`  of the form\n    `Redirect::to(string)` should become `Redirect::to(string.to_string())`,\n    heap-allocating the string before being passed to the constructor.\n\n  * **The [`FromData`] impl for [`Form`] and [`LenientForm`] now return an error\n    of type [`FormDataError`].**\n\n    On non-I/O errors, the form string is stored in the variant as an `&'f str`.\n\n  * **[`Missing`] variant was added to [`ConfigError`].**\n\n    Ensure matches on `ConfigError` include or ignore the `Missing` variant.\n\n  * **The [`FromData`] impl for [`Json`] now returns an error of type\n    [`JsonError`].**\n\n    The previous `SerdeError` is now the `.1` member of the `JsonError` `enum`.\n    Match and destruct the variant for the previous behavior.\n\n  * **[`FromData`] is now emulated by [`FromDataSimple`].**\n\n    Change _implementations_, not uses, of `FromData` to `FromDataSimple`.\n    Consider whether your implementation could benefit from [transformations].\n\n  * **[`FormItems`] iterates over values of type [`FormItem`].**\n\n    Map using `.map(|item| item.key_value())` for the previous behavior.\n\n  * **[`LaunchErrorKind::Collision`] contains a vector of the colliding routes.**\n\n    Destruct using `LaunchErrorKind::Collision(..)` to ignore the vector.\n\n  * **[`Request::get_param()`] and [`Request::get_segments()`] are indexed by\n    _segment_, not dynamic parameter.**\n\n    Modify the `n` argument in calls to these functions appropriately.\n\n  * **Method-based route attributes no longer accept a keyed `path` parameter.**\n\n    Change an attribute of the form `#[get(path = \"..\")]` to `#[get(\"..\")]`.\n\n  * **[`Json`] and [`MsgPack`] data guards no longer reject requests with an\n    unexpected Content-Type**\n\n    To approximate the previous behavior, add a `format = \"json\"` route\n    parameter when using `Json` or `format = \"msgpack\"` when using `MsgPack`.\n\n  * **Implemented [`Responder` for `Status`]. Removed `Failure`,\n    `status::NoContent`, and `status::Reset` responders.**\n\n    Replace uses of `Failure(status)` with `status` directly. Replace\n    `status::NoContent` with `Status::NoContent`. Replace `status::Reset` with\n    `Status::ResetContent`.\n\n  * **[`Config::root()`] returns an `Option<&Path>` instead of an `&Path`.**\n\n    For the previous behavior, use `config.root().unwrap()`.\n\n  * **[`Status::new()`] is no longer `const`.**\n\n    Construct a `Status` directly.\n\n  * **[`Config`] constructors return a `Config` instead of a `Result<Config>`.**\n\n  * **`ConfigError::BadCWD`, `Config.config_path` were removed.**\n\n  * **[`Json`] no longer has a default value for its type parameter.**\n\n  * **Using `data` on a non-payload method route is a warning instead of error.**\n\n  * **The `raw_form_string` method of [`Form`] and [`LenientForm`] was\n    removed.**\n\n  * **Various impossible `Error` associated types are now set to `!`.**\n\n  * **All [`AdHoc`] constructors require a name as the first parameter.**\n\n  * **The top-level `Error` type was removed.**\n\n[`LaunchErrorKind::Collision`]: https://api.rocket.rs/v0.4/rocket/error/enum.LaunchErrorKind.html#variant.Collision\n[`json!`]: https://api.rocket.rs/v0.4/rocket_contrib/macro.json.html\n[`JsonValue`]: https://api.rocket.rs/v0.4/rocket_contrib/json/struct.JsonValue.html\n[`Json`]: https://api.rocket.rs/v0.4/rocket_contrib/json/struct.Json.html\n[`ring`]: https://crates.io/crates/ring\n[`Template::show()`]: https://api.rocket.rs/v0.4/rocket_contrib/templates/struct.Template.html#method.show\n[`Template::render()`]: https://api.rocket.rs/v0.4/rocket_contrib/templates/struct.Template.html#method.render\n[`client.rocket()`]: https://api.rocket.rs/v0.4/rocket/local/struct.Client.html#method.rocket\n[`Request::remote()`]: https://api.rocket.rs/v0.4/rocket/struct.Request.html#method.remote\n[`Request::real_ip()`]: https://api.rocket.rs/v0.4/rocket/struct.Request.html#method.real_ip\n[`Request::client_ip()`]: https://api.rocket.rs/v0.4/rocket/struct.Request.html#method.client_ip\n[`Bind`]: https://api.rocket.rs/v0.4/rocket/error/enum.LaunchErrorKind.html#variant.Bind\n[`LaunchErrorKind`]: https://api.rocket.rs/v0.4/rocket/error/enum.LaunchErrorKind.html\n[`Client::untracked()`]: https://api.rocket.rs/v0.4/rocket/local/struct.Client.html#method.untracked\n[`Uuid`]: https://api.rocket.rs/v0.4/rocket_contrib/uuid/struct.Uuid.html\n[`Route`]: https://api.rocket.rs/v0.4/rocket/struct.Route.html\n[`Redirect`]: https://api.rocket.rs/v0.4/rocket/response/struct.Redirect.html\n[`Request::uri()`]: https://api.rocket.rs/v0.4/rocket/struct.Request.html#method.uri\n[`FormDataError`]: https://api.rocket.rs/v0.4/rocket/request/enum.FormDataError.html\n[`FromData`]: https://api.rocket.rs/v0.4/rocket/data/trait.FromData.html\n[`Form`]: https://api.rocket.rs/v0.4/rocket/request/struct.Form.html\n[`LenientForm`]: https://api.rocket.rs/v0.4/rocket/request/struct.LenientForm.html\n[`AdHoc`]: https://api.rocket.rs/v0.4/rocket/fairing/struct.AdHoc.html\n[`Missing`]: https://api.rocket.rs/v0.4/rocket/config/enum.ConfigError.html#variant.Missing\n[`ConfigError`]: https://api.rocket.rs/v0.4/rocket/config/enum.ConfigError.html\n[`Rocket::register()`]: https://api.rocket.rs/v0.4/rocket/struct.Rocket.html#method.register\n[`JsonError`]: https://api.rocket.rs/v0.4/rocket_contrib/json/enum.JsonError.html\n[transformations]: https://api.rocket.rs/v0.4/rocket/data/trait.FromData.html#transforming\n[`FromDataSimple`]: https://api.rocket.rs/v0.4/rocket/data/trait.FromDataSimple.html\n[`Request::get_param()`]: https://api.rocket.rs/v0.4/rocket/struct.Request.html#method.get_param\n[`Request::get_segments()`]: https://api.rocket.rs/v0.4/rocket/struct.Request.html#method.get_segments\n[`FormItem`]: https://api.rocket.rs/v0.4/rocket/request/struct.FormItem.html\n[`rocket_contrib`]: https://api.rocket.rs/v0.4/rocket_contrib/index.html\n[`MsgPack`]: https://api.rocket.rs/v0.4/rocket_contrib/msgpack/struct.MsgPack.html\n[`Status::new()`]: https://api.rocket.rs/v0.4/rocket/http/struct.Status.html#method.new\n[`Config`]: https://api.rocket.rs/v0.4/rocket/struct.Config.html\n[`Config::root()`]: https://api.rocket.rs/v0.4/rocket/struct.Config.html#method.root\n\n## General Improvements\n\nIn addition to new features, Rocket saw the following improvements:\n\n  * Log messages now refer to routes by name.\n  * Collision errors on launch name the colliding routes.\n  * Launch fairing failures refer to the failing fairing by name.\n  * The default `403` catcher now references authorization, not authentication.\n  * Private cookies are set to `HttpOnly` and are given an expiration date of 1\n    week by default.\n  * A [Tera templates example] was added.\n  * All macros, derives, and attributes are individually documented in\n    [`rocket_codegen`].\n  * Invalid client requests receive a response of `400` instead of `500`.\n  * Response bodies are reliably stripped on `HEAD` requests.\n  * Added a default catcher for `504: Gateway Timeout`.\n  * Configuration information is logged in all environments.\n  * Use of `unsafe` was reduced from 9 to 2 in core library.\n  * [`FormItems`] now parses empty keys and values as well as keys without\n    values.\n  * Added [`Config::active()`] as a shorthand for\n    `Config::new(Environment::active()?)`.\n  * Address/port binding errors at launch are detected and explicitly emitted.\n  * [`Flash`] cookies are cleared only after they are inspected.\n  * `Sync` bound on [`AdHoc::on_attach()`], [`AdHoc::on_launch()`] was removed.\n  * [`AdHoc::on_attach()`], [`AdHoc::on_launch()`] accept an `FnOnce`.\n  * Added [`Config::root_relative()`] for retrieving paths relative to the\n    configuration file.\n  * Added [`Config::tls_enabled()`] for determining whether TLS is actively\n    enabled.\n  * ASCII color codes are not emitted on versions of Windows that do not support\n    them.\n  * Added FLAC (`audio/flac`), Icon (`image/x-icon`), WEBA (`audio/webm`), TIFF\n    (`image/tiff`), AAC (`audio/aac`), Calendar (`text/calendar`), MPEG\n    (`video/mpeg`), TAR (`application/x-tar`), GZIP (`application/gzip`), MOV\n    (`video/quicktime`), MP4 (`video/mp4`), ZIP (`application/zip`) as known\n    media types.\n  * Added `.weba` (`WEBA`), `.ogv` (`OGG`), `.mp4` (`MP4`), `.mpeg4` (`MP4`),\n    `.aac` (`AAC`), `.ics` (`Calendar`), `.bin` (`Binary`), `.mpg` (`MPEG`),\n    `.mpeg` (`MPEG`), `.tar` (`TAR`), `.gz` (`GZIP`), `.tif` (`TIFF`), `.tiff`\n    (`TIFF`), `.mov` (`MOV`) as known extensions.\n  * Interaction between route attributes and declarative macros has been\n    improved.\n  * Generated code now logs through logging infrastructures as opposed to using\n    `println!`.\n  * Routing has been optimized by caching routing metadata.\n  * [`Form`] and [`LenientForm`] can be publicly constructed.\n  * Console coloring uses default terminal colors instead of white.\n  * Console coloring is consistent across all messages.\n  * `i128` and `u128` now implement [`FromParam`], [`FromFormValue`].\n  * The `base64` dependency was updated to `0.10`.\n  * The `log` dependency was updated to `0.4`.\n  * The `handlebars` dependency was updated to `1.0`.\n  * The `tera` dependency was updated to `0.11`.\n  * The `uuid` dependency was updated to `0.7`.\n  * The `rustls` dependency was updated to `0.14`.\n  * The `cookie` dependency was updated to `0.11`.\n\n[Tera templates example]: https://github.com/rwf2/Rocket/tree/v0.4/examples/tera_templates\n[`FormItems`]: https://api.rocket.rs/v0.4/rocket/request/enum.FormItems.html\n[`Config::active()`]: https://api.rocket.rs/v0.4/rocket/config/struct.Config.html#method.active\n[`Flash`]: https://api.rocket.rs/v0.4/rocket/response/struct.Flash.html\n[`AdHoc::on_attach()`]: https://api.rocket.rs/v0.4/rocket/fairing/struct.AdHoc.html#method.on_attach\n[`AdHoc::on_launch()`]: https://api.rocket.rs/v0.4/rocket/fairing/struct.AdHoc.html#method.on_launch\n[`Config::root_relative()`]: https://api.rocket.rs/v0.4/rocket/struct.Config.html#method.root_relative\n[`Config::tls_enabled()`]: https://api.rocket.rs/v0.4/rocket/struct.Config.html#method.tls_enabled\n[`rocket_codegen`]: https://api.rocket.rs/v0.4/rocket_codegen/index.html\n[`FromParam`]: https://api.rocket.rs/v0.4/rocket/request/trait.FromParam.html\n[`FromFormValue`]: https://api.rocket.rs/v0.4/rocket/request/trait.FromFormValue.html\n[`Data`]: https://api.rocket.rs/v0.4/rocket/struct.Data.html\n\n## Infrastructure\n\n  * All documentation is versioned.\n  * Previous, current, and development versions of all documentation are hosted.\n  * The repository was reorganized with top-level directories of `core` and\n    `contrib`.\n  * The `http` module was split into its own `rocket_http` crate. This is an\n    internal change only.\n  * All uses of `unsafe` are documented with informal proofs of correctness.\n\n# Version 0.3.16 (Aug 24, 2018)\n\n## Codegen\n\n  * Codegen was updated for `2018-08-23` nightly.\n  * Minimum required `rustc` is `1.30.0-nightly 2018-08-23`.\n\n## Core\n\n  * Force close only the read end of connections. This allows responses to be\n    sent even when the client transmits more data than expected.\n\n## Docs\n\n  * Add details on retrieving configuration extras to guide.\n\n# Version 0.3.15 (Jul 16, 2018)\n\n## Codegen\n\n  * The `#[catch]` decorator and `catchers!` macro were introduced, replacing\n    `#[error]` and `errors!`.\n  * The `#[error]` decorator and `errors!` macro were deprecated.\n  * Codegen was updated for `2018-07-15` nightly.\n  * Minimum required `rustc` is `1.29.0-nightly 2018-07-15`.\n\n# Version 0.3.14 (Jun 22, 2018)\n\n## Codegen\n\n  * Codegen was updated for `2018-06-22` nightly.\n  * Minimum required `rustc` is `1.28.0-nightly 2018-06-22`.\n\n# Version 0.3.13 (Jun 16, 2018)\n\n## Codegen\n\n  * Codegen was updated for `2018-06-12` nightly.\n  * Minimum required `rustc` is `1.28.0-nightly 2018-06-12`.\n\n# Version 0.3.12 (May 31, 2018)\n\n## Codegen\n\n  * Codegen was updated for `2018-05-30` nightly.\n  * Minimum required `rustc` is `1.28.0-nightly 2018-05-30`.\n\n# Version 0.3.11 (May 19, 2018)\n\n## Core\n\n  * Core was updated for `2018-05-18` nightly.\n\n## Infrastructure\n\n  * Fixed injection of dependencies for codegen compile-fail tests.\n\n# Version 0.3.10 (May 05, 2018)\n\n## Core\n\n  * Fixed parsing of nested TOML structures in config environment variables.\n\n## Codegen\n\n  * Codegen was updated for `2018-05-03` nightly.\n  * Minimum required `rustc` is `1.27.0-nightly 2018-05-04`.\n\n## Contrib\n\n  * Contrib was updated for `2018-05-03` nightly.\n\n## Docs\n\n  * Fixed database pool type in state guide.\n\n# Version 0.3.9 (Apr 26, 2018)\n\n## Core\n\n  * Core was updated for `2018-04-26` nightly.\n  * Minimum required `rustc` is `1.27.0-nightly 2018-04-26`.\n  * Managed state retrieval cost was reduced to an unsynchronized `HashMap`\n    lookup.\n\n## Codegen\n\n  * Codegen was updated for `2018-04-26` nightly.\n  * Minimum required `rustc` is `1.27.0-nightly 2018-04-26`.\n\n## Contrib\n\n  * A 512-byte buffer is preallocated when deserializing JSON, improving\n    performance.\n\n## Docs\n\n  * Fixed various typos in rustdocs and guide.\n\n# Version 0.3.8 (Apr 07, 2018)\n\n## Codegen\n\n  * Codegen was updated for `2018-04-06` nightly.\n  * Minimum required `rustc` is `1.27.0-nightly 2018-04-06`.\n\n# Version 0.3.7 (Apr 03, 2018)\n\n## Core\n\n  * Fixed a bug where incoming request URIs would match routes with the same\n    path prefix and suffix and ignore the rest.\n  * Added known media types for WASM, WEBM, OGG, and WAV.\n  * Fixed fragment URI parsing.\n\n## Codegen\n\n  * Codegen was updated for `2018-04-03` nightly.\n  * Minimum required `rustc` is `1.27.0-nightly 2018-04-03`.\n\n## Contrib\n\n  * JSON data is read eagerly, improving deserialization performance.\n\n## Docs\n\n  * Database example and docs were updated for Diesel 1.1.\n  * Removed outdated README performance section.\n  * Fixed various typos in rustdocs and guide.\n\n## Infrastructure\n\n  * Removed gates for stabilized features: `iterator_for_each`, `i128_type`,\n    `conservative_impl_trait`, `never_type`.\n  * Travis now tests in both debug and release mode.\n\n# Version 0.3.6 (Jan 12, 2018)\n\n## Core\n\n  * `Rocket.state()` method was added to retrieve managed state from `Rocket`\n    instances.\n  * Nested calls to `Rocket.attach()` are now handled correctly.\n  * JSON API (`application/vnd.api+json`) is now a known media type.\n  * Uncached markers for `ContentType` and `Accept` headers are properly\n    preserved on `Request.clone()`.\n  * Minimum required `rustc` is `1.25.0-nightly 2018-01-12`.\n\n## Codegen\n\n  * Codegen was updated for `2017-12-22` nightly.\n  * Minimum required `rustc` is `1.24.0-nightly 2017-12-22`.\n\n## Docs\n\n  * Fixed typo in state guide: ~~simple~~ simply.\n  * Database example and docs were updated for Diesel 1.0.\n\n## Infrastructure\n\n  * Shell scripts now use `git grep` instead of `egrep` for faster searching.\n\n# Version 0.3.5 (Dec 18, 2017)\n\n## Codegen\n\n  * Codegen was updated for `2017-12-17` nightly.\n  * Minimum required `rustc` is `1.24.0-nightly 2017-12-17`.\n\n# Version 0.3.4 (Dec 14, 2017)\n\n## Core\n\n  * `NamedFile`'s `Responder` implementation now uses a sized body when the\n    file's length is known.\n  * `#[repr(C)]` is used on `str` wrappers to guarantee correct structure layout\n    across platforms.\n  * A `status::BadRequest` `Responder` was added.\n\n## Codegen\n\n  * Codegen was updated for `2017-12-13` nightly.\n  * Minimum required `rustc` is `1.24.0-nightly 2017-12-13`.\n\n## Docs\n\n  * The rustdoc `html_root_url` now points to the correct address.\n  * Fixed typo in fairings guide: ~~event~~ events.\n  * Fixed typo in `Outcome` docs: ~~users~~ Users.\n\n# Version 0.3.3 (Sep 25, 2017)\n\n## Core\n\n  * `Config`'s `Debug` implementation now respects formatting options.\n  * `Cow<str>` now implements `FromParam`.\n  * `Vec<u8>` now implements `Responder`.\n  * Added a `Binary` media type for `application/octet-stream`.\n  * Empty fairing collections are no longer logged.\n  * Emojis are no longer emitted to non-terminals.\n  * Minimum required `rustc` is `1.22.0-nightly 2017-09-13`.\n\n## Codegen\n\n  * Improved \"missing argument in handler\" compile-time error message.\n  * Codegen was updated for `2017-09-25` nightly.\n  * Minimum required `rustc` is `1.22.0-nightly 2017-09-25`.\n\n## Docs\n\n  * Fixed typos in site overview: ~~by~~ be, ~~`Reponder`~~ `Responder`.\n  * Markdown indenting was adjusted for CommonMark.\n\n## Infrastructure\n\n  * Shell scripts handle paths with spaces.\n\n# Version 0.3.2 (Aug 15, 2017)\n\n## Core\n\n  * Added conversion methods from and to `Box<UncasedStr>`.\n\n## Codegen\n\n  * Lints were removed due to compiler instability. Lints will likely return as\n    a separate `rocket_lints` crate.\n\n# Version 0.3.1 (Aug 11, 2017)\n\n## Core\n\n  * Added support for ASCII colors on modern Windows consoles.\n  * Form field renames can now include _any_ valid characters, not just idents.\n\n## Codegen\n\n  * Ignored named route parameters are now allowed (`_ident`).\n  * Fixed issue where certain paths would cause a lint `assert!` to fail\n    ([#367](https://github.com/rwf2/Rocket/issues/367)).\n  * Lints were updated for `2017-08-10` nightly.\n  * Minimum required `rustc` is `1.21.0-nightly (2017-08-10)`.\n\n## Contrib\n\n  * Tera errors that were previously skipped internally are now emitted.\n\n## Documentation\n\n  * Typos were fixed across the board.\n\n# Version 0.3.0 (Jul 14, 2017)\n\n## New Features\n\nThis release includes the following new features:\n\n  * [Fairings], Rocket's structure middleware, were introduced.\n  * [Native TLS support] was introduced.\n  * [Private cookies] were introduced.\n  * A [`MsgPack`] type has been added to [`contrib`] for simple consumption and\n    returning of MessagePack data.\n  * Launch failures ([`LaunchError`]) from [`Rocket::launch()`] are now returned\n    for inspection without panicking.\n  * Routes without query parameters now match requests with or without query\n    parameters.\n  * [Default rankings] range from -4 to -1, preferring static paths and routes\n    with query string matches.\n  * A native [`Accept`] header structure was added.\n  * The [`Accept`] request header can be retrieved via [`Request::accept()`].\n  * Incoming form fields [can be renamed] via a new `#[form(field = \"name\")]`\n    structure field attribute.\n  * All active routes can be retrieved via [`Rocket::routes()`].\n  * [`Response::body_string()`] was added to retrieve the response body as a\n    `String`.\n  * [`Response::body_bytes()`] was added to retrieve the response body as a\n    `Vec<u8>`.\n  * [`Response::content_type()`] was added to easily retrieve the Content-Type\n    header of a response.\n  * Size limits on incoming data are [now\n    configurable](https://rocket.rs/v0.3/guide/configuration/#data-limits).\n  * [`Request::limits()`] was added to retrieve incoming data limits.\n  * Responders may dynamically adjust their response based on the incoming\n    request.\n  * [`Request::guard()`] was added for simple retrieval of request guards.\n  * [`Request::route()`] was added to retrieve the active route, if any.\n  * `&Route` is now a request guard.\n  * The base mount path of a [`Route`] can be retrieved via `Route::base` or\n    `Route::base()`.\n  * [`Cookies`] supports _private_ (authenticated encryption) cookies, encrypted\n    with the `secret_key` config key.\n  * `Config::{development, staging, production}` constructors were added for\n    [`Config`].\n  * [`Config::get_datetime()`] was added to retrieve an extra as a `Datetime`.\n  * Forms can be now parsed _leniently_ via the new [`LenientForm`] data guard.\n  * The `?` operator can now be used with `Outcome`.\n  * Quoted string, array, and table  based [configuration parameters] can be set\n    via environment variables.\n  * Log coloring is disabled when `stdout` is not a TTY.\n  * [`FromForm`] is implemented for `Option<T: FromForm>`, `Result<T: FromForm,\n    T::Error>`.\n  * The [`NotFound`] responder was added for simple **404** response\n    construction.\n\n[Fairings]: https://rocket.rs/v0.3/guide/fairings/\n[Native TLS support]: https://rocket.rs/v0.3/guide/configuration/#configuring-tls\n[Private cookies]: https://rocket.rs/v0.3/guide/requests/#private-cookies\n[can be renamed]: https://rocket.rs/v0.3/guide/requests/#field-renaming\n[`MsgPack`]: https://api.rocket.rs/v0.3/rocket_contrib/struct.MsgPack.html\n[`Rocket::launch()`]: https://api.rocket.rs/v0.3/rocket/struct.Rocket.html#method.launch\n[`LaunchError`]: https://api.rocket.rs/v0.3/rocket/error/struct.LaunchError.html\n[Default rankings]: https://api.rocket.rs/v0.3/rocket/struct.Route.html\n[`Route`]: https://api.rocket.rs/v0.3/rocket/struct.Route.html\n[`Accept`]: https://api.rocket.rs/v0.3/rocket/http/struct.Accept.html\n[`Request::accept()`]: https://api.rocket.rs/v0.3/rocket/struct.Request.html#method.accept\n[`contrib`]: https://api.rocket.rs/v0.3/rocket_contrib/\n[`Rocket::routes()`]: https://api.rocket.rs/v0.3/rocket/struct.Rocket.html#method.routes\n[`Response::body_string()`]: https://api.rocket.rs/v0.3/rocket/struct.Response.html#method.body_string\n[`Response::body_bytes()`]: https://api.rocket.rs/v0.3/rocket/struct.Response.html#method.body_bytes\n[`Response::content_type()`]: https://api.rocket.rs/v0.3/rocket/struct.Response.html#method.content_type\n[`Request::guard()`]: https://api.rocket.rs/v0.3/rocket/struct.Request.html#method.guard\n[`Request::limits()`]: https://api.rocket.rs/v0.3/rocket/struct.Request.html#method.limits\n[`Request::route()`]: https://api.rocket.rs/v0.3/rocket/struct.Request.html#method.route\n[`Config`]: https://api.rocket.rs/v0.3/rocket/struct.Config.html\n[`Cookies`]: https://api.rocket.rs/v0.3/rocket/http/enum.Cookies.html\n[`Config::get_datetime()`]: https://api.rocket.rs/v0.3/rocket/struct.Config.html#method.get_datetime\n[`LenientForm`]: https://api.rocket.rs/v0.3/rocket/request/struct.LenientForm.html\n[configuration parameters]: https://api.rocket.rs/v0.3/rocket/config/index.html#environment-variables\n[`NotFound`]: https://api.rocket.rs/v0.3/rocket/response/status/struct.NotFound.html\n\n## Breaking Changes\n\nThis release includes many breaking changes. These changes are listed below\nalong with a short note about how to handle the breaking change in existing\napplications.\n\n  * **`session_key` was renamed to `secret_key`, requires a 256-bit base64 key**\n\n    It's unlikely that `session_key` was previously used. If it was, rename\n    `session_key` to `secret_key`. Generate a random 256-bit base64 key using a\n    tool like openssl: `openssl rand -base64 32`.\n\n  * **The `&Cookies` request guard has been removed in favor of `Cookies`**\n\n    Change `&Cookies` in a request guard position to `Cookies`.\n\n  * **`Rocket::launch()` now returns a `LaunchError`, doesn't panic.**\n\n    For the old behavior, suffix a call to `.launch()` with a semicolon:\n    `.launch();`.\n\n  * **Routes without query parameters match requests with or without query\n    parameters.**\n\n    There is no workaround, but this change may allow manual ranks from routes\n    to be removed.\n\n  * **The `format` route attribute on non-payload requests matches against the\n    Accept header.**\n\n    Excepting a custom request guard, there is no workaround. Previously,\n    `format` always matched against the Content-Type header, regardless of\n    whether the request method indicated a payload or not.\n\n  * **A type of `&str` can no longer be used in form structures or parameters.**\n\n    Use the new [`&RawStr`] type instead.\n\n  * **`ContentType` is no longer a request guard.**\n\n    Use `&ContentType` instead.\n\n  * **`Request::content_type()` returns `&ContentType` instead of\n    `ContentType`.**\n\n    Use `.clone()` on `&ContentType` if a type of `ContentType` is required.\n\n  * **`Response::header_values()` was removed. `Response::headers()` now returns\n    an `&HeaderMap`.**\n\n    A call to `Response::headers()` can be replaced with\n    `Response::headers().iter()`. A call to `Response::header_values(name)` can\n    be replaced with `Response::headers().get(name)`.\n\n  * **Route collisions result in a hard error and panic.**\n\n    There is no workaround. Previously, route collisions were a warning.\n\n  * **The [`IntoOutcome`] trait has been expanded and made more flexible.**\n\n    There is no workaround. `IntoOutcome::into_outcome()` now takes a `Failure`\n    value to use. `IntoOutcome::or_forward()` was added to return a `Forward`\n    outcome if `self` indicates an error.\n\n  * **The 'testing' feature was removed.**\n\n    Remove `features = [\"testing\"]` from `Cargo.toml`. Use the new [`local`]\n    module for testing.\n\n  * **`serde` was updated to 1.0.**\n\n    There is no workaround. Ensure all dependencies rely on `serde` `1.0`.\n\n  * **`config::active()` was removed.**\n\n    Use [`Rocket::config()`] to retrieve the configuration before launch. If\n    needed, use [managed state] to store config information for later use.\n\n  * **The [`Responder`] trait has changed.**\n\n    `Responder::respond(self)` was removed in favor of\n    `Responder::respond_to(self, &Request)`. Responders may dynamically adjust\n    their response based on the incoming request.\n\n  * **`Outcome::of(Responder)` was removed while `Outcome::from(&Request,\n    Responder)` was added.**\n\n    Use `Outcome::from(..)` instead of `Outcome::of(..)`.\n\n  * **Usage of templates requires `Template::fairing()` to be attached.**\n\n    Call `.attach(Template::fairing())` on the application's Rocket instance\n    before launching.\n\n  * **The `Display` implementation of `Template` was removed.**\n\n    Use [`Template::show()`] to render a template directly.\n\n  * **`Request::new()` is no longer exported.**\n\n    There is no workaround.\n\n  * **The [`FromForm`] trait has changed.**\n\n    `Responder::from_form_items(&mut FormItems)` was removed in favor of\n    `Responder::from_form(&mut FormItems, bool)`. The second parameter indicates\n    whether parsing should be strict (if `true`) or lenient (if `false`).\n\n  * **`LoggingLevel` was removed as a root reexport.**\n\n    It can now be imported from `rocket::config::LoggingLevel`.\n\n  * **An `Io` variant was added to [`ConfigError`].**\n\n    Ensure `match`es on `ConfigError` include an `Io` variant.\n\n  * **[`ContentType::from_extension()`] returns an `Option<ContentType>`.**\n\n    For the old behavior, use `.unwrap_or(ContentType::Any)`.\n\n  * **The `IntoValue` config trait was removed in favor of `Into<Value>`.**\n\n    There is no workaround. Use `Into<Value>` as necessary.\n\n  * **The `rocket_contrib::JSON` type has been renamed to\n    [`rocket_contrib::Json`].**\n\n    Use `Json` instead of `JSON`.\n\n  * **All structs in the [`content`] module use TitleCase names.**\n\n    Use `Json`, `Xml`, `Html`, and `Css` instead of `JSON`, `XML`, `HTML`, and\n    `CSS`, respectively.\n\n[`&RawStr`]: https://api.rocket.rs/v0.3/rocket/http/struct.RawStr.html\n[`IntoOutcome`]: https://api.rocket.rs/v0.3/rocket/outcome/trait.IntoOutcome.html\n[`local`]: https://api.rocket.rs/v0.3/rocket/local/index.html\n[`Rocket::config()`]: https://api.rocket.rs/v0.3/rocket/struct.Rocket.html#method.config\n[managed state]: https://rocket.rs/v0.3/guide/state/\n[`Responder`]: https://api.rocket.rs/v0.3/rocket/response/trait.Responder.html\n[`Template::show()`]: https://api.rocket.rs/v0.3/rocket_contrib/struct.Template.html#method.show\n[`FromForm`]: https://api.rocket.rs/v0.3/rocket/request/trait.FromForm.html\n[`ConfigError`]: https://api.rocket.rs/v0.3/rocket/config/enum.ConfigError.html\n[`ContentType::from_extension()`]: https://api.rocket.rs/v0.3/rocket/http/struct.ContentType.html#method.from_extension\n[`rocket_contrib::Json`]: https://api.rocket.rs/v0.3/rocket_contrib/struct.Json.html\n[`content`]: https://api.rocket.rs/v0.3/rocket/response/content/index.html\n\n## General Improvements\n\nIn addition to new features, Rocket saw the following improvements:\n\n  * \"Rocket\" is now capitalized in the `Server` HTTP header.\n  * The generic parameter of `rocket_contrib::Json` defaults to `json::Value`.\n  * The trailing '...' in the launch message was removed.\n  * The launch message prints regardless of the config environment.\n  * For debugging, `FromData` is implemented for `Vec<u8>` and `String`.\n  * The port displayed on launch is the port resolved, not the one configured.\n  * The `uuid` dependency was updated to `0.5`.\n  * The `base64` dependency was updated to `0.6`.\n  * The `toml` dependency was updated to `0.4`.\n  * The `handlebars` dependency was updated to `0.27`.\n  * The `tera` dependency was updated to `0.10`.\n  * [`yansi`] is now used for all terminal coloring.\n  * The `dev` `rustc` release channel is supported during builds.\n  * [`Config`] is now exported from the root.\n  * [`Request`] implements `Clone` and `Debug`.\n  * The `workers` config parameter now defaults to `num_cpus * 2`.\n  * Console logging for table-based config values is improved.\n  * `PartialOrd`, `Ord`, and `Hash` are now implemented for [`State`].\n  * The format of a request is always logged when available.\n  * Route matching on `format` now functions as documented.\n\n[`yansi`]: https://crates.io/crates/yansi\n[`Request`]: https://api.rocket.rs/v0.3/rocket/struct.Request.html\n[`State`]: https://api.rocket.rs/v0.3/rocket/struct.State.html\n\n## Infrastructure\n\n  * All examples include a test suite.\n  * The `master` branch now uses a `-dev` version number.\n\n# Version 0.2.8 (Jun 01, 2017)\n\n## Codegen\n\n  * Lints were updated for `2017-06-01` nightly.\n  * Minimum required `rustc` is `1.19.0-nightly (2017-06-01)`.\n\n# Version 0.2.7 (May 26, 2017)\n\n## Codegen\n\n  * Codegen was updated for `2017-05-26` nightly.\n\n# Version 0.2.6 (Apr 17, 2017)\n\n## Codegen\n\n  * Allow `k` and `v` to be used as fields in `FromForm` structures by avoiding\n    identifier collisions ([#265]).\n\n[#265]: https://github.com/rwf2/Rocket/issues/265\n\n# Version 0.2.5 (Apr 16, 2017)\n\n## Codegen\n\n  * Lints were updated for `2017-04-15` nightly.\n  * Minimum required `rustc` is `1.18.0-nightly (2017-04-15)`.\n\n# Version 0.2.4 (Mar 30, 2017)\n\n## Codegen\n\n  * Codegen was updated for `2017-03-30` nightly.\n  * Minimum required `rustc` is `1.18.0-nightly (2017-03-30)`.\n\n# Version 0.2.3 (Mar 22, 2017)\n\n## Fixes\n\n  * Multiple header values for the same header name are now properly preserved\n    (#223).\n\n## Core\n\n  * The `get_slice` and `get_table` methods were added to `Config`.\n  * The `pub_restricted` feature has been stabilized!\n\n## Codegen\n\n  * Lints were updated for `2017-03-20` nightly.\n  * Minimum required `rustc` is `1.17.0-nightly (2017-03-22)`.\n\n## Infrastructure\n\n  * The test script now denies trailing whitespace.\n\n# Version 0.2.2 (Feb 26, 2017)\n\n## Codegen\n\n  * Lints were updated for `2017-02-25`  and `2017-02-26` nightlies.\n  * Minimum required `rustc` is `1.17.0-nightly (2017-02-26)`.\n\n# Version 0.2.1 (Feb 24, 2017)\n\n## Core Fixes\n\n  * `Flash` cookie deletion functions as expected regardless of the path.\n  * `config` properly accepts IPv6 addresses.\n  * Multiple `Set-Cookie` headers are properly set.\n\n## Core Improvements\n\n  * `Display` and `Error` were implemented for `ConfigError`.\n  * `webp`, `ttf`, `otf`, `woff`, and `woff2` were added as known content types.\n  * Routes are presorted for faster routing.\n  * `into_bytes` and `into_inner` methods were added to `Body`.\n\n## Codegen\n\n  * Fixed `unmanaged_state` lint so that it works with prefilled type aliases.\n\n## Contrib\n\n  * Better errors are emitted on Tera template parse errors.\n\n## Documentation\n\n  * Fixed typos in `manage` and `JSON` docs.\n\n## Infrastructure\n\n  * Updated doctests for latest Cargo nightly.\n\n# Version 0.2.0 (Feb 06, 2017)\n\nDetailed release notes for v0.2 can also be found on\n[rocket.rs](https://rocket.rs/v0.3/news/2017-02-06-version-0.2/).\n\n## New Features\n\nThis release includes the following new features:\n\n  * Introduced managed state.\n  * Added lints that warn on unmanaged state and unmounted routes.\n  * Added the ability to set configuration parameters via environment variables.\n  * `Config` structures can be built via `ConfigBuilder`, which follows the\n    builder pattern.\n  * Logging can be enabled or disabled on custom configuration via a second\n    parameter to the `Rocket::custom` method.\n  * `name` and `value` methods were added to `Header` to retrieve the name and\n    value of a header.\n  * A new configuration parameter, `workers`, can be used to set the number of\n    threads Rocket uses.\n  * The address of the remote connection is available via `Request.remote()`.\n    Request preprocessing overrides remote IP with value from the `X-Real-IP`\n    header, if present.\n  * During testing, the remote address can be set via `MockRequest.remote()`.\n  * The `SocketAddr` request guard retrieves the remote address.\n  * A `UUID` type has been added to `contrib`.\n  * `rocket` and `rocket_codegen` will refuse to build with an incompatible\n    nightly version and emit nice error messages.\n  * Major performance and usability improvements were upstreamed to the `cookie`\n    crate, including the addition of a `CookieBuilder`.\n  * When a checkbox isn't present in a form, `bool` types in a `FromForm`\n    structure will parse as `false`.\n  * The `FormItems` iterator can be queried for a complete parse via `completed`\n    and `exhausted`.\n  * Routes for `OPTIONS` requests can be declared via the `options` decorator.\n  * Strings can be percent-encoded via `URI::percent_encode()`.\n\n## Breaking Changes\n\nThis release includes several breaking changes. These changes are listed below\nalong with a short note about how to handle the breaking change in existing\napplications.\n\n  * **`Rocket::custom` takes two parameters, the first being `Config` by\n    value.**\n\n    A call in v0.1 of the form `Rocket::custom(&config)` is now\n    `Rocket::custom(config, false)`.\n\n  * **Tera templates are named without their extension.**\n\n    A templated named `name.html.tera` is now simply `name`.\n\n  * **`JSON` `unwrap` method has been renamed to `into_inner`.**\n\n    A call to `.unwrap()` should be changed to `.into_inner()`.\n\n  * **The `map!` macro was removed in favor of the `json!` macro.**\n\n    A call of the form `map!{ \"a\" => b }` can be written as: `json!({ \"a\": b\n    })`.\n\n  * **The `hyper::SetCookie` header is no longer exported.**\n\n    Use the `Cookie` type as an `Into<Header>` type directly.\n\n  * **The `Content-Type` for `String` is now `text/plain`.**\n\n    Use `content::HTML<String>` for HTML-based `String` responses.\n\n  * **`Request.content_type()` returns an `Option<ContentType>`.**\n\n    Use `.unwrap_or(ContentType::Any)` to get the old behavior.\n\n  * **The `ContentType` request guard forwards when the request has no\n    `Content-Type` header.**\n\n    Use an `Option<ContentType>` and `.unwrap_or(ContentType::Any)` for the old\n    behavior.\n\n  * **A `Rocket` instance must be declared _before_ a `MockRequest`.**\n\n    Change the order of the `rocket::ignite()` and `MockRequest::new()` calls.\n\n  * **A route with `format` specified only matches requests with the same\n    format.**\n\n    Previously, a route with a `format` would match requests without a format\n    specified. There is no workaround to this change; simply specify formats\n    when required.\n\n  * **`FormItems` can no longer be constructed directly.**\n\n    Instead of constructing as `FormItems(string)`, construct as\n    `FormItems::from(string)`.\n\n  * **`from_from_string(&str)` in `FromForm` removed in favor of\n    `from_form_items(&mut FormItems)`.**\n\n    Most implementation should be using `FormItems` internally; simply use the\n    passed in `FormItems`. In other cases, the form string can be retrieved via\n    the `inner_str` method of `FormItems`.\n\n  * **`Config::{set, default_for}` are deprecated.**\n\n    Use the `set_{param}` methods instead of `set`, and `new` or `build` in\n    place of `default_for`.\n\n  * **Route paths must be absolute.**\n\n    Prepend a `/` to convert a relative path into an absolute one.\n\n  * **Route paths cannot contain empty segments.**\n\n    Remove any empty segments, including trailing ones, from a route path.\n\n## Bug Fixes\n\nA couple of bugs were fixed in this release:\n\n  * Handlebars partials were not properly registered\n    ([#122](https://github.com/rwf2/Rocket/issues/122)).\n  * `Rocket::custom` did not set the custom configuration as the `active`\n    configuration.\n  * Route path segments containing more than one dynamic parameter were\n    allowed.\n\n## General Improvements\n\nIn addition to new features, Rocket saw the following smaller improvements:\n\n  * Rocket no longer overwrites a catcher's response status.\n  * The `port` `Config` type is now a proper `u16`.\n  * Clippy issues injected by codegen are resolved.\n  * Handlebars was updated to `0.25`.\n  * The `PartialEq` implementation of `Config` doesn't consider the path or\n    secret key.\n  * Hyper dependency updated to `0.10`.\n  * The `Error` type for `JSON as FromData` has been exposed as `SerdeError`.\n  * SVG was added as a known Content-Type.\n  * Serde was updated to `0.9`.\n  * Form parse failure now results in a **422** error code.\n  * Tera has been updated to `0.7`.\n  * `pub(crate)` is used throughout to enforce visibility rules.\n  * Query parameters in routes (`/path?<param>`) are now logged.\n  * Routes with and without query parameters no longer _collide_.\n\n## Infrastructure\n\n  * Testing was parallelized, resulting in 3x faster Travis builds.\n\n# Version 0.1.6 (Jan 26, 2017)\n\n## Infrastructure\n\n  * Hyper version pinned to 0.9.14 due to upstream non-semver breaking change.\n\n# Version 0.1.5 (Jan 14, 2017)\n\n## Core\n\n  * Fixed security checks in `FromSegments` implementation for `PathBuf`.\n\n## Infrastructure\n\n  * `proc_macro` feature removed from examples due to stability.\n\n# Version 0.1.4 (Jan 4, 2017)\n\n## Core\n\n  * Header names are treated as case-preserving.\n\n## Codegen\n\n  * Minimum supported nightly is `2017-01-03`.\n\n# Version 0.1.3 (Dec 31, 2016)\n\n## Core\n\n  * Typo in `Outcome` formatting fixed (Succcess -> Success).\n  * Added `ContentType::CSV`.\n  * Dynamic segments parameters are properly resolved, even when mounted.\n  * Request methods are only overridden via `_method` field on POST.\n  * Form value `String`s are properly decoded.\n\n## Codegen\n\n  * The `_method` field is now properly ignored in `FromForm` derivation.\n  * Unknown Content-Types in `format` no longer result in an error.\n  * Deriving `FromForm` no longer results in a deprecation warning.\n  * Codegen will refuse to build with incompatible rustc, presenting error\n    message and suggestion.\n  * Added `head` as a valid decorator for `HEAD` requests.\n  * Added `route(OPTIONS)` as a valid decorator for `OPTIONS` requests.\n\n## Contrib\n\n  * Templates with the `.tera` extension are properly autoescaped.\n  * Nested template names are properly resolved on Windows.\n  * Template implements `Display`.\n  * Tera dependency updated to version 0.6.\n\n## Docs\n\n  * Todo example requirements clarified in its `README`.\n\n## Testing\n\n  * Tests added for `config`, `optional_result`, `optional_redirect`, and\n    `query_params` examples.\n  * Testing script checks for and disallows tab characters.\n\n## Infrastructure\n\n  * New script (`bump_version.sh`) automates version bumps.\n  * Config script emits error when readlink/readpath support is bad.\n  * Travis badge points to public builds.\n\n# Version 0.1.2 (Dec 24, 2016)\n\n## Codegen\n\n  * Fix `get_raw_segments` index argument in route codegen\n    ([#41](https://github.com/rwf2/Rocket/issues/41)).\n  * Segments params (`<param..>`) respect prefixes.\n\n## Contrib\n\n  * Fix nested template name resolution\n    ([#42](https://github.com/rwf2/Rocket/issues/42)).\n\n## Infrastructure\n\n  * New script (`publish.sh`) automates publishing to crates.io.\n  * New script (`bump_version.sh`) automates version bumps.\n\n# Version 0.1.1 (Dec 23, 2016)\n\n## Core\n\n  * `NamedFile` `Responder` lost its body in the shuffle; it's back!\n\n# Version 0.1.0 (Dec 23, 2016)\n\nThis is the first public release of Rocket!\n\n## Breaking\n\nAll of the mentions to `hyper` types in core Rocket types are no more. Rocket\nnow implements its own `Request` and `Response` types.\n\n  * `ContentType` uses associated constants instead of static methods.\n  * `StatusCode` removed in favor of new `Status` type.\n  * `Response` type alias superseded by `Response` type.\n  * `Responder::respond` no longer takes in hyper type.\n  * `Responder::respond` returns `Response`, takes `self` by move.\n  * `Handler` returns `Outcome` instead of `Response` type alias.\n  * `ErrorHandler` returns `Result`.\n  * All `Hyper*` types were moved to unprefixed versions in `hyper::`.\n  * `MockRequest::dispatch` now returns a `Response` type.\n  * `URIBuf` removed in favor of unified `URI`.\n  * Rocket panics when an illegal, dynamic mount point is used.\n\n## Core\n\n  * Rocket handles `HEAD` requests automatically.\n  * New `Response` and `ResponseBuilder` types.\n  * New `Request`, `Header`, `Status`, and `ContentType` types.\n\n## Testing\n\n  * `MockRequest` allows any type of header.\n  * `MockRequest` allows cookies.\n\n## Codegen\n\n  * Debug output disabled by default.\n  * The `ROCKET_CODEGEN_DEBUG` environment variables enables codegen logging.\n\n# Version 0.0.11 (Dec 11, 2016)\n\n## Streaming Requests\n\nAll incoming request data is now streamed. This resulted in a major change to\nthe Rocket APIs. They are summarized through the following API changes:\n\n  * The `form` route parameter has been removed.\n  * The `data` route parameter has been introduced.\n  * Forms are now handled via the `data` parameter and `Form` type.\n  * Removed the `data` parameter from `Request`.\n  * Added `FromData` conversion trait and default implementation.\n  * `FromData` is used to automatically derive the `data` parameter.\n  * `Responder`s are now final: they cannot forward to other requests.\n  * `Responder`s may only forward to catchers.\n\n## Breaking\n\n  * Request `uri` parameter is private. Use `uri()` method instead.\n  * `form` module moved under `request` module.\n  * `response::data` was renamed to `response::content`.\n  * Introduced `Outcome` with `Success`, `Failure`, and `Forward` variants.\n  * `outcome` module moved to top-level.\n  * `Response` is now a type alias to `Outcome`.\n  * `Empty` `Responder` was removed.\n  * `StatusResponder` removed in favor of `response::status` module.\n\n## Codegen\n\n  * Error handlers can now take 0, 1, or 2 parameters.\n  * `FromForm` derive now works on empty structs.\n  * Lifetimes are now properly stripped in code generation.\n  * Any valid ident is now allowed in single-parameter route parameters.\n\n## Core\n\n  * Route is now cloneable.\n  * `Request` no longer has any lifetime parameters.\n  * `Handler` type now includes a `Data` parameter.\n  * `http` module is public.\n  * `Responder` implemented for `()` type as an empty response.\n  * Add `config::get()` for global config access.\n  * Introduced `testing` module.\n  * `Rocket.toml` allows global configuration via `[global]` table.\n\n## Docs\n\n  * Added a `raw_upload` example.\n  * Added a `pastebin` example.\n  * Documented all public APIs.\n\n## Testing\n\n  * Now building and running tests with `--all-features` flag.\n  * Added appveyor config for Windows CI testing.\n\n# Version 0.0.10 (Oct 03, 2016)\n\n## Breaking\n\n  * Remove `Rocket::new` in favor of `ignite` method.\n  * Remove `Rocket::mount_and_launch` in favor of chaining `mount(..).launch()`.\n  * `mount` and `catch` take `Rocket` type by value.\n  * All types related to HTTP have been moved into `http` module.\n  * `Template::render` in `contrib` now takes context by reference.\n\n## Core\n\n  * Rocket now parses option `Rocket.toml` for configuration, defaulting to sane\n    values.\n  * `ROCKET_ENV` environment variable can be used to specify running environment.\n\n## Docs\n\n  * Document `ContentType`.\n  * Document `Request`.\n  * Add script that builds docs.\n\n## Testing\n\n  * Scripts can now be run from any directory.\n  * Cache Cargo directories in Travis for faster testing.\n  * Check that library version numbers match in testing script.\n\n# Version 0.0.9 (Sep 29, 2016)\n\n## Breaking\n\n  * Rename `response::data_type` to `response::data`.\n\n## Core\n\n  * Rocket interprets `_method` field in forms as the incoming request's method.\n  * Add `Outcome::Bad` to signify responses that failed internally.\n  * Add a `NamedFile` `Responder` type that uses a file's extension for the\n    response's content type.\n  * Add a `Stream` `Responder` for streaming responses.\n\n## Contrib\n\n  * Introduce the `contrib` crate.\n  * Add JSON support via `JSON`, which implements `FromRequest` and `Responder`.\n  * Add templating support via `Template` which implements `Responder`.\n\n## Docs\n\n  * Initial guide-like documentation.\n  * Add documentation, testing, and contributing sections to README.\n\n## Testing\n\n  * Add a significant number of codegen tests.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Rocket\n\n**Please read this document before contributing!**\n\nThank you for contributing! We welcome your contributions in whichever form they\nmay come.\n\nThis document provides guidelines and resources to help you successfully\ncontribute to the project. Rocket is a tool designed to push the envelope of\nusability, security, _and_ performance in web frameworks, and accordingly, our\nquality standards are high. To make the best use of everyone's time and avoid\nwasted efforts, take a moment to understand our expectations and conventions\noutlined here.\n\n## Submitting Pull Requests\n\nBefore creating a new pull request:\n\n  * Read and understand [Code Style Conventions], [Commit Message Guidelines],\n    and [Testing].\n  * If you're resolving an open issue, follow [Resolving an Open Issue].\n  * If you're implementing new functionality, check whether the functionality\n    you're implementing has been proposed before, either as an [issue] or [pull\n    request]. Ensure your PR resolves any previously raised concerns. Then,\n    follow [Implementing an Unproposed Feature].\n  * For everything else, see [Other Common Contributions].\n\nWe aim to keep Rocket's code quality at the highest level. This means that any\ncode you contribute must be:\n\n  * **Commented:** Complex or subtle functionality must be properly commented.\n  * **Documented:** Public items must have doc comments with examples.\n  * **Styled:** Your code must follow the [Code Style Conventions].\n  * **Simple:** Your code should accomplish its task as simply and\n    idiomatically as possible.\n  * **Tested:** You must write (and pass) convincing [tests](#testing) for all\n    new or changed functionality.\n  * **Focused:** Your code should do what it's supposed to and nothing more.\n\n### Resolving an Open Issue\n[Resolving an Open Issue]: #resolving-an-open-issue\n\nIf you spot an open issue that you'd like to resolve:\n\n  1. **First identify if there's a proposed solution to the problem.**\n\n     If there is, proceed to step 2. If there isn't, your first course of\n     action, before writing any code, is to propose a solution. To do so, leave\n     a comment describing your solution in the relevant issue. It's especially\n     useful to see test cases and hypothetical examples. This step is critical:\n     it allows us to identify and resolve concerns with a proposed solution\n     before anyone spends time writing code. It may also allow us to point you\n     in more efficient implementation directions.\n\n  2. **Write a failing test case you expect to pass after resolving the issue.**\n\n     If you can write proper tests cases that fail, do so (see [Testing]). If\n     you cannot, for instance because you're introducing new APIs which can't be\n     used until they exist, write a test case that mocks usage of those APIs. In\n     either case, allow the tests and mock examples to guide your progress.\n\n  3. **Write basic functionality, pass tests, and submit a PR.**\n\n     Think about edge cases to the problem and ensure you have tests for those\n     edge cases. Once your implementation is functionally complete, submit a PR.\n     Don't spend time writing or changing a bunch of documentation just yet.\n\n  4. **Wait for a review, iterate, and polish.**\n\n     If a review doesn't come in a few days, feel free to ping a maintainer.\n     Once someone reviews your PR, integrate their feedback. If the PR solves the\n     issue (which it should because you have passing tests) and fits the project\n     (which it should since you sought feedback _before_ submitting), it will be\n     _conditionally_ approved pending final polish: documentation (rustdocs,\n     guide docs), style improvements, and testing. Your PR will then be merged.\n\n### Implementing an Unproposed Feature\n[Implementing an Unproposed Feature]: #implementing-an-unproposed-feature\n\nFirst and foremost, **please do not submit a PR that implements a new feature\nwithout first proposing a design and seeking feedback.** We take the addition of\nnew features _very_ seriously because they directly impact usability.\n\nTo propose a new feature, create a [new feature request issue] and follow the\ntemplate. Note that certain classes of features require particularly compelling\njustification to be taken into consideration. These include features that:\n\n  * Can be implemented outside of Rocket.\n  * Introduce new dependencies, especially heavier ones.\n  * Only exist to add support for an external crate.\n  * Are too specific to one use-case.\n  * Are overtly complex _and_ have \"simple\" workarounds.\n  * Only partially solve a bigger deficiency.\n\nOnce your feature request is accepted, follow [Resolving an Open Issue].\n\n[new feature request issue]: https://github.com/rwf2/Rocket/issues/new?assignees=&labels=request&projects=&template=feature-request.yml\n\n### Other Common Contributions\n[Other Common Contributions]: #other-common-contributions\n\n  * **Doc fixes, typos, wording improvements.**\n\n    We encourage any of these! Just a submit a PR with your changes. Please\n    preserve the surrounding markdown formatting as much as possible. This\n    typically means keeping lines under 80 characters, keeping table delimiters\n    aligned, and preserving indentation accordingly.\n\n    The guide's source files are at [docs/guide]. Note the following special\n    syntax available in guide markdown:\n\n    - **Cross-linking** pages is accomplished via relative links. Outside\n      of the index, this is: `../{page}#anchor`. For instance, to link to\n      **Quickstart > Running Examples**, use `../quickstart#running-examples`.\n    - **Aliases** are shorthand URLs that start with `@` (e.g, `@api`). They are\n      used throughout the guide to simplify creating versioned URLs. They are\n      replaced at build time with the appropriate versioned instance.\n\n  * **New examples or changes to existing ones.**\n\n    Please follow the [Implementing an Unproposed Feature] process.\n\n  * **Formatting or other purely cosmetic changes.**\n\n    We generally do not accept purely cosmetic changes to the codebase such as\n    style or formatting changes. All PRs must add something substantial to\n    Rocket's functionality, coherence, testing, performance, usability, bug\n    fixes, security, documentation, or overall maintainability.\n\n  * **Advertisements of any nature.**\n\n    We do not accept any contributions that resemble advertisements or\n    promotional content. If you are interested in supporting Rocket, we\n    encourage you to [sponsor the project].\n\n## Testing\n[Testing]: #testing\n\nAll testing happens through [test.sh]. Before submitting a PR, run the script\nand fix any issues. The default mode (passing no arguments or `--default`) will\nusually suffice, but you may also wish to execute additional tests. In\nparticular:\n\n  * If you make changes to `contrib`: `test.sh --contrib`\n  * If you make user-facing API changes or update deps: `test.sh --examples`\n  * If you add or modify feature flags: `test.sh --core`\n  * If you modify codegen: see [UI Tests].\n\nRun `test.sh --help` to get an overview of how to execute the script:\n\n```sh\nUSAGE:\n  ./scripts/test.sh [+<TOOLCHAIN>] [--help|-h] [--<TEST>]\n\nOPTIONS:\n  +<TOOLCHAIN>   Forwarded to Cargo to select toolchain.\n  --help, -h     Print this help message and exit.\n  --<TEST>       Run the specified test suite.\n                 (Run without --<TEST> to run default tests.)\n\nAVAILABLE <TEST> OPTIONS:\n  default\n  all\n  core\n  contrib\n  examples\n  benchmarks\n  testbench\n  ui\n\nEXAMPLES:\n  ./scripts/test.sh                     # Run default tests on current toolchain.\n  ./scripts/test.sh +stable --all       # Run all tests on stable toolchain.\n  ./scripts/test.sh --ui                # Run UI tests on current toolchain.\n```\n\n### Writing Tests\n\nRocket is tested in a variety of ways. This includes via Rust's regular testing\nfacilities such as doctests, unit tests, and integration tests, as well Rocket's\nexamples, testbench, and [UI Tests]:\n\n  - **Examples**: The [`examples`](examples/) directory contains applications\n    that make use of many of Rocket's features. Each example is integration\n    tested using Rocket's built-in [local testing]. This both ensures that\n    typical Rocket code continues to work as expected and serves as a way to\n    detect and resolve user-facing breaking changes.\n\n  - **Testbench**: Rocket's [testbench](testbench/) tests end-to-end server or\n    protocol properties by starting up full Rocket servers to which it\n    dispatches real HTTP requests. Each server is independently written in\n    [testbench/src/servers/](testbench/src/servers/). You're unlikely to need to\n    write a testbench test unless you're modifying low-level details.\n\n  - **UI Tests**: UI tests ensure Rocket's codegen produces meaningful compiler\n    diagnostics. They compile Rocket applications and compare the compiler's\n    output to expected results. If you're changing codegen, you'll need to\n    update or create UI tests. See [UI Tests] for details.\n\nFor any change that affects functionality, we ask that you write a test that\nverifies that functionality. Minimally, this means a unit test, doctest,\nintegration test, or some combination of these. For small changes, unit tests\nwill likely suffice. If the change affects the user in any way, then doctests\nshould be added or modified. And if the change requires using unrelated APIs to\ntest, then an integration test should be added.\n\nAdditionally, the following scenarios require special attention:\n\n  - **Improved Features**\n\n    Modifying an existing example is a great place to write tests for improved\n    features. If you do modify an example, make sure you modify the README in\n    the example directory, too.\n\n  - **New Features**\n\n    For major features, introducing a new example that showcases idiomatic use\n    of the feature can be useful. Make sure you modify the README in the\n    `examples` directory if you do. In addition, all newly introduced public\n    APIs should be fully documented and include doctests as well as unit and\n    integration tests.\n\n  - **Fixing a Bug**\n\n    To avoid regressions, _always_ introduce or modify an integration or\n    testbench test for a bugfix. Integration tests should live in the usual\n    `tests/` directory and be named `short-issue-description-NNNN.rs`, where\n    `NNNN` is the GitHub issue number for the bug. For example,\n    `forward-includes-status-1560.rs`.\n\n[local testing]: https://api.rocket.rs/master/rocket/local/\n\n### UI Tests\n[UI Tests]: #ui-tests\n\nChanges to codegen (i.e, `rocket_codegen` and other `_codegen` crates)\nnecessitate adding and running UI tests, which capture compiler output and\ncompare it against some expected output. UI tests use [`trybuild`].\n\nTests can be found in the `codegen/tests/ui-fail` directories of respective\n`codegen` crates. Each test is symlinked into sibling `ui-fail-stable` and\n`ui-fail-nightly` directories, which also contain the expected error output for\nstable and nightly compilers, respectively. For example:\n\n```\n./core/codegen/tests\n├── ui-fail\n│   ├── async-entry.rs\n│   ├── ...\n│   └── uri_display_type_errors.rs\n├── ui-fail-nightly\n│   ├── async-entry.rs -> ../ui-fail/async-entry.rs\n│   ├── async-entry.stderr\n│   ├── ...\n│   ├── uri_display_type_errors.rs -> ../ui-fail/uri_display_type_errors.rs\n│   └── uri_display_type_errors.stderr\n└── ui-fail-stable\n    ├── async-entry.rs -> ../ui-fail/async-entry.rs\n    ├── async-entry.stderr\n    ├── ...\n    ├── uri_display_type_errors.rs -> ../ui-fail/uri_display_type_errors.rs\n    └── uri_display_type_errors.stderr\n```\n\nIf you make changes to codegen, run the UI tests for stable and nightly with\n`test.sh +stable --ui` and `test.sh +nightly --ui`. If there are failures,\nupdate the outputs with `TRYBUILD=overwrite test.sh +nightly --ui` and\n`TRYBUILD=overwrite test.sh +stable --ui`. Look at the diff to see what's\nchanged. Ensure that error messages properly attribute (i.e., visually underline\nor point to) the source of the error. For example, if a type need to implement a\ntrait, then that type should be underlined. We strive to emit the most helpful\nand descriptive error messages possible.\n\n### API Docs\n\nIf you make changes to documentation, you should build the API docs and verify\nthat your changes look as you expect. API documentation is built with\n[mk-docs.sh] and output to the usual `target/docs` directory. By default, the\nscript will `clean` any existing docs to avoid potential caching issues. To\noverride this behavior, use `mk-docs.sh -d`.\n\n## Code Style Conventions\n[Code Style Conventions]: #code-style-conventions\n\nWe _do not_ use `rustfmt` or `cargo fmt` due to bugs and missing functionality.\nInstead, we ask that you follow the [Rust Style Guide] with the following\nchanges:\n\n**Always separate items with one blank line.**\n\n<table>\n<thead>\n <tr>\n  <th width=\"350px\"><b>✅ Yes</b></th>\n  <th width=\"350px\"><b>No 🚫</b></th>\n </tr>\n</thead>\n<tbody>\n <tr>\n    <td>\n\n```rust\nfn foo() {\n    // ..\n}\n\nfn bar() {\n    // ..\n}\n```\n\n</td>\n<td>\n\n```rust\nfn foo() {\n    // ..\n}\nfn bar() {\n    // ..\n}\n```\n\n</td>\n</tr>\n</tbody>\n</table>\n\n**Prefer a where-clause over block-indented generics.**\n\n<table>\n<thead>\n <tr>\n  <th width=\"350px\"><b>✅ Yes</b></th>\n  <th width=\"350px\"><b>No 🚫</b></th>\n </tr>\n</thead>\n<tbody>\n <tr>\n    <td>\n\n```rust\nfn foo<T, U>(x: Vec<T>, y: Vec<U>)\n    where T: Display, U: Debug\n{\n    // ..\n}\n```\n\n</td>\n<td>\n\n```rust\nfn foo<\n    T: Display,\n    U: Debug,\n>(x: Vec<T>, y: Vec<U>) {\n    // ..\n}\n```\n\n</td>\n</tr>\n</tbody>\n</table>\n\n**For \"short\" where-clauses, follow Rust guidelines. For \"long\" where-clauses,\nblock-indent `where`, place the first bound on the same line as `where`, and\nblock-align the remaining bounds.**\n\n<table>\n<thead>\n <tr>\n  <th width=\"350px\"><b>✅ Yes</b></th>\n  <th width=\"350px\"><b>No 🚫</b></th>\n </tr>\n</thead>\n<tbody>\n <tr>\n    <td>\n\n```rust\nfn foo<T, F, Item, G>(v: Foo<T, F, Item>) -> G\n    where T: for<'x> SomeTrait<'x>\n          F: Fn(Item) -> G,\n          Item: Display + Debug,\n          G: Error,\n{\n    // ..\n}\n```\n\n</td>\n<td>\n\n```rust\nfn foo<T, F, Item, G>(v: Foo<T, F, Item>) -> G\n    where\n        T: for<'x> SomeTrait<'x>\n        F: Fn(Item) -> G,\n        Item: Display + Debug,\n        G: Error,\n{\n    // ..\n}\n```\n\n</td>\n</tr>\n</tbody>\n</table>\n\n**Do not use multi-line imports. Use multiple lines grouped by import kind if\npossible.**\n\n<table>\n<thead>\n <tr>\n  <th width=\"350px\"><b>✅ Yes</b></th>\n  <th width=\"350px\"><b>No 🚫</b></th>\n </tr>\n</thead>\n<tbody>\n <tr>\n    <td>\n\n```rust\nuse foo::{Long, List, Of, Type, Imports};\nuse foo::{some_macro, imports};\n```\n\n</td>\n<td>\n\n```rust\nuse foo::{\n    Long, List, Of, Type, Imports,\n    some_macro, imports,\n};\n```\n\n</td>\n</tr>\n</tbody>\n</table>\n\n**Order imports in order of decreasing \"distance\" to the current module: `std`,\n`core`, and `alloc`, external crates, then current crate. Prefer using `crate`\nrelative imports to `super`. Separate each category with one blank line.**\n\n<table>\n<thead>\n <tr>\n  <th width=\"350px\"><b>✅ Yes</b></th>\n  <th width=\"350px\"><b>No 🚫</b></th>\n </tr>\n</thead>\n<tbody>\n <tr>\n    <td>\n\n```rust\nuse std::{foo, bar};\nuse alloc::{bar, baz};\n\nuse either::Either;\nuse futures::{SomeItem, OtherItem};\n\nuse crate::{item1, item2};\nuse crate::module::item3;\nuse crate::module2::item4;\n```\n\n</td>\n<td>\n\n```rust\nuse crate::{item1, item2};\nuse std::{foo, bar};\nuse either::Either;\nuse alloc::{bar, baz};\nuse futures::{SomeItem, OtherItem};\n\nuse super::{item3, item4};\nuse super::item4;\n```\n\n</td>\n</tr>\n</tbody>\n</table>\n\n## Commit Message Guidelines\n[Commit Message Guidelines]: #commit-message-guidelines\n\nGit commit messages should start with a single-line _header_ of at most 50\ncharacters followed by a body with any number of descriptive paragraphs, with\nlines not to exceed 72 characters, and a footer.\n\nThe **header** must be an imperative statement that precisely describes the\nprimary change made by the commit. The goal is to give the reader a good\nunderstanding of what the commit does via only the header. It should not require\ncontext to understand. It should not include references to git commits or\nissues. Avoid using Markdown in the header if possible.\n\nTypically, the first word in the header will be one of the following:\n\n  * **Fix** - to fix a functional or doc bug\n    - Example: `Fix 'TcpListener': allow 'udp://' prefix.`\n  * **Improve** - for minor feature or doc improvements\n    - Example: `Improve 'FromParam' derive error messages.`\n  * **Introduce** - for major feature introductions\n    - Example: `Introduce WebSocket support.`\n  * **Add**, **Remove** - for changes\n    - Example: `Add 'Foo::new()' constructor.`\n    - Example: `Remove 'Foo::new()'; add 'Foo::build()'.`\n  * **Update** - for crate updates\n    - Example: `Update 'base64' to 0.12.`\n  * **Impl** or **Implement** - for trait implementations\n    - Example: `Implement 'FromForm' for 'ThisNewType'.`\n\nNote how generic words like \"change\" are avoided, and how the headers are\nspecific about the changes they made. You need not limit yourself to this\nvocabulary. When in doubt, consult the `git log` for examples.\n\n| **✅ Yes**                                       | **No 🚫**                                  |\n|--------------------------------------------------|--------------------------------------------|\n| Fix 'FromForm' derive docs typo: 'yis' -> 'yes'. | ~~Change word in docs~~                    |\n| Default 'MsgPack<T>' to named variant.           | ~~Change default to more likely variant.~~ |\n| Fix 'Compact' advice in 'MsgPack' docs.          | ~~Update docs to make sense~~              |\n| Improve 'Sentinel' docs: explain 'Sentry'.       | ~~Add missing doc details.~~               |\n| Fix CI: pin macOS CI 'mysql-client' to '8.4'.    | ~~Fix CI~~                                 |\n| Fix link to 'rocket::build()' in config guide.   | ~~Fix wrong URL in guide (configuration~~) |\n\nThe **body** should describe what the commit does. For example, if the commit\nintroduces a new feature it should describe what the feature enables and how it\nenables it. A body may be unnecessary if the header sufficiently describes the\ncommit. Avoid referencing issues in the body as well: we'll do that in the\nfooter. If you reference a commit, reference it by shorthash only. Feel free to\nuse markdown including lists and code.\n\nFinally, the **footer** is where references to issues should be made. See the\nGitHub's [linked issues] documentation.\n\n[linked issues]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue\n[Rust Style Guide]: https://doc.rust-lang.org/nightly/style-guide/\n[issue]: https://github.com/rwf2/Rocket/issues\n[pull request]: https://github.com/rwf2/Rocket/pulls\n[test.sh]: scripts/test.sh\n[mk-docs.sh]: scripts/mk-docs.sh\n[`trybuild`]: https://docs.rs/trybuild\n[sponsor the project]: https://github.com/sponsors/rwf2\n[docs/guide]: docs/guide\n\n## Licensing\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in Rocket by you shall be dual licensed under the MIT License and\nApache License, Version 2.0, without any additional terms or conditions.\n\nThe Rocket website docs are licensed under [separate terms](docs/LICENSE). Any\ncontribution intentionally submitted for inclusion in the Rocket website docs by\nyou shall be licensed under those terms.\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"core/lib/\",\n  \"core/codegen/\",\n  \"core/http/\",\n  \"contrib/db_pools/codegen/\",\n  \"contrib/db_pools/lib/\",\n  \"contrib/sync_db_pools/codegen/\",\n  \"contrib/sync_db_pools/lib/\",\n  \"contrib/dyn_templates/\",\n  \"contrib/ws/\",\n  \"docs/tests\",\n]\n\n[workspace.lints.rust]\nunexpected_cfgs = { level = \"warn\", check-cfg = ['cfg(nightly)'] }\nrust_2018_idioms = \"warn\"\nasync_fn_in_trait = \"allow\"\nrefining_impl_trait = \"allow\"\n# unreachable_pub = \"warn\"\n# single_use_lifetimes = \"warn\"\n# missing_docs = \"warn\"\n\n[workspace.lints.clippy]\ntype_complexity = \"allow\"\nmodule_inception = \"allow\"\nmultiple_bound_locations = \"allow\"\nmanual_range_contains = \"allow\"\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. 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\n2. 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\n3. 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\n4. 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\n5. 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\n6. 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\n7. 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\n8. 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\n9. 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\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: 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\nCopyright 2016 Sergio Benitez\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "The MIT License (MIT)\nCopyright (c) 2016 Sergio Benitez\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Rocket\n\n[![Build Status](https://github.com/rwf2/Rocket/workflows/CI/badge.svg)](https://github.com/rwf2/Rocket/actions)\n[![Rocket Homepage](https://img.shields.io/badge/web-rocket.rs-red.svg?style=flat&label=https&colorB=d33847)](https://rocket.rs)\n[![Current Crates.io Version](https://img.shields.io/crates/v/rocket.svg)](https://crates.io/crates/rocket)\n[![Matrix: #rocket:mozilla.org](https://img.shields.io/badge/style-%23rocket:mozilla.org-blue.svg?style=flat&label=[m])](https://chat.mozilla.org/#/room/#rocket:mozilla.org)\n\nRocket is an async web framework for Rust with a focus on usability, security,\nextensibility, and speed.\n\n```rust\n#[macro_use] extern crate rocket;\n\n#[get(\"/<name>/<age>\")]\nfn hello(name: &str, age: u8) -> String {\n    format!(\"Hello, {} year old named {}!\", age, name)\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/hello\", routes![hello])\n}\n```\n\nVisiting `localhost:8000/hello/John/58`, for example, will trigger the `hello`\nroute resulting in the string `Hello, 58 year old named John!` being sent to the\nbrowser. If an `<age>` string was passed in that can't be parsed as a `u8`, the\nroute won't get called, resulting in a 404 error.\n\n## Documentation\n\nRocket is extensively documented:\n\n  * [Overview]: A brief look at what makes Rocket special.\n  * [Quickstart]: How to get started as quickly as possible.\n  * [Getting Started]: How to start your first Rocket project.\n  * [Guide]: A detailed guide and reference to Rocket.\n  * [API Documentation]: The \"rustdocs\".\n\n[Quickstart]: https://rocket.rs/guide/quickstart\n[Getting Started]: https://rocket.rs/guide/getting-started\n[Overview]: https://rocket.rs/overview/\n[Guide]: https://rocket.rs/guide/\n[API Documentation]: https://api.rocket.rs\n\nDocumentation for the `master` branch is available at https://rocket.rs/master\nand https://api.rocket.rs/master.\n\nDocumentation for major release version `${x}` is available at\n`https://[api.]rocket.rs/v${x}`. For example, the v0.4 docs are available at\nhttps://rocket.rs/v0.4 and https://api.rocket.rs/v0.4.\n\nFinally, API docs for active git branches are available at\n`https://api.rocket.rs/${branch}`. For example, API docs for the `master` branch\nare available at https://api.rocket.rs/master. Branch rustdocs are built and\ndeployed on every commit.\n\n## Examples\n\nThe [examples](examples#readme) directory contains complete crates that showcase\nRocket's features and usage. Each example can be compiled and run with Cargo.\nFor instance, the following sequence of commands builds and runs the `hello`\nexample:\n\n```sh\ncd examples/hello\ncargo run\n```\n\n## Getting Help\n\nIf you find yourself needing help outside of the documentation, you may:\n\n  * Ask questions via [GitHub discussions questions].\n  * Chat with us at [`#rocket:mozilla.org`] on Matrix (join [via Element]).\n\n[`#rocket:mozilla.org`]: https://chat.mozilla.org/#/room/#rocket:mozilla.org\n[via Element]: https://chat.mozilla.org/#/room/#rocket:mozilla.org\n[GitHub discussions questions]: https://github.com/rwf2/Rocket/discussions/categories/questions\n\n## Contributing\n\nContributions are absolutely, positively welcomed and encouraged! If you're\ninterested in contributing code, please first read [CONTRIBUTING] for complete\nguidelines. Additionally, you could:\n\n  1. Submit a feature request or bug report as an [issue].\n  2. Ask for improved documentation as an [issue].\n  3. Comment on [issues that require feedback].\n  4. Answers questions in [GitHub discussions questions].\n  5. Share a project in [GitHub discussions show & tell].\n\n[issue]: https://github.com/rwf2/Rocket/issues\n[issues that require feedback]: https://github.com/rwf2/Rocket/issues?q=is%3Aissue+is%3Aopen+label%3A%22feedback+wanted%22\n[pull requests]: https://github.com/rwf2/Rocket/pulls\n[CONTRIBUTING]: CONTRIBUTING.md\n[GitHub discussions show & tell]: https://github.com/rwf2/Rocket/discussions/categories/show-tell\n\n## License\n\nRocket is licensed under either of the following, at your option:\n\n * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)\n * MIT License ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in Rocket by you shall be dual licensed under the MIT License and\nApache License, Version 2.0, without any additional terms or conditions.\n\nThe Rocket website docs are licensed under [separate terms](docs/LICENSE). Any\ncontribution intentionally submitted for inclusion in the Rocket website docs by\nyou shall be licensed under those terms.\n"
  },
  {
    "path": "benchmarks/Cargo.toml",
    "content": "[package]\nname = \"rocket-benchmarks\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n[workspace]\n\n[[bench]]\nname = \"main\"\npath = \"src/bench.rs\"\nharness = false\n\n[dev-dependencies]\nrocket = { path = \"../core/lib/\" }\ncriterion = \"0.5.1\"\n"
  },
  {
    "path": "benchmarks/src/bench.rs",
    "content": "mod routing;\n\ncriterion::criterion_main!(routing::routing);\n"
  },
  {
    "path": "benchmarks/src/routing.rs",
    "content": "use criterion::{criterion_group, Criterion};\n\nuse rocket::{route, config, Request, Data, Route, Config};\nuse rocket::http::{Method, RawStr, ContentType, Accept, Status};\nuse rocket::local::blocking::{Client, LocalRequest};\n\nfn dummy_handler<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {\n    route::Outcome::from(req, ()).pin()\n}\n\nfn parse_routes_table(table: &str) -> Vec<Route> {\n    let mut routes = vec![];\n    for line in table.split(\"\\n\").filter(|s| !s.is_empty()) {\n        let mut components = line.split(\" \");\n        let method: Method = components.next().expect(\"c\").parse().expect(\"method\");\n        let uri: &str = components.next().unwrap();\n\n        let (mut rank, mut name, mut format) = (None, None, None);\n        for component in components {\n            match component {\n                c if c.starts_with('[') => rank = c.trim_matches(&['[', ']'][..]).parse().ok(),\n                c if c.starts_with('(') => name = Some(c.trim_matches(&['(', ')'][..])),\n                c => format = c.parse().ok(),\n            }\n        }\n\n        let mut route = Route::new(method, uri, dummy_handler);\n        if let Some(rank) = rank {\n            route.rank = rank;\n        }\n\n        route.format = format;\n        route.name = name.map(|s| s.to_string().into());\n        routes.push(route);\n    }\n\n    routes\n}\n\nfn generate_matching_requests<'c>(client: &'c Client, routes: &[Route]) -> Vec<LocalRequest<'c>> {\n    fn staticify_segment(segment: &RawStr) -> &str {\n        segment.as_str().trim_matches(&['<', '>', '.', '_'][..])\n    }\n\n    fn request_for_route<'c>(client: &'c Client, route: &Route) -> LocalRequest<'c> {\n        let path = route.uri.path()\n            .raw_segments()\n            .map(staticify_segment)\n            .collect::<Vec<_>>()\n            .join(\"/\");\n\n        let query = route.uri.query()\n            .map(|q| q.raw_segments())\n            .into_iter()\n            .flatten()\n            .map(staticify_segment)\n            .collect::<Vec<_>>()\n            .join(\"&\");\n\n        let uri = format!(\"/{}?{}\", path, query);\n        let mut req = client.req(route.method.unwrap(), uri);\n        if let Some(ref format) = route.format {\n            if let Some(true) = route.method.and_then(|m| m.allows_request_body()) {\n                req.add_header(ContentType::from(format.clone()));\n            } else {\n                req.add_header(Accept::from(format.clone()));\n            }\n        }\n\n        req\n    }\n\n    routes.iter()\n        .map(|route| request_for_route(client, route))\n        .collect()\n}\n\nfn client(routes: Vec<Route>) -> Client {\n    let config = Config {\n        profile: Config::RELEASE_PROFILE,\n        log_level: None,\n        cli_colors: config::CliColors::Never,\n        shutdown: config::ShutdownConfig {\n            ctrlc: false,\n            #[cfg(unix)]\n            signals: std::collections::hash_set::HashSet::new(),\n            ..Default::default()\n        },\n        ..Default::default()\n    };\n\n    match Client::untracked(rocket::custom(config).mount(\"/\", routes)) {\n        Ok(client) => client,\n        Err(e) => {\n            drop(e);\n            panic!(\"bad launch\")\n        }\n    }\n}\n\npub fn bench_rust_lang_routes(c: &mut Criterion) {\n    let table = include_str!(\"../static/rust-lang.routes\");\n    let routes = parse_routes_table(table);\n    let client = client(routes.clone());\n    let requests = generate_matching_requests(&client, &routes);\n    c.bench_function(\"rust-lang.routes\", |b| b.iter(|| {\n        for request in requests.clone() {\n            let response = request.dispatch();\n            assert_eq!(response.status(), Status::Ok);\n        }\n    }));\n}\n\npub fn bench_bitwarden_routes(c: &mut Criterion) {\n    let table = include_str!(\"../static/bitwarden_rs.routes\");\n    let routes = parse_routes_table(table);\n    let client = client(routes.clone());\n    let requests = generate_matching_requests(&client, &routes);\n    c.bench_function(\"bitwarden_rs.routes\", |b| b.iter(|| {\n        for request in requests.clone() {\n            let response = request.dispatch();\n            assert_eq!(response.status(), Status::Ok);\n        }\n    }));\n}\n\ncriterion_group!(routing, bench_rust_lang_routes, bench_bitwarden_routes);\n"
  },
  {
    "path": "benchmarks/static/bitwarden_rs.routes",
    "content": "GET /attachments/<uuid>/<file..> (attachments)\nGET /alive (alive)\nGET /bwrs_static/<filename> (static_files)\nPOST /api/accounts/register (register)\nGET /api/accounts/profile (profile)\nPUT /api/accounts/profile (put_profile)\nPOST /api/accounts/profile (post_profile)\nGET /api/users/<uuid>/public-key (get_public_keys)\nPOST /api/accounts/keys (post_keys)\nPOST /api/accounts/password (post_password)\nPOST /api/accounts/kdf (post_kdf)\nPOST /api/accounts/key (post_rotatekey)\nPOST /api/accounts/security-stamp (post_sstamp)\nPOST /api/accounts/email-token (post_email_token)\nPOST /api/accounts/email (post_email)\nPOST /api/accounts/verify-email (post_verify_email)\nPOST /api/accounts/verify-email-token (post_verify_email_token)\nPOST /api/accounts/delete-recover (post_delete_recover)\nPOST /api/accounts/delete-recover-token (post_delete_recover_token)\nDELETE /api/accounts (delete_account)\nPOST /api/accounts/delete (post_delete_account)\nGET /api/accounts/revision-date (revision_date)\nPOST /api/accounts/password-hint (password_hint)\nPOST /api/accounts/prelogin (prelogin)\nPOST /api/accounts/verify-password (verify_password)\nGET /api/sync?<data..> (sync)\nGET /api/ciphers (get_ciphers)\nGET /api/ciphers/<uuid> (get_cipher)\nGET /api/ciphers/<uuid>/admin (get_cipher_admin)\nGET /api/ciphers/<uuid>/details (get_cipher_details)\nPOST /api/ciphers (post_ciphers)\nPUT /api/ciphers/<uuid>/admin (put_cipher_admin)\nPOST /api/ciphers/admin (post_ciphers_admin)\nPOST /api/ciphers/create (post_ciphers_create)\nPOST /api/ciphers/import (post_ciphers_import)\nPOST /api/ciphers/<uuid>/attachment multipart/form-data (post_attachment)\nPOST /api/ciphers/<uuid>/attachment-admin multipart/form-data (post_attachment_admin)\nPOST /api/ciphers/<uuid>/attachment/<attachment_id>/share multipart/form-data (post_attachment_share)\nPOST /api/ciphers/<uuid>/attachment/<attachment_id>/delete (delete_attachment_post)\nPOST /api/ciphers/<uuid>/attachment/<attachment_id>/delete-admin (delete_attachment_post_admin)\nDELETE /api/ciphers/<uuid>/attachment/<attachment_id> (delete_attachment)\nDELETE /api/ciphers/<uuid>/attachment/<attachment_id>/admin (delete_attachment_admin)\nPOST /api/ciphers/<uuid>/admin (post_cipher_admin)\nPOST /api/ciphers/<uuid>/share (post_cipher_share)\nPUT /api/ciphers/<uuid>/share (put_cipher_share)\nPUT /api/ciphers/share (put_cipher_share_selected)\nPOST /api/ciphers/<uuid> (post_cipher)\nPUT /api/ciphers/<uuid> (put_cipher)\nPOST /api/ciphers/<uuid>/delete (delete_cipher_post)\nPOST /api/ciphers/<uuid>/delete-admin (delete_cipher_post_admin)\nPUT /api/ciphers/<uuid>/delete (delete_cipher_put)\nPUT /api/ciphers/<uuid>/delete-admin (delete_cipher_put_admin)\nDELETE /api/ciphers/<uuid> (delete_cipher)\nDELETE /api/ciphers/<uuid>/admin (delete_cipher_admin)\nDELETE /api/ciphers (delete_cipher_selected)\nPOST /api/ciphers/delete (delete_cipher_selected_post)\nPUT /api/ciphers/delete (delete_cipher_selected_put)\nDELETE /api/ciphers/admin (delete_cipher_selected_admin)\nPOST /api/ciphers/delete-admin (delete_cipher_selected_post_admin)\nPUT /api/ciphers/delete-admin (delete_cipher_selected_put_admin)\nPUT /api/ciphers/<uuid>/restore (restore_cipher_put)\nPUT /api/ciphers/<uuid>/restore-admin (restore_cipher_put_admin)\nPUT /api/ciphers/restore (restore_cipher_selected)\nPOST /api/ciphers/purge?<organization..> (delete_all)\nPOST /api/ciphers/move (move_cipher_selected)\nPUT /api/ciphers/move (move_cipher_selected_put)\nPUT /api/ciphers/<uuid>/collections (put_collections_update)\nPOST /api/ciphers/<uuid>/collections (post_collections_update)\nPOST /api/ciphers/<uuid>/collections-admin (post_collections_admin)\nPUT /api/ciphers/<uuid>/collections-admin (put_collections_admin)\nGET /api/folders (get_folders)\nGET /api/folders/<uuid> (get_folder)\nPOST /api/folders (post_folders)\nPOST /api/folders/<uuid> (post_folder)\nPUT /api/folders/<uuid> (put_folder)\nPOST /api/folders/<uuid>/delete (delete_folder_post)\nDELETE /api/folders/<uuid> (delete_folder)\nGET /api/organizations/<org_id> (get_organization)\nPOST /api/organizations (create_organization)\nDELETE /api/organizations/<org_id> (delete_organization)\nPOST /api/organizations/<org_id>/delete (post_delete_organization)\nPOST /api/organizations/<org_id>/leave (leave_organization)\nGET /api/collections (get_user_collections)\nGET /api/organizations/<org_id>/collections (get_org_collections)\nGET /api/organizations/<org_id>/collections/<coll_id>/details (get_org_collection_detail)\nGET /api/organizations/<org_id>/collections/<coll_id>/users (get_collection_users)\nPUT /api/organizations/<org_id>/collections/<coll_id>/users (put_collection_users)\nPUT /api/organizations/<org_id> (put_organization)\nPOST /api/organizations/<org_id> (post_organization)\nPOST /api/organizations/<org_id>/collections (post_organization_collections)\nDELETE /api/organizations/<org_id>/collections/<col_id>/user/<org_user_id> (delete_organization_collection_user)\nPOST /api/organizations/<org_id>/collections/<col_id>/delete-user/<org_user_id> (post_organization_collection_delete_user)\nPOST /api/organizations/<org_id>/collections/<col_id> (post_organization_collection_update)\nPUT /api/organizations/<org_id>/collections/<col_id> (put_organization_collection_update)\nDELETE /api/organizations/<org_id>/collections/<col_id> (delete_organization_collection)\nPOST /api/organizations/<org_id>/collections/<col_id>/delete (post_organization_collection_delete)\nGET /api/ciphers/organization-details?<data..> (get_org_details)\nGET /api/organizations/<org_id>/users (get_org_users)\nPOST /api/organizations/<org_id>/users/invite (send_invite)\nPOST /api/organizations/<org_id>/users/<user_org>/reinvite (reinvite_user)\nPOST /api/organizations/<org_id>/users/<org_user_id>/confirm (confirm_invite)\nPOST /api/organizations/<_org_id>/users/<_org_user_id>/accept (accept_invite)\nGET /api/organizations/<org_id>/users/<org_user_id> (get_user)\nPOST /api/organizations/<org_id>/users/<org_user_id> [1] (edit_user)\nPUT /api/organizations/<org_id>/users/<org_user_id> (put_organization_user)\nDELETE /api/organizations/<org_id>/users/<org_user_id> (delete_user)\nPOST /api/organizations/<org_id>/users/<org_user_id>/delete (post_delete_user)\nPOST /api/ciphers/import-organization?<query..> (post_org_import)\nGET /api/organizations/<org_id>/policies (list_policies)\nGET /api/organizations/<org_id>/policies/token?<token> (list_policies_token)\nGET /api/organizations/<org_id>/policies/<pol_type> (get_policy)\nPUT /api/organizations/<org_id>/policies/<pol_type> (put_policy)\nGET /api/organizations/<org_id>/tax (get_organization_tax)\nGET /api/plans (get_plans)\nGET /api/plans/sales-tax-rates (get_plans_tax_rates)\nPOST /api/organizations/<org_id>/import (import)\nGET /api/two-factor (get_twofactor)\nPOST /api/two-factor/get-recover (get_recover)\nPOST /api/two-factor/recover (recover)\nPOST /api/two-factor/disable (disable_twofactor)\nPUT /api/two-factor/disable (disable_twofactor_put)\nPOST /api/two-factor/get-authenticator (generate_authenticator)\nPOST /api/two-factor/authenticator (activate_authenticator)\nPUT /api/two-factor/authenticator (activate_authenticator_put)\nPOST /api/two-factor/get-duo (get_duo)\nPOST /api/two-factor/duo (activate_duo)\nPUT /api/two-factor/duo (activate_duo_put)\nPOST /api/two-factor/get-email (get_email)\nPOST /api/two-factor/send-email-login (send_email_login)\nPOST /api/two-factor/send-email (send_email)\nPUT /api/two-factor/email (email)\nPOST /api/two-factor/get-u2f (generate_u2f)\nPOST /api/two-factor/get-u2f-challenge (generate_u2f_challenge)\nPOST /api/two-factor/u2f (activate_u2f)\nPUT /api/two-factor/u2f (activate_u2f_put)\nDELETE /api/two-factor/u2f (delete_u2f)\nPOST /api/two-factor/get-yubikey (generate_yubikey)\nPOST /api/two-factor/yubikey (activate_yubikey)\nPUT /api/two-factor/yubikey (activate_yubikey_put)\nPOST /api/sends (post_send)\nPOST /api/sends/file multipart/form-data (post_send_file)\nPOST /api/sends/access/<access_id> (post_access)\nPOST /api/sends/<send_id>/access/file/<file_id> (post_access_file)\nPUT /api/sends/<id> (put_send)\nDELETE /api/sends/<id> (delete_send)\nPUT /api/sends/<id>/remove-password (put_remove_password)\nPUT /api/devices/identifier/<uuid>/clear-token (clear_device_token)\nPUT /api/devices/identifier/<uuid>/token (put_device_token)\nGET /api/settings/domains (get_eq_domains)\nPOST /api/settings/domains (post_eq_domains)\nPUT /api/settings/domains (put_eq_domains)\nGET /api/hibp/breach?<username> (hibp_breach)\nGET /admin (admin_disabled)\nPOST /identity/connect/token (login)\nGET /icons/<domain>/icon.png (icon)\nPOST /notifications/hub/negotiate (negotiate)\nGET /notifications/hub (websockets_err)\n"
  },
  {
    "path": "benchmarks/static/rust-lang.routes",
    "content": "GET / (index)\nGET /<category> (category)\nGET /governance (governance)\nGET /governance/<section>/<team> [2] (team)\nGET /production/users (production)\nGET /sponsors (sponsors)\nGET /<category>/<subject> [4] (subject)\nGET /static/<file..> (files)\nGET /robots.txt (robots_txt)\nGET /logos/<file..> (logos)\nGET /components/<_file..> (components)\nGET /<locale> [3] (index_locale)\nGET /<locale>/<category> [11] (category_locale)\nGET /<locale>/governance [10] (governance_locale)\nGET /<locale>/governance/<section>/<team> [12] (team_locale)\nGET /<locale>/production/users [10] (production_locale)\nGET /<locale>/sponsors [10] (sponsors_locale)\nGET /<locale>/<category>/<subject> [14] (subject_locale)\nGET /<locale>/components/<_file..> [12] (components_locale)\nGET /<dest> [19] (redirect)\nGET /pdfs/<dest> (redirect_pdfs)\nGET /en-US (redirect_bare_en_us)\nGET /<_locale> [20] (redirect_bare_locale)\nGET /en-US/<dest> (redirect_en_us)\nGET /<_locale>/<dest> [20] (redirect_locale)\n"
  },
  {
    "path": "contrib/db_pools/README.md",
    "content": "# `db_pools` [![ci.svg]][ci] [![crates.io]][crate] [![docs.svg]][crate docs]\n\n[crates.io]: https://img.shields.io/crates/v/rocket_db_pools.svg\n[crate]: https://crates.io/crates/rocket_db_pools\n[docs.svg]: https://img.shields.io/badge/web-master-red.svg?style=flat&label=docs&colorB=d33847\n[crate docs]: https://api.rocket.rs/master/rocket_db_pools\n[ci.svg]: https://github.com/rwf2/Rocket/workflows/CI/badge.svg\n[ci]: https://github.com/rwf2/Rocket/actions\n\nAsynchronous database driver integration for Rocket. See the [crate docs] for\nfull usage details.\n\n## Usage\n\n1. Add `rocket_db_pools` as a dependency with one or more [database driver\n   features] enabled:\n\n   ```toml\n   [dependencies.rocket_db_pools]\n   version = \"0.1.0\"\n   features = [\"sqlx_sqlite\"]\n   ```\n\n2. Choose a name for your database, here `sqlite_logs`. [Configure] _at least_ a\n   URL for the database:\n\n   ```toml\n   [default.databases.sqlite_logs]\n   url = \"/path/to/database.sqlite\"\n   ```\n\n3. [Derive `Database`] for a unit type (`Logs` here) which\n   wraps the selected driver's [`Pool`] type and is decorated with\n   `#[database(\"name\")]`. Attach `Type::init()` to your application's `Rocket`\n   to initialize the database pool:\n\n   ```rust\n   use rocket_db_pools::{Database, Connection};\n\n   #[derive(Database)]\n   #[database(\"sqlite_logs\")]\n   struct Logs(sqlx::SqlitePool);\n\n   #[launch]\n   fn rocket() -> _ {\n       rocket::build().attach(Logs::init())\n   }\n   ```\n\n4. Use [`Connection<Type>`] as a request guard to retrieve an\n   active database connection:\n\n   ```rust\n   #[get(\"/<id>\")]\n   async fn read(mut db: Connection<Logs>, id: i64) -> Result<Log> {\n       sqlx::query!(\"SELECT content FROM logs WHERE id = ?\", id)\n           .fetch_one(&mut *db)\n           .map_ok(|r| Log(r.content))\n           .await\n   }\n   ```\n\n[database driver features]: https://api.rocket.rs/master/rocket_db_pools/index.html#supported-drivers\n[`Pool`]: https://api.rocket.rs/master/rocket_db_pools/index.html#supported-drivers\n[Configure]: https://api.rocket.rs/master/rocket_db_pools/index.html#configuration\n[Derive `Database`]: https://api.rocket.rs/master/rocket_db_pools/derive.Database.html\n[`Connection<Type>`]: https://api.rocket.rs/master/rocket_db_pools/struct.Connection.html\n"
  },
  {
    "path": "contrib/db_pools/codegen/Cargo.toml",
    "content": "[package]\nname = \"rocket_db_pools_codegen\"\nversion = \"0.1.0\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\", \"Jeb Rosen <jeb@jebrosen.com>\"]\ndescription = \"Procedural macros for rocket_db_pools.\"\nrepository = \"https://github.com/rwf2/Rocket/tree/master/contrib/db_pools\"\nreadme = \"../README.md\"\nkeywords = [\"rocket\", \"framework\", \"database\", \"pools\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[lib]\nproc-macro = true\n\n[lints]\nworkspace = true\n\n[dependencies]\ndevise = \"0.4\"\nquote = \"1\"\n\n[dev-dependencies]\nrocket = { path = \"../../../core/lib\", default-features = false }\nrocket_db_pools = { path = \"../lib\", features = [\"deadpool_postgres\"] }\ntrybuild = \"1.0\"\nversion_check = \"0.9\"\n"
  },
  {
    "path": "contrib/db_pools/codegen/src/database.rs",
    "content": "use proc_macro::TokenStream;\n\nuse devise::{DeriveGenerator, FromMeta, MapperBuild, Support, ValidatorBuild};\nuse devise::proc_macro2_diagnostics::SpanDiagnosticExt;\nuse devise::syn::{self, spanned::Spanned};\n\nconst ONE_DATABASE_ATTR: &str = \"missing `#[database(\\\"name\\\")]` attribute\";\nconst ONE_UNNAMED_FIELD: &str = \"struct must have exactly one unnamed field\";\n\n#[derive(Debug, FromMeta)]\nstruct DatabaseAttribute {\n    #[meta(naked)]\n    name: String,\n}\n\npub fn derive_database(input: TokenStream) -> TokenStream {\n    DeriveGenerator::build_for(input, quote!(impl rocket_db_pools::Database))\n        .support(Support::TupleStruct)\n        .validator(ValidatorBuild::new()\n            .struct_validate(|_, s| {\n                if s.fields.len() == 1 {\n                    Ok(())\n                } else {\n                    Err(s.span().error(ONE_UNNAMED_FIELD))\n                }\n            })\n        )\n        .outer_mapper(MapperBuild::new()\n            .struct_map(|_, s| {\n                let pool_type = match &s.fields {\n                    syn::Fields::Unnamed(f) => &f.unnamed[0].ty,\n                    _ => unreachable!(\"Support::TupleStruct\"),\n                };\n\n                let decorated_type = &s.ident;\n                let db_ty = quote_spanned!(decorated_type.span() =>\n                    <#decorated_type as rocket_db_pools::Database>\n                );\n\n                quote_spanned! { decorated_type.span() =>\n                    impl From<#pool_type> for #decorated_type {\n                        fn from(pool: #pool_type) -> Self {\n                            Self(pool)\n                        }\n                    }\n\n                    impl std::ops::Deref for #decorated_type {\n                        type Target = #pool_type;\n\n                        fn deref(&self) -> &Self::Target {\n                            &self.0\n                        }\n                    }\n\n                    impl std::ops::DerefMut for #decorated_type {\n                        fn deref_mut(&mut self) -> &mut Self::Target {\n                            &mut self.0\n                        }\n                    }\n\n                    #[rocket::async_trait]\n                    impl<'r> rocket::request::FromRequest<'r> for &'r #decorated_type {\n                        type Error = ();\n\n                        async fn from_request(\n                            req: &'r rocket::request::Request<'_>\n                        ) -> rocket::request::Outcome<Self, Self::Error> {\n                            match #db_ty::fetch(req.rocket()) {\n                                Some(db) => rocket::outcome::Outcome::Success(db),\n                                None => rocket::outcome::Outcome::Error((\n                                    rocket::http::Status::InternalServerError, ()))\n                            }\n                        }\n                    }\n\n                    impl rocket::Sentinel for &#decorated_type {\n                        fn abort(rocket: &rocket::Rocket<rocket::Ignite>) -> bool {\n                            #db_ty::fetch(rocket).is_none()\n                        }\n                    }\n                }\n            })\n        )\n        .outer_mapper(quote!(#[rocket::async_trait]))\n        .inner_mapper(MapperBuild::new()\n            .try_struct_map(|_, s| {\n                let db_name = DatabaseAttribute::one_from_attrs(\"database\", &s.attrs)?\n                    .map(|attr| attr.name)\n                    .ok_or_else(|| s.span().error(ONE_DATABASE_ATTR))?;\n\n                let fairing_name = format!(\"'{}' Database Pool\", db_name);\n\n                let pool_type = match &s.fields {\n                    syn::Fields::Unnamed(f) => &f.unnamed[0].ty,\n                    _ => unreachable!(\"Support::TupleStruct\"),\n                };\n\n                Ok(quote_spanned! { pool_type.span() =>\n                    type Pool = #pool_type;\n\n                    const NAME: &'static str = #db_name;\n\n                    fn init() -> rocket_db_pools::Initializer<Self> {\n                        rocket_db_pools::Initializer::with_name(#fairing_name)\n                    }\n                })\n            })\n        )\n        .to_tokens()\n}\n"
  },
  {
    "path": "contrib/db_pools/codegen/src/lib.rs",
    "content": "#![recursion_limit=\"256\"]\n#![warn(rust_2018_idioms)]\n\n//! # `rocket_db_pool` - Code Generation\n//!\n//! Implements the code generation portion of the `rocket_db_pool` crate. This\n//! is an implementation detail. This create should never be depended on\n//! directly.\n\n#[macro_use] extern crate quote;\n\nmod database;\n\n/// Automatic derive for the [`Database`] trait.\n///\n/// ```rust\n/// use rocket_db_pools::Database;\n/// # type PoolType = rocket_db_pools::deadpool_postgres::Pool;\n///\n/// #[derive(Database)]\n/// #[database(\"database_name\")]\n/// struct Db(PoolType);\n/// ```\n///\n/// The derive generates an implementation of [`Database`] as follows:\n///\n/// * [`Database::NAME`] is set to the value in the `#[database(\"name\")]`\n///   attribute.\n///\n///   This names the database, providing an anchor to configure the database via\n///   `Rocket.toml` or any other configuration source. Specifically, the\n///   configuration in `databases.name` is used to configure the driver.\n///\n/// * [`Database::Pool`] is set to the wrapped type: `PoolType` above. The type\n///   must implement [`Pool`].\n///\n/// To meet the required [`Database`] supertrait bounds, this derive also\n/// generates implementations for:\n///\n/// * `From<Db::Pool>`\n///\n/// * `Deref<Target = Db::Pool>`\n///\n/// * `DerefMut<Target = Db::Pool>`\n///\n/// * `FromRequest<'_> for &Db`\n///\n/// * `Sentinel for &Db`\n///\n/// The `Deref` impls enable accessing the database pool directly from\n/// references `&Db` or `&mut Db`. To force a dereference to the underlying\n/// type, use `&db.0` or `&**db` or their `&mut` variants.\n///\n/// [`Database`]: ../rocket_db_pools/trait.Database.html\n/// [`Database::NAME`]: ../rocket_db_pools/trait.Database.html#associatedconstant.NAME\n/// [`Database::Pool`]: ../rocket_db_pools/trait.Database.html#associatedtype.Pool\n/// [`Pool`]: ../rocket_db_pools/trait.Pool.html\n#[proc_macro_derive(Database, attributes(database))]\npub fn derive_database(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n    crate::database::derive_database(input)\n}\n"
  },
  {
    "path": "contrib/db_pools/codegen/tests/ui-fail/database-syntax.rs",
    "content": "use rocket_db_pools::{deadpool_postgres, Database};\n\n#[derive(Database)]\n#[database(123)]\nstruct A(deadpool_postgres::Pool);\n\n#[derive(Database)]\n#[database(\"some-name\", \"another\")]\nstruct B(deadpool_postgres::Pool);\n\n#[derive(Database)]\n#[database(\"some-name\", name = \"another\")]\nstruct C(deadpool_postgres::Pool);\n\n#[derive(Database)]\n#[database(\"foo\")]\nenum D {  }\n\n#[derive(Database)]\nstruct E(deadpool_postgres::Pool);\n\n#[derive(Database)]\n#[database(\"foo\")]\nstruct F;\n\n#[derive(Database)]\n#[database(\"foo\")]\nstruct G(deadpool_postgres::Pool, deadpool_postgres::Pool);\n\n#[derive(Database)]\n#[database(\"foo\")]\nstruct H {\n    foo: deadpool_postgres::Pool,\n}\n\nfn main() {  }\n"
  },
  {
    "path": "contrib/db_pools/codegen/tests/ui-fail/database-types.rs",
    "content": "#[macro_use] extern crate rocket_db_pools;\n\nstruct Unknown;\n\n#[derive(Database)]\n#[database(\"foo\")]\nstruct A(Unknown);\n\n#[derive(Database)]\n#[database(\"bar\")]\nstruct B(Vec<i32>);\n\nfn main() {  }\n"
  },
  {
    "path": "contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.stderr",
    "content": "error: invalid value: expected string literal\n --> tests/ui-fail-nightly/database-syntax.rs:4:12\n  |\n4 | #[database(123)]\n  |            ^^^\n  |\nnote: error occurred while deriving `Database`\n --> tests/ui-fail-nightly/database-syntax.rs:3:10\n  |\n3 | #[derive(Database)]\n  |          ^^^^^^^^\n  = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected key/value `key = value`\n --> tests/ui-fail-nightly/database-syntax.rs:8:25\n  |\n8 | #[database(\"some-name\", \"another\")]\n  |                         ^^^^^^^^^\n  |\nnote: error occurred while deriving `Database`\n --> tests/ui-fail-nightly/database-syntax.rs:7:10\n  |\n7 | #[derive(Database)]\n  |          ^^^^^^^^\n  = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected attribute parameter: `name`\n  --> tests/ui-fail-nightly/database-syntax.rs:12:25\n   |\n12 | #[database(\"some-name\", name = \"another\")]\n   |                         ^^^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `Database`\n  --> tests/ui-fail-nightly/database-syntax.rs:11:10\n   |\n11 | #[derive(Database)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: enums are not supported\n  --> tests/ui-fail-nightly/database-syntax.rs:16:1\n   |\n16 | / #[database(\"foo\")]\n17 | | enum D {  }\n   | |___________^\n   |\nnote: error occurred while deriving `Database`\n  --> tests/ui-fail-nightly/database-syntax.rs:15:10\n   |\n15 | #[derive(Database)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: missing `#[database(\"name\")]` attribute\n  --> tests/ui-fail-nightly/database-syntax.rs:20:1\n   |\n20 | struct E(deadpool_postgres::Pool);\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `Database`\n  --> tests/ui-fail-nightly/database-syntax.rs:19:10\n   |\n19 | #[derive(Database)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one unnamed field\n  --> tests/ui-fail-nightly/database-syntax.rs:23:1\n   |\n23 | / #[database(\"foo\")]\n24 | | struct F;\n   | |_________^\n   |\nnote: error occurred while deriving `Database`\n  --> tests/ui-fail-nightly/database-syntax.rs:22:10\n   |\n22 | #[derive(Database)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one unnamed field\n  --> tests/ui-fail-nightly/database-syntax.rs:27:1\n   |\n27 | / #[database(\"foo\")]\n28 | | struct G(deadpool_postgres::Pool, deadpool_postgres::Pool);\n   | |___________________________________________________________^\n   |\nnote: error occurred while deriving `Database`\n  --> tests/ui-fail-nightly/database-syntax.rs:26:10\n   |\n26 | #[derive(Database)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n  --> tests/ui-fail-nightly/database-syntax.rs:31:1\n   |\n31 | / #[database(\"foo\")]\n32 | | struct H {\n33 | |     foo: deadpool_postgres::Pool,\n34 | | }\n   | |_^\n   |\nnote: error occurred while deriving `Database`\n  --> tests/ui-fail-nightly/database-syntax.rs:30:10\n   |\n30 | #[derive(Database)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.stderr",
    "content": "error[E0277]: the trait bound `Unknown: Pool` is not satisfied\n --> tests/ui-fail-nightly/database-types.rs:7:10\n  |\n7 | struct A(Unknown);\n  |          ^^^^^^^ the trait `Pool` is not implemented for `Unknown`\n  |\n  = help: the trait `Pool` is implemented for `deadpool::managed::Pool<M, C>`\nnote: required by a bound in `rocket_db_pools::Database::Pool`\n --> $WORKSPACE/contrib/db_pools/lib/src/database.rs\n  |\n  |     type Pool: Pool;\n  |                ^^^^ required by this bound in `Database::Pool`\n\nerror[E0277]: the trait bound `Vec<i32>: Pool` is not satisfied\n  --> tests/ui-fail-nightly/database-types.rs:11:10\n   |\n11 | struct B(Vec<i32>);\n   |          ^^^^^^^^ the trait `Pool` is not implemented for `Vec<i32>`\n   |\n   = help: the trait `Pool` is implemented for `deadpool::managed::Pool<M, C>`\nnote: required by a bound in `rocket_db_pools::Database::Pool`\n  --> $WORKSPACE/contrib/db_pools/lib/src/database.rs\n   |\n   |     type Pool: Pool;\n   |                ^^^^ required by this bound in `Database::Pool`\n"
  },
  {
    "path": "contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.stderr",
    "content": "error: invalid value: expected string literal\n --> tests/ui-fail-stable/database-syntax.rs:4:12\n  |\n4 | #[database(123)]\n  |            ^^^\n\nerror: [note] error occurred while deriving `Database`\n --> tests/ui-fail-stable/database-syntax.rs:3:10\n  |\n3 | #[derive(Database)]\n  |          ^^^^^^^^\n  |\n  = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected key/value `key = value`\n --> tests/ui-fail-stable/database-syntax.rs:8:25\n  |\n8 | #[database(\"some-name\", \"another\")]\n  |                         ^^^^^^^^^\n\nerror: [note] error occurred while deriving `Database`\n --> tests/ui-fail-stable/database-syntax.rs:7:10\n  |\n7 | #[derive(Database)]\n  |          ^^^^^^^^\n  |\n  = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected attribute parameter: `name`\n  --> tests/ui-fail-stable/database-syntax.rs:12:25\n   |\n12 | #[database(\"some-name\", name = \"another\")]\n   |                         ^^^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `Database`\n  --> tests/ui-fail-stable/database-syntax.rs:11:10\n   |\n11 | #[derive(Database)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: enums are not supported\n  --> tests/ui-fail-stable/database-syntax.rs:16:1\n   |\n16 | / #[database(\"foo\")]\n17 | | enum D {  }\n   | |___________^\n\nerror: [note] error occurred while deriving `Database`\n  --> tests/ui-fail-stable/database-syntax.rs:15:10\n   |\n15 | #[derive(Database)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: missing `#[database(\"name\")]` attribute\n  --> tests/ui-fail-stable/database-syntax.rs:20:1\n   |\n20 | struct E(deadpool_postgres::Pool);\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `Database`\n  --> tests/ui-fail-stable/database-syntax.rs:19:10\n   |\n19 | #[derive(Database)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one unnamed field\n  --> tests/ui-fail-stable/database-syntax.rs:23:1\n   |\n23 | / #[database(\"foo\")]\n24 | | struct F;\n   | |_________^\n\nerror: [note] error occurred while deriving `Database`\n  --> tests/ui-fail-stable/database-syntax.rs:22:10\n   |\n22 | #[derive(Database)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one unnamed field\n  --> tests/ui-fail-stable/database-syntax.rs:27:1\n   |\n27 | / #[database(\"foo\")]\n28 | | struct G(deadpool_postgres::Pool, deadpool_postgres::Pool);\n   | |___________________________________________________________^\n\nerror: [note] error occurred while deriving `Database`\n  --> tests/ui-fail-stable/database-syntax.rs:26:10\n   |\n26 | #[derive(Database)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n  --> tests/ui-fail-stable/database-syntax.rs:31:1\n   |\n31 | / #[database(\"foo\")]\n32 | | struct H {\n33 | |     foo: deadpool_postgres::Pool,\n34 | | }\n   | |_^\n\nerror: [note] error occurred while deriving `Database`\n  --> tests/ui-fail-stable/database-syntax.rs:30:10\n   |\n30 | #[derive(Database)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Database` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "contrib/db_pools/codegen/tests/ui-fail-stable/database-types.stderr",
    "content": "error[E0277]: the trait bound `Unknown: Pool` is not satisfied\n --> tests/ui-fail-stable/database-types.rs:7:10\n  |\n7 | struct A(Unknown);\n  |          ^^^^^^^ the trait `Pool` is not implemented for `Unknown`\n  |\n  = help: the trait `Pool` is implemented for `deadpool::managed::Pool<M, C>`\nnote: required by a bound in `rocket_db_pools::Database::Pool`\n --> $WORKSPACE/contrib/db_pools/lib/src/database.rs\n  |\n  |     type Pool: Pool;\n  |                ^^^^ required by this bound in `Database::Pool`\n\nerror[E0277]: the trait bound `Vec<i32>: Pool` is not satisfied\n  --> tests/ui-fail-stable/database-types.rs:11:10\n   |\n11 | struct B(Vec<i32>);\n   |          ^^^^^^^^ the trait `Pool` is not implemented for `Vec<i32>`\n   |\n   = help: the trait `Pool` is implemented for `deadpool::managed::Pool<M, C>`\nnote: required by a bound in `rocket_db_pools::Database::Pool`\n  --> $WORKSPACE/contrib/db_pools/lib/src/database.rs\n   |\n   |     type Pool: Pool;\n   |                ^^^^ required by this bound in `Database::Pool`\n"
  },
  {
    "path": "contrib/db_pools/codegen/tests/ui-fail.rs",
    "content": "#[test]\n#[ignore]\nfn ui() {\n    let path = match version_check::is_feature_flaggable() {\n        Some(true) => \"ui-fail-nightly\",\n        _ => \"ui-fail-stable\"\n    };\n\n    let t = trybuild::TestCases::new();\n    t.compile_fail(format!(\"tests/{}/*.rs\", path));\n}\n"
  },
  {
    "path": "contrib/db_pools/lib/Cargo.toml",
    "content": "[package]\nname = \"rocket_db_pools\"\nversion = \"0.1.0\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\", \"Jeb Rosen <jeb@jebrosen.com>\"]\ndescription = \"Rocket async database pooling support\"\nrepository = \"https://github.com/rwf2/Rocket/tree/master/contrib/db_pools\"\nreadme = \"../README.md\"\nkeywords = [\"rocket\", \"framework\", \"database\", \"pools\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[package.metadata.docs.rs]\nall-features = true\n\n[lints]\nworkspace = true\n\n[features]\n# deadpool features\ndeadpool_postgres = [\"deadpool-postgres\", \"deadpool\"]\ndeadpool_redis = [\"deadpool-redis\", \"deadpool\"]\n# sqlx features\nsqlx_mysql = [\"sqlx\", \"sqlx/mysql\", \"log\"]\nsqlx_postgres = [\"sqlx\", \"sqlx/postgres\", \"log\"]\nsqlx_sqlite = [\"sqlx\", \"sqlx/sqlite\", \"log\"]\nsqlx_macros = [\"sqlx/macros\"]\n# diesel features\ndiesel_postgres = [\"diesel-async/postgres\", \"diesel-async/deadpool\", \"deadpool\", \"diesel\"]\ndiesel_mysql = [\"diesel-async/mysql\", \"diesel-async/deadpool\", \"deadpool\", \"diesel\"]\n# implicit features: mongodb\n\n[dependencies.rocket]\npath = \"../../../core/lib\"\nversion = \"0.6.0-dev\"\ndefault-features = false\n\n[dependencies.rocket_db_pools_codegen]\npath = \"../codegen\"\nversion = \"0.1.0\"\n\n[dependencies.deadpool]\nversion = \"0.12.1\"\ndefault-features = false\nfeatures = [\"rt_tokio_1\", \"managed\"]\noptional = true\n\n[dependencies.deadpool-postgres]\nversion = \"0.14\"\ndefault-features = false\nfeatures = [\"rt_tokio_1\"]\noptional = true\n\n[dependencies.deadpool-redis]\nversion = \"0.16\"\ndefault-features = false\nfeatures = [\"rt_tokio_1\"]\noptional = true\n\n[dependencies.mongodb]\nversion = \"3\"\ndefault-features = false\nfeatures = [\"compat-3-0-0\", \"rustls-tls\"]\noptional = true\n\n[dependencies.diesel-async]\nversion = \"0.6.0\"\ndefault-features = false\nfeatures = [\"async-connection-wrapper\"]\noptional = true\n\n[dependencies.diesel]\nversion = \"2.1\"\ndefault-features = false\noptional = true\n\n[dependencies.sqlx]\nversion = \"0.8\"\ndefault-features = false\nfeatures = [\"runtime-tokio-rustls\"]\noptional = true\n\n[dependencies.log]\nversion = \"0.4\"\ndefault-features = false\noptional = true\n\n[dev-dependencies.rocket]\npath = \"../../../core/lib\"\ndefault-features = false\nfeatures = [\"json\"]\n\n[build-dependencies]\nversion_check = \"0.9\"\n"
  },
  {
    "path": "contrib/db_pools/lib/src/config.rs",
    "content": "use rocket::serde::{Deserialize, Serialize};\n\n/// Base configuration for all database drivers.\n///\n/// A dictionary matching this structure is extracted from the active\n/// [`Figment`](crate::figment::Figment), scoped to `databases.name`, where\n/// `name` is the name of the database, by the\n/// [`Initializer`](crate::Initializer) fairing on ignition and used to\n/// configure the relevant database and database pool.\n///\n/// With the default provider, these parameters are typically configured in a\n/// `Rocket.toml` file:\n///\n/// ```toml\n/// [default.databases.db_name]\n/// url = \"/path/to/db.sqlite\"\n///\n/// # Only `url` is required. These have sane defaults and are optional.\n/// min_connections = 64\n/// max_connections = 1024\n/// connect_timeout = 5\n/// idle_timeout = 120\n///\n/// # This option is only supported by the `sqlx_sqlite` driver.\n/// extensions = [\"memvfs\", \"rot13\"]\n/// ```\n///\n/// Alternatively, a custom provider can be used. For example, a custom `Figment`\n/// with a global `databases.name` configuration:\n///\n/// ```rust\n/// # use rocket::launch;\n/// #[launch]\n/// fn rocket() -> _ {\n///     let figment = rocket::Config::figment()\n///         .merge((\"databases.name\", rocket_db_pools::Config {\n///             url: \"db:specific@config&url\".into(),\n///             min_connections: None,\n///             max_connections: 1024,\n///             connect_timeout: 3,\n///             idle_timeout: None,\n///             extensions: None,\n///         }));\n///\n///     rocket::custom(figment)\n/// }\n/// ```\n///\n/// For general information on configuration in Rocket, see [`rocket::config`].\n/// For higher-level details on configuring a database, see the [crate-level\n/// docs](crate#configuration).\n// NOTE: Defaults provided by the figment created in the `Initializer` fairing.\n#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]\n#[serde(crate = \"rocket::serde\")]\npub struct Config {\n    /// Database-specific connection and configuration URL.\n    ///\n    /// The format of the URL is database specific; consult your database's\n    /// documentation.\n    pub url: String,\n    /// Minimum number of connections to maintain in the pool.\n    ///\n    /// **Note:** `deadpool` drivers do not support and thus ignore this value.\n    ///\n    /// _Default:_ `None`.\n    pub min_connections: Option<u32>,\n    /// Maximum number of connections to maintain in the pool.\n    ///\n    /// _Default:_ `workers * 4`.\n    pub max_connections: usize,\n    /// Number of seconds to wait for a connection before timing out.\n    ///\n    /// If the timeout elapses before a connection can be made or retrieved from\n    /// a pool, an error is returned.\n    ///\n    /// _Default:_ `5`.\n    pub connect_timeout: u64,\n    /// Maximum number of seconds to keep a connection alive for.\n    ///\n    /// After a connection is established, it is maintained in a pool for\n    /// efficient connection retrieval. When an `idle_timeout` is set, that\n    /// connection will be closed after the timeout elapses. If an\n    /// `idle_timeout` is not specified, the behavior is driver specific but\n    /// typically defaults to keeping a connection active indefinitely.\n    ///\n    /// _Default:_ `None`.\n    pub idle_timeout: Option<u64>,\n    /// A list of database extensions to load at run-time.\n    ///\n    /// **Note:** Only the `sqlx_sqlite` driver supports this option (for SQLite\n    /// extensions) at this time. All other drivers ignore this option.\n    ///\n    /// _Default:_ `None`.\n    pub extensions: Option<Vec<String>>,\n}\n\nimpl Default for Config {\n    fn default() -> Self {\n        Self {\n            url: Default::default(),\n            min_connections: Default::default(),\n            max_connections: rocket::Config::default().workers * 4,\n            connect_timeout: 5,\n            idle_timeout: Default::default(),\n            extensions: Default::default(),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::Config;\n\n    #[test]\n    fn default_values_sane() {\n        let config = Config::default();\n        assert_ne!(config.max_connections, 0);\n        assert_eq!(config.connect_timeout, 5);\n    }\n}\n"
  },
  {
    "path": "contrib/db_pools/lib/src/database.rs",
    "content": "use std::marker::PhantomData;\nuse std::ops::{Deref, DerefMut};\n\nuse rocket::{error, Build, Ignite, Phase, Rocket, Sentinel, Orbit};\nuse rocket::fairing::{self, Fairing, Info, Kind};\nuse rocket::request::{FromRequest, Outcome, Request};\nuse rocket::figment::providers::Serialized;\nuse rocket::http::Status;\n\nuse crate::Pool;\n\n/// Derivable trait which ties a database [`Pool`] with a configuration name.\n///\n/// This trait should rarely, if ever, be implemented manually. Instead, it\n/// should be derived:\n///\n/// ```rust\n/// # #[cfg(feature = \"deadpool_redis\")] mod _inner {\n/// # use rocket::launch;\n/// use rocket_db_pools::{deadpool_redis, Database};\n///\n/// #[derive(Database)]\n/// #[database(\"memdb\")]\n/// struct Db(deadpool_redis::Pool);\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().attach(Db::init())\n/// }\n/// # }\n/// ```\n///\n/// See the [`Database` derive](derive@crate::Database) for details.\npub trait Database: From<Self::Pool> + DerefMut<Target = Self::Pool> + Send + Sync + 'static {\n    /// The [`Pool`] type of connections to this database.\n    ///\n    /// When `Database` is derived, this takes the value of the `Inner` type in\n    /// `struct Db(Inner)`.\n    type Pool: Pool;\n\n    /// The configuration name for this database.\n    ///\n    /// When `Database` is derived, this takes the value `\"name\"` in the\n    /// `#[database(\"name\")]` attribute.\n    const NAME: &'static str;\n\n    /// Returns a fairing that initializes the database and its connection pool.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[cfg(feature = \"deadpool_postgres\")] mod _inner {\n    /// # use rocket::launch;\n    /// use rocket_db_pools::{deadpool_postgres, Database};\n    ///\n    /// #[derive(Database)]\n    /// #[database(\"pg_db\")]\n    /// struct Db(deadpool_postgres::Pool);\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build().attach(Db::init())\n    /// }\n    /// # }\n    /// ```\n    fn init() -> Initializer<Self> {\n        Initializer::new()\n    }\n\n    /// Returns a reference to the initialized database in `rocket`. The\n    /// initializer fairing returned by `init()` must have already executed for\n    /// `Option` to be `Some`. This is guaranteed to be the case if the fairing\n    /// is attached and either:\n    ///\n    ///   * Rocket is in the [`Orbit`](rocket::Orbit) phase. That is, the\n    ///     application is running. This is always the case in request guards\n    ///     and liftoff fairings,\n    ///   * _or_ Rocket is in the [`Build`](rocket::Build) or\n    ///     [`Ignite`](rocket::Ignite) phase and the `Initializer` fairing has\n    ///     already been run. This is the case in all fairing callbacks\n    ///     corresponding to fairings attached _after_ the `Initializer`\n    ///     fairing.\n    ///\n    /// # Example\n    ///\n    /// Run database migrations in an ignite fairing. It is imperative that the\n    /// migration fairing be registered _after_ the `init()` fairing.\n    ///\n    /// ```rust\n    /// # #[cfg(feature = \"sqlx_sqlite\")] mod _inner {\n    /// # use rocket::launch;\n    /// use rocket::{Rocket, Build};\n    /// use rocket::fairing::{self, AdHoc};\n    ///\n    /// use rocket_db_pools::{sqlx, Database};\n    ///\n    /// #[derive(Database)]\n    /// #[database(\"sqlite_db\")]\n    /// struct Db(sqlx::SqlitePool);\n    ///\n    /// async fn run_migrations(rocket: Rocket<Build>) -> fairing::Result {\n    ///     if let Some(db) = Db::fetch(&rocket) {\n    ///         // run migrations using `db`. get the inner type with &db.0.\n    ///         Ok(rocket)\n    ///     } else {\n    ///         Err(rocket)\n    ///     }\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .attach(Db::init())\n    ///         .attach(AdHoc::try_on_ignite(\"DB Migrations\", run_migrations))\n    /// }\n    /// # }\n    /// ```\n    fn fetch<P: Phase>(rocket: &Rocket<P>) -> Option<&Self> {\n        if let Some(db) = rocket.state() {\n            return Some(db);\n        }\n\n        let conn = std::any::type_name::<Self>();\n        error!(\"`{conn}::init()` is not attached\\n\\\n            the fairing must be attached to use `{conn}` in routes.\");\n\n        None\n    }\n}\n\n/// A [`Fairing`] which initializes a [`Database`] and its connection pool.\n///\n/// A value of this type can be created for any type `D` that implements\n/// [`Database`] via the [`Database::init()`] method on the type. Normally, a\n/// value of this type _never_ needs to be constructed directly. This\n/// documentation exists purely as a reference.\n///\n/// This fairing initializes a database pool. Specifically, it:\n///\n///   1. Reads the configuration at `database.db_name`, where `db_name` is\n///      [`Database::NAME`].\n///\n///   2. Sets [`Config`](crate::Config) defaults on the configuration figment.\n///\n///   3. Calls [`Pool::init()`].\n///\n///   4. Stores the database instance in managed storage, retrievable via\n///      [`Database::fetch()`].\n///\n/// The name of the fairing itself is `Initializer<D>`, with `D` replaced with\n/// the type name `D` unless a name is explicitly provided via\n/// [`Self::with_name()`].\npub struct Initializer<D: Database>(Option<&'static str>, PhantomData<fn() -> D>);\n\n/// A request guard which retrieves a single connection to a [`Database`].\n///\n/// For a database type of `Db`, a request guard of `Connection<Db>` retrieves a\n/// single connection to `Db`.\n///\n/// The request guard succeeds if the database was initialized by the\n/// [`Initializer`] fairing and a connection is available within\n/// [`connect_timeout`](crate::Config::connect_timeout) seconds.\n///   * If the `Initializer` fairing was _not_ attached, the guard _fails_ with\n///   status `InternalServerError`. A [`Sentinel`] guards this condition, and so\n///   this type of error is unlikely to occur. A `None` error is returned.\n///   * If a connection is not available within `connect_timeout` seconds or\n///   another error occurs, the guard _fails_ with status `ServiceUnavailable`\n///   and the error is returned in `Some`.\n///\n/// ## Deref\n///\n/// A type of `Connection<Db>` dereferences, mutably and immutably, to the\n/// native database connection type. The [driver table](crate#supported-drivers)\n/// lists the concrete native `Deref` types.\n///\n/// # Example\n///\n/// ```rust\n/// # #[cfg(feature = \"sqlx_sqlite\")] mod _inner {\n/// # use rocket::get;\n/// # type Pool = rocket_db_pools::sqlx::SqlitePool;\n/// use rocket_db_pools::{Database, Connection};\n///\n/// #[derive(Database)]\n/// #[database(\"db\")]\n/// struct Db(Pool);\n///\n/// #[get(\"/\")]\n/// async fn db_op(db: Connection<Db>) {\n///     // use `&*db` to get an immutable borrow to the native connection type\n///     // use `&mut *db` to get a mutable borrow to the native connection type\n/// }\n/// # }\n/// ```\npub struct Connection<D: Database>(<D::Pool as Pool>::Connection);\n\nimpl<D: Database> Initializer<D> {\n    /// Returns a database initializer fairing for `D`.\n    ///\n    /// This method should never need to be called manually. See the [crate\n    /// docs](crate) for usage information.\n    pub fn new() -> Self {\n        Self(None, std::marker::PhantomData)\n    }\n\n    /// Returns a database initializer fairing for `D` with name `name`.\n    ///\n    /// This method should never need to be called manually. See the [crate\n    /// docs](crate) for usage information.\n    pub fn with_name(name: &'static str) -> Self {\n        Self(Some(name), std::marker::PhantomData)\n    }\n}\n\nimpl<D: Database> Connection<D> {\n    /// Returns the internal connection value. See the [`Connection` Deref\n    /// column](crate#supported-drivers) for the expected type of this value.\n    ///\n    /// Note that `Connection<D>` derefs to the internal connection type, so\n    /// using this method is likely unnecessary. See [deref](Connection#deref)\n    /// for examples.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[cfg(feature = \"sqlx_sqlite\")] mod _inner {\n    /// # use rocket::get;\n    /// # type Pool = rocket_db_pools::sqlx::SqlitePool;\n    /// use rocket_db_pools::{Database, Connection};\n    ///\n    /// #[derive(Database)]\n    /// #[database(\"db\")]\n    /// struct Db(Pool);\n    ///\n    /// #[get(\"/\")]\n    /// async fn db_op(db: Connection<Db>) {\n    ///     let inner = db.into_inner();\n    /// }\n    /// # }\n    /// ```\n    pub fn into_inner(self) -> <D::Pool as Pool>::Connection {\n        self.0\n    }\n}\n\n#[rocket::async_trait]\nimpl<D: Database> Fairing for Initializer<D> {\n    fn info(&self) -> Info {\n        Info {\n            name: self.0.unwrap_or(std::any::type_name::<Self>()),\n            kind: Kind::Ignite | Kind::Shutdown,\n        }\n    }\n\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {\n        let workers: usize = rocket.figment()\n            .extract_inner(rocket::Config::WORKERS)\n            .unwrap_or_else(|_| rocket::Config::default().workers);\n\n        let figment = rocket.figment()\n            .focus(&format!(\"databases.{}\", D::NAME))\n            .join(Serialized::default(\"max_connections\", workers * 4))\n            .join(Serialized::default(\"connect_timeout\", 5));\n\n        match <D::Pool>::init(&figment).await {\n            Ok(pool) => Ok(rocket.manage(D::from(pool))),\n            Err(e) => {\n                error!(\"database initialization failed: {e}\");\n                Err(rocket)\n            }\n        }\n    }\n\n    async fn on_shutdown(&self, rocket: &Rocket<Orbit>) {\n        if let Some(db) = D::fetch(rocket) {\n            db.close().await;\n        }\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r, D: Database> FromRequest<'r> for Connection<D> {\n    type Error = Option<<D::Pool as Pool>::Error>;\n\n    async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n        match D::fetch(req.rocket()) {\n            Some(db) => match db.get().await {\n                Ok(conn) => Outcome::Success(Connection(conn)),\n                Err(e) => Outcome::Error((Status::ServiceUnavailable, Some(e))),\n            },\n            None => Outcome::Error((Status::InternalServerError, None)),\n        }\n    }\n}\n\nimpl<D: Database> Sentinel for Connection<D> {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        D::fetch(rocket).is_none()\n    }\n}\n\nimpl<D: Database> Deref for Connection<D> {\n    type Target = <D::Pool as Pool>::Connection;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<D: Database> DerefMut for Connection<D> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n"
  },
  {
    "path": "contrib/db_pools/lib/src/diesel.rs",
    "content": "//! Re-export of [`diesel`] with prelude types overridden with `async` variants\n//! from [`diesel_async`].\n//!\n//! # Usage\n//!\n//! To use `async` `diesel` support provided here, enable the following\n//! dependencies in your `Cargo.toml`:\n//!\n//! ```toml\n//! [dependencies]\n//! rocket = \"0.6.0-dev\"\n//! diesel = \"2\"\n//!\n//! [dependencies.rocket_db_pools]\n//! version = \"0.1.0\"\n//! features = [\"diesel_mysql\"]\n//! ```\n//!\n//! Then, import `rocket_db_pools::diesel::prelude::*` as well as the\n//! appropriate pool type and, optionally, [`QueryResult`]. To use macros or\n//! `diesel` functions, use `diesel::` directly. That is, _do not_ import\n//! `rocket_db_pools::diesel`. Doing so will, by design, cause import errors.\n//!\n//! # Example\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! # #[cfg(feature = \"diesel_mysql\")] {\n//! use rocket_db_pools::{Database, Connection};\n//! use rocket_db_pools::diesel::{QueryResult, MysqlPool, prelude::*};\n//!\n//! #[derive(Database)]\n//! #[database(\"diesel_mysql\")]\n//! struct Db(MysqlPool);\n//!\n//! #[derive(Queryable, Insertable)]\n//! #[diesel(table_name = posts)]\n//! struct Post {\n//!     id: i64,\n//!     title: String,\n//!     published: bool,\n//! }\n//!\n//! diesel::table! {\n//!     posts (id) {\n//!         id -> BigInt,\n//!         title -> Text,\n//!         published -> Bool,\n//!     }\n//! }\n//!\n//! #[get(\"/\")]\n//! async fn list(mut db: Connection<Db>) -> QueryResult<String> {\n//!     let post_ids: Vec<i64> = posts::table\n//!         .select(posts::id)\n//!         .load(&mut db)\n//!         .await?;\n//!\n//!     Ok(format!(\"{post_ids:?}\"))\n//! }\n//! # }\n//! ```\n\n/// The [`diesel`] prelude with `sync`-only traits replaced with their\n/// [`diesel_async`] variants.\npub mod prelude {\n    #[doc(inline)]\n    pub use diesel::prelude::*;\n\n    #[doc(inline)]\n    pub use diesel_async::{AsyncConnection, RunQueryDsl, SaveChangesDsl};\n}\n\n#[doc(hidden)]\npub use diesel::*;\n\n#[doc(hidden)]\npub use diesel_async::{RunQueryDsl, SaveChangesDsl, *};\n\n#[doc(hidden)]\n#[cfg(feature = \"diesel_postgres\")]\npub use diesel_async::pg;\n\n#[doc(inline)]\npub use diesel_async::pooled_connection::deadpool::Pool;\n\n#[doc(inline)]\npub use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;\n\n#[doc(inline)]\n#[cfg(feature = \"diesel_mysql\")]\npub use diesel_async::AsyncMysqlConnection;\n\n#[doc(inline)]\n#[cfg(feature = \"diesel_postgres\")]\npub use diesel_async::AsyncPgConnection;\n\n/// Alias of a `Result` with an error type of [`Debug`] for a `diesel::Error`.\n///\n/// `QueryResult` is a [`Responder`](rocket::response::Responder) when `T` (the\n/// `Ok` value) is a `Responder`. By using this alias as a route handler's\n/// return type, the `?` operator can be applied to fallible `diesel` functions\n/// in the route handler while still providing a valid `Responder` return type.\n///\n/// See the [module level docs](self#example) for a usage example.\n///\n/// [`Debug`]: rocket::response::Debug\npub type QueryResult<T, E = rocket::response::Debug<diesel::result::Error>> = Result<T, E>;\n\n/// Type alias for an `async` pool of MySQL connections for `async` [diesel].\n///\n/// ```rust\n/// # extern crate rocket;\n/// # #[cfg(feature = \"diesel_mysql\")] {\n/// # use rocket::get;\n/// use rocket_db_pools::{Database, Connection};\n/// use rocket_db_pools::diesel::{MysqlPool, prelude::*};\n///\n/// #[derive(Database)]\n/// #[database(\"my_mysql_db_name\")]\n/// struct Db(MysqlPool);\n///\n/// #[get(\"/\")]\n/// async fn use_db(mut db: Connection<Db>) {\n///     /* .. */\n/// }\n/// # }\n/// ```\n#[cfg(feature = \"diesel_mysql\")]\npub type MysqlPool = Pool<AsyncMysqlConnection>;\n\n/// Type alias for an `async` pool of Postgres connections for `async` [diesel].\n///\n/// ```rust\n/// # extern crate rocket;\n/// # #[cfg(feature = \"diesel_postgres\")] {\n/// # use rocket::get;\n/// use rocket_db_pools::{Database, Connection};\n/// use rocket_db_pools::diesel::{PgPool, prelude::*};\n///\n/// #[derive(Database)]\n/// #[database(\"my_pg_db_name\")]\n/// struct Db(PgPool);\n///\n/// #[get(\"/\")]\n/// async fn use_db(mut db: Connection<Db>) {\n///     /* .. */\n/// }\n/// # }\n/// ```\n#[cfg(feature = \"diesel_postgres\")]\npub type PgPool = Pool<AsyncPgConnection>;\n"
  },
  {
    "path": "contrib/db_pools/lib/src/error.rs",
    "content": "use std::fmt;\n\n/// A general error type for use by [`Pool`](crate::Pool#implementing)\n/// implementors and returned by the [`Connection`](crate::Connection) request\n/// guard.\n#[derive(Debug)]\npub enum Error<A, B = A> {\n    /// An error that occurred during database/pool initialization.\n    Init(A),\n\n    /// An error that occurred while retrieving a connection from the pool.\n    Get(B),\n\n    /// A [`Figment`](crate::figment::Figment) configuration error.\n    Config(crate::figment::Error),\n}\n\nimpl<A: fmt::Display, B: fmt::Display> fmt::Display for Error<A, B> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Error::Init(e) => write!(f, \"failed to initialize database: {}\", e),\n            Error::Get(e) => write!(f, \"failed to get db connection: {}\", e),\n            Error::Config(e) => write!(f, \"bad configuration: {}\", e),\n        }\n    }\n}\n\nimpl<A, B> std::error::Error for Error<A, B>\n    where A: fmt::Debug + fmt::Display, B: fmt::Debug + fmt::Display {}\n\nimpl<A, B> From<crate::figment::Error> for Error<A, B> {\n    fn from(e: crate::figment::Error) -> Self {\n        Self::Config(e)\n    }\n}\n"
  },
  {
    "path": "contrib/db_pools/lib/src/lib.rs",
    "content": "//! Asynchronous database driver connection pooling integration for Rocket.\n//!\n//! # Quickstart\n//!\n//! 1. Add `rocket_db_pools` as a dependency with one or more [database driver\n//!    features](#supported-drivers) enabled:\n//!\n//!    ```toml\n//!    [dependencies.rocket_db_pools]\n//!    version = \"0.1.0\"\n//!    features = [\"sqlx_sqlite\"]\n//!    ```\n//!\n//! 2. Choose a name for your database, here `sqlite_logs`.\n//!    [Configure](#configuration) _at least_ a URL for the database:\n//!\n//!    ```toml\n//!    [default.databases.sqlite_logs]\n//!    url = \"/path/to/database.sqlite\"\n//!    ```\n//!\n//! 3. [Derive](derive@Database) [`Database`] for a unit type (`Logs` here)\n//!    which wraps the selected driver's [`Pool`] type (see [the driver\n//!    table](#supported-drivers)) and is decorated with `#[database(\"name\")]`.\n//!    Attach `Type::init()` to your application's `Rocket` to initialize the\n//!    database pool:\n//!\n//!    ```rust\n//!    # #[cfg(feature = \"sqlx_sqlite\")] mod _inner {\n//!    # use rocket::launch;\n//!    use rocket_db_pools::{sqlx, Database};\n//!\n//!    #[derive(Database)]\n//!    #[database(\"sqlite_logs\")]\n//!    struct Logs(sqlx::SqlitePool);\n//!\n//!    #[launch]\n//!    fn rocket() -> _ {\n//!        rocket::build().attach(Logs::init())\n//!    }\n//!    # }\n//!    ```\n//!\n//! 4. Use [`Connection<Type>`](Connection) as a request guard to retrieve an\n//!    active database connection, which dereferences to the native type in the\n//!    [`Connection` deref](#supported-drivers) column.\n//!\n//!    ```rust\n//!    # #[cfg(feature = \"sqlx_sqlite\")] mod _inner {\n//!    # use rocket::{get, response::Responder};\n//!    # use rocket_db_pools::{sqlx, Database};\n//!    # #[derive(Database)]\n//!    # #[database(\"sqlite_logs\")]\n//!    # struct Logs(sqlx::SqlitePool);\n//!    #\n//!    # #[derive(Responder)]\n//!    # struct Log(String);\n//!    #\n//!    use rocket_db_pools::Connection;\n//!    use rocket_db_pools::sqlx::Row;\n//!\n//!    #[get(\"/<id>\")]\n//!    async fn read(mut db: Connection<Logs>, id: i64) -> Option<Log> {\n//!        sqlx::query(\"SELECT content FROM logs WHERE id = ?\").bind(id)\n//!            .fetch_one(&mut **db).await\n//!            .and_then(|r| Ok(Log(r.try_get(0)?)))\n//!            .ok()\n//!    }\n//!    # }\n//!    ```\n//!\n//!    Alternatively, use a reference to the database type as a request guard to\n//!    retrieve the entire pool, but note that unlike retrieving a `Connection`,\n//!    doing so does _not_ guarantee that a connection is available:\n//!\n//!    ```rust\n//!    # #[cfg(feature = \"sqlx_sqlite\")] mod _inner {\n//!    # use rocket::{get, response::Responder};\n//!    # use rocket_db_pools::{sqlx, Database};\n//!    # #[derive(Database)]\n//!    # #[database(\"sqlite_logs\")]\n//!    # struct Logs(sqlx::SqlitePool);\n//!    #\n//!    # #[derive(Responder)]\n//!    # struct Log(String);\n//!    #\n//!    use rocket_db_pools::sqlx::Row;\n//!\n//!    #[get(\"/<id>\")]\n//!    async fn read(db: &Logs, id: i64) -> Option<Log> {\n//!        sqlx::query(\"SELECT content FROM logs WHERE id = ?\").bind(id)\n//!            .fetch_one(&db.0).await\n//!            .and_then(|r| Ok(Log(r.try_get(0)?)))\n//!            .ok()\n//!    }\n//!    # }\n//!    ```\n//!\n//! # Supported Drivers\n//!\n//! At present, this crate supports _four_ drivers: [`deadpool`], [`sqlx`],\n//! [`mongodb`], and [`diesel`]. Each driver may support multiple databases.\n//! Drivers have a varying degree of support for graceful shutdown, affected by\n//! the `Type::init()` fairing on Rocket shutdown.\n//!\n//! ## `deadpool` (v0.12)\n//!\n//! | Database | Feature                     | [`Pool`] Type               | [`Connection`] Deref                 |\n//! |----------|-----------------------------|-----------------------------|--------------------------------------|\n//! | Postgres | `deadpool_postgres` (v0.14) | [`deadpool_postgres::Pool`] | [`deadpool_postgres::ClientWrapper`] |\n//! | Redis    | `deadpool_redis` (v0.16)    | [`deadpool_redis::Pool`]    | [`deadpool_redis::Connection`]       |\n//!\n//! On shutdown, new connections are denied. Shutdown _does not_ wait for\n//! connections to be returned.\n//!\n//! ## `sqlx` (v0.7)\n//!\n//! | Database | Feature         | [`Pool`] Type        | [`Connection`] Deref                     |\n//! |----------|-----------------|----------------------|------------------------------------------|\n//! | Postgres | `sqlx_postgres` | [`sqlx::PgPool`]     | [`sqlx::pool::PoolConnection<Postgres>`] |\n//! | MySQL    | `sqlx_mysql`    | [`sqlx::MySqlPool`]  | [`sqlx::pool::PoolConnection<MySql>`]    |\n//! | SQLite   | `sqlx_sqlite`   | [`sqlx::SqlitePool`] | [`sqlx::pool::PoolConnection<Sqlite>`]   |\n//!\n//! [`sqlx::PgPool`]: https://docs.rs/sqlx/0.6/sqlx/type.PgPool.html\n//! [`sqlx::MySqlPool`]: https://docs.rs/sqlx/0.6/sqlx/type.MySqlPool.html\n//! [`sqlx::SqlitePool`]: https://docs.rs/sqlx/0.6/sqlx/type.SqlitePool.html\n//! [`sqlx::pool::PoolConnection<Postgres>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html\n//! [`sqlx::pool::PoolConnection<MySql>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html\n//! [`sqlx::pool::PoolConnection<Sqlite>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html\n//!\n//! On shutdown, new connections are denied. Shutdown waits for connections to\n//! be returned.\n//!\n//! ## `mongodb` (v3)\n//!\n//! | Database | Feature   | [`Pool`] Type and [`Connection`] Deref |\n//! |----------|-----------|----------------------------------------|\n//! | MongoDB  | `mongodb` | [`mongodb::Client`]                    |\n//!\n//! Graceful shutdown is not supported.\n//!\n//! ## `diesel` (v2)\n//!\n//! | Database | Feature           | [`Pool`] Type         | [`Connection`] Deref             |\n//! |----------|-------------------|-----------------------|----------------------------------|\n//! | Postgres | `diesel_postgres` | [`diesel::PgPool`]    | [`diesel::AsyncPgConnection`]    |\n//! | MySQL    | `diesel_mysql`    | [`diesel::MysqlPool`] | [`diesel::AsyncMysqlConnection`] | //!\n//!\n//! See [`diesel`] for usage details.\n//!\n//! On shutdown, new connections are denied. Shutdown _does not_ wait for\n//! connections to be returned.\n//!\n//! ## Enabling Additional Driver Features\n//!\n//! Only the minimal features for each driver crate are enabled by\n//! `rocket_db_pools`. To use additional driver functionality exposed via its\n//! crate's features, you'll need to depend on the crate directly with those\n//! features enabled in `Cargo.toml`:\n//!\n//! ```toml\n//! [dependencies.sqlx]\n//! version = \"0.7\"\n//! default-features = false\n//! features = [\"macros\", \"migrate\"]\n//!\n//! [dependencies.rocket_db_pools]\n//! version = \"0.1.0\"\n//! features = [\"sqlx_sqlite\"]\n//! ```\n//!\n//! # Configuration\n//!\n//! Configuration for a database named `db_name` is deserialized from a\n//! `databases.db_name` configuration parameter into a [`Config`] structure via\n//! Rocket's [configuration facilities](rocket::config). By default,\n//! configuration can be provided in `Rocket.toml`:\n//!\n//! ```toml\n//! [default.databases.db_name]\n//! url = \"db.sqlite\"\n//!\n//! # Only `url` is required. These have sane defaults and are optional.\n//! min_connections = 64\n//! max_connections = 1024\n//! connect_timeout = 5\n//! idle_timeout = 120\n//!\n//! # This option is only supported by the `sqlx_sqlite` driver.\n//! extensions = [\"memvfs\", \"rot13\"]\n//! ```\n//!\n//! Or via environment variables:\n//!\n//! ```sh\n//! ROCKET_DATABASES='{db_name={url=\"db.sqlite\",idle_timeout=120}}'\n//! ```\n//!\n//! See [`Config`] for details on configuration parameters.\n//!\n//! **Note:** `deadpool` and `diesel` drivers do not support and thus ignore the\n//! `min_connections` value.\n//!\n//! ## Driver Defaults\n//!\n//! Some drivers provide configuration defaults different from the underlying\n//! database's defaults. A best-effort attempt is made to document those\n//! differences below:\n//!\n//! * `sqlx_sqlite`\n//!\n//!   - foreign keys   : `enabled`\n//!   - journal mode   : `WAL`\n//!   - create-missing :  `enabled`\n//!   - synchronous    : `full` (even when `WAL`)\n//!   - busy timeout   : `connection_timeout`\n//!\n//! * `sqlx_postgres`\n//!\n//!   - sslmode                  : `prefer`\n//!   - statement-cache-capacity : `100`\n//!   - user                     : result of `whoami`\n//!\n//! * `sqlx_mysql`\n//!\n//!   - sslmode                  : `PREFERRED`\n//!   - statement-cache-capacity : `100`\n//!\n//! # Extending\n//!\n//! Any database driver can implement support for this library by implementing\n//! the [`Pool`] trait.\n\n#![doc(html_root_url = \"https://api.rocket.rs/master/rocket_db_pools\")]\n#![doc(html_favicon_url = \"https://rocket.rs/images/favicon.ico\")]\n#![doc(html_logo_url = \"https://rocket.rs/images/logo-boxed.png\")]\n\n#![deny(missing_docs)]\n\npub use rocket;\n\n/// Re-export of the `figment` crate.\n#[doc(inline)]\npub use rocket::figment;\n\n#[cfg(any(feature = \"diesel_postgres\", feature = \"diesel_mysql\"))] pub mod diesel;\n#[cfg(feature = \"deadpool_postgres\")] pub use deadpool_postgres;\n#[cfg(feature = \"deadpool_redis\")] pub use deadpool_redis;\n#[cfg(feature = \"mongodb\")] pub use mongodb;\n#[cfg(feature = \"sqlx\")] pub use sqlx;\n\nmod database;\nmod error;\nmod pool;\nmod config;\n\npub use self::database::{Connection, Database, Initializer};\npub use self::error::Error;\npub use self::pool::Pool;\npub use self::config::Config;\n\npub use rocket_db_pools_codegen::*;\n"
  },
  {
    "path": "contrib/db_pools/lib/src/pool.rs",
    "content": "use rocket::figment::Figment;\n\n#[allow(unused_imports)]\nuse {std::time::Duration, crate::{Error, Config}};\n\n/// Generic [`Database`](crate::Database) driver connection pool trait.\n///\n/// This trait provides a generic interface to various database pooling\n/// implementations in the Rust ecosystem. It can be implemented by anyone, but\n/// this crate provides implementations for common drivers.\n///\n/// **Implementations of this trait outside of this crate should be rare. You\n/// _do not_ need to implement this trait or understand its specifics to use\n/// this crate.**\n///\n/// ## Async Trait\n///\n/// [`Pool`] is an _async_ trait. Implementations of `Pool` must be decorated\n/// with an attribute of `#[async_trait]`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::figment::Figment;\n/// use rocket_db_pools::Pool;\n///\n/// # struct MyPool;\n/// # type Connection = ();\n/// # type Error = std::convert::Infallible;\n/// #[rocket::async_trait]\n/// impl Pool for MyPool {\n///     type Connection = Connection;\n///\n///     type Error = Error;\n///\n///     async fn init(figment: &Figment) -> Result<Self, Self::Error> {\n///         todo!(\"initialize and return an instance of the pool\");\n///     }\n///\n///     async fn get(&self) -> Result<Self::Connection, Self::Error> {\n///         todo!(\"fetch one connection from the pool\");\n///     }\n///\n///     async fn close(&self) {\n///         todo!(\"gracefully shutdown connection pool\");\n///     }\n/// }\n/// ```\n///\n/// ## Implementing\n///\n/// Implementations of `Pool` typically trace the following outline:\n///\n///   1. The `Error` associated type is set to [`Error`].\n///\n///   2. A [`Config`] is [extracted](Figment::extract()) from the `figment`\n///      passed to init.\n///\n///   3. The pool is initialized and returned in `init()`, wrapping\n///      initialization errors in [`Error::Init`].\n///\n///   4. A connection is retrieved in `get()`, wrapping errors in\n///      [`Error::Get`].\n///\n/// Concretely, this looks like:\n///\n/// ```rust\n/// use rocket::figment::Figment;\n/// use rocket_db_pools::{Pool, Config, Error};\n/// #\n/// # type InitError = std::convert::Infallible;\n/// # type GetError = std::convert::Infallible;\n/// # type Connection = ();\n/// #\n/// # struct MyPool(Config);\n/// # impl MyPool {\n/// #    fn new(c: Config) -> Result<Self, InitError> {\n/// #        Ok(Self(c))\n/// #    }\n/// #\n/// #    fn acquire(&self) -> Result<Connection, GetError> {\n/// #        Ok(())\n/// #    }\n/// #\n/// #   async fn shutdown(&self) { }\n/// # }\n///\n/// #[rocket::async_trait]\n/// impl Pool for MyPool {\n///     type Connection = Connection;\n///\n///     type Error = Error<InitError, GetError>;\n///\n///     async fn init(figment: &Figment) -> Result<Self, Self::Error> {\n///         // Extract the config from `figment`.\n///         let config: Config = figment.extract()?;\n///\n///         // Read config values, initialize `MyPool`. Map errors of type\n///         // `InitError` to `Error<InitError, _>` with `Error::Init`.\n///         let pool = MyPool::new(config).map_err(Error::Init)?;\n///\n///         // Return the fully initialized pool.\n///         Ok(pool)\n///     }\n///\n///     async fn get(&self) -> Result<Self::Connection, Self::Error> {\n///         // Get one connection from the pool, here via an `acquire()` method.\n///         // Map errors of type `GetError` to `Error<_, GetError>`.\n///         self.acquire().map_err(Error::Get)\n///     }\n///\n///     async fn close(&self) {\n///         self.shutdown().await;\n///     }\n/// }\n/// ```\n#[rocket::async_trait]\npub trait Pool: Sized + Send + 'static {\n    /// The connection type managed by this pool, returned by [`Self::get()`].\n    type Connection;\n\n    /// The error type returned by [`Self::init()`] and [`Self::get()`].\n    type Error: std::error::Error;\n\n    /// Constructs a pool from a [Value](rocket::figment::value::Value).\n    ///\n    /// It is up to each implementor of `Pool` to define its accepted\n    /// configuration value(s) via the `Config` associated type.  Most\n    /// integrations provided in `rocket_db_pools` use [`Config`], which\n    /// accepts a (required) `url` and an (optional) `pool_size`.\n    ///\n    /// ## Errors\n    ///\n    /// This method returns an error if the configuration is not compatible, or\n    /// if creating a pool failed due to an unavailable database server,\n    /// insufficient resources, or another database-specific error.\n    async fn init(figment: &Figment) -> Result<Self, Self::Error>;\n\n    /// Asynchronously retrieves a connection from the factory or pool.\n    ///\n    /// ## Errors\n    ///\n    /// This method returns an error if a connection could not be retrieved,\n    /// such as a preconfigured timeout elapsing or when the database server is\n    /// unavailable.\n    async fn get(&self) -> Result<Self::Connection, Self::Error>;\n\n    /// Shutdown the connection pool, disallowing any new connections from being\n    /// retrieved and waking up any tasks with active connections.\n    ///\n    /// The returned future may either resolve when all connections are known to\n    /// have closed or at any point prior. Details are implementation specific.\n    async fn close(&self);\n}\n\n#[cfg(feature = \"deadpool\")]\nmod deadpool_postgres {\n    use deadpool::{Runtime, managed::{Manager, Pool, PoolError, Object}};\n    use super::{Duration, Error, Config, Figment};\n\n    #[cfg(feature = \"diesel\")]\n    use diesel_async::pooled_connection::AsyncDieselConnectionManager;\n\n    pub trait DeadManager: Manager + Sized + Send + 'static {\n        fn new(config: &Config) -> Result<Self, Self::Error>;\n    }\n\n    #[cfg(feature = \"deadpool_postgres\")]\n    impl DeadManager for deadpool_postgres::Manager {\n        fn new(config: &Config) -> Result<Self, Self::Error> {\n            Ok(Self::new(config.url.parse()?, deadpool_postgres::tokio_postgres::NoTls))\n        }\n    }\n\n    #[cfg(feature = \"deadpool_redis\")]\n    impl DeadManager for deadpool_redis::Manager {\n        fn new(config: &Config) -> Result<Self, Self::Error> {\n            Self::new(config.url.as_str())\n        }\n    }\n\n    #[cfg(feature = \"diesel_postgres\")]\n    impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncPgConnection> {\n        fn new(config: &Config) -> Result<Self, Self::Error> {\n            Ok(Self::new(config.url.as_str()))\n        }\n    }\n\n    #[cfg(feature = \"diesel_mysql\")]\n    impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncMysqlConnection> {\n        fn new(config: &Config) -> Result<Self, Self::Error> {\n            Ok(Self::new(config.url.as_str()))\n        }\n    }\n\n    #[rocket::async_trait]\n    impl<M: DeadManager, C: From<Object<M>>> crate::Pool for Pool<M, C>\n        where M::Type: Send, C: Send + 'static, M::Error: std::error::Error\n    {\n        type Error = Error<PoolError<M::Error>>;\n\n        type Connection = C;\n\n        async fn init(figment: &Figment) -> Result<Self, Self::Error> {\n            let config: Config = figment.extract()?;\n            let manager = M::new(&config).map_err(|e| Error::Init(e.into()))?;\n\n            Pool::builder(manager)\n                .max_size(config.max_connections)\n                .wait_timeout(Some(Duration::from_secs(config.connect_timeout)))\n                .create_timeout(Some(Duration::from_secs(config.connect_timeout)))\n                .recycle_timeout(config.idle_timeout.map(Duration::from_secs))\n                .runtime(Runtime::Tokio1)\n                .build()\n                .map_err(|_| Error::Init(PoolError::NoRuntimeSpecified))\n        }\n\n        async fn get(&self) -> Result<Self::Connection, Self::Error> {\n            self.get().await.map_err(Error::Get)\n        }\n\n        async fn close(&self) {\n            <Pool<M, C>>::close(self)\n        }\n    }\n}\n\n#[cfg(feature = \"sqlx\")]\nmod sqlx {\n    use sqlx::ConnectOptions;\n    use super::{Duration, Error, Config, Figment};\n    use rocket::tracing::level_filters::LevelFilter;\n\n    type Options<D> = <<D as sqlx::Database>::Connection as sqlx::Connection>::Options;\n\n    // Provide specialized configuration for particular databases.\n    fn specialize(__options: &mut dyn std::any::Any, __config: &Config) {\n        #[cfg(feature = \"sqlx_sqlite\")]\n        if let Some(o) = __options.downcast_mut::<sqlx::sqlite::SqliteConnectOptions>() {\n            *o = std::mem::take(o)\n                .busy_timeout(Duration::from_secs(__config.connect_timeout))\n                .create_if_missing(true);\n\n            if let Some(ref exts) = __config.extensions {\n                for ext in exts {\n                    *o = std::mem::take(o).extension(ext.clone());\n                }\n            }\n        }\n    }\n\n    #[rocket::async_trait]\n    impl<D: sqlx::Database> crate::Pool for sqlx::Pool<D> {\n        type Error = Error<sqlx::Error>;\n\n        type Connection = sqlx::pool::PoolConnection<D>;\n\n        async fn init(figment: &Figment) -> Result<Self, Self::Error> {\n            let config = figment.extract::<Config>()?;\n            let mut opts = config.url.parse::<Options<D>>().map_err(Error::Init)?;\n            specialize(&mut opts, &config);\n\n            opts = opts.disable_statement_logging();\n            if let Ok(value) = figment.find_value(rocket::Config::LOG_LEVEL) {\n                if let Some(level) = value.as_str().and_then(|v| v.parse().ok()) {\n                    let log_level = match level {\n                        LevelFilter::OFF => log::LevelFilter::Off,\n                        LevelFilter::ERROR => log::LevelFilter::Error,\n                        LevelFilter::WARN => log::LevelFilter::Warn,\n                        LevelFilter::INFO => log::LevelFilter::Info,\n                        LevelFilter::DEBUG => log::LevelFilter::Debug,\n                        LevelFilter::TRACE => log::LevelFilter::Trace,\n                    };\n\n                    opts = opts.log_statements(log_level)\n                        .log_slow_statements(log_level, Duration::default());\n                }\n            }\n\n            Ok(sqlx::pool::PoolOptions::new()\n                .max_connections(config.max_connections as u32)\n                .acquire_timeout(Duration::from_secs(config.connect_timeout))\n                .idle_timeout(config.idle_timeout.map(Duration::from_secs))\n                .min_connections(config.min_connections.unwrap_or_default())\n                .connect_lazy_with(opts))\n        }\n\n        async fn get(&self) -> Result<Self::Connection, Self::Error> {\n            self.acquire().await.map_err(Error::Get)\n        }\n\n        async fn close(&self) {\n            <sqlx::Pool<D>>::close(self).await;\n        }\n    }\n}\n\n#[cfg(feature = \"mongodb\")]\nmod mongodb {\n    use mongodb::{Client, options::ClientOptions};\n    use super::{Duration, Error, Config, Figment};\n\n    #[rocket::async_trait]\n    impl crate::Pool for Client {\n        type Error = Error<mongodb::error::Error, std::convert::Infallible>;\n\n        type Connection = Client;\n\n        async fn init(figment: &Figment) -> Result<Self, Self::Error> {\n            let config = figment.extract::<Config>()?;\n            let mut opts = ClientOptions::parse(&config.url).await.map_err(Error::Init)?;\n            opts.min_pool_size = config.min_connections;\n            opts.max_pool_size = Some(config.max_connections as u32);\n            opts.max_idle_time = config.idle_timeout.map(Duration::from_secs);\n            opts.connect_timeout = Some(Duration::from_secs(config.connect_timeout));\n            opts.server_selection_timeout = Some(Duration::from_secs(config.connect_timeout));\n            Client::with_options(opts).map_err(Error::Init)\n        }\n\n        async fn get(&self) -> Result<Self::Connection, Self::Error> {\n            Ok(self.clone())\n        }\n\n        async fn close(&self) {\n            // nothing to do for mongodb\n        }\n    }\n}\n"
  },
  {
    "path": "contrib/db_pools/lib/tests/databases.rs",
    "content": "macro_rules! check_types_match {\n    ($feature:expr, $name:ident, $Pool:ty, $Conn:ty $(,)?) => (\n        #[cfg(feature = $feature)]\n        mod $name {\n            use rocket::*;\n            use rocket_db_pools::{Connection, Database};\n\n            #[derive(Database)]\n            #[database(\"foo\")]\n            struct Db($Pool);\n\n            #[get(\"/\")]\n            fn _db(conn: Connection<Db>) {\n                let _: &$Conn = &*conn;\n            }\n        }\n    )\n}\n\ncheck_types_match!(\n    \"deadpool_postgres\",\n    deadpool_postgres,\n    deadpool_postgres::Pool,\n    deadpool_postgres::ClientWrapper,\n);\n\ncheck_types_match!(\n    \"deadpool_redis\",\n    deadpool_redis,\n    deadpool_redis::Pool,\n    deadpool_redis::Connection,\n);\n\ncheck_types_match!(\n    \"sqlx_postgres\",\n    sqlx_postgres,\n    sqlx::PgPool,\n    sqlx::pool::PoolConnection<sqlx::Postgres>,\n);\n\ncheck_types_match!(\n    \"sqlx_mysql\",\n    sqlx_mysql,\n    sqlx::MySqlPool,\n    sqlx::pool::PoolConnection<sqlx::MySql>,\n);\n\ncheck_types_match!(\n    \"sqlx_sqlite\",\n    sqlx_sqlite,\n    sqlx::SqlitePool,\n    sqlx::pool::PoolConnection<sqlx::Sqlite>,\n);\n\ncheck_types_match!(\n    \"mongodb\",\n    mongodb,\n    mongodb::Client,\n    mongodb::Client,\n);\n"
  },
  {
    "path": "contrib/dyn_templates/Cargo.toml",
    "content": "[package]\nname = \"rocket_dyn_templates\"\nversion = \"0.1.0\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\"]\ndescription = \"Dynamic templating engine integration for Rocket.\"\ndocumentation = \"https://api.rocket.rs/master/rocket_dyn_templates/\"\nhomepage = \"https://rocket.rs\"\nrepository = \"https://github.com/rwf2/Rocket/tree/master/contrib/dyn_templates\"\nreadme = \"README.md\"\nkeywords = [\"rocket\", \"framework\", \"templates\", \"templating\", \"engine\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[lints]\nworkspace = true\n\n[features]\ntera = [\"dep:tera\"]\nhandlebars = [\"dep:handlebars\"]\nminijinja = [\"dep:minijinja\"]\n\n[dependencies]\nwalkdir = \"2.4\"\nnotify = \"7\"\nnormpath = \"1\"\n\ntera = { version = \"1.19.0\", optional = true }\nhandlebars = { version = \"6.0\", optional = true }\n\n[dependencies.minijinja]\nversion = \"2.0.1\"\noptional = true\nfeatures = [\"loader\", \"speedups\", \"json\", \"urlencode\"]\n\n[dependencies.rocket]\nversion = \"0.6.0-dev\"\npath = \"../../core/lib\"\ndefault-features = false\n\n[dev-dependencies]\npretty_assertions = \"1.4\"\n\n[package.metadata.docs.rs]\nall-features = true\n"
  },
  {
    "path": "contrib/dyn_templates/README.md",
    "content": "# `dyn_templates` [![ci.svg]][ci] [![crates.io]][crate] [![docs.svg]][crate docs]\n\n[crates.io]: https://img.shields.io/crates/v/rocket_dyn_templates.svg\n[crate]: https://crates.io/crates/rocket_dyn_templates\n[docs.svg]: https://img.shields.io/badge/web-master-red.svg?style=flat&label=docs&colorB=d33847\n[crate docs]: https://api.rocket.rs/master/rocket_dyn_templates\n[ci.svg]: https://github.com/rwf2/Rocket/workflows/CI/badge.svg\n[ci]: https://github.com/rwf2/Rocket/actions\n\nThis crate adds support for dynamic template rendering to Rocket. It\nautomatically discovers templates, provides a `Responder` to render templates,\nand automatically reloads templates when compiled in debug mode. It supports [Handlebars], [Tera] and [MiniJinja].\n\n[Tera]: https://docs.rs/crate/tera/1\n[Handlebars]: https://docs.rs/crate/handlebars/5\n[MiniJinja]: https://docs.rs/crate/minijinja/2.0.1\n\n# Usage\n\n  1. Enable the `rocket_dyn_templates` feature corresponding to your templating\n     engine(s) of choice:\n\n     ```toml\n     [dependencies.rocket_dyn_templates]\n     version = \"0.1.0\"\n     features = [\"handlebars\", \"tera\", \"minijinja\"]\n     ```\n\n  1. Write your template files in Handlebars (`.hbs`) and/or Tera (`.tera`) in\n     the configurable `template_dir` directory (default:\n     `{rocket_root}/templates`).\n\n  2. Attach `Template::fairing()` and return a `Template` using\n     `Template::render()`, supplying the name of the template file **minus the\n     last two extensions**:\n\n     ```rust\n     use rocket_dyn_templates::{Template, context};\n\n     #[get(\"/\")]\n     fn index() -> Template {\n         Template::render(\"template-name\", context! { field: \"value\" })\n     }\n\n     #[launch]\n     fn rocket() -> _ {\n         rocket::build().attach(Template::fairing())\n     }\n     ```\n\nSee the [crate docs] for full details.\n"
  },
  {
    "path": "contrib/dyn_templates/src/context.rs",
    "content": "use std::path::{Path, PathBuf};\nuse std::collections::HashMap;\nuse std::error::Error;\n\nuse crate::engine::Engines;\nuse crate::template::TemplateInfo;\n\nuse rocket::http::ContentType;\nuse normpath::PathExt;\n\npub(crate) type Callback =\n    Box<dyn Fn(&mut Engines) -> Result<(), Box<dyn Error>> + Send + Sync + 'static>;\n\npub(crate) struct Context {\n    /// The root of the template directory.\n    pub root: PathBuf,\n    /// Mapping from template name to its information.\n    pub templates: HashMap<String, TemplateInfo>,\n    /// Loaded template engines\n    pub engines: Engines,\n}\n\npub(crate) use self::manager::ContextManager;\n\nimpl Context {\n    /// Load all of the templates at `root`, initialize them using the relevant\n    /// template engine, and store all of the initialized state in a `Context`\n    /// structure, which is returned if all goes well.\n    pub fn initialize(root: &Path, callback: &Callback) -> Option<Context> {\n        fn is_file_with_ext(entry: &walkdir::DirEntry, ext: &str) -> bool {\n            let is_file = entry.file_type().is_file();\n            let has_ext = entry.path().extension().map_or(false, |e| e == ext);\n            is_file && has_ext\n        }\n\n        let root = match root.normalize() {\n            Ok(root) => root.into_path_buf(),\n            Err(e) => {\n                error!(\"Invalid template directory '{}': {}.\", root.display(), e);\n                return None;\n            }\n        };\n\n        let mut templates: HashMap<String, TemplateInfo> = HashMap::new();\n        for &ext in Engines::ENABLED_EXTENSIONS {\n            for entry in walkdir::WalkDir::new(&root).follow_links(true) {\n                let entry = match entry {\n                    Ok(entry) if is_file_with_ext(&entry, ext) => entry,\n                    Ok(_) | Err(_) => continue,\n                };\n\n                let (template, data_type_str) = split_path(&root, entry.path());\n                if let Some(info) = templates.get(&*template) {\n                    warn!(\n                        %template,\n                        first_path = %entry.path().display(),\n                        second_path = info.path.as_ref().map(|p| display(p.display())),\n                        data_type = %info.data_type,\n                        \"Template name '{template}' can refer to multiple templates.\\n\\\n                         First path will be used. Second path is ignored.\"\n                    );\n\n                    continue;\n                }\n\n                let data_type = data_type_str.as_ref()\n                    .and_then(|ext| ContentType::from_extension(ext))\n                    .unwrap_or(ContentType::Text);\n\n                templates.insert(template, TemplateInfo {\n                    path: Some(entry.into_path()),\n                    engine_ext: ext,\n                    data_type,\n                });\n            }\n        }\n\n        let mut engines = Engines::init(&templates)?;\n        if let Err(reason) = callback(&mut engines) {\n            error!(%reason, \"template customization callback failed\");\n            return None;\n        }\n\n        for (name, engine_ext) in engines.templates() {\n            if !templates.contains_key(name) {\n                let data_type = Path::new(name).extension()\n                    .and_then(|osstr| osstr.to_str())\n                    .and_then(ContentType::from_extension)\n                    .unwrap_or(ContentType::Text);\n\n                let info = TemplateInfo { path: None, engine_ext, data_type };\n                templates.insert(name.to_string(), info);\n            }\n        }\n\n        Some(Context { root, templates, engines })\n    }\n}\n\n#[cfg(not(debug_assertions))]\nmod manager {\n    use std::ops::Deref;\n    use super::Context;\n\n    /// Wraps a Context. With `cfg(debug_assertions)` active, this structure\n    /// additionally provides a method to reload the context at runtime.\n    pub(crate) struct ContextManager(Context);\n\n    impl ContextManager {\n        pub fn new(ctxt: Context) -> ContextManager {\n            ContextManager(ctxt)\n        }\n\n        pub fn context<'a>(&'a self) -> impl Deref<Target=Context> + 'a {\n            &self.0\n        }\n\n        pub fn is_reloading(&self) -> bool {\n            false\n        }\n    }\n}\n\n#[cfg(debug_assertions)]\nmod manager {\n    use std::ops::{Deref, DerefMut};\n    use std::sync::{RwLock, Mutex};\n    use std::sync::mpsc::{channel, Receiver};\n\n    use notify::{recommended_watcher, Error, Event, RecommendedWatcher, RecursiveMode, Watcher};\n\n    use super::{Callback, Context};\n\n    /// Wraps a Context. With `cfg(debug_assertions)` active, this structure\n    /// additionally provides a method to reload the context at runtime.\n    pub(crate) struct ContextManager {\n        /// The current template context, inside an RwLock so it can be updated.\n        context: RwLock<Context>,\n        /// A filesystem watcher and the receive queue for its events.\n        watcher: Option<(RecommendedWatcher, Mutex<Receiver<Result<Event, Error>>>)>,\n    }\n\n    impl ContextManager {\n        pub fn new(ctxt: Context) -> ContextManager {\n            let (tx, rx) = channel();\n            let watcher = recommended_watcher(tx).and_then(|mut watcher| {\n                watcher.watch(&ctxt.root.canonicalize()?, RecursiveMode::Recursive)?;\n                Ok(watcher)\n            });\n\n            let watcher = match watcher {\n                Ok(watcher) => Some((watcher, Mutex::new(rx))),\n                Err(e) => {\n                    warn!(\"live template reloading initialization failed: {e}\\n\\\n                        live template reloading is unavailable\");\n                    None\n                }\n            };\n\n            ContextManager { watcher, context: RwLock::new(ctxt), }\n        }\n\n        pub fn context(&self) -> impl Deref<Target=Context> + '_ {\n            self.context.read().unwrap()\n        }\n\n        pub fn is_reloading(&self) -> bool {\n            self.watcher.is_some()\n        }\n\n        fn context_mut(&self) -> impl DerefMut<Target=Context> + '_ {\n            self.context.write().unwrap()\n        }\n\n        /// Checks whether any template files have changed on disk. If there\n        /// have been changes since the last reload, all templates are\n        /// reinitialized from disk and the user's customization callback is run\n        /// again.\n        pub fn reload_if_needed(&self, callback: &Callback) {\n            let templates_changes = self.watcher.as_ref()\n                .map(|(_, rx)| rx.lock().expect(\"fsevents lock\").try_iter().count() > 0);\n\n            if let Some(true) = templates_changes {\n                debug!(\"template change detected: reloading templates\");\n                let root = self.context().root.clone();\n                if let Some(new_ctxt) = Context::initialize(&root, callback) {\n                    *self.context_mut() = new_ctxt;\n                } else {\n                    warn!(\"error while reloading template\\n\\\n                        existing templates will remain active.\")\n                };\n            }\n        }\n    }\n}\n\n/// Removes the file path's extension or does nothing if there is none.\nfn remove_extension(path: &Path) -> PathBuf {\n    let stem = match path.file_stem() {\n        Some(stem) => stem,\n        None => return path.to_path_buf()\n    };\n\n    match path.parent() {\n        Some(parent) => parent.join(stem),\n        None => PathBuf::from(stem)\n    }\n}\n\n/// Splits a path into a name that may be used to identify the template, and the\n/// template's data type, if any.\nfn split_path(root: &Path, path: &Path) -> (String, Option<String>) {\n    let rel_path = path.strip_prefix(root).unwrap().to_path_buf();\n    let path_no_ext = remove_extension(&rel_path);\n    let data_type = path_no_ext.extension();\n    let mut name = remove_extension(&path_no_ext).to_string_lossy().into_owned();\n\n    // Ensure template name consistency on Windows systems\n    if cfg!(windows) {\n        name = name.replace('\\\\', \"/\");\n    }\n\n    (name, data_type.map(|d| d.to_string_lossy().into_owned()))\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn template_path_index_html() {\n        for root in &[\"/\", \"/a/b/c/\", \"/a/b/c/d/\", \"/a/\"] {\n            for filename in &[\"index.html.hbs\", \"index.html.tera\"] {\n                let path = Path::new(root).join(filename);\n                let (name, data_type) = split_path(Path::new(root), &path);\n\n                assert_eq!(name, \"index\");\n                assert_eq!(data_type, Some(\"html\".into()));\n            }\n        }\n    }\n\n    #[test]\n    fn template_path_subdir_index_html() {\n        for root in &[\"/\", \"/a/b/c/\", \"/a/b/c/d/\", \"/a/\"] {\n            for sub in &[\"a/\", \"a/b/\", \"a/b/c/\", \"a/b/c/d/\"] {\n                for filename in &[\"index.html.hbs\", \"index.html.tera\"] {\n                    let path = Path::new(root).join(sub).join(filename);\n                    let (name, data_type) = split_path(Path::new(root), &path);\n\n                    let expected_name = format!(\"{}index\", sub);\n                    assert_eq!(name, expected_name.as_str());\n                    assert_eq!(data_type, Some(\"html\".into()));\n                }\n            }\n        }\n    }\n\n    #[test]\n    fn template_path_doc_examples() {\n        fn name_for(path: &str) -> String {\n            split_path(Path::new(\"templates/\"), &Path::new(\"templates/\").join(path)).0\n        }\n\n        assert_eq!(name_for(\"index.html.hbs\"), \"index\");\n        assert_eq!(name_for(\"index.tera\"), \"index\");\n        assert_eq!(name_for(\"index.hbs\"), \"index\");\n        assert_eq!(name_for(\"dir/index.hbs\"), \"dir/index\");\n        assert_eq!(name_for(\"dir/index.html.tera\"), \"dir/index\");\n        assert_eq!(name_for(\"index.template.html.hbs\"), \"index.template\");\n        assert_eq!(name_for(\"subdir/index.template.html.hbs\"), \"subdir/index.template\");\n    }\n}\n"
  },
  {
    "path": "contrib/dyn_templates/src/engine/handlebars.rs",
    "content": "use std::path::Path;\n\nuse handlebars::Handlebars;\nuse rocket::serde::Serialize;\n\nuse crate::engine::Engine;\n\nimpl Engine for Handlebars<'static> {\n    const EXT: &'static str = \"hbs\";\n\n    fn init<'a>(templates: impl Iterator<Item = (&'a str, &'a Path)>) -> Option<Self> {\n        let mut hb = Handlebars::new();\n        let mut ok = true;\n        for (template, path) in templates {\n            if let Err(e) = hb.register_template_file(template, path) {\n                error!(template, path = %path.display(),\n                    \"failed to register Handlebars template: {e}\");\n\n                ok = false;\n            }\n        }\n\n        ok.then_some(hb)\n    }\n\n    fn render<C: Serialize>(&self, template: &str, context: C) -> Option<String> {\n        if self.get_template(template).is_none() {\n            error!(template, \"requested Handlebars template does not exist.\");\n            return None;\n        }\n\n        Handlebars::render(self, template, &context)\n            .map_err(|e| error!(\"Handlebars render error: {}\", e))\n            .ok()\n    }\n}\n"
  },
  {
    "path": "contrib/dyn_templates/src/engine/minijinja.rs",
    "content": "use std::sync::Arc;\nuse std::path::Path;\nuse std::collections::HashMap;\n\nuse rocket::serde::Serialize;\nuse minijinja::{Environment, Error, ErrorKind, AutoEscape};\n\nuse crate::engine::Engine;\n\nimpl Engine for Environment<'static> {\n    const EXT: &'static str = \"j2\";\n\n    fn init<'a>(templates: impl Iterator<Item = (&'a str, &'a Path)>) -> Option<Self> {\n        let _templates = Arc::new(templates\n            .map(|(k, p)| (k.to_owned(), p.to_owned()))\n            .collect::<HashMap<_, _>>());\n\n        let templates = _templates.clone();\n        let mut env = Environment::new();\n        env.set_loader(move |name| {\n            let Some(path) = templates.get(name) else {\n                return Ok(None);\n            };\n\n            match std::fs::read_to_string(path) {\n                Ok(result) => Ok(Some(result)),\n                Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),\n                Err(e) => Err(\n                    Error::new(ErrorKind::InvalidOperation, \"template read failed\").with_source(e)\n                ),\n            }\n        });\n\n        let templates = _templates.clone();\n        env.set_auto_escape_callback(move |name| {\n            templates.get(name)\n                .and_then(|path| path.to_str())\n                .map(minijinja::default_auto_escape_callback)\n                .unwrap_or(AutoEscape::None)\n        });\n\n        Some(env)\n    }\n\n    fn render<C: Serialize>(&self, template: &str, context: C) -> Option<String> {\n        let Ok(templ) = self.get_template(template) else {\n            error!(template, \"requested template does not exist\");\n            return None;\n        };\n\n        match templ.render(context) {\n            Ok(result) => Some(result),\n            Err(e) => {\n                span_error!(\"templating\", template, \"failed to render Minijinja template\" => {\n                    let mut error = Some(&e as &dyn std::error::Error);\n                    while let Some(err) = error {\n                        error!(\"{err}\");\n                        error = err.source();\n                    }\n                });\n\n                None\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "contrib/dyn_templates/src/engine/mod.rs",
    "content": "use std::path::Path;\nuse std::collections::HashMap;\n\nuse rocket::serde::Serialize;\n\nuse crate::template::TemplateInfo;\n\n#[cfg(feature = \"tera\")]\nmod tera;\n#[cfg(feature = \"tera\")]\nuse ::tera::Tera;\n\n#[cfg(feature = \"handlebars\")]\nmod handlebars;\n#[cfg(feature = \"handlebars\")]\nuse ::handlebars::Handlebars;\n\n#[cfg(feature = \"minijinja\")]\nmod minijinja;\n#[cfg(feature = \"minijinja\")]\nuse ::minijinja::Environment;\n\npub(crate) trait Engine: Send + Sync + Sized + 'static {\n    const EXT: &'static str;\n\n    fn init<'a>(templates: impl Iterator<Item = (&'a str, &'a Path)>) -> Option<Self>;\n    fn render<C: Serialize>(&self, name: &str, context: C) -> Option<String>;\n}\n\n/// A structure exposing access to templating engines.\n///\n/// Calling methods on the exposed template engine types may require importing\n/// types from the respective templating engine library. These types should be\n/// imported from the reexported crate at the root of `rocket_dyn_templates` to\n/// avoid version mismatches. For instance, when registering a Tera filter, the\n/// [`tera::Value`] and [`tera::Result`] types are required. Import them from\n/// `rocket_dyn_templates::tera`. The example below illustrates this:\n///\n/// ```rust\n/// # #[cfg(feature = \"tera\")] {\n/// use std::collections::HashMap;\n///\n/// use rocket_dyn_templates::{Template, Engines};\n/// use rocket_dyn_templates::tera::{self, Value};\n///\n/// fn my_filter(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> {\n///     # /*\n///     ...\n///     # */ unimplemented!();\n/// }\n///\n/// fn main() {\n///     rocket::build()\n///         // ...\n///         .attach(Template::custom(|engines: &mut Engines| {\n///             engines.tera.register_filter(\"my_filter\", my_filter);\n///         }))\n///         // ...\n///         # ;\n/// }\n/// # }\n/// ```\n///\n/// [`tera::Value`]: crate::tera::Value\n/// [`tera::Result`]: crate::tera::Result\npub struct Engines {\n    /// A `Tera` templating engine.\n    ///\n    /// This field is only available when the `tera` feature is enabled. When\n    /// calling methods on the `Tera` instance, ensure you use types imported\n    /// from `rocket_dyn_templates::tera` to avoid version mismatches.\n    #[cfg(feature = \"tera\")]\n    pub tera: Tera,\n\n    /// The Handlebars templating engine.\n    ///\n    /// This field is only available when the `handlebars` feature is enabled.\n    /// When calling methods on the `Handlebars` instance, ensure you use types\n    /// imported from `rocket_dyn_templates::handlebars` to avoid version\n    /// mismatches.\n    #[cfg(feature = \"handlebars\")]\n    pub handlebars: Handlebars<'static>,\n\n    /// The minijinja templating engine.\n    ///\n    /// This field is only available when the `minijinja` feature is enabled.\n    /// When calling methods on the [`Environment`] instance, ensure you use\n    /// types imported from `rocket_dyn_templates::minijinja` to avoid version\n    /// mismatches.\n    #[cfg(feature = \"minijinja\")]\n    pub minijinja: Environment<'static>,\n}\n\nimpl Engines {\n    pub(crate) const ENABLED_EXTENSIONS: &'static [&'static str] = &[\n        #[cfg(feature = \"tera\")] Tera::EXT,\n        #[cfg(feature = \"handlebars\")] Handlebars::EXT,\n        #[cfg(feature = \"minijinja\")] Environment::EXT,\n    ];\n\n    pub(crate) fn init(templates: &HashMap<String, TemplateInfo>) -> Option<Engines> {\n        fn inner<E: Engine>(templates: &HashMap<String, TemplateInfo>) -> Option<E> {\n            let named_templates = templates.iter()\n                .filter(|&(_, i)| i.engine_ext == E::EXT)\n                .filter_map(|(k, i)| Some((k.as_str(), i.path.as_ref()?)))\n                .map(|(k, p)| (k, p.as_path()));\n\n            E::init(named_templates)\n        }\n\n        Some(Engines {\n            #[cfg(feature = \"tera\")]\n            tera: match inner::<Tera>(templates) {\n                Some(tera) => tera,\n                None => return None\n            },\n            #[cfg(feature = \"handlebars\")]\n            handlebars: match inner::<Handlebars<'static>>(templates) {\n                Some(hb) => hb,\n                None => return None\n            },\n            #[cfg(feature = \"minijinja\")]\n            minijinja: match inner::<Environment<'static>>(templates) {\n                Some(hb) => hb,\n                None => return None\n            },\n        })\n    }\n\n    pub(crate) fn render<C: Serialize>(\n        &self,\n        name: &str,\n        info: &TemplateInfo,\n        context: C,\n    ) -> Option<String> {\n        #[cfg(feature = \"tera\")] {\n            if info.engine_ext == Tera::EXT {\n                return Engine::render(&self.tera, name, context);\n            }\n        }\n\n        #[cfg(feature = \"handlebars\")] {\n            if info.engine_ext == Handlebars::EXT {\n                return Engine::render(&self.handlebars, name, context);\n            }\n        }\n\n        #[cfg(feature = \"minijinja\")] {\n            if info.engine_ext == Environment::EXT {\n                return Engine::render(&self.minijinja, name, context);\n            }\n        }\n\n        None\n    }\n\n    /// Returns iterator over template (name, engine_extension).\n    pub(crate) fn templates(&self) -> impl Iterator<Item = (&str, &'static str)> {\n        #[cfg(feature = \"tera\")]\n        let tera = self.tera.get_template_names().map(|name| (name, Tera::EXT));\n\n        #[cfg(feature = \"handlebars\")]\n        let handlebars = self.handlebars.get_templates().keys()\n                .map(|name| (name.as_str(), Handlebars::EXT));\n\n        #[cfg(feature = \"minijinja\")]\n        let minijinja = self.minijinja.templates()\n            .map(|(name, _)| (name, Environment::EXT));\n\n        #[cfg(not(feature = \"tera\"))] let tera = std::iter::empty();\n        #[cfg(not(feature = \"handlebars\"))] let handlebars = std::iter::empty();\n        #[cfg(not(feature = \"minijinja\"))] let minijinja = std::iter::empty();\n\n        tera.chain(handlebars).chain(minijinja)\n    }\n}\n"
  },
  {
    "path": "contrib/dyn_templates/src/engine/tera.rs",
    "content": "use std::path::Path;\nuse std::error::Error;\n\nuse tera::{Context, Tera};\nuse rocket::serde::Serialize;\n\nuse crate::engine::Engine;\n\nimpl Engine for Tera {\n    const EXT: &'static str = \"tera\";\n\n    fn init<'a>(templates: impl Iterator<Item = (&'a str, &'a Path)>) -> Option<Self> {\n        // Create the Tera instance.\n        let mut tera = Tera::default();\n        let ext = [\".html.tera\", \".htm.tera\", \".xml.tera\", \".html\", \".htm\", \".xml\"];\n        tera.autoescape_on(ext.to_vec());\n\n        // Collect into a tuple of (name, path) for Tera. If we register one at\n        // a time, it will complain about unregistered base templates.\n        let files = templates.map(|(name, path)| (path, Some(name)));\n\n        // Finally try to tell Tera about all of the templates.\n        if let Err(e) = tera.add_template_files(files) {\n            span_error!(\"templating\", \"Tera templating initialization failed\" => {\n                let mut error = Some(&e as &dyn Error);\n                while let Some(err) = error {\n                    error!(\"{err}\");\n                    error = err.source();\n                }\n            });\n\n            None\n        } else {\n            Some(tera)\n        }\n    }\n\n    fn render<C: Serialize>(&self, template: &str, context: C) -> Option<String> {\n        if self.get_template(template).is_err() {\n            error!(template, \"requested template does not exist\");\n            return None;\n        };\n\n        let tera_ctx = Context::from_serialize(context)\n            .map_err(|e| error!(\"Tera context error: {}.\", e))\n            .ok()?;\n\n        match Tera::render(self, template, &tera_ctx) {\n            Ok(string) => Some(string),\n            Err(e) => {\n                span_error!(\"templating\", template, \"failed to render Tera template\" => {\n                    let mut error = Some(&e as &dyn Error);\n                    while let Some(err) = error {\n                        error!(\"{err}\");\n                        error = err.source();\n                    }\n                });\n\n                None\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "contrib/dyn_templates/src/fairing.rs",
    "content": "use rocket::{Rocket, Build, Orbit};\nuse rocket::fairing::{self, Fairing, Info, Kind};\nuse rocket::figment::{Source, value::magic::RelativePathBuf};\nuse rocket::trace::Trace;\n\nuse crate::context::{Callback, Context, ContextManager};\nuse crate::template::DEFAULT_TEMPLATE_DIR;\nuse crate::engine::Engines;\n\n/// The TemplateFairing initializes the template system on attach, running\n/// custom_callback after templates have been loaded. In debug mode, the fairing\n/// checks for modifications to templates before every request and reloads them\n/// if necessary.\npub struct TemplateFairing {\n    /// The user-provided customization callback, allowing the use of\n    /// functionality specific to individual template engines. In debug mode,\n    /// this callback might be run multiple times as templates are reloaded.\n    pub callback: Callback,\n}\n\n#[rocket::async_trait]\nimpl Fairing for TemplateFairing {\n    fn info(&self) -> Info {\n        let kind = Kind::Ignite | Kind::Liftoff;\n        #[cfg(debug_assertions)] let kind = kind | Kind::Request;\n\n        Info { kind, name: \"Templating\" }\n    }\n\n    /// Initializes the template context. Templates will be searched for in the\n    /// `template_dir` config variable or the default ([DEFAULT_TEMPLATE_DIR]).\n    /// The user's callback, if any was supplied, is called to customize the\n    /// template engines. In debug mode, the `ContextManager::new` method\n    /// initializes a directory watcher for auto-reloading of templates.\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {\n        let configured_dir = rocket.figment()\n            .extract_inner::<RelativePathBuf>(\"template_dir\")\n            .map(|path| path.relative());\n\n        let path = match configured_dir {\n            Ok(dir) => dir,\n            Err(e) if e.missing() => DEFAULT_TEMPLATE_DIR.into(),\n            Err(e) => {\n                e.trace_error();\n                return Err(rocket);\n            }\n        };\n\n        if let Some(ctxt) = Context::initialize(&path, &self.callback) {\n            Ok(rocket.manage(ContextManager::new(ctxt)))\n        } else {\n            error!(\"Template initialization failed. Aborting launch.\");\n            Err(rocket)\n        }\n    }\n\n    async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {\n        let cm = rocket.state::<ContextManager>()\n            .expect(\"Template ContextManager registered in on_ignite\");\n\n        span_info!(\"templating\" => {\n            info!(directory = %Source::from(&*cm.context().root));\n            info!(engines = ?Engines::ENABLED_EXTENSIONS);\n        });\n    }\n\n    #[cfg(debug_assertions)]\n    async fn on_request(&self, req: &mut rocket::Request<'_>, _data: &mut rocket::Data<'_>) {\n        let cm = req.rocket().state::<ContextManager>()\n            .expect(\"Template ContextManager registered in on_ignite\");\n\n        cm.reload_if_needed(&self.callback);\n    }\n}\n"
  },
  {
    "path": "contrib/dyn_templates/src/lib.rs",
    "content": "//! Dynamic templating engine support for Rocket.\n//!\n//! This crate adds support for dynamic template rendering to Rocket. It\n//! automatically discovers templates, provides a `Responder` to render\n//! templates, and automatically reloads templates when compiled in debug mode.\n//! At present, it supports [Handlebars] and [Tera].\n//!\n//! # Usage\n//!\n//!   1. Depend on `rocket_dyn_templates`. Enable the feature(s) corresponding\n//!      to your templating engine(s) of choice:\n//!\n//!      ```toml\n//!      [dependencies.rocket_dyn_templates]\n//!      version = \"0.1.0\"\n//!      features = [\"handlebars\", \"tera\", \"minijinja\"]\n//!      ```\n//!\n//!   2. Write your templates inside of the [configurable]\n//!      `${ROCKET_ROOT}/templates`. The filename _must_ end with an extension\n//!      corresponding to an enabled engine. The second-to-last extension should\n//!      correspond to the file's type:\n//!\n//!      | Engine       | Extension | Example                                    |\n//!      |--------------|-----------|--------------------------------------------|\n//!      | [Tera]       | `.tera`   | `${ROCKET_ROOT}/templates/index.html.tera` |\n//!      | [Handlebars] | `.hbs`    | `${ROCKET_ROOT}/templates/index.html.hbs`  |\n//!      | [MiniJinja]  | `.j2`     | `${ROCKET_ROOT}/templates/index.html.j2`   |\n//!\n//!      [configurable]: #configuration\n//!      [Tera]: https://docs.rs/crate/tera/1\n//!      [Handlebars]: https://docs.rs/crate/handlebars/6\n//!      [MiniJinja]: https://docs.rs/minijinja/2\n//!\n//!   3. Attach `Template::fairing()` and return a [`Template`] from your routes\n//!      via [`Template::render()`], supplying the name of the template file\n//!      **minus the last two extensions**:\n//!\n//!      ```rust\n//!      # #[macro_use] extern crate rocket;\n//!      use rocket_dyn_templates::{Template, context};\n//!\n//!      #[get(\"/\")]\n//!      fn index() -> Template {\n//!          Template::render(\"index\", context! { field: \"value\" })\n//!      }\n//!\n//!      #[launch]\n//!      fn rocket() -> _ {\n//!          rocket::build().attach(Template::fairing())\n//!      }\n//!      ```\n//!\n//! ## Configuration\n//!\n//! This crate reads one configuration parameter from the configured figment:\n//!\n//!   * `template_dir` (**default: `templates/`**)\n//!\n//!      A path to a directory to search for template files in. Relative paths\n//!      are considered relative to the configuration file, or there is no file,\n//!      the current working directory.\n//!\n//! For example, to change the default and set `template_dir` to different\n//! values based on whether the application was compiled for debug or release\n//! from a `Rocket.toml` file (read by the default figment), you might write:\n//!\n//! ```toml\n//! [debug]\n//! template_dir = \"static/templates\"\n//!\n//! [release]\n//! template_dir = \"/var/opt/www/templates\"\n//! ```\n//!\n//! **Note:** `template_dir` defaults to `templates/`. It _does not_ need to be\n//! specified if the default suffices.\n//!\n//! See the [configuration chapter] of the guide for more information on\n//! configuration.\n//!\n//! [configuration chapter]: https://rocket.rs/master/guide/configuration\n//!\n//! ## Template Naming and Content-Types\n//!\n//! Templates are rendered by _name_ via [`Template::render()`], which returns a\n//! [`Template`] responder. The _name_ of the template is the path to the\n//! template file, relative to `template_dir`, minus at most two extensions.\n//!\n//! The `Content-Type` of the response is automatically determined by the\n//! non-engine extension using [`ContentType::from_extension()`]. If there is no\n//! such extension or it is unknown, `text/plain` is used.\n//!\n//! The following table contains examples:\n//!\n//! | template path                                 | [`Template::render()`] call       | content-type |\n//! |-----------------------------------------------|-----------------------------------|--------------|\n//! | {template_dir}/index.html.hbs                 | `render(\"index\")`                 | HTML         |\n//! | {template_dir}/index.tera                     | `render(\"index\")`                 | `text/plain` |\n//! | {template_dir}/index.hbs                      | `render(\"index\")`                 | `text/plain` |\n//! | {template_dir}/dir/index.hbs                  | `render(\"dir/index\")`             | `text/plain` |\n//! | {template_dir}/dir/data.json.tera             | `render(\"dir/data\")`              | JSON         |\n//! | {template_dir}/data.template.xml.hbs          | `render(\"data.template\")`         | XML          |\n//! | {template_dir}/subdir/index.template.html.hbs | `render(\"subdir/index.template\")` | HTML         |\n//!\n//! The recommended naming scheme is to use two extensions: one for the file\n//! type, and one for the template extension. This means that template\n//! extensions should look like: `.html.hbs`, `.html.tera`, `.xml.hbs`, and so\n//! on.\n//!\n//! [`ContentType::from_extension()`]: ../rocket/http/struct.ContentType.html#method.from_extension\n//!\n//! ### Rendering Context\n//!\n//! In addition to a name, [`Template::render()`] requires a context to use\n//! during rendering. The context can be any [`Serialize`] type that serializes\n//! to an `Object` (a dictionary) value. The [`context!`] macro can be used to\n//! create inline `Serialize`-able context objects.\n//!\n//! [`Serialize`]: rocket::serde::Serialize\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use rocket::serde::Serialize;\n//! use rocket_dyn_templates::{Template, context};\n//!\n//! #[get(\"/\")]\n//! fn index() -> Template {\n//!     // Using the `context! { }` macro.\n//!     Template::render(\"index\", context! {\n//!         site_name: \"Rocket - Home Page\",\n//!         version: 127,\n//!     })\n//! }\n//!\n//! #[get(\"/\")]\n//! fn index2() -> Template {\n//!     #[derive(Serialize)]\n//!     #[serde(crate = \"rocket::serde\")]\n//!     struct IndexContext {\n//!         site_name: &'static str,\n//!         version: u8\n//!     }\n//!\n//!     // Using an existing `IndexContext`, which implements `Serialize`.\n//!     Template::render(\"index\", IndexContext {\n//!         site_name: \"Rocket - Home Page\",\n//!         version: 127,\n//!     })\n//! }\n//! ```\n//!\n//! ### Discovery, Automatic Reloads, and Engine Customization\n//!\n//! As long as one of [`Template::fairing()`], [`Template::custom()`], or\n//! [`Template::try_custom()`] is [attached], any file in the configured\n//! `template_dir` ending with a known engine extension (as described in the\n//! [usage section](#usage)) can be rendered. The latter two fairings allow\n//! customizations such as registering helpers and templates from strings.\n//!\n//! _**Note:** Templates that are registered directly via [`Template::custom()`],\n//! use whatever name provided during that registration; no extensions are\n//! automatically removed._\n//!\n//! In debug mode (without the `--release` flag passed to `cargo`), templates\n//! are **automatically reloaded** from disk when changes are made. In release\n//! builds, template reloading is disabled to improve performance and cannot be\n//! enabled.\n//!\n//! [attached]: rocket::Rocket::attach()\n//!\n//! ### Metadata and Rendering to `String`\n//!\n//! The [`Metadata`] request guard allows dynamically querying templating\n//! metadata, such as whether a template is known to exist\n//! ([`Metadata::contains_template()`]), and to render templates to `String`\n//! ([`Metadata::render()`]).\n\n#![doc(html_root_url = \"https://api.rocket.rs/master/rocket_dyn_templates\")]\n#![doc(html_favicon_url = \"https://rocket.rs/images/favicon.ico\")]\n#![doc(html_logo_url = \"https://rocket.rs/images/logo-boxed.png\")]\n\n#[macro_use] extern crate rocket;\n\n#[doc(inline)]\n#[cfg(feature = \"tera\")]\n/// The tera templating engine library, reexported.\npub use tera;\n\n#[doc(inline)]\n#[cfg(feature = \"handlebars\")]\n/// The handlebars templating engine library, reexported.\npub use handlebars;\n\n#[doc(inline)]\n#[cfg(feature = \"minijinja\")]\n/// The minijinja templating engine library, reexported.\npub use minijinja;\n\n#[doc(hidden)]\npub use rocket::serde;\n\nmod engine;\nmod fairing;\nmod context;\nmod metadata;\nmod template;\n\npub use engine::Engines;\npub use metadata::Metadata;\npub use template::Template;\n"
  },
  {
    "path": "contrib/dyn_templates/src/metadata.rs",
    "content": "use std::fmt;\nuse std::borrow::Cow;\n\nuse rocket::{Request, Rocket, Ignite, Sentinel};\nuse rocket::http::{Status, ContentType};\nuse rocket::request::{self, FromRequest};\nuse rocket::serde::Serialize;\n\nuse crate::{Template, context::ContextManager};\n\n/// Request guard for dynamically querying template metadata.\n///\n/// # Usage\n///\n/// The `Metadata` type implements Rocket's [`FromRequest`] trait, so it can be\n/// used as a request guard in any request handler.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[macro_use] extern crate rocket_dyn_templates;\n/// use rocket_dyn_templates::{Template, Metadata, context};\n///\n/// #[get(\"/\")]\n/// fn homepage(metadata: Metadata) -> Template {\n///     // Conditionally render a template if it's available.\n///     # let context = ();\n///     if metadata.contains_template(\"some-template\") {\n///         Template::render(\"some-template\", &context)\n///     } else {\n///         Template::render(\"fallback\", &context)\n///     }\n/// }\n///\n/// fn main() {\n///     rocket::build()\n///         .attach(Template::fairing())\n///         // ...\n///     # ;\n/// }\n/// ```\npub struct Metadata<'a>(&'a ContextManager);\n\nimpl Metadata<'_> {\n    /// Returns `true` if the template with the given `name` is currently\n    /// loaded.  Otherwise, returns `false`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// # extern crate rocket_dyn_templates;\n    /// #\n    /// use rocket_dyn_templates::Metadata;\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(metadata: Metadata) {\n    ///     // Returns `true` if the template with name `\"name\"` was loaded.\n    ///     let loaded = metadata.contains_template(\"name\");\n    /// }\n    /// ```\n    pub fn contains_template(&self, name: &str) -> bool {\n        self.0.context().templates.contains_key(name)\n    }\n\n    /// Returns `true` if template reloading is enabled.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// # extern crate rocket_dyn_templates;\n    /// #\n    /// use rocket_dyn_templates::Metadata;\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(metadata: Metadata) {\n    ///     // Returns `true` if template reloading is enabled.\n    ///     let reloading = metadata.reloading();\n    /// }\n    /// ```\n    pub fn reloading(&self) -> bool {\n        self.0.is_reloading()\n    }\n\n    /// Directly render the template named `name` with the context `context`\n    /// into a `String`. Also returns the template's detected `ContentType`. See\n    /// [`Template::render()`] for more details on rendering.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::ContentType;\n    /// use rocket_dyn_templates::{Metadata, Template, context};\n    ///\n    /// #[get(\"/\")]\n    /// fn send_email(metadata: Metadata) -> Option<()> {\n    ///     let (mime, string) = metadata.render(\"email\", context! {\n    ///         field: \"Hello, world!\"\n    ///     })?;\n    ///\n    ///     # /*\n    ///     send_email(mime, string).await?;\n    ///     # */\n    ///     Some(())\n    /// }\n    ///\n    /// #[get(\"/\")]\n    /// fn raw_render(metadata: Metadata) -> Option<(ContentType, String)> {\n    ///     metadata.render(\"index\", context! { field: \"Hello, world!\" })\n    /// }\n    ///\n    /// // Prefer the following, however, which is nearly identical but pithier:\n    ///\n    /// #[get(\"/\")]\n    /// fn render() -> Template {\n    ///     Template::render(\"index\", context! { field: \"Hello, world!\" })\n    /// }\n    /// ```\n    pub fn render<S, C>(&self, name: S, context: C) -> Option<(ContentType, String)>\n        where S: Into<Cow<'static, str>>, C: Serialize\n    {\n        Template::render(name.into(), context).finalize(&self.0.context()).ok()\n    }\n}\n\nimpl fmt::Debug for Metadata<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_map()\n            .entries(&self.0.context().templates)\n            .finish()\n    }\n}\n\nimpl Sentinel for Metadata<'_> {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        if rocket.state::<ContextManager>().is_none() {\n            error!(\n                \"uninitialized template context: missing `Template::fairing()`.\\n\\\n                To use templates, you must attach `Template::fairing()`.\"\n            );\n\n            return true;\n        }\n\n        false\n    }\n}\n\n/// Retrieves the template metadata. If a template fairing hasn't been attached,\n/// an error is printed and an empty `Err` with status `InternalServerError`\n/// (`500`) is returned.\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for Metadata<'r> {\n    type Error = ();\n\n    async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        request.rocket().state::<ContextManager>()\n            .map(|cm| request::Outcome::Success(Metadata(cm)))\n            .unwrap_or_else(|| {\n                error!(\n                    \"uninitialized template context: missing `Template::fairing()`.\\n\\\n                    To use templates, you must attach `Template::fairing()`.\"\n                );\n\n                request::Outcome::Error((Status::InternalServerError, ()))\n            })\n    }\n}\n"
  },
  {
    "path": "contrib/dyn_templates/src/template.rs",
    "content": "use std::borrow::Cow;\nuse std::path::PathBuf;\n\nuse rocket::{Rocket, Orbit, Ignite, Sentinel};\nuse rocket::request::Request;\nuse rocket::fairing::Fairing;\nuse rocket::response::{self, Responder};\nuse rocket::http::{ContentType, Status};\nuse rocket::figment::{value::Value, error::Error};\nuse rocket::trace::Trace;\nuse rocket::serde::Serialize;\n\nuse crate::Engines;\nuse crate::fairing::TemplateFairing;\nuse crate::context::{Context, ContextManager};\n\npub(crate) const DEFAULT_TEMPLATE_DIR: &str = \"templates\";\n\n/// Responder that renders a dynamic template.\n///\n/// `Template` serves as a _proxy_ type for rendering a template and _does not_\n/// contain the rendered template itself. The template is lazily rendered, at\n/// response time. To render a template greedily, use [`Template::show()`].\n///\n/// See the [crate root](crate) for usage details.\n#[derive(Debug)]\npub struct Template {\n    name: Cow<'static, str>,\n    value: Result<Value, Error>,\n}\n\n#[derive(Debug)]\npub(crate) struct TemplateInfo {\n    /// The complete path, including `template_dir`, to this template, if any.\n    pub(crate) path: Option<PathBuf>,\n    /// The extension for the engine of this template.\n    pub(crate) engine_ext: &'static str,\n    /// The extension before the engine extension in the template, if any.\n    pub(crate) data_type: ContentType\n}\n\nimpl Template {\n    /// Returns a fairing that initializes and maintains templating state.\n    ///\n    /// This fairing, or the one returned by [`Template::custom()`], _must_ be\n    /// attached to any `Rocket` instance that wishes to render templates.\n    /// Failure to attach this fairing will result in a \"Uninitialized template\n    /// context: missing fairing.\" error message when a template is attempted to\n    /// be rendered.\n    ///\n    /// If you wish to customize the internal templating engines, use\n    /// [`Template::custom()`] instead.\n    ///\n    /// # Example\n    ///\n    /// To attach this fairing, simple call `attach` on the application's\n    /// `Rocket` instance with `Template::fairing()`:\n    ///\n    /// ```rust\n    /// extern crate rocket;\n    /// extern crate rocket_dyn_templates;\n    ///\n    /// use rocket_dyn_templates::Template;\n    ///\n    /// fn main() {\n    ///     rocket::build()\n    ///         // ...\n    ///         .attach(Template::fairing())\n    ///         // ...\n    ///     # ;\n    /// }\n    /// ```\n    pub fn fairing() -> impl Fairing {\n        Template::custom(|_| {})\n    }\n\n    /// Returns a fairing that initializes and maintains templating state.\n    ///\n    /// Unlike [`Template::fairing()`], this method allows you to configure\n    /// templating engines via the function `f`. Note that only the enabled\n    /// templating engines will be accessible from the `Engines` type.\n    ///\n    /// This method does not allow the function `f` to fail. If `f` is fallible,\n    /// use [`Template::try_custom()`] instead.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// extern crate rocket;\n    /// extern crate rocket_dyn_templates;\n    ///\n    /// use rocket_dyn_templates::Template;\n    ///\n    /// fn main() {\n    ///     rocket::build()\n    ///         // ...\n    ///         .attach(Template::custom(|engines| {\n    ///             // engines.handlebars.register_helper ...\n    ///         }))\n    ///         // ...\n    ///     # ;\n    /// }\n    /// ```\n    pub fn custom<F: Send + Sync + 'static>(f: F) -> impl Fairing\n        where F: Fn(&mut Engines)\n    {\n        Self::try_custom(move |engines| { f(engines); Ok(()) })\n    }\n\n    /// Returns a fairing that initializes and maintains templating state.\n    ///\n    /// This variant of [`Template::custom()`] allows a fallible `f`. If `f`\n    /// returns an error during initialization, it will cancel the launch. If\n    /// `f` returns an error during template reloading (in debug mode), then the\n    /// newly-reloaded templates are discarded.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// extern crate rocket;\n    /// extern crate rocket_dyn_templates;\n    ///\n    /// use rocket_dyn_templates::Template;\n    ///\n    /// fn main() {\n    ///     rocket::build()\n    ///         // ...\n    ///         .attach(Template::try_custom(|engines| {\n    ///             // engines.handlebars.register_helper ...\n    ///             Ok(())\n    ///         }))\n    ///         // ...\n    ///     # ;\n    /// }\n    /// ```\n    pub fn try_custom<F: Send + Sync + 'static>(f: F) -> impl Fairing\n        where F: Fn(&mut Engines) -> Result<(), Box<dyn std::error::Error>>\n    {\n        TemplateFairing { callback: Box::new(f) }\n    }\n\n    /// Render the template named `name` with the context `context`. The\n    /// `context` is typically created using the [`context!()`](crate::context!)\n    /// macro, but it can be of any type that implements `Serialize`, such as\n    /// `HashMap` or a custom `struct`.\n    ///\n    /// To render a template directly into a string, use\n    /// [`Metadata::render()`](crate::Metadata::render()).\n    ///\n    /// # Examples\n    ///\n    /// Using the `context` macro:\n    ///\n    /// ```rust\n    /// use rocket_dyn_templates::{Template, context};\n    ///\n    /// let template = Template::render(\"index\", context! {\n    ///     foo: \"Hello, world!\",\n    /// });\n    /// ```\n    ///\n    /// Using a `HashMap` as the context:\n    ///\n    /// ```rust\n    /// use std::collections::HashMap;\n    /// use rocket_dyn_templates::Template;\n    ///\n    /// // Create a `context` from a `HashMap`.\n    /// let mut context = HashMap::new();\n    /// context.insert(\"foo\", \"Hello, world!\");\n    ///\n    /// let template = Template::render(\"index\", context);\n    /// ```\n    #[inline]\n    pub fn render<S, C>(name: S, context: C) -> Template\n        where S: Into<Cow<'static, str>>, C: Serialize\n    {\n        Template {\n            name: name.into(),\n            value: Value::serialize(context),\n        }\n    }\n\n    /// Render the template named `name` with the context `context` into a\n    /// `String`. This method should **not** be used in any running Rocket\n    /// application. This method should only be used during testing to validate\n    /// `Template` responses. For other uses, use [`render()`](#method.render)\n    /// instead.\n    ///\n    /// The `context` can be of any type that implements `Serialize`. This is\n    /// typically a `HashMap` or a custom `struct`.\n    ///\n    /// Returns `Some` if the template could be rendered. Otherwise, returns\n    /// `None`. If rendering fails, error output is printed to the console.\n    /// `None` is also returned if a `Template` fairing has not been attached.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # extern crate rocket;\n    /// # extern crate rocket_dyn_templates;\n    /// use std::collections::HashMap;\n    ///\n    /// use rocket_dyn_templates::Template;\n    /// use rocket::local::blocking::Client;\n    ///\n    /// fn main() {\n    ///     let rocket = rocket::build().attach(Template::fairing());\n    ///     let client = Client::untracked(rocket).expect(\"valid rocket\");\n    ///\n    ///     // Create a `context`. Here, just an empty `HashMap`.\n    ///     let mut context = HashMap::new();\n    ///     # context.insert(\"test\", \"test\");\n    ///     let template = Template::show(client.rocket(), \"index\", context);\n    /// }\n    /// ```\n    #[inline]\n    pub fn show<S, C>(rocket: &Rocket<Orbit>, name: S, context: C) -> Option<String>\n        where S: Into<Cow<'static, str>>, C: Serialize\n    {\n        let ctxt = rocket.state::<ContextManager>()\n            .map(ContextManager::context)\n            .or_else(|| {\n                error!(\"Uninitialized template context: missing fairing.\\n\\\n                    To use templates, you must attach `Template::fairing()`.\\n\\\n                    See the `Template` documentation for more information.\");\n\n                None\n            })?;\n\n        Template::render(name, context).finalize(&ctxt).ok().map(|v| v.1)\n    }\n\n    /// Actually render this template given a template context. This method is\n    /// called by the `Template` `Responder` implementation as well as\n    /// `Template::show()`.\n    #[inline(always)]\n    pub(crate) fn finalize(self, ctxt: &Context) -> Result<(ContentType, String), Status> {\n        let template = &*self.name;\n        let info = ctxt.templates.get(template).ok_or_else(|| {\n            let ts: Vec<_> = ctxt.templates.keys().map(|s| s.as_str()).collect();\n            error!(\n                %template, search_path = %ctxt.root.display(), known_templates = ?ts,\n                \"requested template not found\"\n            );\n\n            Status::InternalServerError\n        })?;\n\n        let value = self.value.map_err(|e| {\n            span_error!(\"templating\", \"template context failed to serialize\" => e.trace_error());\n            Status::InternalServerError\n        })?;\n\n        let string = ctxt.engines.render(template, info, value).ok_or_else(|| {\n            error!(template, \"template failed to render\");\n            Status::InternalServerError\n        })?;\n\n        Ok((info.data_type.clone(), string))\n    }\n}\n\n/// Returns a response with the Content-Type derived from the template's\n/// extension and a fixed-size body containing the rendered template. If\n/// rendering fails, an `Err` of `Status::InternalServerError` is returned.\nimpl<'r> Responder<'r, 'static> for Template {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n        let ctxt = req.rocket()\n            .state::<ContextManager>()\n            .ok_or_else(|| {\n                error!(\n                    \"uninitialized template context: missing `Template::fairing()`.\\n\\\n                    To use templates, you must attach `Template::fairing()`.\"\n                );\n\n                Status::InternalServerError\n            })?;\n\n        self.finalize(&ctxt.context())?.respond_to(req)\n    }\n}\n\nimpl Sentinel for Template {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        if rocket.state::<ContextManager>().is_none() {\n            error!(\n                \"Missing `Template::fairing()`.\\n\\\n                 To use templates, you must attach `Template::fairing()`.\"\n            );\n\n            return true;\n        }\n\n        false\n    }\n}\n\n/// A macro to easily create a template rendering context.\n///\n/// Invocations of this macro expand to a value of an anonymous type which\n/// implements [`Serialize`]. Fields can be literal expressions or variables\n/// captured from a surrounding scope, as long as all fields implement\n/// `Serialize`.\n///\n/// # Examples\n///\n/// The following code:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use rocket_dyn_templates::{Template, context};\n/// #[get(\"/<foo>\")]\n/// fn render_index(foo: u64) -> Template {\n///     Template::render(\"index\", context! {\n///         // Note that shorthand field syntax is supported.\n///         // This is equivalent to `foo: foo,`\n///         foo,\n///         bar: \"Hello world\",\n///     })\n/// }\n/// ```\n///\n/// is equivalent to the following, but without the need to manually define an\n/// `IndexContext` struct:\n///\n/// ```rust\n/// # use rocket_dyn_templates::Template;\n/// # use rocket::serde::Serialize;\n/// # use rocket::get;\n/// #[derive(Serialize)]\n/// # #[serde(crate = \"rocket::serde\")]\n/// struct IndexContext<'a> {\n///     foo: u64,\n///     bar: &'a str,\n/// }\n///\n/// #[get(\"/<foo>\")]\n/// fn render_index(foo: u64) -> Template {\n///     Template::render(\"index\", IndexContext {\n///         foo,\n///         bar: \"Hello world\",\n///     })\n/// }\n/// ```\n///\n/// ## Nesting\n///\n/// Nested objects can be created by nesting calls to `context!`:\n///\n/// ```rust\n/// # use rocket_dyn_templates::context;\n/// # fn main() {\n/// let ctx = context! {\n///     planet: \"Earth\",\n///     info: context! {\n///         mass: 5.97e24,\n///         radius: \"6371 km\",\n///         moons: 1,\n///     },\n/// };\n/// # }\n/// ```\n#[macro_export]\nmacro_rules! context {\n    ($($key:ident $(: $value:expr)?),*$(,)?) => {{\n        use $crate::serde::ser::{Serialize, Serializer, SerializeMap};\n        use ::std::fmt::{Debug, Formatter};\n        use ::std::result::Result;\n\n        #[allow(non_camel_case_types)]\n        struct ContextMacroCtxObject<$($key: Serialize),*> {\n            $($key: $key),*\n        }\n\n        #[allow(non_camel_case_types)]\n        impl<$($key: Serialize),*> Serialize for ContextMacroCtxObject<$($key),*> {\n            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n                where S: Serializer,\n            {\n                let mut map = serializer.serialize_map(None)?;\n                $(map.serialize_entry(stringify!($key), &self.$key)?;)*\n                map.end()\n            }\n        }\n\n        #[allow(non_camel_case_types)]\n        impl<$($key: Debug + Serialize),*> Debug for ContextMacroCtxObject<$($key),*> {\n            fn fmt(&self, f: &mut Formatter<'_>) -> ::std::fmt::Result {\n                f.debug_struct(\"context!\")\n                    $(.field(stringify!($key), &self.$key))*\n                    .finish()\n            }\n        }\n\n        ContextMacroCtxObject {\n            $($key $(: $value)?),*\n        }\n    }};\n}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/hbs/common/footer.html.hbs",
    "content": "Done.\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/hbs/common/header.html.hbs",
    "content": "Hello {{ title }}!\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/hbs/reload.txt.hbs",
    "content": "initial"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/hbs/test.html.hbs",
    "content": "{{> hbs/common/header }}\n<main> {{ content }} </main>\n{{> hbs/common/footer }}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/j2/[test]/html_test.html.j2",
    "content": "{% extends \"j2/base\" %}\n{% block title %}{{ title }}{% endblock title %}\n{% block content %}\n{{ content }}\n{% endblock content %}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/j2/base.txt.j2",
    "content": "{% block head %}\nh_start\ntitle: {% block title %}{% endblock title %}\nh_end\n{% endblock head %}\n{% block content %}{% endblock content %}\n{% block footer %}foot{% endblock footer %}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/j2/html_test.html.j2",
    "content": "{% extends \"j2/base\" %}\n{% block title %}{{ title }}{% endblock title %}\n{% block content %}\n{{ content }}\n{% endblock content %}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/j2/txt_test.txt.j2",
    "content": "{% extends \"j2/base\" %}\n{% block title %}{{ title }}{% endblock title %}\n{% block content %}\n{{ content }}\n{% endblock content %}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/tera/[test]/html_test.html.tera",
    "content": "{% extends \"tera/base\" %}\n{% block title %}{{ title }}{% endblock title %}\n{% block content %}\n{{ content }}\n{% endblock content %}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/tera/base.txt.tera",
    "content": "{% block head %}\nh_start\ntitle: {% block title %}{% endblock title %}\nh_end\n{% endblock head %}\n{% block content %}{% endblock content %}\n{% block footer %}foot{% endblock footer -%}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/tera/html_test.html.tera",
    "content": "{% extends \"tera/base\" %}\n{% block title %}{{ title }}{% endblock title %}\n{% block content %}\n{{ content }}\n{% endblock content %}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates/tera/txt_test.txt.tera",
    "content": "{% extends \"tera/base\" %}\n{% block title %}{{ title }}{% endblock title %}\n{% block content %}\n{{ content }}\n{% endblock content %}\n"
  },
  {
    "path": "contrib/dyn_templates/tests/templates.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse std::path::{Path, PathBuf};\n\nuse rocket::{Rocket, Build};\nuse rocket::config::Config;\nuse rocket::figment::value::Value;\nuse rocket::serde::{Serialize, Deserialize};\nuse rocket_dyn_templates::{Template, Metadata, context};\n\n#[get(\"/<engine>/<name>\")]\nfn template_check(md: Metadata<'_>, engine: &str, name: &str) -> Option<()> {\n    md.contains_template(&format!(\"{}/{}\", engine, name)).then(|| ())\n}\n\n#[get(\"/is_reloading\")]\nfn is_reloading(md: Metadata<'_>) -> Option<()> {\n    if md.reloading() { Some(()) } else { None }\n}\n\nfn template_root() -> PathBuf {\n    Path::new(env!(\"CARGO_MANIFEST_DIR\")).join(\"tests\").join(\"templates\")\n}\n\nfn rocket() -> Rocket<Build> {\n    rocket::custom(Config::figment().merge((\"template_dir\", template_root())))\n        .attach(Template::fairing())\n        .mount(\"/\", routes![template_check, is_reloading])\n}\n\n#[test]\nfn test_callback_error() {\n    use rocket::{local::blocking::Client, error::ErrorKind::FailedFairings};\n\n    let rocket = rocket::build().attach(Template::try_custom(|_| {\n        Err(\"error reloading templates!\".into())\n    }));\n\n    let error = Client::debug(rocket).expect_err(\"client failure\");\n    match error.kind() {\n        FailedFairings(failures) => assert_eq!(failures[0].name, \"Templating\"),\n        _ => panic!(\"Wrong kind of launch error\"),\n    }\n}\n\n#[test]\nfn test_sentinel() {\n    use rocket::{local::blocking::Client, error::ErrorKind::SentinelAborts};\n\n    let err = Client::debug_with(routes![is_reloading]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    let err = Client::debug_with(routes![is_reloading, template_check]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 2));\n\n    #[get(\"/\")]\n    fn return_template() -> Template {\n        Template::render(\"foo\", ())\n    }\n\n    let err = Client::debug_with(routes![return_template]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[get(\"/\")]\n    fn return_opt_template() -> Option<Template> {\n        Some(Template::render(\"foo\", ()))\n    }\n\n    let err = Client::debug_with(routes![return_opt_template]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[derive(rocket::Responder)]\n    struct MyThing<T>(T);\n\n    #[get(\"/\")]\n    fn return_custom_template() -> MyThing<Template> {\n        MyThing(Template::render(\"foo\", ()))\n    }\n\n    let err = Client::debug_with(routes![return_custom_template]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[derive(rocket::Responder)]\n    struct MyOkayThing<T>(Option<T>);\n\n    impl<T> rocket::Sentinel for MyOkayThing<T> {\n        fn abort(_: &Rocket<rocket::Ignite>) -> bool {\n            false\n        }\n    }\n\n    #[get(\"/\")]\n    fn always_ok_sentinel() -> MyOkayThing<Template> {\n        MyOkayThing(None)\n    }\n\n    Client::debug_with(routes![always_ok_sentinel]).expect(\"no sentinel abort\");\n}\n\n#[test]\nfn test_context_macro() {\n    macro_rules! assert_same_object {\n        ($ctx:expr, $obj:expr $(,)?) => {{\n            let ser_ctx = Value::serialize(&$ctx).unwrap();\n            let deser_ctx = ser_ctx.deserialize().unwrap();\n            assert_eq!($obj, deser_ctx);\n        }};\n    }\n\n    {\n        #[derive(Deserialize, PartialEq, Debug)]\n        #[serde(crate = \"rocket::serde\")]\n        struct Empty { }\n\n        assert_same_object!(context! { }, Empty { });\n    }\n\n    {\n        #[derive(Deserialize, PartialEq, Debug)]\n        #[serde(crate = \"rocket::serde\")]\n        struct Object {\n            a: u32,\n            b: String,\n        }\n\n        let a = 93;\n        let b = \"Hello\".to_string();\n\n        fn make_context() -> impl Serialize {\n            let b = \"Hello\".to_string();\n\n            context! { a: 93, b: b }\n        }\n\n        assert_same_object!(\n            make_context(),\n            Object { a, b },\n        );\n    }\n\n    {\n        #[derive(Deserialize, PartialEq, Debug)]\n        #[serde(crate = \"rocket::serde\")]\n        struct Outer {\n            s: String,\n            inner: Inner,\n        }\n\n        #[derive(Deserialize, PartialEq, Debug)]\n        #[serde(crate = \"rocket::serde\")]\n        struct Inner {\n            center: Center,\n        }\n\n        #[derive(Deserialize, PartialEq, Debug)]\n        #[serde(crate = \"rocket::serde\")]\n        struct Center {\n            value_a: bool,\n            value_b: u8,\n        }\n\n        let a = true;\n        let value_b = 123;\n        let outer_string = String::from(\"abc 123\");\n\n        assert_same_object!(\n            context! {\n                s: &outer_string,\n                inner: context! {\n                    center: context! {\n                        value_a: a,\n                        value_b,\n                    },\n                },\n            },\n            Outer {\n                s: outer_string,\n                inner: Inner {\n                    center: Center {\n                        value_a: a,\n                        value_b,\n                    },\n                },\n            },\n        );\n    }\n\n    {\n        #[derive(Deserialize, PartialEq, Debug)]\n        #[serde(crate = \"rocket::serde\")]\n        struct Object {\n            a: String,\n        }\n\n        let owned = String::from(\"foo\");\n        let ctx = context! { a: &owned };\n        assert_same_object!(ctx, Object { a: \"foo\".into() });\n        drop(ctx);\n        drop(owned);\n    }\n}\n\n#[cfg(feature = \"tera\")]\nmod tera_tests {\n    use super::*;\n    use std::collections::HashMap;\n    use rocket::http::{ContentType, Status};\n    use rocket::request::FromRequest;\n    use pretty_assertions::assert_eq;\n\n    const UNESCAPED_EXPECTED: &'static str\n        = \"\\nh_start\\ntitle: _test_\\nh_end\\n\\n\\n<script />\\n\\nfoot\";\n    const ESCAPED_EXPECTED: &'static str\n        = \"\\nh_start\\ntitle: _test_\\nh_end\\n\\n\\n&lt;script &#x2F;&gt;\\n\\nfoot\";\n\n    #[async_test]\n    async fn test_tera_templates() {\n        use rocket::local::asynchronous::Client;\n\n        let client = Client::debug(rocket()).await.unwrap();\n        let req = client.get(\"/\");\n        let metadata = Metadata::from_request(&req).await.unwrap();\n\n        let mut map = HashMap::new();\n        map.insert(\"title\", \"_test_\");\n        map.insert(\"content\", \"<script />\");\n\n        // Test with a txt file, which shouldn't escape.\n        let template = Template::show(client.rocket(), \"tera/txt_test\", &map);\n        let md_rendered = metadata.render(\"tera/txt_test\", &map);\n        assert_eq!(template, Some(UNESCAPED_EXPECTED.into()));\n        assert_eq!(md_rendered, Some((ContentType::Text, UNESCAPED_EXPECTED.into())));\n\n        // Now with an HTML file, which should escape.\n        let template = Template::show(client.rocket(), \"tera/html_test\", &map);\n        let md_rendered = metadata.render(\"tera/html_test\", &map);\n        assert_eq!(template, Some(ESCAPED_EXPECTED.into()));\n        assert_eq!(md_rendered, Some((ContentType::HTML, ESCAPED_EXPECTED.into())));\n    }\n\n    #[async_test]\n    async fn test_globby_paths() {\n        use rocket::local::asynchronous::Client;\n\n        let client = Client::debug(rocket()).await.unwrap();\n        let req = client.get(\"/\");\n        let metadata = Metadata::from_request(&req).await.unwrap();\n        assert!(metadata.contains_template(\"tera/[test]/html_test\"));\n    }\n\n    // u128 is not supported. enable when it is.\n    // #[test]\n    // fn test_tera_u128() {\n    //     const EXPECTED: &'static str\n    //         = \"\\nh_start\\ntitle: 123\\nh_end\\n\\n\\n1208925819614629174706176\\n\\nfoot\\n\";\n    //\n    //     let client = Client::debug(rocket()).unwrap();\n    //     let mut map = HashMap::new();\n    //     map.insert(\"title\", 123);\n    //     map.insert(\"number\", 1u128 << 80);\n    //\n    //     let template = Template::show(client.rocket(), \"tera/txt_test\", &map);\n    //     assert_eq!(template, Some(EXPECTED.into()));\n    // }\n\n    #[test]\n    fn test_template_metadata_with_tera() {\n        use rocket::local::blocking::Client;\n\n        let client = Client::debug(rocket()).unwrap();\n\n        let response = client.get(\"/tera/txt_test\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n\n        let response = client.get(\"/tera/html_test\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n\n        let response = client.get(\"/tera/not_existing\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n\n        let response = client.get(\"/hbs/txt_test\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n    }\n}\n\n#[cfg(feature = \"handlebars\")]\nmod handlebars_tests {\n    use super::*;\n    use std::collections::HashMap;\n    use rocket::request::FromRequest;\n    use rocket::http::{ContentType, Status};\n    use pretty_assertions::assert_eq;\n\n    #[async_test]\n    async fn test_handlebars_templates() {\n        use rocket::local::asynchronous::Client;\n\n        const EXPECTED: &'static str\n            = \"Hello _test_!\\n<main> &lt;script /&gt; hi </main>\\nDone.\\n\";\n\n        let client = Client::debug(rocket()).await.unwrap();\n        let req = client.get(\"/\");\n        let metadata = Metadata::from_request(&req).await.unwrap();\n\n        let mut map = HashMap::new();\n        map.insert(\"title\", \"_test_\");\n        map.insert(\"content\", \"<script /> hi\");\n\n        // Test with a txt file, which shouldn't escape.\n        let template = Template::show(client.rocket(), \"hbs/test\", &map);\n        let md_rendered = metadata.render(\"hbs/test\", &map);\n        assert_eq!(template, Some(EXPECTED.into()));\n        assert_eq!(md_rendered, Some((ContentType::HTML, EXPECTED.into())));\n    }\n\n    // u128 is not supported. enable when it is.\n    // #[test]\n    // fn test_handlebars_u128() {\n    //     const EXPECTED: &'static str\n    //         = \"Hello 123!\\n\\n<main> 1208925819614629174706176 </main>\\nDone.\\n\\n\";\n    //\n    //     let client = Client::debug(rocket()).unwrap();\n    //     let mut map = HashMap::new();\n    //     map.insert(\"title\", 123);\n    //     map.insert(\"number\", 1u128 << 80);\n    //\n    //     let template = Template::show(client.rocket(), \"hbs/test\", &map);\n    //     assert_eq!(template, Some(EXPECTED.into()));\n    // }\n\n    #[test]\n    fn test_template_metadata_with_handlebars() {\n        use rocket::local::blocking::Client;\n\n        let client = Client::debug(rocket()).unwrap();\n\n        let response = client.get(\"/hbs/test\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n\n        let response = client.get(\"/hbs/not_existing\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n\n        let response = client.get(\"/tera/test\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n    }\n\n    #[test]\n    #[cfg(debug_assertions)]\n    fn test_template_reload() {\n        use std::fs::File;\n        use std::io::Write;\n        use std::time::Duration;\n\n        use rocket::local::blocking::Client;\n\n        const RELOAD_TEMPLATE: &str = \"hbs/reload\";\n        const INITIAL_TEXT: &str = \"initial\";\n        const NEW_TEXT: &str = \"reload\";\n\n        fn write_file(path: &Path, text: &str) {\n            let mut file = File::create(path).expect(\"open file\");\n            file.write_all(text.as_bytes()).expect(\"write file\");\n            file.sync_all().expect(\"sync file\");\n        }\n\n        // set up the template before initializing the Rocket instance so\n        // that it will be picked up in the initial loading of templates.\n        let reload_path = template_root().join(\"hbs\").join(\"reload.txt.hbs\");\n        write_file(&reload_path, INITIAL_TEXT);\n\n        // set up the client. if we can't reload templates, then just quit\n        let client = Client::debug(rocket()).unwrap();\n        let res = client.get(\"/is_reloading\").dispatch();\n        if res.status() != Status::Ok {\n            return;\n        }\n\n        // verify that the initial content is correct\n        let initial_rendered = Template::show(client.rocket(), RELOAD_TEMPLATE, ());\n        assert_eq!(initial_rendered, Some(INITIAL_TEXT.into()));\n\n        // write a change to the file\n        write_file(&reload_path, NEW_TEXT);\n\n        for _ in 0..6 {\n            // dispatch any request to trigger a template reload\n            client.get(\"/\").dispatch();\n\n            // if the new content is correct, we are done\n            let new_rendered = Template::show(client.rocket(), RELOAD_TEMPLATE, ());\n            if new_rendered == Some(NEW_TEXT.into()) {\n                write_file(&reload_path, INITIAL_TEXT);\n                return;\n            }\n\n            // otherwise, retry a few times, waiting 250ms in between\n            std::thread::sleep(Duration::from_millis(250));\n        }\n\n        panic!(\"failed to reload modified template in 1.5s\");\n    }\n}\n\n#[cfg(feature = \"minijinja\")]\nmod j2_tests {\n    use super::*;\n    use std::collections::HashMap;\n    use rocket::http::{ContentType, Status};\n    use rocket::request::FromRequest;\n    use pretty_assertions::assert_eq;\n\n    const UNESCAPED_EXPECTED: &'static str\n        = \"\\nh_start\\ntitle: _test_\\nh_end\\n\\n\\n<script />\\n\\nfoot\";\n    const ESCAPED_EXPECTED: &'static str\n        = \"\\nh_start\\ntitle: _test_\\nh_end\\n\\n\\n&lt;script &#x2f;&gt;\\n\\nfoot\";\n\n    #[async_test]\n    async fn test_j2_templates() {\n        use rocket::local::asynchronous::Client;\n\n        let client = Client::debug(rocket()).await.unwrap();\n        let req = client.get(\"/\");\n        let metadata = Metadata::from_request(&req).await.unwrap();\n\n        let mut map = HashMap::new();\n        map.insert(\"title\", \"_test_\");\n        map.insert(\"content\", \"<script />\");\n\n        // Test with a txt file, which shouldn't escape.\n        let template = Template::show(client.rocket(), \"j2/txt_test\", &map);\n        let md_rendered = (&metadata).render(\"j2/txt_test\", &map);\n        assert_eq!(template, Some(UNESCAPED_EXPECTED.into()));\n        assert_eq!(md_rendered, Some((ContentType::Text, UNESCAPED_EXPECTED.into())));\n\n        // Now with an HTML file, which should escaped.\n        let template = Template::show(client.rocket(), \"j2/html_test\", &map);\n        let md_rendered = metadata.render(\"j2/html_test\", &map);\n        assert_eq!(template, Some(ESCAPED_EXPECTED.into()));\n        assert_eq!(md_rendered, Some((ContentType::HTML, ESCAPED_EXPECTED.into())));\n    }\n\n    #[async_test]\n    async fn test_globby_paths() {\n        use rocket::local::asynchronous::Client;\n\n        let client = Client::debug(rocket()).await.unwrap();\n        let req = client.get(\"/\");\n        let metadata = Metadata::from_request(&req).await.unwrap();\n        assert!(metadata.contains_template(\"j2/[test]/html_test\"));\n    }\n\n    #[test]\n    fn test_j2_u128() {\n        const EXPECTED: &'static str\n            = \"\\nh_start\\ntitle: 123\\nh_end\\n\\n\\n1208925819614629174706176\\n\\nfoot\";\n\n        use rocket::local::blocking::Client;\n\n        let client = Client::debug(rocket()).unwrap();\n        let mut map = HashMap::new();\n        map.insert(\"title\", 123);\n        map.insert(\"content\", 1u128 << 80);\n\n        let template = Template::show(client.rocket(), \"j2/txt_test\", &map);\n        assert_eq!(template, Some(EXPECTED.into()));\n    }\n\n    #[test]\n    fn test_template_metadata_with_j2() {\n        use rocket::local::blocking::Client;\n\n        let client = Client::debug(rocket()).unwrap();\n\n        let response = client.get(\"/j2/txt_test\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n\n        let response = client.get(\"/j2/html_test\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n\n        let response = client.get(\"/j2/not_existing\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n\n        let response = client.get(\"/hbs/txt_test\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/README.md",
    "content": "# `sync_db_pools` [![ci.svg]][ci] [![crates.io]][crate] [![docs.svg]][crate docs]\n\n[crates.io]: https://img.shields.io/crates/v/rocket_sync_db_pools.svg\n[crate]: https://crates.io/crates/rocket_sync_db_pools\n[docs.svg]: https://img.shields.io/badge/web-master-red.svg?style=flat&label=docs&colorB=d33847\n[crate docs]: https://api.rocket.rs/master/rocket_sync_db_pools\n[ci.svg]: https://github.com/rwf2/Rocket/workflows/CI/badge.svg\n[ci]: https://github.com/rwf2/Rocket/actions\n\nThis crate provides traits, utilities, and a procedural macro for configuring\nand accessing database connection pools in Rocket. This implementation is backed\nby [`r2d2`] and exposes connections through request guards.\n\n[`r2d2`]: https://docs.rs/r2d2\n\n## Usage\n\nFirst, enable the feature corresponding to your database type:\n\n```toml\n[dependencies.rocket_sync_db_pools]\nversion = \"0.1.0\"\nfeatures = [\"diesel_sqlite_pool\"]\n```\n\nA full list of supported databases and their associated feature names is\navailable in the [crate docs]. In whichever configuration source you choose,\nconfigure a `databases` dictionary with a key for each database, here\n`sqlite_logs` in a TOML source:\n\n```toml\n[default.databases]\nsqlite_logs = { url = \"/path/to/database.sqlite\" }\n```\n\nIn your application's source code:\n\n```rust\n#[macro_use] extern crate rocket;\n\nuse rocket_sync_db_pools::{database, diesel};\n\n#[database(\"sqlite_logs\")]\nstruct LogsDbConn(diesel::SqliteConnection);\n\n#[get(\"/logs/<id>\")]\nasync fn get_logs(conn: LogsDbConn, id: usize) -> Result<Logs> {\n    conn.run(|c| Logs::by_id(c, id)).await\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().attach(LogsDbConn::fairing())\n}\n```\n\nSee the [crate docs] for full details.\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/Cargo.toml",
    "content": "[package]\nname = \"rocket_sync_db_pools_codegen\"\nversion = \"0.1.0\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\"]\ndescription = \"Procedural macros for rocket_sync_db_pools.\"\nrepository = \"https://github.com/rwf2/Rocket/tree/master/contrib/sync_db_pools\"\nreadme = \"../README.md\"\nkeywords = [\"rocket\", \"framework\", \"database\", \"pools\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[lib]\nproc-macro = true\n\n[lints]\nworkspace = true\n\n[dependencies]\nquote = \"1.0\"\ndevise = \"0.4\"\n\n[dev-dependencies]\nversion_check = \"0.9\"\ntrybuild = \"1.0\"\nrocket_sync_db_pools = { path = \"../lib\" }\nrocket = { path = \"../../../core/lib\" }\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/src/database.rs",
    "content": "use proc_macro::TokenStream;\nuse devise::{Spanned, Result, ext::SpanDiagnosticExt};\n\nuse crate::syn;\n\n#[derive(Debug)]\nstruct DatabaseInvocation {\n    /// The attributes on the attributed structure.\n    attrs: Vec<syn::Attribute>,\n    /// The name of the structure on which `#[database(..)] struct This(..)` was invoked.\n    type_name: syn::Ident,\n    /// The visibility of the structure on which `#[database(..)] struct This(..)` was invoked.\n    visibility: syn::Visibility,\n    /// The database name as passed in via #[database('database name')].\n    db_name: String,\n    /// The type inside the structure: struct MyDb(ThisType).\n    connection_type: syn::Type,\n}\n\nconst EXAMPLE: &str = \"example: `struct MyDatabase(diesel::SqliteConnection);`\";\nconst ONLY_ON_STRUCTS_MSG: &str = \"`database` attribute can only be used on structs\";\nconst ONLY_UNNAMED_FIELDS: &str = \"`database` attribute can only be applied to \\\n    structs with exactly one unnamed field\";\nconst NO_GENERIC_STRUCTS: &str = \"`database` attribute cannot be applied to structs \\\n    with generics\";\n\nfn parse_invocation(attr: TokenStream, input: TokenStream) -> Result<DatabaseInvocation> {\n    let attr_stream2 = crate::proc_macro2::TokenStream::from(attr);\n    let string_lit = crate::syn::parse2::<syn::LitStr>(attr_stream2)?;\n\n    let input = crate::syn::parse::<syn::DeriveInput>(input).unwrap();\n    if !input.generics.params.is_empty() {\n        return Err(input.generics.span().error(NO_GENERIC_STRUCTS));\n    }\n\n    let structure = match input.data {\n        syn::Data::Struct(s) => s,\n        _ => return Err(input.span().error(ONLY_ON_STRUCTS_MSG))\n    };\n\n    let inner_type = match structure.fields {\n        syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => {\n            let first = fields.unnamed.first().expect(\"checked length\");\n            first.ty.clone()\n        }\n        _ => return Err(structure.fields.span().error(ONLY_UNNAMED_FIELDS).help(EXAMPLE))\n    };\n\n    Ok(DatabaseInvocation {\n        attrs: input.attrs,\n        type_name: input.ident,\n        visibility: input.vis,\n        db_name: string_lit.value(),\n        connection_type: inner_type,\n    })\n}\n\n#[allow(non_snake_case)]\npub fn database_attr(attr: TokenStream, input: TokenStream) -> Result<TokenStream> {\n    let invocation = parse_invocation(attr, input)?;\n\n    // Store everything we're going to need to generate code.\n    let conn_type = &invocation.connection_type;\n    let name = &invocation.db_name;\n    let attrs = &invocation.attrs;\n    let guard_type = &invocation.type_name;\n    let vis = &invocation.visibility;\n    let fairing_name = format!(\"'{}' Database Pool\", name);\n    let span = conn_type.span();\n\n    // A few useful paths.\n    let root = quote_spanned!(span => ::rocket_sync_db_pools);\n    let rocket = quote!(#root::rocket);\n\n    let request_guard_type = quote_spanned! { span =>\n        #(#attrs)* #vis struct #guard_type(#[allow(dead_code)] #root::Connection<Self, #conn_type>);\n    };\n\n    let pool = quote_spanned!(span => #root::ConnectionPool<Self, #conn_type>);\n    let conn = quote_spanned!(span => #root::Connection<Self, #conn_type>);\n\n    Ok(quote_spanned! { span =>\n        #request_guard_type\n\n        #[allow(dead_code)]\n        impl #guard_type {\n            /// Returns a fairing that initializes the database connection pool.\n            pub fn fairing() -> impl #rocket::fairing::Fairing {\n                <#pool>::fairing(#fairing_name, #name)\n            }\n\n            /// Returns an opaque type that represents the connection pool\n            /// backing connections of type `Self`.\n            pub fn pool<P: #rocket::Phase>(__rocket: &#rocket::Rocket<P>) -> Option<&#pool> {\n                <#pool>::pool(&__rocket)\n            }\n\n            /// Runs the provided function `__f` in an async-safe blocking\n            /// thread.\n            pub async fn run<F, R>(&self, __f: F) -> R\n                where F: FnOnce(&mut #conn_type) -> R + Send + 'static,\n                      R: Send + 'static,\n            {\n                self.0.run(__f).await\n            }\n\n            /// Retrieves a connection of type `Self` from the `rocket` instance.\n            pub async fn get_one<P: #rocket::Phase>(__rocket: &#rocket::Rocket<P>) -> Option<Self> {\n                <#pool>::get_one(&__rocket).await.map(Self)\n            }\n        }\n\n        #[#rocket::async_trait]\n        impl<'r> #rocket::request::FromRequest<'r> for #guard_type {\n            type Error = ();\n\n            async fn from_request(\n                __r: &'r #rocket::request::Request<'_>\n            ) -> #rocket::request::Outcome<Self, ()> {\n                <#conn>::from_request(__r).await.map(Self)\n            }\n        }\n\n        impl #rocket::Sentinel for #guard_type {\n            fn abort(__r: &#rocket::Rocket<#rocket::Ignite>) -> bool {\n                <#conn>::abort(__r)\n            }\n        }\n    }.into())\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/src/lib.rs",
    "content": "//! Code generation for rocket-sync-db-pools.\n\n#![recursion_limit=\"256\"]\n#![warn(rust_2018_idioms)]\n\n#[macro_use]\nextern crate quote;\n\nmod database;\n\nuse devise::{syn, proc_macro2};\nuse proc_macro::TokenStream;\n\n/// Generates a request guard and fairing for retrieving a database connection.\n///\n/// The syntax for the `databases` macro is:\n///\n/// <pre>\n/// macro := 'database' '( DATABASE_NAME ')'\n///\n/// DATABASE_NAME := string literal\n/// </pre>\n///\n/// The attribute accepts a single string parameter that indicates the name of\n/// the database. This corresponds to the database name set as the database's\n/// configuration key:\n///\n/// The macro generates a [`FromRequest`] implementation for the decorated type,\n/// allowing the type to be used as a request guard. This implementation\n/// retrieves a connection from the database pool or fails with a\n/// `Status::ServiceUnavailable` if connecting to the database times out.\n///\n/// The macro also generates three inherent methods on the decorated type:\n///\n///   * `fn fairing() -> impl Fairing`\n///\n///      Returns a fairing that initializes the associated database connection\n///      pool.\n///\n///   * `async fn get_one<P: Phase>(&Rocket<P>) -> Option<Self>`\n///\n///     Retrieves a connection wrapper from the configured pool. Returns `Some`\n///     as long as `Self::fairing()` has been attached.\n///\n///   * `async fn run<R: Send + 'static>(&self, impl FnOnce(&mut Db) -> R + Send + 'static) -> R`\n///\n///     Runs the specified function or closure, providing it access to the\n///     underlying database connection (`&mut Db`). Returns the value returned\n///     by the function or closure.\n///\n/// [`FromRequest`]: rocket::request::FromRequest\n#[proc_macro_attribute]\npub fn database(attr: TokenStream, input: TokenStream) -> TokenStream {\n    crate::database::database_attr(attr, input)\n        .unwrap_or_else(|diag| diag.emit_as_item_tokens().into())\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/tests/ui-fail/database-syntax.rs",
    "content": "use rocket_sync_db_pools::database;\n\nstruct Connection;\nstruct Manager;\n\nuse rocket::{Rocket, Build};\nuse rocket_sync_db_pools::{r2d2, Poolable, PoolResult};\n\nimpl r2d2::ManageConnection for Manager {\n    type Connection = Connection;\n    type Error = std::convert::Infallible;\n\n    fn connect(&self) -> Result<Self::Connection, Self::Error> { Ok(Connection) }\n    fn is_valid(&self, _: &mut Self::Connection) -> Result<(), Self::Error> { Ok(()) }\n    fn has_broken(&self, _: &mut Self::Connection) -> bool { true }\n}\n\nimpl Poolable for Connection {\n    type Manager = Manager;\n    type Error = std::convert::Infallible;\n\n    fn pool(_: &str, _: &Rocket<Build>) -> PoolResult<Self> {\n        todo!()\n    }\n}\n\n#[database]\nstruct A(Connection);\n\n#[database(1)]\nstruct B(Connection);\n\n#[database(123)]\nstruct C(Connection);\n\n#[database(\"hello\" \"hi\")]\nstruct D(Connection);\n\n#[database(\"test\")]\nenum Foo {  }\n\n#[database(\"test\")]\nstruct Bar(Connection, Connection);\n\n#[database(\"test\")]\nunion Baz {  }\n\n#[database(\"test\")]\nstruct E<'r>(&'r str);\n\n#[database(\"test\")]\nstruct F<T>(T);\n\nfn main() {  }\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/tests/ui-fail/database-types.rs",
    "content": "#[macro_use] extern crate rocket_sync_db_pools;\n\nstruct Unknown;\n\n#[database(\"foo\")]\nstruct A(Unknown);\n\n#[database(\"foo\")]\nstruct B(Vec<i32>);\n\nfn main() {  }\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/tests/ui-fail-nightly/database-syntax.stderr",
    "content": "error: unexpected end of input, expected string literal\n  --> tests/ui-fail-nightly/database-syntax.rs:27:1\n   |\n27 | #[database]\n   | ^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected string literal\n  --> tests/ui-fail-nightly/database-syntax.rs:30:12\n   |\n30 | #[database(1)]\n   |            ^\n\nerror: expected string literal\n  --> tests/ui-fail-nightly/database-syntax.rs:33:12\n   |\n33 | #[database(123)]\n   |            ^^^\n\nerror: unexpected token\n  --> tests/ui-fail-nightly/database-syntax.rs:36:20\n   |\n36 | #[database(\"hello\" \"hi\")]\n   |                    ^^^^\n\nerror: `database` attribute can only be used on structs\n  --> tests/ui-fail-nightly/database-syntax.rs:40:1\n   |\n40 | enum Foo {  }\n   | ^^^^^^^^^^^^^\n\nerror: `database` attribute can only be applied to structs with exactly one unnamed field\n  --> tests/ui-fail-nightly/database-syntax.rs:43:11\n   |\n43 | struct Bar(Connection, Connection);\n   |           ^^^^^^^^^^^^^^^^^^^^^^^^\n   |\n   = help: example: `struct MyDatabase(diesel::SqliteConnection);`\n\nerror: `database` attribute can only be used on structs\n  --> tests/ui-fail-nightly/database-syntax.rs:46:1\n   |\n46 | union Baz {  }\n   | ^^^^^^^^^^^^^^\n\nerror: `database` attribute cannot be applied to structs with generics\n  --> tests/ui-fail-nightly/database-syntax.rs:49:9\n   |\n49 | struct E<'r>(&'r str);\n   |         ^^^^\n\nerror: `database` attribute cannot be applied to structs with generics\n  --> tests/ui-fail-nightly/database-syntax.rs:52:9\n   |\n52 | struct F<T>(T);\n   |         ^^^\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/tests/ui-fail-nightly/database-types.stderr",
    "content": "error[E0277]: the trait bound `Unknown: Poolable` is not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n6 | struct A(Unknown);\n  |          ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`\n  |\nnote: required by a bound in `rocket_sync_db_pools::Connection`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  |                             ^^^^^^^^ required by this bound in `Connection`\n\nerror[E0599]: the function or associated item `fairing` exists for struct `ConnectionPool<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `ConnectionPool<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0277]: the trait bound `Unknown: Poolable` is not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n6 | struct A(Unknown);\n  |          ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`\n  |\nnote: required by a bound in `ConnectionPool`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct ConnectionPool<K, C: Poolable> {\n  |                                 ^^^^^^^^ required by this bound in `ConnectionPool`\n\nerror[E0599]: the method `run` exists for struct `Connection<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ method cannot be called on `Connection<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0599]: the function or associated item `get_one` exists for struct `ConnectionPool<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `ConnectionPool<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`\n  |\nnote: required by a bound in `rocket_sync_db_pools::Connection`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  |                             ^^^^^^^^ required by this bound in `Connection`\n\nerror[E0599]: the function or associated item `fairing` exists for struct `ConnectionPool<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `ConnectionPool<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`\n  |\nnote: required by a bound in `ConnectionPool`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct ConnectionPool<K, C: Poolable> {\n  |                                 ^^^^^^^^ required by this bound in `ConnectionPool`\n\nerror[E0599]: the method `run` exists for struct `Connection<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ method cannot be called on `Connection<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0599]: the function or associated item `get_one` exists for struct `ConnectionPool<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `ConnectionPool<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0599]: the function or associated item `pool` exists for struct `ConnectionPool<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `ConnectionPool<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0599]: the function or associated item `from_request` exists for struct `Connection<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `Connection<A, Unknown>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: FromRequest<'_>`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<A, Unknown>: FromRequest<'_>`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0599]: the function or associated item `abort` exists for struct `Connection<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `Connection<A, Unknown>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: Sentinel`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<A, Unknown>: Sentinel`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  = help: items from traits can only be used if the trait is in scope\nhelp: trait `DefaultSentinel` which provides `abort` is implemented but not in scope; perhaps you want to import it\n  |\n1   + use crate::rocket_sync_db_pools::rocket::sentinel::resolution::DefaultSentinel;\n    |\n\nerror[E0599]: the function or associated item `pool` exists for struct `ConnectionPool<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `ConnectionPool<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0599]: the function or associated item `from_request` exists for struct `Connection<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `Connection<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: FromRequest<'_>`\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<B, Vec<i32>>: FromRequest<'_>`\n\nerror[E0599]: the function or associated item `abort` exists for struct `Connection<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-nightly/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `Connection<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: Sentinel`\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<B, Vec<i32>>: Sentinel`\n  = help: items from traits can only be used if the trait is in scope\nhelp: trait `DefaultSentinel` which provides `abort` is implemented but not in scope; perhaps you want to import it\n  |\n1   + use crate::rocket_sync_db_pools::rocket::sentinel::resolution::DefaultSentinel;\n    |\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/tests/ui-fail-stable/database-syntax.stderr",
    "content": "error: unexpected end of input, expected string literal\n  --> tests/ui-fail-stable/database-syntax.rs:27:1\n   |\n27 | #[database]\n   | ^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected string literal\n  --> tests/ui-fail-stable/database-syntax.rs:30:12\n   |\n30 | #[database(1)]\n   |            ^\n\nerror: expected string literal\n  --> tests/ui-fail-stable/database-syntax.rs:33:12\n   |\n33 | #[database(123)]\n   |            ^^^\n\nerror: unexpected token\n  --> tests/ui-fail-stable/database-syntax.rs:36:20\n   |\n36 | #[database(\"hello\" \"hi\")]\n   |                    ^^^^\n\nerror: `database` attribute can only be used on structs\n  --> tests/ui-fail-stable/database-syntax.rs:40:1\n   |\n40 | enum Foo {  }\n   | ^^^^^^^^^^^^^\n\nerror: `database` attribute can only be applied to structs with exactly one unnamed field\n       = help: example: `struct MyDatabase(diesel::SqliteConnection);`\n  --> tests/ui-fail-stable/database-syntax.rs:43:11\n   |\n43 | struct Bar(Connection, Connection);\n   |           ^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: `database` attribute can only be used on structs\n  --> tests/ui-fail-stable/database-syntax.rs:46:1\n   |\n46 | union Baz {  }\n   | ^^^^^^^^^^^^^^\n\nerror: `database` attribute cannot be applied to structs with generics\n  --> tests/ui-fail-stable/database-syntax.rs:49:9\n   |\n49 | struct E<'r>(&'r str);\n   |         ^^^^\n\nerror: `database` attribute cannot be applied to structs with generics\n  --> tests/ui-fail-stable/database-syntax.rs:52:9\n   |\n52 | struct F<T>(T);\n   |         ^^^\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/tests/ui-fail-stable/database-types.stderr",
    "content": "error[E0277]: the trait bound `Unknown: Poolable` is not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n6 | struct A(Unknown);\n  |          ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`\n  |\nnote: required by a bound in `rocket_sync_db_pools::Connection`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  |                             ^^^^^^^^ required by this bound in `Connection`\n\nerror[E0599]: the function or associated item `fairing` exists for struct `ConnectionPool<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `ConnectionPool<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0277]: the trait bound `Unknown: Poolable` is not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n6 | struct A(Unknown);\n  |          ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`\n  |\nnote: required by a bound in `ConnectionPool`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct ConnectionPool<K, C: Poolable> {\n  |                                 ^^^^^^^^ required by this bound in `ConnectionPool`\n\nerror[E0599]: the method `run` exists for struct `Connection<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ method cannot be called on `Connection<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0599]: the function or associated item `get_one` exists for struct `ConnectionPool<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `ConnectionPool<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`\n  |\nnote: required by a bound in `rocket_sync_db_pools::Connection`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  |                             ^^^^^^^^ required by this bound in `Connection`\n\nerror[E0599]: the function or associated item `fairing` exists for struct `ConnectionPool<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `ConnectionPool<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`\n  |\nnote: required by a bound in `ConnectionPool`\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct ConnectionPool<K, C: Poolable> {\n  |                                 ^^^^^^^^ required by this bound in `ConnectionPool`\n\nerror[E0599]: the method `run` exists for struct `Connection<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ method cannot be called on `Connection<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0599]: the function or associated item `get_one` exists for struct `ConnectionPool<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `ConnectionPool<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0599]: the function or associated item `pool` exists for struct `ConnectionPool<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `ConnectionPool<A, Unknown>` due to unsatisfied trait bounds\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0599]: the function or associated item `from_request` exists for struct `Connection<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `Connection<A, Unknown>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: FromRequest<'_>`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<A, Unknown>: FromRequest<'_>`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0599]: the function or associated item `abort` exists for struct `Connection<A, Unknown>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:6:10\n  |\n3 | struct Unknown;\n  | -------------- doesn't satisfy `Unknown: Poolable`\n...\n6 | struct A(Unknown);\n  |          ^^^^^^^ function or associated item cannot be called on `Connection<A, Unknown>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: Sentinel`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Unknown: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<A, Unknown>: Sentinel`\nnote: the trait `Poolable` must be implemented\n --> $WORKSPACE/contrib/sync_db_pools/lib/src/poolable.rs\n  |\n  | pub trait Poolable: Send + Sized + 'static {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  = help: items from traits can only be used if the trait is in scope\nhelp: trait `DefaultSentinel` which provides `abort` is implemented but not in scope; perhaps you want to import it\n  |\n1   + use crate::rocket_sync_db_pools::rocket::sentinel::resolution::DefaultSentinel;\n    |\n\nerror[E0599]: the function or associated item `pool` exists for struct `ConnectionPool<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `ConnectionPool<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n\nerror[E0599]: the function or associated item `from_request` exists for struct `Connection<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `Connection<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: FromRequest<'_>`\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<B, Vec<i32>>: FromRequest<'_>`\n\nerror[E0599]: the function or associated item `abort` exists for struct `Connection<B, Vec<i32>>`, but its trait bounds were not satisfied\n --> tests/ui-fail-stable/database-types.rs:9:10\n  |\n9 | struct B(Vec<i32>);\n  |          ^^^^^^^^ function or associated item cannot be called on `Connection<B, Vec<i32>>` due to unsatisfied trait bounds\n  |\n ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs\n  |\n  | pub struct Connection<K, C: Poolable> {\n  | ------------------------------------- doesn't satisfy `_: Sentinel`\n  |\n ::: $RUST/alloc/src/vec/mod.rs\n  |\n  | pub struct Vec<T, #[unstable(feature = \"allocator_api\", issue = \"32838\")] A: Allocator = Global> {\n  | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<i32>: Poolable`\n  |\n  = note: the following trait bounds were not satisfied:\n          `Vec<i32>: Poolable`\n          which is required by `rocket_sync_db_pools::Connection<B, Vec<i32>>: Sentinel`\n  = help: items from traits can only be used if the trait is in scope\nhelp: trait `DefaultSentinel` which provides `abort` is implemented but not in scope; perhaps you want to import it\n  |\n1   + use crate::rocket_sync_db_pools::rocket::sentinel::resolution::DefaultSentinel;\n    |\n"
  },
  {
    "path": "contrib/sync_db_pools/codegen/tests/ui-fail.rs",
    "content": "#[test]\n#[ignore]\nfn ui() {\n    let path = match version_check::is_feature_flaggable() {\n        Some(true) => \"ui-fail-nightly\",\n        _ => \"ui-fail-stable\"\n    };\n\n    let t = trybuild::TestCases::new();\n    t.compile_fail(format!(\"tests/{}/*.rs\", path));\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/Cargo.toml",
    "content": "[package]\nname = \"rocket_sync_db_pools\"\nversion = \"0.1.0\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\"]\ndescription = \"Rocket async database pooling support for sync database drivers.\"\nrepository = \"https://github.com/rwf2/Rocket/tree/master/contrib/sync_db_pools\"\nreadme = \"../README.md\"\nkeywords = [\"rocket\", \"framework\", \"database\", \"pools\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[lints]\nworkspace = true\n\n[features]\ndiesel_sqlite_pool = [\"diesel/sqlite\", \"diesel/r2d2\"]\ndiesel_postgres_pool = [\"diesel/postgres\", \"diesel/r2d2\"]\ndiesel_mysql_pool = [\"diesel/mysql\", \"diesel/r2d2\"]\nsqlite_pool = [\"rusqlite\", \"r2d2_sqlite\"]\npostgres_pool = [\"postgres\", \"r2d2_postgres\"]\nmemcache_pool = [\"memcache\"]\n\n[dependencies]\nr2d2 = \"0.8\"\ntokio = { version = \"1.6.1\", features = [\"rt\", \"rt-multi-thread\"] }\nserde = { version = \"1.0\", features = [\"derive\"] }\n\ndiesel = { version = \"2.0.0\", default-features = false, optional = true }\n\npostgres = { version = \"0.19\", optional = true }\nr2d2_postgres = { version = \"0.18\", optional = true }\n\nrusqlite = { version = \"0.31.0\", optional = true }\nr2d2_sqlite = { version = \"0.24.0\", optional = true }\n\nmemcache = { version = \"0.17.2\", optional = true }\n\n[dependencies.rocket_sync_db_pools_codegen]\nversion = \"0.1.0\"\npath = \"../codegen\"\n\n[dependencies.rocket]\nversion = \"0.6.0-dev\"\npath = \"../../../core/lib\"\ndefault-features = false\n\n[build-dependencies]\nversion_check = \"0.9.1\"\n\n[dev-dependencies.rocket]\nversion = \"0.6.0-dev\"\npath = \"../../../core/lib\"\ndefault-features = false\nfeatures = [\"trace\"]\n\n[package.metadata.docs.rs]\nall-features = true\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/build.rs",
    "content": "fn main() {\n    if let Some(true) = version_check::is_feature_flaggable() {\n        println!(\"cargo:rustc-cfg=nightly\");\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/src/config.rs",
    "content": "use rocket::{Rocket, Build};\nuse rocket::figment::{self, Figment, providers::Serialized};\n\nuse serde::{Serialize, Deserialize};\n\n/// A base `Config` for any `Poolable` type.\n///\n/// For the following configuration:\n///\n/// ```toml\n/// [global.databases.my_database]\n/// url = \"postgres://root:root@localhost/my_database\"\n/// pool_size = 10\n/// timeout = 5\n/// ```\n///\n/// ...`Config::from(\"my_database\", rocket)` would return the following struct:\n///\n/// ```rust\n/// # use rocket_sync_db_pools::Config;\n/// Config {\n///     url: \"postgres://root:root@localhost/my_database\".into(),\n///     pool_size: 10,\n///     timeout: 5\n/// };\n/// ```\n///\n/// If you want to implement your own custom database adapter (or other\n/// database-like struct that can be pooled by `r2d2`) and need some more\n/// configurations options, you may need to define a custom `Config` struct.\n/// Note, however, that the configuration values in `Config` are required.\n#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]\npub struct Config {\n    /// Connection URL specified in the Rocket configuration.\n    pub url: String,\n    /// Initial pool size. Defaults to the number of Rocket workers * 4.\n    pub pool_size: u32,\n    /// How long to wait, in seconds, for a new connection before timing out.\n    /// Defaults to `5`.\n    // FIXME: Use `time`.\n    pub timeout: u8,\n}\n\nimpl Config {\n    /// Retrieves the database configuration for the database named `name`.\n    ///\n    /// This function is primarily used by the generated code from the\n    /// `#[database]` attribute.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[cfg(feature = \"diesel_sqlite_pool\")] {\n    /// # use rocket::figment::{Figment, providers::{Format, Toml}};\n    /// // Assume that these are the contents of `Rocket.toml`:\n    /// # let toml = Toml::string(r#\"\n    /// [default.databases]\n    /// my_db = { url = \"db/db.sqlite\", pool_size = 25 }\n    /// my_other_db = { url = \"mysql://root:root@localhost/database\" }\n    /// # \"#).nested();\n    ///\n    /// use rocket::{Rocket, Build};\n    /// use rocket_sync_db_pools::Config;\n    ///\n    /// fn pool(rocket: &Rocket<Build>) {\n    ///     let config = Config::from(\"my_db\", rocket).unwrap();\n    ///     assert_eq!(config.url, \"db/db.sqlite\");\n    ///     assert_eq!(config.pool_size, 25);\n    ///\n    ///     let config = Config::from(\"my_other_db\", rocket).unwrap();\n    ///     assert_eq!(config.url, \"mysql://root:root@localhost/database\");\n    ///\n    ///     let workers = rocket.figment().extract_inner::<u32>(rocket::Config::WORKERS);\n    ///     assert_eq!(config.pool_size, (workers.unwrap() * 4));\n    ///\n    ///     let config = Config::from(\"unknown_db\", rocket);\n    ///     assert!(config.is_err())\n    /// }\n    /// #\n    /// # let config = Figment::from(rocket::Config::default()).merge(toml);\n    /// # let rocket = rocket::custom(config);\n    /// # pool(&rocket);\n    /// # }\n    /// ```\n    pub fn from(db_name: &str, rocket: &Rocket<Build>) -> Result<Config, figment::Error> {\n        Config::figment(db_name, rocket).extract::<Self>()\n    }\n\n    /// Returns a `Figment` focused on the configuration for the database with\n    /// name `db_name`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::{Rocket, Build};\n    /// use rocket_sync_db_pools::Config;\n    ///\n    /// fn pool(rocket: &Rocket<Build>) {\n    ///     let my_db_figment = Config::figment(\"my_db\", rocket);\n    ///     let mysql_prod_figment = Config::figment(\"mysql_prod\", rocket);\n    /// }\n    /// ```\n    pub fn figment(db_name: &str, rocket: &Rocket<Build>) -> Figment {\n        let db_key = format!(\"databases.{}\", db_name);\n        let default_pool_size = rocket.figment()\n            .extract_inner::<u32>(rocket::Config::WORKERS)\n            .map(|workers| workers * 4)\n            .ok();\n\n        let figment = Figment::from(rocket.figment())\n            .focus(&db_key)\n            .join(Serialized::default(\"timeout\", 5));\n\n        match default_pool_size {\n            Some(pool_size) => figment.join(Serialized::default(\"pool_size\", pool_size)),\n            None => figment\n        }\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/src/connection.rs",
    "content": "use std::sync::Arc;\nuse std::marker::PhantomData;\n\nuse rocket::{Phase, Rocket, Ignite, Sentinel};\nuse rocket::fairing::{AdHoc, Fairing};\nuse rocket::request::{Request, Outcome, FromRequest};\nuse rocket::outcome::IntoOutcome;\nuse rocket::http::Status;\nuse rocket::trace::Trace;\n\nuse rocket::tokio::time::timeout;\nuse rocket::tokio::sync::{OwnedSemaphorePermit, Semaphore, Mutex};\n\nuse crate::{Config, Poolable, Error};\n\n/// Unstable internal details of generated code for the #[database] attribute.\n///\n/// This type is implemented here instead of in generated code to ensure all\n/// types are properly checked.\n#[doc(hidden)]\npub struct ConnectionPool<K, C: Poolable> {\n    config: Config,\n    // This is an 'Option' so that we can drop the pool in a 'spawn_blocking'.\n    pool: Option<r2d2::Pool<C::Manager>>,\n    semaphore: Arc<Semaphore>,\n    _marker: PhantomData<fn() -> K>,\n}\n\nimpl<K, C: Poolable> Clone for ConnectionPool<K, C> {\n    fn clone(&self) -> Self {\n        ConnectionPool {\n            config: self.config.clone(),\n            pool: self.pool.clone(),\n            semaphore: self.semaphore.clone(),\n            _marker: PhantomData\n        }\n    }\n}\n\n/// Unstable internal details of generated code for the #[database] attribute.\n///\n/// This type is implemented here instead of in generated code to ensure all\n/// types are properly checked.\n#[doc(hidden)]\npub struct Connection<K, C: Poolable> {\n    connection: Arc<Mutex<Option<r2d2::PooledConnection<C::Manager>>>>,\n    permit: Option<OwnedSemaphorePermit>,\n    _marker: PhantomData<fn() -> K>,\n}\n\n// A wrapper around spawn_blocking that propagates panics to the calling code.\nasync fn run_blocking<F, R>(job: F) -> R\n    where F: FnOnce() -> R + Send + 'static, R: Send + 'static,\n{\n    match tokio::task::spawn_blocking(job).await {\n        Ok(ret) => ret,\n        Err(e) => match e.try_into_panic() {\n            Ok(panic) => std::panic::resume_unwind(panic),\n            Err(_) => unreachable!(\"spawn_blocking tasks are never cancelled\"),\n        }\n    }\n}\n\nimpl<K: 'static, C: Poolable> ConnectionPool<K, C> {\n    pub fn fairing(fairing_name: &'static str, database: &'static str) -> impl Fairing {\n        AdHoc::try_on_ignite(fairing_name, move |rocket| async move {\n            run_blocking(move || {\n                let config = match Config::from(database, &rocket) {\n                    Ok(config) => config,\n                    Err(e) => {\n                        span_error!(\"database configuration error\", database => e.trace_error());\n                        return Err(rocket);\n                    }\n                };\n\n                let pool_size = config.pool_size;\n                match C::pool(database, &rocket) {\n                    Ok(pool) => Ok(rocket.manage(ConnectionPool::<K, C> {\n                        config,\n                        pool: Some(pool),\n                        semaphore: Arc::new(Semaphore::new(pool_size as usize)),\n                        _marker: PhantomData,\n                    })),\n                    Err(Error::Config(e)) => {\n                        span_error!(\"database configuration error\", database => e.trace_error());\n                        Err(rocket)\n                    }\n                    Err(Error::Pool(reason)) => {\n                        error!(database, %reason, \"database pool initialization failed\");\n                        Err(rocket)\n                    }\n                    Err(Error::Custom(reason)) => {\n                        error!(database, ?reason, \"database pool failure\");\n                        Err(rocket)\n                    }\n                }\n            }).await\n        })\n    }\n\n    pub async fn get(&self) -> Option<Connection<K, C>> {\n        let type_name = std::any::type_name::<K>();\n        let duration = std::time::Duration::from_secs(self.config.timeout as u64);\n        let permit = match timeout(duration, self.semaphore.clone().acquire_owned()).await {\n            Ok(p) => p.expect(\"internal invariant broken: semaphore should not be closed\"),\n            Err(_) => {\n                error!(type_name, \"database connection retrieval timed out\");\n                return None;\n            }\n        };\n\n        let pool = self.pool.as_ref().cloned()\n            .expect(\"internal invariant broken: self.pool is Some\");\n\n        match run_blocking(move || pool.get_timeout(duration)).await {\n            Ok(c) => Some(Connection {\n                connection: Arc::new(Mutex::new(Some(c))),\n                permit: Some(permit),\n                _marker: PhantomData,\n            }),\n            Err(e) => {\n                error!(type_name, \"failed to get a database connection: {}\", e);\n                None\n            }\n        }\n    }\n\n    #[inline]\n    pub async fn get_one<P: Phase>(rocket: &Rocket<P>) -> Option<Connection<K, C>> {\n        match Self::pool(rocket) {\n            Some(pool) => match pool.get().await {\n                Some(conn) => Some(conn),\n                None => {\n                    error!(\"no connections available for `{}`\", std::any::type_name::<K>());\n                    None\n                }\n            },\n            None => {\n                error!(\"missing database fairing for `{}`\", std::any::type_name::<K>());\n                None\n            }\n        }\n    }\n\n    #[inline]\n    pub fn pool<P: Phase>(rocket: &Rocket<P>) -> Option<&Self> {\n        rocket.state::<Self>()\n    }\n}\n\nimpl<K: 'static, C: Poolable> Connection<K, C> {\n    pub async fn run<F, R>(&self, f: F) -> R\n        where F: FnOnce(&mut C) -> R + Send + 'static,\n              R: Send + 'static,\n    {\n        // It is important that this inner Arc<Mutex<>> (or the OwnedMutexGuard\n        // derived from it) never be a variable on the stack at an await point,\n        // where Drop might be called at any time. This causes (synchronous)\n        // Drop to be called from asynchronous code, which some database\n        // wrappers do not or can not handle.\n        let connection = self.connection.clone();\n\n        // Since connection can't be on the stack in an async fn during an\n        // await, we have to spawn a new blocking-safe thread...\n        run_blocking(move || {\n            // And then re-enter the runtime to wait on the async mutex, but in\n            // a blocking fashion.\n            let mut connection = tokio::runtime::Handle::current().block_on(async {\n                connection.lock_owned().await\n            });\n\n            let conn = connection.as_mut()\n                .expect(\"internal invariant broken: self.connection is Some\");\n\n            f(conn)\n        }).await\n    }\n}\n\nimpl<K, C: Poolable> Drop for Connection<K, C> {\n    fn drop(&mut self) {\n        let connection = self.connection.clone();\n        let permit = self.permit.take();\n\n        // Only use spawn_blocking if the Tokio runtime is still available\n        if let Ok(handle) = tokio::runtime::Handle::try_current() {\n            // See above for motivation of this arrangement of spawn_blocking/block_on\n            handle.spawn_blocking(move || {\n                let mut connection = tokio::runtime::Handle::current()\n                    .block_on(async { connection.lock_owned().await });\n\n                if let Some(conn) = connection.take() {\n                    drop(conn);\n                }\n            });\n        } else {\n            warn!(type_name = std::any::type_name::<K>(),\n                \"database connection is being dropped outside of an async context\\n\\\n                this means you have stored a connection beyond a request's lifetime\\n\\\n                this is not recommended: connections are not valid indefinitely\\n\\\n                instead, store a connection pool and get connections as needed\");\n\n            if let Some(conn) = connection.blocking_lock().take() {\n                drop(conn);\n            }\n        }\n\n        // Explicitly drop permit here to release only after dropping connection.\n        drop(permit);\n    }\n}\n\nimpl<K, C: Poolable> Drop for ConnectionPool<K, C> {\n    fn drop(&mut self) {\n        // Use spawn_blocking if the Tokio runtime is still available. Otherwise\n        // the pool will be dropped on the current thread.\n        let pool = self.pool.take();\n        if let Ok(handle) = tokio::runtime::Handle::try_current() {\n            handle.spawn_blocking(move || drop(pool));\n        }\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r, K: 'static, C: Poolable> FromRequest<'r> for Connection<K, C> {\n    type Error = ();\n\n    #[inline]\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, ()> {\n        match request.rocket().state::<ConnectionPool<K, C>>() {\n            Some(c) => c.get().await.or_error((Status::ServiceUnavailable, ())),\n            None => {\n                let conn = std::any::type_name::<K>();\n                error!(\"`{conn}::fairing()` is not attached\\n\\\n                    the fairing must be attached to use `{conn} in routes.\");\n                Outcome::Error((Status::InternalServerError, ()))\n            }\n        }\n    }\n}\n\nimpl<K: 'static, C: Poolable> Sentinel for Connection<K, C> {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        if rocket.state::<ConnectionPool<K, C>>().is_none() {\n            let conn = std::any::type_name::<K>();\n            error!(\"`{conn}::fairing()` is not attached\\n\\\n                the fairing must be attached to use `{conn} in routes.\");\n\n            return true;\n        }\n\n        false\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/src/error.rs",
    "content": "use rocket::figment;\n\n/// A wrapper around `r2d2::Error`s or a custom database error type.\n///\n/// This type is only relevant to implementors of the [`Poolable`] trait. See\n/// the [`Poolable`] documentation for more information on how to use this type.\n///\n/// [`Poolable`]: crate::Poolable\n#[derive(Debug)]\npub enum Error<T> {\n    /// A custom error of type `T`.\n    Custom(T),\n    /// An error occurred while initializing an `r2d2` pool.\n    Pool(r2d2::Error),\n    /// An error occurred while extracting a `figment` configuration.\n    Config(figment::Error),\n}\n\nimpl<T> From<figment::Error> for Error<T> {\n    fn from(error: figment::Error) -> Self {\n        Error::Config(error)\n    }\n}\n\nimpl<T> From<r2d2::Error> for Error<T> {\n    fn from(error: r2d2::Error) -> Self {\n        Error::Pool(error)\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/src/lib.rs",
    "content": "//! Traits, utilities, and a macro for easy database connection pooling.\n//!\n//! # Overview\n//!\n//! This crate provides traits, utilities, and a procedural macro for\n//! configuring and accessing database connection pools in Rocket. A _database\n//! connection pool_ is a data structure that maintains active database\n//! connections for later use in the application. This implementation is backed\n//! by [`r2d2`] and exposes connections through request guards.\n//!\n//! Databases are individually configured through Rocket's regular configuration\n//! mechanisms. Connecting a Rocket application to a database using this library\n//! occurs in three simple steps:\n//!\n//!   1. Configure your databases in `Rocket.toml`.\n//!      (see [Configuration](#configuration))\n//!   2. Associate a request guard type and fairing with each database.\n//!      (see [Guard Types](#guard-types))\n//!   3. Use the request guard to retrieve a connection in a handler.\n//!      (see [Handlers](#handlers))\n//!\n//! For a list of supported databases, see [Provided Databases](#provided). This\n//! support can be easily extended by implementing the [`Poolable`] trait. See\n//! [Extending](#extending) for more.\n//!\n//! ## Example\n//!\n//! Before using this library, the feature corresponding to your database type\n//! in `rocket_sync_db_pools` must be enabled:\n//!\n//! ```toml\n//! [dependencies.rocket_sync_db_pools]\n//! version = \"0.1.0\"\n//! features = [\"diesel_sqlite_pool\"]\n//! ```\n//!\n//! See [Provided](#provided) for a list of supported database and their\n//! associated feature name.\n//!\n//! In whichever configuration source you choose, configure a `databases`\n//! dictionary with an internal dictionary for each database, here `sqlite_logs`\n//! in a TOML source:\n//!\n//! ```toml\n//! [default.databases]\n//! sqlite_logs = { url = \"/path/to/database.sqlite\" }\n//! ```\n//!\n//! In your application's source code, one-time:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! # #[cfg(feature = \"diesel_sqlite_pool\")]\n//! # mod test {\n//! use rocket_sync_db_pools::{database, diesel};\n//!\n//! #[database(\"sqlite_logs\")]\n//! struct LogsDbConn(diesel::SqliteConnection);\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//!     rocket::build().attach(LogsDbConn::fairing())\n//! }\n//! # } fn main() {}\n//! ```\n//!\n//! Whenever a connection to the database is needed:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! # #[macro_use] extern crate rocket_sync_db_pools;\n//! #\n//! # #[cfg(feature = \"diesel_sqlite_pool\")]\n//! # mod test {\n//! # use rocket_sync_db_pools::diesel;\n//! #\n//! # #[database(\"sqlite_logs\")]\n//! # struct LogsDbConn(diesel::SqliteConnection);\n//! #\n//! # type Logs = ();\n//! # type Result<T> = std::result::Result<T, ()>;\n//! #\n//! #[get(\"/logs/<id>\")]\n//! async fn get_logs(conn: LogsDbConn, id: usize) -> Result<Logs> {\n//! # /*\n//!     conn.run(|c| Logs::by_id(c, id)).await\n//! # */\n//! # Ok(())\n//! }\n//! # } fn main() {}\n//! ```\n//!\n//! # Usage\n//!\n//! ## Configuration\n//!\n//! Databases can be configured as any other values. Using the default\n//! configuration provider, either via `Rocket.toml` or environment variables.\n//! You can also use a custom provider.\n//!\n//! ### `Rocket.toml`\n//!\n//! To configure a database via `Rocket.toml`, add a table for each database to\n//! the `databases` table where the key is a name of your choice. The table\n//! should have a `url` key and, optionally, `pool_size` and `timeout` keys.\n//! This looks as follows:\n//!\n//! ```toml\n//! # Option 1:\n//! [global.databases]\n//! sqlite_db = { url = \"db.sqlite\" }\n//!\n//! # Option 2:\n//! [global.databases.my_db]\n//! url = \"postgres://root:root@localhost/my_db\"\n//!\n//! # With `pool_size` and `timeout` keys:\n//! [global.databases.sqlite_db]\n//! url = \"db.sqlite\"\n//! pool_size = 20\n//! timeout = 5\n//! ```\n//!\n//! The table _requires_ one key:\n//!\n//!   * `url` - the URl to the database\n//!\n//! Additionally, all configurations accept the following _optional_ keys:\n//!\n//!   * `pool_size` - the size of the pool, i.e., the number of connections to\n//!     pool (defaults to the configured number of workers * 4)\n//!   * `timeout` - max number of seconds to wait for a connection to become\n//!     available (defaults to `5`)\n//!\n//! Additional options may be required or supported by other adapters.\n//!\n//! ### Procedurally\n//!\n//! Databases can also be configured procedurally via `rocket::custom()`.\n//! The example below does just this:\n//!\n//! ```rust\n//! # #[cfg(feature = \"diesel_sqlite_pool\")] {\n//! # use rocket::launch;\n//! use rocket::figment::{value::{Map, Value}, util::map};\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//!     let db: Map<_, Value> = map! {\n//!         \"url\" => \"db.sqlite\".into(),\n//!         \"pool_size\" => 10.into(),\n//!         \"timeout\" => 5.into(),\n//!     };\n//!\n//!     let figment = rocket::Config::figment()\n//!         .merge((\"databases\", map![\"my_db\" => db]));\n//!\n//!     rocket::custom(figment)\n//! }\n//! # rocket();\n//! # }\n//! ```\n//!\n//! ### Environment Variables\n//!\n//! Lastly, databases can be configured via environment variables by specifying\n//! the `databases` table as detailed in the [Environment Variables\n//! configuration\n//! guide](https://rocket.rs/master/guide/configuration/#environment-variables):\n//!\n//! ```bash\n//! ROCKET_DATABASES='{my_db={url=\"db.sqlite\"}}'\n//! ```\n//!\n//! Multiple databases can be specified in the `ROCKET_DATABASES` environment variable\n//! as well by comma separating them:\n//!\n//! ```bash\n//! ROCKET_DATABASES='{my_db={url=\"db.sqlite\"},my_pg_db={url=\"postgres://root:root@localhost/my_pg_db\"}}'\n//! ```\n//!\n//! ## Guard Types\n//!\n//! Once a database has been configured, the `#[database]` attribute can be used\n//! to tie a type in your application to a configured database. The database\n//! attribute accepts a single string parameter that indicates the name of the\n//! database. This corresponds to the database name set as the database's\n//! configuration key.\n//!\n//! See [`ExampleDb`](example::ExampleDb) for everything that the macro\n//! generates. Specifically, it generates:\n//!\n//!   * A [`FromRequest`] implementation for the decorated type.\n//!   * A [`Sentinel`](rocket::Sentinel) implementation for the decorated type.\n//!   * A [`fairing()`](example::ExampleDb::fairing()) method to initialize the\n//!     database.\n//!   * A [`run()`](example::ExampleDb::run()) method to execute blocking\n//!     database operations in an `async`-safe manner.\n//!   * A [`pool()`](example::ExampleDb::pool()) method to retrieve the\n//!     backing connection pool.\n//!\n//! The attribute can only be applied to tuple structs with one field. The\n//! internal type of the structure must implement [`Poolable`].\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket_sync_db_pools;\n//! # #[cfg(feature = \"diesel_sqlite_pool\")]\n//! # mod test {\n//! use rocket_sync_db_pools::diesel;\n//!\n//! #[database(\"my_db\")]\n//! struct MyDatabase(diesel::SqliteConnection);\n//! # }\n//! ```\n//!\n//! Other databases can be used by specifying their respective [`Poolable`]\n//! type:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket_sync_db_pools;\n//! # #[cfg(feature = \"postgres_pool\")]\n//! # mod test {\n//! use rocket_sync_db_pools::postgres;\n//!\n//! #[database(\"my_pg_db\")]\n//! struct MyPgDatabase(postgres::Client);\n//! # }\n//! ```\n//!\n//! The fairing returned from the generated `fairing()` method _must_ be\n//! attached for the request guard implementation to succeed. Putting the pieces\n//! together, a use of the `#[database]` attribute looks as follows:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! # #[macro_use] extern crate rocket_sync_db_pools;\n//! #\n//! # #[cfg(feature = \"diesel_sqlite_pool\")] {\n//! # use rocket::figment::{value::{Map, Value}, util::map};\n//! use rocket_sync_db_pools::diesel;\n//!\n//! #[database(\"my_db\")]\n//! struct MyDatabase(diesel::SqliteConnection);\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//! #   let db: Map<_, Value> = map![\n//! #        \"url\" => \"db.sqlite\".into(), \"pool_size\" => 10.into()\n//! #   ];\n//! #   let figment = rocket::Config::figment().merge((\"databases\", map![\"my_db\" => db]));\n//!     rocket::custom(figment).attach(MyDatabase::fairing())\n//! }\n//! # }\n//! ```\n//!\n//! ## Handlers\n//!\n//! Finally, use your type as a request guard in a handler to retrieve a\n//! connection wrapper for the database:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! # #[macro_use] extern crate rocket_sync_db_pools;\n//! #\n//! # #[cfg(feature = \"diesel_sqlite_pool\")]\n//! # mod test {\n//! # use rocket_sync_db_pools::diesel;\n//! #[database(\"my_db\")]\n//! struct MyDatabase(diesel::SqliteConnection);\n//!\n//! #[get(\"/\")]\n//! fn my_handler(conn: MyDatabase) {\n//!     // ...\n//! }\n//! # }\n//! ```\n//!\n//! A connection can be retrieved and used with the `run()` method:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! # #[macro_use] extern crate rocket_sync_db_pools;\n//! #\n//! # #[cfg(feature = \"diesel_sqlite_pool\")]\n//! # mod test {\n//! # use rocket_sync_db_pools::diesel;\n//! # type Data = ();\n//! #[database(\"my_db\")]\n//! struct MyDatabase(diesel::SqliteConnection);\n//!\n//! fn load_from_db(conn: &diesel::SqliteConnection) -> Data {\n//!     // Do something with connection, return some data.\n//!     # ()\n//! }\n//!\n//! #[get(\"/\")]\n//! async fn my_handler(mut conn: MyDatabase) -> Data {\n//!     conn.run(|c| load_from_db(c)).await\n//! }\n//! # }\n//! ```\n//!\n//! # Database Support\n//!\n//! Built-in support is provided for many popular databases and drivers. Support\n//! can be easily extended by [`Poolable`] implementations.\n//!\n//! ## Provided\n//!\n//! The list below includes all presently supported database adapters and their\n//! corresponding [`Poolable`] type.\n//!\n// Note: Keep this table in sync with site/guide/6-state.md\n//! | Kind     | Driver                | Version   | `Poolable` Type                | Feature                |\n//! |----------|-----------------------|-----------|--------------------------------|------------------------|\n//! | Sqlite   | [Diesel]              | `2`       | [`diesel::SqliteConnection`]   | `diesel_sqlite_pool`   |\n//! | Postgres | [Diesel]              | `2`       | [`diesel::PgConnection`]       | `diesel_postgres_pool` |\n//! | MySQL    | [Diesel]              | `2`       | [`diesel::MysqlConnection`]    | `diesel_mysql_pool`    |\n//! | Postgres | [Rust-Postgres]       | `0.19`    | [`postgres::Client`]           | `postgres_pool`        |\n//! | Sqlite   | [`Rusqlite`]          | `0.31`    | [`rusqlite::Connection`]       | `sqlite_pool`          |\n//! | Memcache | [`memcache`]          | `0.17`    | [`memcache::Client`]           | `memcache_pool`        |\n//!\n//! [Diesel]: https://diesel.rs\n//! [`diesel::SqliteConnection`]: https://docs.rs/diesel/2/diesel/sqlite/struct.SqliteConnection.html\n//! [`diesel::PgConnection`]: https://docs.rs/diesel/2/diesel/pg/struct.PgConnection.html\n//! [`diesel::MysqlConnection`]: https://docs.rs/diesel/2/diesel/mysql/struct.MysqlConnection.html\n//! [Rust-Postgres]: https://github.com/sfackler/rust-postgres\n//! [`postgres::Client`]: https://docs.rs/postgres/0.19/postgres/struct.Client.html\n//! [`Rusqlite`]: https://github.com/jgallagher/rusqlite\n//! [`rusqlite::Connection`]: https://docs.rs/rusqlite/0.31/rusqlite/struct.Connection.html\n//! [`diesel::PgConnection`]: http://docs.diesel.rs/diesel/pg/struct.PgConnection.html\n//! [`memcache`]: https://github.com/aisk/rust-memcache\n//! [`memcache::Client`]: https://docs.rs/memcache/0.17/memcache/struct.Client.html\n//!\n//! The above table lists all the supported database adapters in this library.\n//! In order to use particular `Poolable` type that's included in this library,\n//! you must first enable the feature listed in the \"Feature\" column. The\n//! interior type of your decorated database type should match the type in the\n//! \"`Poolable` Type\" column.\n//!\n//! ## Extending\n//!\n//! Extending Rocket's support to your own custom database adapter (or other\n//! database-like struct that can be pooled by `r2d2`) is as easy as\n//! implementing the [`Poolable`] trait. See the documentation for [`Poolable`]\n//! for more details on how to implement it.\n//!\n//! [`FromRequest`]: rocket::request::FromRequest\n//! [request guards]: rocket::request::FromRequest\n//! [`Poolable`]: crate::Poolable\n\n#![doc(html_root_url = \"https://api.rocket.rs/master/rocket_sync_db_pools\")]\n#![doc(html_favicon_url = \"https://rocket.rs/images/favicon.ico\")]\n#![doc(html_logo_url = \"https://rocket.rs/images/logo-boxed.png\")]\n#![cfg_attr(nightly, feature(doc_cfg))]\n\n#[doc(hidden)]\n#[macro_use]\npub extern crate rocket;\n\n#[cfg(any(\n    feature = \"diesel_sqlite_pool\",\n    feature = \"diesel_postgres_pool\",\n    feature = \"diesel_mysql_pool\"\n))]\npub use diesel;\n\n#[cfg(feature = \"postgres_pool\")] pub use postgres;\n#[cfg(feature = \"postgres_pool\")] pub use r2d2_postgres;\n\n#[cfg(feature = \"sqlite_pool\")] pub use rusqlite;\n#[cfg(feature = \"sqlite_pool\")] pub use r2d2_sqlite;\n\n#[cfg(feature = \"memcache_pool\")] pub use memcache;\n\npub use r2d2;\n\nmod poolable;\nmod config;\nmod error;\nmod connection;\n\npub use self::poolable::{Poolable, PoolResult};\npub use self::config::Config;\npub use self::error::Error;\n\npub use rocket_sync_db_pools_codegen::*;\npub use self::connection::*;\n\n/// Example of code generated by the `#[database]` attribute.\n#[cfg(all(nightly, doc, feature = \"diesel_sqlite_pool\"))]\npub mod example {\n    use crate::diesel;\n\n    /// Example of code generated by the `#[database]` attribute.\n    ///\n    /// This implementation of `ExampleDb` was generated by:\n    ///\n    /// ```rust\n    /// use rocket_sync_db_pools::{database, diesel};\n    ///\n    /// #[database(\"example\")]\n    /// pub struct ExampleDb(diesel::SqliteConnection);\n    /// ```\n    pub struct ExampleDb(crate::Connection<Self, diesel::SqliteConnection>);\n\n    impl ExampleDb {\n        /// Returns a fairing that initializes the database connection pool\n        /// associated with `Self`.\n        ///\n        /// The fairing _must_ be attached before `Self` can be used as a\n        /// request guard.\n        ///\n        /// # Example\n        ///\n        /// ```rust\n        /// # #[macro_use] extern crate rocket;\n        /// # #[macro_use] extern crate rocket_sync_db_pools;\n        /// #\n        /// # #[cfg(feature = \"diesel_sqlite_pool\")] {\n        /// use rocket_sync_db_pools::diesel;\n        ///\n        /// #[database(\"my_db\")]\n        /// struct MyConn(diesel::SqliteConnection);\n        ///\n        /// #[launch]\n        /// fn rocket() -> _ {\n        ///     rocket::build().attach(MyConn::fairing())\n        /// }\n        /// # }\n        /// ```\n        pub fn fairing() -> impl crate::rocket::fairing::Fairing {\n            <crate::ConnectionPool<Self, diesel::SqliteConnection>>::fairing(\n                \"'example' Database Pool\",\n                \"example\",\n            )\n        }\n\n        /// Returns an opaque type that represents the connection pool backing\n        /// connections of type `Self` _as long as_ the fairing returned by\n        /// [`Self::fairing()`] is attached and has run on `__rocket`.\n        ///\n        /// The returned pool is `Clone`. Values of type `Self` can be retrieved\n        /// from the pool by calling `pool.get().await` which has the same\n        /// signature and semantics as [`Self::get_one()`].\n        ///\n        /// # Example\n        ///\n        /// ```rust\n        /// # #[macro_use] extern crate rocket;\n        /// # #[macro_use] extern crate rocket_sync_db_pools;\n        /// #\n        /// # #[cfg(feature = \"diesel_sqlite_pool\")] {\n        /// use rocket::tokio::{task, time};\n        /// use rocket::fairing::AdHoc;\n        /// use rocket_sync_db_pools::diesel;\n        ///\n        /// #[database(\"my_db\")]\n        /// struct MyConn(diesel::SqliteConnection);\n        ///\n        /// #[launch]\n        /// fn rocket() -> _ {\n        ///     rocket::build()\n        ///         .attach(MyConn::fairing())\n        ///         .attach(AdHoc::try_on_ignite(\"Background DB\", |rocket| async {\n        ///             let pool = match MyConn::pool(&rocket) {\n        ///                 Some(pool) => pool.clone(),\n        ///                 None => return Err(rocket)\n        ///             };\n        ///\n        ///             // Start a background task that runs some database\n        ///             // operation every 10 seconds. If a connection isn't\n        ///             // available, retries 10 + timeout seconds later.\n        ///             tokio::task::spawn(async move {\n        ///                 loop {\n        ///                     time::sleep(time::Duration::from_secs(10)).await;\n        ///                     if let Some(conn) = pool.get().await {\n        ///                         conn.run(|c| { /* perform db ops */ }).await;\n        ///                     }\n        ///                 }\n        ///             });\n        ///\n        ///             Ok(rocket)\n        ///         }))\n        /// }\n        /// # }\n        /// ```\n        pub fn pool<P: crate::rocket::Phase>(\n            __rocket: &crate::rocket::Rocket<P>,\n        ) -> Option<&crate::ConnectionPool<Self, diesel::SqliteConnection>>\n        {\n            <crate::ConnectionPool<Self, diesel::SqliteConnection>>::pool(\n                &__rocket,\n            )\n        }\n\n        /// Runs the provided function `__f` in an async-safe blocking thread.\n        /// The function is supplied with a mutable reference to the raw\n        /// connection (a value of type `&mut Self.0`). `.await`ing the return\n        /// value of this function yields the value returned by `__f`.\n        ///\n        /// # Example\n        ///\n        /// ```rust\n        /// # #[macro_use] extern crate rocket;\n        /// # #[macro_use] extern crate rocket_sync_db_pools;\n        /// #\n        /// # #[cfg(feature = \"diesel_sqlite_pool\")] {\n        /// use rocket_sync_db_pools::diesel;\n        ///\n        /// #[database(\"my_db\")]\n        /// struct MyConn(diesel::SqliteConnection);\n        ///\n        /// #[get(\"/\")]\n        /// async fn f(conn: MyConn) {\n        ///     // The type annotation is illustrative and isn't required.\n        ///     let result = conn.run(|c: &mut diesel::SqliteConnection| {\n        ///         // Use `c`.\n        ///     }).await;\n        /// }\n        /// # }\n        /// ```\n        pub async fn run<F, R>(&self, __f: F) -> R\n        where\n            F: FnOnce(&mut diesel::SqliteConnection) -> R + Send + 'static,\n            R: Send + 'static,\n        {\n            self.0.run(__f).await\n        }\n\n        /// Retrieves a connection of type `Self` from the `rocket` instance.\n        /// Returns `Some` as long as `Self::fairing()` has been attached and\n        /// there is a connection available within at most `timeout` seconds.\n        pub async fn get_one<P: crate::rocket::Phase>(\n            __rocket: &crate::rocket::Rocket<P>,\n        ) -> Option<Self> {\n            <crate::ConnectionPool<Self, diesel::SqliteConnection>>::get_one(\n                &__rocket,\n            )\n            .await\n            .map(Self)\n        }\n    }\n\n    /// Retrieves a connection from the database pool or fails with a\n    /// `Status::ServiceUnavailable` if doing so times out.\n    impl<'r> crate::rocket::request::FromRequest<'r> for ExampleDb {\n        type Error = ();\n        #[allow(\n            clippy::let_unit_value,\n            clippy::no_effect_underscore_binding,\n            clippy::shadow_same,\n            clippy::type_complexity,\n            clippy::type_repetition_in_bounds,\n            clippy::used_underscore_binding\n        )]\n        fn from_request<'life0, 'async_trait>(\n            __r: &'r crate::rocket::request::Request<'life0>,\n        ) -> ::core::pin::Pin<\n            Box<\n                dyn ::core::future::Future<\n                        Output = crate::rocket::request::Outcome<Self, ()>,\n                    > + ::core::marker::Send\n                    + 'async_trait,\n            >,\n        >\n        where\n            'r: 'async_trait,\n            'life0: 'async_trait,\n            Self: 'async_trait,\n        {\n            Box::pin(async move {\n                if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<\n                    crate::rocket::request::Outcome<Self, ()>,\n                > {\n                    return __ret;\n                }\n                let __r = __r;\n                let __ret: crate::rocket::request::Outcome<Self, ()> = {\n                    < crate :: Connection < Self , diesel :: SqliteConnection > >\n                        :: from_request (__r) . await . map (Self)\n                };\n                #[allow(unreachable_code)]\n                __ret\n            })\n        }\n    }\n    impl crate::rocket::Sentinel for ExampleDb {\n        fn abort(\n            __r: &crate::rocket::Rocket<crate::rocket::Ignite>,\n        ) -> bool {\n            <crate::Connection<Self, diesel::SqliteConnection>>::abort(__r)\n        }\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/src/poolable.rs",
    "content": "#[allow(unused)]\nuse std::time::Duration;\n\nuse r2d2::ManageConnection;\nuse rocket::{Rocket, Build};\n\n#[allow(unused_imports)]\nuse crate::{Config, Error};\n\n/// Trait implemented by `r2d2`-based database adapters.\n///\n/// # Provided Implementations\n///\n/// Implementations of `Poolable` are provided for the following types:\n///\n///   * [`diesel::MysqlConnection`](diesel::MysqlConnection)\n///   * [`diesel::PgConnection`](diesel::PgConnection)\n///   * [`diesel::SqliteConnection`](diesel::SqliteConnection)\n///   * [`postgres::Client`](postgres::Client)\n///   * [`rusqlite::Connection`](rusqlite::Connection)\n///   * [`memcache::Client`](memcache::Client)\n///\n/// # Implementation Guide\n///\n/// As an r2d2-compatible database (or other resource) adapter provider,\n/// implementing `Poolable` in your own library will enable Rocket users to\n/// consume your adapter with its built-in connection pooling support.\n///\n/// ## Example\n///\n/// Consider a library `foo` with the following types:\n///\n///   * `foo::ConnectionManager`, which implements [`r2d2::ManageConnection`]\n///   * `foo::Connection`, the `Connection` associated type of\n///     `foo::ConnectionManager`\n///   * `foo::Error`, errors resulting from manager instantiation\n///\n/// In order for Rocket to generate the required code to automatically provision\n/// a r2d2 connection pool into application state, the `Poolable` trait needs to\n/// be implemented for the connection type. The following example implements\n/// `Poolable` for `foo::Connection`:\n///\n/// ```rust\n/// # mod foo {\n/// #     use std::fmt;\n/// #     use rocket_sync_db_pools::r2d2;\n/// #     #[derive(Debug)] pub struct Error;\n/// #     impl std::error::Error for Error {  }\n/// #     impl fmt::Display for Error {\n/// #         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Ok(()) }\n/// #     }\n/// #\n/// #     pub struct Connection;\n/// #     pub struct ConnectionManager;\n/// #\n/// #     type Result<T> = std::result::Result<T, Error>;\n/// #\n/// #     impl ConnectionManager {\n/// #         pub fn new(url: &str) -> Result<Self> { Err(Error) }\n/// #     }\n/// #\n/// #     impl self::r2d2::ManageConnection for ConnectionManager {\n/// #          type Connection = Connection;\n/// #          type Error = Error;\n/// #          fn connect(&self) -> Result<Connection> { panic!() }\n/// #          fn is_valid(&self, _: &mut Connection) -> Result<()> { panic!() }\n/// #          fn has_broken(&self, _: &mut Connection) -> bool { panic!() }\n/// #     }\n/// # }\n/// use std::time::Duration;\n/// use rocket::{Rocket, Build};\n/// use rocket_sync_db_pools::{r2d2, Error, Config, Poolable, PoolResult};\n///\n/// impl Poolable for foo::Connection {\n///     type Manager = foo::ConnectionManager;\n///     type Error = foo::Error;\n///\n///     fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {\n///         let config = Config::from(db_name, rocket)?;\n///         let manager = foo::ConnectionManager::new(&config.url).map_err(Error::Custom)?;\n///         Ok(r2d2::Pool::builder()\n///             .max_size(config.pool_size)\n///             .connection_timeout(Duration::from_secs(config.timeout as u64))\n///             .build(manager)?)\n///     }\n/// }\n/// ```\n///\n/// In this example, `ConnectionManager::new()` method returns a `foo::Error` on\n/// failure. The [`Error`] enum consolidates this type, the `r2d2::Error` type\n/// that can result from `r2d2::Pool::builder()`, and the\n/// [`figment::Error`](rocket::figment::Error) type from\n/// `database::Config::from()`.\n///\n/// In the event that a connection manager isn't fallible (as is the case with\n/// Diesel's r2d2 connection manager, for instance), the associated error type\n/// for the `Poolable` implementation should be `std::convert::Infallible`.\n///\n/// For more concrete example, consult Rocket's existing implementations of\n/// [`Poolable`].\npub trait Poolable: Send + Sized + 'static {\n    /// The associated connection manager for the given connection type.\n    type Manager: ManageConnection<Connection=Self>;\n\n    /// The associated error type in the event that constructing the connection\n    /// manager and/or the connection pool fails.\n    type Error: std::fmt::Debug;\n\n    /// Creates an `r2d2` connection pool for `Manager::Connection`, returning\n    /// the pool on success.\n    fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self>;\n}\n\n/// A type alias for the return type of [`Poolable::pool()`].\n#[allow(type_alias_bounds)]\npub type PoolResult<P: Poolable> = Result<r2d2::Pool<P::Manager>, Error<P::Error>>;\n\n#[cfg(feature = \"diesel_sqlite_pool\")]\nimpl Poolable for diesel::SqliteConnection {\n    type Manager = diesel::r2d2::ConnectionManager<diesel::SqliteConnection>;\n    type Error = std::convert::Infallible;\n\n    fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {\n        use diesel::{SqliteConnection, connection::SimpleConnection};\n        use diesel::r2d2::{CustomizeConnection, ConnectionManager, Error, Pool};\n\n        #[derive(Debug)]\n        struct Customizer;\n\n        impl CustomizeConnection<SqliteConnection, Error> for Customizer {\n            fn on_acquire(&self, conn: &mut SqliteConnection) -> Result<(), Error> {\n                conn.batch_execute(\"\\\n                    PRAGMA journal_mode = WAL;\\\n                    PRAGMA busy_timeout = 5000;\\\n                    PRAGMA foreign_keys = ON;\\\n                \").map_err(Error::QueryError)?;\n\n                Ok(())\n            }\n        }\n\n        let config = Config::from(db_name, rocket)?;\n        let manager = ConnectionManager::new(&config.url);\n        let pool = Pool::builder()\n            .connection_customizer(Box::new(Customizer))\n            .max_size(config.pool_size)\n            .connection_timeout(Duration::from_secs(config.timeout as u64))\n            .build(manager)?;\n\n        Ok(pool)\n    }\n}\n\n#[cfg(feature = \"diesel_postgres_pool\")]\nimpl Poolable for diesel::PgConnection {\n    type Manager = diesel::r2d2::ConnectionManager<diesel::PgConnection>;\n    type Error = std::convert::Infallible;\n\n    fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {\n        let config = Config::from(db_name, rocket)?;\n        let manager = diesel::r2d2::ConnectionManager::new(&config.url);\n        let pool = r2d2::Pool::builder()\n            .max_size(config.pool_size)\n            .connection_timeout(Duration::from_secs(config.timeout as u64))\n            .build(manager)?;\n\n        Ok(pool)\n    }\n}\n\n#[cfg(feature = \"diesel_mysql_pool\")]\nimpl Poolable for diesel::MysqlConnection {\n    type Manager = diesel::r2d2::ConnectionManager<diesel::MysqlConnection>;\n    type Error = std::convert::Infallible;\n\n    fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {\n        let config = Config::from(db_name, rocket)?;\n        let manager = diesel::r2d2::ConnectionManager::new(&config.url);\n        let pool = r2d2::Pool::builder()\n            .max_size(config.pool_size)\n            .connection_timeout(Duration::from_secs(config.timeout as u64))\n            .build(manager)?;\n\n        Ok(pool)\n    }\n}\n\n// TODO: Add a feature to enable TLS in `postgres`; parse a suitable `config`.\n#[cfg(feature = \"postgres_pool\")]\nimpl Poolable for postgres::Client {\n    type Manager = r2d2_postgres::PostgresConnectionManager<postgres::tls::NoTls>;\n    type Error = postgres::Error;\n\n    fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {\n        let config = Config::from(db_name, rocket)?;\n        let url = config.url.parse().map_err(Error::Custom)?;\n        let manager = r2d2_postgres::PostgresConnectionManager::new(url, postgres::tls::NoTls);\n        let pool = r2d2::Pool::builder()\n            .max_size(config.pool_size)\n            .connection_timeout(Duration::from_secs(config.timeout as u64))\n            .build(manager)?;\n\n        Ok(pool)\n    }\n}\n\n#[cfg(feature = \"sqlite_pool\")]\nimpl Poolable for rusqlite::Connection {\n    type Manager = r2d2_sqlite::SqliteConnectionManager;\n    type Error = std::convert::Infallible;\n\n    fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {\n        use rocket::figment::providers::Serialized;\n\n        #[derive(Debug, serde::Deserialize, serde::Serialize)]\n        #[serde(rename_all = \"snake_case\")]\n        enum OpenFlag {\n            ReadOnly,\n            ReadWrite,\n            Create,\n            Uri,\n            Memory,\n            NoMutex,\n            FullMutex,\n            SharedCache,\n            PrivateCache,\n            Nofollow,\n        }\n\n        let figment = Config::figment(db_name, rocket);\n        let config: Config = figment.extract()?;\n        let open_flags: Vec<OpenFlag> = figment\n            .join(Serialized::default(\"open_flags\", <Vec<OpenFlag>>::new()))\n            .extract_inner(\"open_flags\")?;\n\n        let mut flags = rusqlite::OpenFlags::default();\n        for flag in open_flags {\n            let sql_flag = match flag {\n                OpenFlag::ReadOnly => rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY,\n                OpenFlag::ReadWrite => rusqlite::OpenFlags::SQLITE_OPEN_READ_WRITE,\n                OpenFlag::Create => rusqlite::OpenFlags::SQLITE_OPEN_CREATE,\n                OpenFlag::Uri => rusqlite::OpenFlags::SQLITE_OPEN_URI,\n                OpenFlag::Memory => rusqlite::OpenFlags::SQLITE_OPEN_MEMORY,\n                OpenFlag::NoMutex => rusqlite::OpenFlags::SQLITE_OPEN_NO_MUTEX,\n                OpenFlag::FullMutex => rusqlite::OpenFlags::SQLITE_OPEN_FULL_MUTEX,\n                OpenFlag::SharedCache => rusqlite::OpenFlags::SQLITE_OPEN_SHARED_CACHE,\n                OpenFlag::PrivateCache => rusqlite::OpenFlags::SQLITE_OPEN_PRIVATE_CACHE,\n                OpenFlag::Nofollow => rusqlite::OpenFlags::SQLITE_OPEN_NOFOLLOW,\n            };\n\n            flags.insert(sql_flag)\n        };\n\n        let manager = r2d2_sqlite::SqliteConnectionManager::file(&*config.url)\n            .with_flags(flags);\n\n        let pool = r2d2::Pool::builder()\n            .max_size(config.pool_size)\n            .connection_timeout(Duration::from_secs(config.timeout as u64))\n            .build(manager)?;\n\n        Ok(pool)\n    }\n}\n\n#[cfg(feature = \"memcache_pool\")]\nmod memcache_pool {\n    use memcache::{Client, Connectable, MemcacheError};\n\n    use super::*;\n\n    #[derive(Debug)]\n    pub struct ConnectionManager {\n        urls: Vec<String>,\n    }\n\n    impl ConnectionManager {\n        pub fn new<C: Connectable>(target: C) -> Self {\n            Self { urls: target.get_urls(), }\n        }\n    }\n\n    impl r2d2::ManageConnection for ConnectionManager {\n        type Connection = Client;\n        type Error = MemcacheError;\n\n        fn connect(&self) -> Result<Client, MemcacheError> {\n            Client::connect(self.urls.clone())\n        }\n\n        fn is_valid(&self, connection: &mut Client) -> Result<(), MemcacheError> {\n            connection.version().map(|_| ())\n        }\n\n        fn has_broken(&self, _connection: &mut Client) -> bool {\n            false\n        }\n    }\n\n    impl super::Poolable for memcache::Client {\n        type Manager = ConnectionManager;\n        type Error = MemcacheError;\n\n        fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {\n            let config = Config::from(db_name, rocket)?;\n            let manager = ConnectionManager::new(&*config.url);\n            let pool = r2d2::Pool::builder()\n                .max_size(config.pool_size)\n                .connection_timeout(Duration::from_secs(config.timeout as u64))\n                .build(manager)?;\n\n            Ok(pool)\n        }\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/tests/databases.rs",
    "content": "#[cfg(all(feature = \"diesel_sqlite_pool\", feature = \"diesel_postgres_pool\"))]\nmod databases_tests {\n    #![allow(dead_code)]\n\n    use rocket_sync_db_pools::database;\n\n    #[database(\"example\")]\n    struct ExampleDb(diesel::SqliteConnection);\n\n    #[database(\"bar\")]\n    struct PrimaryDb(diesel::PgConnection);\n}\n\n#[cfg(feature = \"memcache_pool\")]\nmod memcache_pool_tests {\n    #![allow(dead_code)]\n\n    use rocket_sync_db_pools::database;\n\n    #[database(\"test_db\")]\n    struct MemcacheDb(memcache::Client);\n}\n\n#[cfg(test)]\n#[cfg(all(feature = \"sqlite_pool\"))]\nmod rusqlite_integration_test {\n    use rocket_sync_db_pools::{rusqlite, database};\n\n    use rusqlite::types::ToSql;\n\n    #[database(\"test_db\")]\n    struct SqliteDb(pub rusqlite::Connection);\n\n    // Test to ensure that multiple databases of the same type can be used\n    #[database(\"test_db_2\")]\n    struct SqliteDb2(pub rusqlite::Connection);\n\n    #[rocket::async_test]\n    async fn test_db() {\n        use rocket::figment::{Figment, util::map};\n\n        let options = map![\"url\" => \":memory:\"];\n        let config = Figment::from(rocket::Config::debug_default())\n            .merge((\"databases\", map![\"test_db\" => &options]))\n            .merge((\"databases\", map![\"test_db_2\" => &options]));\n\n        let rocket = rocket::custom(config)\n            .attach(SqliteDb::fairing())\n            .attach(SqliteDb2::fairing())\n            .ignite()\n            .await\n            .unwrap();\n\n        let conn = SqliteDb::get_one(&rocket).await\n            .expect(\"unable to get connection\");\n\n        // Rusqlite's `transaction()` method takes `&mut self`; this tests that\n        // the &mut method can be called inside the closure passed to `run()`.\n        conn.run(|conn| {\n            let tx = conn.transaction().unwrap();\n            let _: i32 = tx.query_row(\n                \"SELECT 1\", &[] as &[&dyn ToSql], |row| row.get(0)\n            ).expect(\"get row\");\n\n            tx.commit().expect(\"committed transaction\");\n        }).await;\n    }\n}\n\n#[cfg(test)]\nmod sentinel_and_runtime_test {\n    use rocket::{Rocket, Build};\n    use r2d2::{ManageConnection, Pool};\n    use rocket_sync_db_pools::{database, Poolable, PoolResult};\n    use tokio::runtime::Runtime;\n\n    #[allow(dead_code)]\n    struct ContainsRuntime(Runtime);\n    struct TestConnection;\n\n    impl ManageConnection for ContainsRuntime {\n        type Connection = TestConnection;\n        type Error = std::convert::Infallible;\n\n        fn connect(&self) -> Result<Self::Connection, Self::Error> {\n            Ok(TestConnection)\n        }\n\n        fn is_valid(&self, _conn: &mut Self::Connection) -> Result<(), Self::Error> {\n            Ok(())\n        }\n\n        fn has_broken(&self, _conn: &mut Self::Connection) -> bool {\n            false\n        }\n    }\n\n    impl Poolable for TestConnection {\n        type Manager = ContainsRuntime;\n        type Error = ();\n\n        fn pool(_db_name: &str, _rocket: &Rocket<Build>) -> PoolResult<Self> {\n            let manager = ContainsRuntime(tokio::runtime::Runtime::new().unwrap());\n            Ok(Pool::builder().build(manager)?)\n        }\n    }\n\n    #[database(\"test_db\")]\n    struct TestDb(TestConnection);\n\n    #[rocket::async_test]\n    async fn test_drop_runtime() {\n        use rocket::figment::{Figment, util::map};\n\n        let config = Figment::from(rocket::Config::debug_default())\n            .merge((\"databases\", map![\"test_db\" => map![\"url\" => \"\"]]));\n\n        let rocket = rocket::custom(config).attach(TestDb::fairing());\n        drop(rocket);\n    }\n\n    #[test]\n    fn test_sentinel() {\n        use rocket::{*, local::blocking::Client, error::ErrorKind::SentinelAborts};\n\n        #[get(\"/\")]\n        fn use_db(_db: TestDb) {}\n\n        let err = Client::debug_with(routes![use_db]).unwrap_err();\n        assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n    }\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/tests/drop-with-connection.rs",
    "content": "#![cfg(feature = \"diesel_sqlite_pool\")]\n\nuse rocket::figment::Figment;\nuse rocket_sync_db_pools::database;\n\n#[database(\"example\")]\nstruct ExampleDb(diesel::SqliteConnection);\n\n#[test]\nfn can_drop_connection_in_sync_context() {\n    let conn = rocket::execute(async {\n        let figment = Figment::from(rocket::Config::debug_default())\n            .merge((\"databases.example.url\", \":memory:\"));\n\n        let rocket = rocket::custom(figment)\n            .attach(ExampleDb::fairing())\n            .ignite().await\n            .expect(\"rocket\");\n\n        ExampleDb::get_one(&rocket).await\n            .expect(\"attach => connection\")\n    });\n\n    drop(conn);\n}\n"
  },
  {
    "path": "contrib/sync_db_pools/lib/tests/shutdown.rs",
    "content": "#[cfg(test)]\n#[cfg(all(feature = \"diesel_sqlite_pool\"))]\nmod sqlite_shutdown_test {\n    use rocket::{async_test, Build, Rocket};\n    use rocket_sync_db_pools::database;\n\n    #[database(\"test\")]\n    struct Pool(diesel::SqliteConnection);\n\n    async fn rocket() -> Rocket<Build> {\n        use rocket::figment::{util::map, Figment};\n\n        let options = map![\"url\" => \":memory:\"];\n        let config = Figment::from(rocket::Config::debug_default())\n            .merge((\"port\", 0))\n            .merge((\"databases\", map![\"test\" => &options]));\n\n        rocket::custom(config).attach(Pool::fairing())\n    }\n\n    #[test]\n    fn test_shutdown() {\n        let _rocket = async_test(\n            async {\n                let rocket = rocket().await.ignite().await.expect(\"unable to ignite\");\n                // request shutdown\n                rocket.shutdown().notify();\n                rocket.launch().await.expect(\"unable to launch\")\n            }\n        );\n        // _rocket is dropped here after the runtime is dropped\n    }\n}\n"
  },
  {
    "path": "contrib/ws/Cargo.toml",
    "content": "[package]\nname = \"rocket_ws\"\nversion = \"0.1.0\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\"]\ndescription = \"WebSocket support for Rocket.\"\ndocumentation = \"https://api.rocket.rs/master/rocket_ws/\"\nhomepage = \"https://rocket.rs\"\nrepository = \"https://github.com/rwf2/Rocket/tree/master/contrib/ws\"\nreadme = \"README.md\"\nkeywords = [\"rocket\", \"web\", \"framework\", \"websocket\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[lints]\nworkspace = true\n\n[features]\ndefault = [\"tungstenite\"]\ntungstenite = [\"tokio-tungstenite\"]\n\n[dependencies]\ntokio-tungstenite = { version = \"0.24\", optional = true }\n\n[dependencies.rocket]\nversion = \"0.6.0-dev\"\npath = \"../../core/lib\"\ndefault-features = false\n\n[package.metadata.docs.rs]\nall-features = true\n"
  },
  {
    "path": "contrib/ws/README.md",
    "content": "# `ws` [![ci.svg]][ci] [![crates.io]][crate] [![docs.svg]][crate docs]\n\n[crates.io]: https://img.shields.io/crates/v/rocket_ws.svg\n[crate]: https://crates.io/crates/rocket_ws\n[docs.svg]: https://img.shields.io/badge/web-master-red.svg?style=flat&label=docs&colorB=d33847\n[crate docs]: https://api.rocket.rs/master/rocket_ws\n[ci.svg]: https://github.com/rwf2/Rocket/workflows/CI/badge.svg\n[ci]: https://github.com/rwf2/Rocket/actions\n\nThis crate provides WebSocket support for Rocket via integration with Rocket's\n[connection upgrades] API.\n\n# Usage\n\n  1. Depend on `rocket_ws`, renamed here to `ws`:\n\n     ```toml\n     [dependencies]\n     ws = { package = \"rocket_ws\", version = \"0.1.0\" }\n     ```\n\n   2. Use it!\n\n      ```rust\n      #[get(\"/echo\")]\n      fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n          ws::Stream! { ws =>\n              for await message in ws {\n                  yield message?;\n              }\n          }\n      }\n      ```\n\nSee the [crate docs] for full details.\n"
  },
  {
    "path": "contrib/ws/src/duplex.rs",
    "content": "use std::pin::Pin;\nuse std::task::{Context, Poll};\n\nuse rocket::data::IoStream;\nuse rocket::futures::{StreamExt, SinkExt, Sink};\nuse rocket::futures::stream::{Stream, FusedStream};\n\nuse crate::frame::{Message, CloseFrame};\nuse crate::result::{Result, Error};\n\n/// A readable and writeable WebSocket [`Message`] `async` stream.\n///\n/// This struct implements [`Stream`] and [`Sink`], allowing for `async` reading\n/// and writing of [`Message`]s. The [`StreamExt`] and [`SinkExt`] traits can be\n/// imported to provide additional functionality for streams and sinks:\n///\n/// ```rust\n/// # use rocket::get;\n/// # use rocket_ws as ws;\n/// use rocket::futures::{SinkExt, StreamExt};\n///\n/// #[get(\"/echo/manual\")]\n/// fn echo_manual<'r>(ws: ws::WebSocket) -> ws::Channel<'r> {\n///     ws.channel(move |mut stream| Box::pin(async move {\n///         while let Some(message) = stream.next().await {\n///             let _ = stream.send(message?).await;\n///         }\n///\n///         Ok(())\n///     }))\n/// }\n/// ```\n///\n/// [`StreamExt`]: rocket::futures::StreamExt\n/// [`SinkExt`]: rocket::futures::SinkExt\npub struct DuplexStream(tokio_tungstenite::WebSocketStream<IoStream>);\n\nimpl DuplexStream {\n    pub(crate) async fn new(stream: IoStream, config: crate::Config) -> Self {\n        use tokio_tungstenite::WebSocketStream;\n        use crate::tungstenite::protocol::Role;\n\n        let inner = WebSocketStream::from_raw_socket(stream, Role::Server, Some(config));\n        DuplexStream(inner.await)\n    }\n\n    /// Close the stream now. This does not typically need to be called.\n    pub async fn close(&mut self, msg: Option<CloseFrame<'_>>) -> Result<()> {\n        self.0.close(msg).await\n    }\n}\n\nimpl Stream for DuplexStream {\n    type Item = Result<Message>;\n\n    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {\n        self.get_mut().0.poll_next_unpin(cx)\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.0.size_hint()\n    }\n}\n\nimpl FusedStream for DuplexStream {\n    fn is_terminated(&self) -> bool {\n        self.0.is_terminated()\n    }\n}\n\nimpl Sink<Message> for DuplexStream {\n    type Error = Error;\n\n    fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        self.get_mut().0.poll_ready_unpin(cx)\n    }\n\n    fn start_send(self: Pin<&mut Self>, item: Message) -> Result<(), Self::Error> {\n        self.get_mut().0.start_send_unpin(item)\n    }\n\n    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        self.get_mut().0.poll_flush_unpin(cx)\n    }\n\n    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {\n        self.get_mut().0.poll_close_unpin(cx)\n    }\n}\n"
  },
  {
    "path": "contrib/ws/src/lib.rs",
    "content": "//! WebSocket support for Rocket.\n//!\n//! This crate implements support for WebSockets via Rocket's [connection\n//! upgrade API](rocket::Response#upgrading) and\n//! [tungstenite](tokio_tungstenite).\n//!\n//! # Usage\n//!\n//! Depend on the crate. Here, we rename the dependency to `ws` for convenience:\n//!\n//! ```toml\n//! [dependencies]\n//! ws = { package = \"rocket_ws\", version = \"0.1.0\" }\n//! ```\n//!\n//! Then, use [`WebSocket`] as a request guard in any route and either call\n//! [`WebSocket::channel()`] or return a stream via [`Stream!`] or\n//! [`WebSocket::stream()`] in the handler. The examples below are equivalent:\n//!\n//! ```rust\n//! # use rocket::get;\n//! # use rocket_ws as ws;\n//! #\n//! #[get(\"/echo?channel\")]\n//! fn echo_channel(ws: ws::WebSocket) -> ws::Channel<'static> {\n//!     use rocket::futures::{SinkExt, StreamExt};\n//!\n//!     ws.channel(move |mut stream| Box::pin(async move {\n//!         while let Some(message) = stream.next().await {\n//!             let _ = stream.send(message?).await;\n//!         }\n//!\n//!         Ok(())\n//!     }))\n//! }\n//!\n//! #[get(\"/echo?stream\")]\n//! fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n//!     ws::Stream! { ws =>\n//!         for await message in ws {\n//!             yield message?;\n//!         }\n//!     }\n//! }\n//!\n//! #[get(\"/echo?compose\")]\n//! fn echo_compose(ws: ws::WebSocket) -> ws::Stream!['static] {\n//!     ws.stream(|io| io)\n//! }\n//! ```\n//!\n//! WebSocket connections are configurable via [`WebSocket::config()`]:\n//!\n//! ```rust\n//! # use rocket::get;\n//! # use rocket_ws as ws;\n//! #\n//! #[get(\"/echo\")]\n//! fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n//!     let ws = ws.config(ws::Config {\n//!         max_send_queue: Some(5),\n//!         ..Default::default()\n//!     });\n//!\n//!     ws::Stream! { ws =>\n//!         for await message in ws {\n//!             yield message?;\n//!         }\n//!     }\n//! }\n//! ```\n\n#![doc(html_root_url = \"https://api.rocket.rs/master/rocket_ws\")]\n#![doc(html_favicon_url = \"https://rocket.rs/images/favicon.ico\")]\n#![doc(html_logo_url = \"https://rocket.rs/images/logo-boxed.png\")]\n\nmod tungstenite {\n    #[doc(inline)] pub use tokio_tungstenite::tungstenite::*;\n}\n\nmod duplex;\nmod websocket;\n\npub use self::websocket::{WebSocket, Channel};\n\n/// A WebSocket message.\n///\n/// A value of this type is typically constructed by calling `.into()` on a\n/// supported message type. This includes strings via `&str` and `String` and\n/// bytes via `&[u8]` and `Vec<u8>`:\n///\n/// ```rust\n/// # use rocket::get;\n/// # use rocket_ws as ws;\n/// #\n/// #[get(\"/echo\")]\n/// fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n///     ws::Stream! { ws =>\n///         yield \"Hello\".into();\n///         yield String::from(\"Hello\").into();\n///         yield (&[1u8, 2, 3][..]).into();\n///         yield vec![1u8, 2, 3].into();\n///     }\n/// }\n/// ```\n///\n/// Other kinds of messages can be constructed directly:\n///\n/// ```rust\n/// # use rocket::get;\n/// # use rocket_ws as ws;\n/// #\n/// #[get(\"/echo\")]\n/// fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n///     ws::Stream! { ws =>\n///         yield ws::Message::Ping(vec![b'h', b'i'])\n///     }\n/// }\n/// ```\npub use self::tungstenite::Message;\n\n/// WebSocket connection configuration.\n///\n/// The default configuration for a [`WebSocket`] can be changed by calling\n/// [`WebSocket::config()`] with a value of this type. The defaults are obtained\n/// via [`Default::default()`]. You don't generally need to reconfigure a\n/// `WebSocket` unless you're certain you need different values. In other words,\n/// this structure should rarely be used.\n///\n/// # Example\n///\n/// ```rust\n/// # use rocket::get;\n/// # use rocket_ws as ws;\n/// use rocket::data::ToByteUnit;\n///\n/// #[get(\"/echo\")]\n/// fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n///     let ws = ws.config(ws::Config {\n///         // Enable backpressure with a max send queue size of `5`.\n///         max_send_queue: Some(5),\n///         // Decrease the maximum (complete) message size to 4MiB.\n///         max_message_size: Some(4.mebibytes().as_u64() as usize),\n///         // Decrease the maximum size of _one_ frame (not message) to 1MiB.\n///         max_frame_size: Some(1.mebibytes().as_u64() as usize),\n///         // Use the default values for the rest.\n///         ..Default::default()\n///     });\n///\n///     ws::Stream! { ws =>\n///         for await message in ws {\n///             yield message?;\n///         }\n///     }\n/// }\n/// ```\n///\n/// **Original `tungstenite` Documentation Follows**\n///\npub use self::tungstenite::protocol::WebSocketConfig as Config;\n\n/// Structures for constructing raw WebSocket frames.\npub mod frame {\n    #[doc(hidden)] pub use crate::Message;\n    pub use crate::tungstenite::protocol::frame::{CloseFrame, Frame};\n    pub use crate::tungstenite::protocol::frame::coding::CloseCode;\n}\n\n/// Types representing incoming and/or outgoing `async` [`Message`] streams.\npub mod stream {\n    pub use crate::duplex::DuplexStream;\n    pub use crate::websocket::MessageStream;\n}\n\n/// Library [`Error`](crate::result::Error) and\n/// [`Result`](crate::result::Result) types.\npub mod result {\n    pub use crate::tungstenite::error::{Result, Error};\n}\n\n/// Type and expression macro for `async` WebSocket [`Message`] streams.\n///\n/// This macro can be used both where types are expected or\n/// where expressions are expected.\n///\n/// # Type Position\n///\n/// When used in a type position, the macro invoked as `Stream['r]` expands to:\n///\n/// - [`MessageStream`]`<'r, impl `[`Stream`]`<Item = `[`Result`]`<`[`Message`]`>>> + 'r>`\n///\n/// The lifetime need not be specified as `'r`. For instance, `Stream['request]`\n/// is valid and expands as expected:\n///\n/// - [`MessageStream`]`<'request, impl `[`Stream`]`<Item = `[`Result`]`<`[`Message`]`>>> + 'request>`\n///\n/// As a convenience, when the macro is invoked as `Stream![]`, the lifetime\n/// defaults to `'static`. That is, `Stream![]` is equivalent to\n/// `Stream!['static]`.\n///\n/// [`MessageStream`]: crate::stream::MessageStream\n/// [`Stream`]: rocket::futures::stream::Stream\n/// [`Result`]: crate::result::Result\n/// [`Message`]: crate::Message\n///\n/// # Expression Position\n///\n/// When invoked as an expression, the macro behaves similarly to Rocket's\n/// [`stream!`](rocket::response::stream::stream) macro. Specifically, it\n/// supports `yield` and `for await` syntax. It is invoked as follows:\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket_ws as ws;\n///\n/// #[get(\"/\")]\n/// fn echo(ws: ws::WebSocket) -> ws::Stream![] {\n///     ws::Stream! { ws =>\n///         for await message in ws {\n///             yield message?;\n///             yield \"foo\".into();\n///             yield vec![1, 2, 3, 4].into();\n///         }\n///     }\n/// }\n/// ```\n///\n/// It enjoins the following type requirements:\n///\n///   * The type of `ws` _must_ be [`WebSocket`]. `ws` can be any ident.\n///   * The type of yielded expressions (`expr` in `yield expr`) _must_ be [`Message`].\n///   * The `Err` type of expressions short-circuited with `?` _must_ be [`Error`].\n///\n/// [`Error`]: crate::result::Error\n///\n/// The macro takes any series of statements and expands them into an expression\n/// of type `impl Stream<Item = `[`Result`]`<T>>`, a stream that `yield`s elements of\n/// type [`Result`]`<T>`. It automatically converts yielded items of type `T` into\n/// `Ok(T)`. It supports any Rust statement syntax with the following\n/// extensions:\n///\n///   * `?` short-circuits stream termination on `Err`\n///\n///     The type of the error value must be [`Error`].\n///     <br /> <br />\n///\n///   * `yield expr`\n///\n///     Yields the result of evaluating `expr` to the caller (the stream\n///     consumer) wrapped in `Ok`.\n///\n///     `expr` must be of type `T`.\n///     <br /> <br />\n///\n///   * `for await x in stream { .. }`\n///\n///     `await`s the next element in `stream`, binds it to `x`, and executes the\n///     block with the binding.\n///\n///     `stream` must implement `Stream<Item = T>`; the type of `x` is `T`.\n///\n/// ### Examples\n///\n/// Borrow from the request. Send a single message and close:\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket_ws as ws;\n///\n/// #[get(\"/hello/<user>\")]\n/// fn ws_hello(ws: ws::WebSocket, user: &str) -> ws::Stream!['_] {\n///     ws::Stream! { ws =>\n///         yield user.into();\n///     }\n/// }\n/// ```\n///\n/// Borrow from the request with explicit lifetime:\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket_ws as ws;\n///\n/// #[get(\"/hello/<user>\")]\n/// fn ws_hello<'r>(ws: ws::WebSocket, user: &'r str) -> ws::Stream!['r] {\n///     ws::Stream! { ws =>\n///         yield user.into();\n///     }\n/// }\n/// ```\n///\n/// Emit several messages and short-circuit if the client sends a bad message:\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket_ws as ws;\n///\n/// #[get(\"/\")]\n/// fn echo(ws: ws::WebSocket) -> ws::Stream![] {\n///     ws::Stream! { ws =>\n///         for await message in ws {\n///             for i in 0..5u8 {\n///                 yield i.to_string().into();\n///             }\n///\n///             yield message?;\n///         }\n///     }\n/// }\n/// ```\n///\n#[macro_export]\nmacro_rules! Stream {\n    () => ($crate::Stream!['static]);\n    ($l:lifetime) => (\n        $crate::stream::MessageStream<$l, impl rocket::futures::Stream<\n            Item = $crate::result::Result<$crate::Message>\n        > + $l>\n    );\n    ($channel:ident => $($token:tt)*) => (\n        let ws: $crate::WebSocket = $channel;\n        ws.stream(move |$channel| rocket::async_stream::try_stream! {\n            $($token)*\n        })\n    );\n}\n"
  },
  {
    "path": "contrib/ws/src/websocket.rs",
    "content": "use std::io;\n\nuse rocket::data::{IoHandler, IoStream};\nuse rocket::futures::{self, StreamExt, SinkExt, future::BoxFuture, stream::SplitStream};\nuse rocket::response::{self, Responder, Response};\nuse rocket::request::{FromRequest, Request, Outcome};\nuse rocket::http::Status;\n\nuse crate::{Config, Message};\nuse crate::stream::DuplexStream;\nuse crate::result::{Result, Error};\n\n/// A request guard identifying WebSocket requests. Converts into a [`Channel`]\n/// or [`MessageStream`].\n///\n/// For example usage, see the [crate docs](crate#usage).\n///\n/// ## Details\n///\n/// This is the entrypoint to the library. Every WebSocket response _must_\n/// initiate via the `WebSocket` request guard. The guard identifies valid\n/// WebSocket connection requests and, if the request is valid, succeeds to be\n/// converted into a streaming WebSocket response via\n/// [`Stream!`](crate::Stream!), [`WebSocket::channel()`], or\n/// [`WebSocket::stream()`]. The connection can be configured via\n/// [`WebSocket::config()`]; see [`Config`] for details on configuring a\n/// connection.\n///\n/// ### Forwarding\n///\n/// If the incoming request is not a valid WebSocket request, the guard\n/// forwards with a status of `BadRequest`. The guard never fails.\npub struct WebSocket {\n    config: Config,\n    key: String,\n}\n\nimpl WebSocket {\n    /// Change the default connection configuration to `config`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::get;\n    /// # use rocket_ws as ws;\n    /// #\n    /// #[get(\"/echo\")]\n    /// fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n    ///     let ws = ws.config(ws::Config {\n    ///         max_send_queue: Some(5),\n    ///         ..Default::default()\n    ///     });\n    ///\n    ///     ws::Stream! { ws =>\n    ///         for await message in ws {\n    ///             yield message?;\n    ///         }\n    ///     }\n    /// }\n    /// ```\n    pub fn config(mut self, config: Config) -> Self {\n        self.config = config;\n        self\n    }\n\n    /// Create a read/write channel to the client and call `handler` with it.\n    ///\n    /// This method takes a `FnOnce`, `handler`, that consumes a read/write\n    /// WebSocket channel, [`DuplexStream`] to the client. See [`DuplexStream`]\n    /// for details on how to make use of the channel.\n    ///\n    /// The `handler` must return a `Box`ed and `Pin`ned future: calling\n    /// [`Box::pin()`] with a future does just this as is the preferred\n    /// mechanism to create a `Box<Pin<Future>>`. The future must return a\n    /// [`Result<()>`](crate::result::Result). The WebSocket connection is\n    /// closed successfully if the future returns `Ok` and with an error if\n    /// the future returns `Err`.\n    ///\n    /// # Lifetimes\n    ///\n    /// The `Channel` may borrow from the request. If it does, the lifetime\n    /// should be specified as something other than `'static`. Otherwise, the\n    /// `'static` lifetime should be used.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::get;\n    /// # use rocket_ws as ws;\n    /// use rocket::futures::{SinkExt, StreamExt};\n    ///\n    /// #[get(\"/hello/<name>\")]\n    /// fn hello(ws: ws::WebSocket, name: &str) -> ws::Channel<'_> {\n    ///     ws.channel(move |mut stream| Box::pin(async move {\n    ///         let message = format!(\"Hello, {}!\", name);\n    ///         let _ = stream.send(message.into()).await;\n    ///         Ok(())\n    ///     }))\n    /// }\n    ///\n    /// #[get(\"/echo\")]\n    /// fn echo(ws: ws::WebSocket) -> ws::Channel<'static> {\n    ///     ws.channel(move |mut stream| Box::pin(async move {\n    ///         while let Some(message) = stream.next().await {\n    ///             let _ = stream.send(message?).await;\n    ///         }\n    ///\n    ///         Ok(())\n    ///     }))\n    /// }\n    /// ```\n    pub fn channel<'r, F>(self, handler: F) -> Channel<'r>\n        where F: FnOnce(DuplexStream) -> BoxFuture<'r, Result<()>> + Send + 'r\n    {\n        Channel { ws: self, handler: Box::new(handler), }\n    }\n\n    /// Create a stream that consumes client [`Message`]s and emits its own.\n    ///\n    /// This method takes a `FnOnce` `stream` that consumes a read-only stream\n    /// and returns a stream of [`Message`]s. While the returned stream can be\n    /// constructed in any manner, the [`Stream!`](crate::Stream!) macro is the\n    /// preferred method. In any case, the stream must be `Send`.\n    ///\n    /// The returned stream must emit items of type `Result<Message>`. Items\n    /// that are `Ok(Message)` are sent to the client while items of type\n    /// `Err(Error)` result in the connection being closed and the remainder of\n    /// the stream discarded.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::get;\n    /// # use rocket_ws as ws;\n    ///\n    /// // Use `Stream!`, which internally calls `WebSocket::stream()`.\n    /// #[get(\"/echo?stream\")]\n    /// fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n    ///     ws::Stream! { ws =>\n    ///         for await message in ws {\n    ///             yield message?;\n    ///         }\n    ///     }\n    /// }\n    ///\n    /// // Use a raw stream.\n    /// #[get(\"/echo?compose\")]\n    /// fn echo_compose(ws: ws::WebSocket) -> ws::Stream!['static] {\n    ///     ws.stream(|io| io)\n    /// }\n    /// ```\n    pub fn stream<'r, F, S>(self, stream: F) -> MessageStream<'r, S>\n        where F: FnOnce(SplitStream<DuplexStream>) -> S + Send + 'r,\n              S: futures::Stream<Item = Result<Message>> + Send + 'r\n    {\n        MessageStream { ws: self, handler: Box::new(stream), }\n    }\n\n    /// Returns the server's fully computed and encoded WebSocket handshake\n    /// accept key.\n    ///\n    /// > The server takes the value of the `Sec-WebSocket-Key` sent in the\n    /// > handshake request, appends `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`,\n    /// > SHA-1 of the new value, and is then base64 encoded.\n    /// >\n    /// > -- [`Sec-WebSocket-Accept`]\n    ///\n    /// This is the value returned via the [`Sec-WebSocket-Accept`] header\n    /// during the acceptance response.\n    ///\n    /// [`Sec-WebSocket-Accept`]:\n    /// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-WebSocket-Accept\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::get;\n    /// # use rocket_ws as ws;\n    /// #\n    /// #[get(\"/echo\")]\n    /// fn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n    ///     let accept_key = ws.accept_key();\n    ///     ws.stream(|io| io)\n    /// }\n    /// ```\n    pub fn accept_key(&self) -> &str {\n        &self.key\n    }\n\n}\n\n/// A streaming channel, returned by [`WebSocket::channel()`].\n///\n/// `Channel` has no methods or functionality beyond its trait implementations.\npub struct Channel<'r> {\n    ws: WebSocket,\n    handler: Box<dyn FnOnce(DuplexStream) -> BoxFuture<'r, Result<()>> + Send + 'r>,\n}\n\n/// A [`Stream`](futures::Stream) of [`Message`]s, returned by\n/// [`WebSocket::stream()`], used via [`Stream!`].\n///\n/// This type should not be used directly. Instead, it is used via the\n/// [`Stream!`] macro, which expands to both the type itself and an expression\n/// which evaluates to this type. See [`Stream!`] for details.\n///\n/// [`Stream!`]: crate::Stream!\n// TODO: Get rid of this or `Channel` via a single `enum`.\npub struct MessageStream<'r, S> {\n    ws: WebSocket,\n    handler: Box<dyn FnOnce(SplitStream<DuplexStream>) -> S + Send + 'r>\n}\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for WebSocket {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n        use crate::tungstenite::handshake::derive_accept_key;\n        use rocket::http::uncased::eq;\n\n        let headers = req.headers();\n        let is_upgrade = headers.get(\"Connection\")\n            .any(|h| h.split(',').any(|v| eq(v.trim(), \"upgrade\")));\n\n        let is_ws = headers.get(\"Upgrade\")\n            .any(|h| h.split(',').any(|v| eq(v.trim(), \"websocket\")));\n\n        let is_13 = headers.get_one(\"Sec-WebSocket-Version\").map_or(false, |v| v == \"13\");\n        let key = headers.get_one(\"Sec-WebSocket-Key\").map(|k| derive_accept_key(k.as_bytes()));\n        match key {\n            Some(key) if is_upgrade && is_ws && is_13 => {\n                Outcome::Success(WebSocket { key, config: Config::default() })\n            },\n            Some(_) | None => Outcome::Forward(Status::BadRequest)\n        }\n    }\n}\n\nimpl<'r, 'o: 'r> Responder<'r, 'o> for Channel<'o> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {\n        Response::build()\n            .raw_header(\"Sec-Websocket-Version\", \"13\")\n            .raw_header(\"Sec-WebSocket-Accept\", self.ws.key.clone())\n            .upgrade(\"websocket\", self)\n            .ok()\n    }\n}\n\nimpl<'r, 'o: 'r, S> Responder<'r, 'o> for MessageStream<'o, S>\n    where S: futures::Stream<Item = Result<Message>> + Send + 'o\n{\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {\n        Response::build()\n            .raw_header(\"Sec-Websocket-Version\", \"13\")\n            .raw_header(\"Sec-WebSocket-Accept\", self.ws.key.clone())\n            .upgrade(\"websocket\", self)\n            .ok()\n    }\n}\n\n#[rocket::async_trait]\nimpl IoHandler for Channel<'_> {\n    async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {\n        let stream = DuplexStream::new(io, self.ws.config).await;\n        let result = (self.handler)(stream).await;\n        handle_result(result).map(|_| ())\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r, S> IoHandler for MessageStream<'r, S>\n    where S: futures::Stream<Item = Result<Message>> + Send + 'r\n{\n    async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {\n        let (mut sink, source) = DuplexStream::new(io, self.ws.config).await.split();\n        let stream = (self.handler)(source);\n        rocket::tokio::pin!(stream);\n        while let Some(msg) = stream.next().await {\n            let result = match msg {\n                Ok(msg) if msg.is_close() => return Ok(()),\n                Ok(msg) => sink.send(msg).await,\n                Err(e) => Err(e)\n            };\n\n            if !handle_result(result)? {\n                return Ok(());\n            }\n        }\n\n        Ok(())\n    }\n}\n\n/// Returns `Ok(true)` if processing should continue, `Ok(false)` if processing\n/// has terminated without error, and `Err(e)` if an error has occurred.\nfn handle_result(result: Result<()>) -> io::Result<bool> {\n    match result {\n        Ok(_) => Ok(true),\n        Err(Error::ConnectionClosed) => Ok(false),\n        Err(Error::Io(e)) => Err(e),\n        Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))\n    }\n}\n"
  },
  {
    "path": "core/codegen/Cargo.toml",
    "content": "[package]\nname = \"rocket_codegen\"\nversion = \"0.6.0-dev\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\"]\ndescription = \"Procedural macros for the Rocket web framework.\"\ndocumentation = \"https://api.rocket.rs/master/rocket_codegen/\"\nhomepage = \"https://rocket.rs\"\nrepository = \"https://github.com/rwf2/Rocket\"\nreadme = \"../../README.md\"\nkeywords = [\"rocket\", \"web\", \"framework\", \"code\", \"generation\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[lints]\nworkspace = true\n\n[lib]\nproc-macro = true\n\n[dependencies]\nindexmap = \"2\"\nquote = \"1.0\"\nsyn = { version = \"2.0\", features = [\"full\", \"visit\", \"visit-mut\", \"extra-traits\"] }\nproc-macro2 = \"1.0.60\"\ndevise = \"0.4\"\nrocket_http = { version = \"0.6.0-dev\", path = \"../http/\" }\nunicode-xid = \"0.2\"\nversion_check = \"0.9\"\nglob = \"0.3\"\n\n[dev-dependencies]\nrocket = { path = \"../lib\", features = [\"json\", \"msgpack\"] }\ntime = { version =  \"0.3\", features = [\"macros\"] }\npretty_assertions = \"1\"\nversion_check = \"0.9\"\ntrybuild = \"1.0\"\n"
  },
  {
    "path": "core/codegen/src/attribute/async_bound/mod.rs",
    "content": "use proc_macro2::{TokenStream, Span};\nuse devise::{Spanned, Result, ext::SpanDiagnosticExt};\nuse syn::{Token, parse_quote, parse_quote_spanned};\nuse syn::{TraitItemFn, TypeParamBound, ReturnType, Attribute};\nuse syn::punctuated::Punctuated;\nuse syn::parse::Parser;\n\nfn _async_bound(\n    args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream\n) -> Result<TokenStream> {\n    let bounds = <Punctuated<TypeParamBound, Token![+]>>::parse_terminated.parse(args)?;\n    if bounds.is_empty() {\n        return Ok(input.into());\n    }\n\n    let mut func: TraitItemFn = syn::parse(input)?;\n    let original: TraitItemFn = func.clone();\n    if func.sig.asyncness.is_none() {\n        let diag = Span::call_site()\n            .error(\"attribute can only be applied to async fns\")\n            .span_help(func.sig.span(), \"this fn declaration must be `async`\");\n\n        return Err(diag);\n    }\n\n    let doc: Attribute = parse_quote! {\n        #[doc = concat!(\n            \"# Future Bounds\",\n            \"\\n\",\n            \"**The `Future` generated by this `async fn` must be `\", stringify!(#bounds), \"`**.\"\n        )]\n    };\n\n    func.sig.asyncness = None;\n    func.sig.output = match func.sig.output {\n        ReturnType::Type(arrow, ty) => parse_quote_spanned!(ty.span() =>\n            #arrow impl ::core::future::Future<Output = #ty> + #bounds\n        ),\n        default@ReturnType::Default => parse_quote_spanned!(default.span() =>\n            -> impl ::core::future::Future<Output = ()> + #bounds\n        ),\n    };\n\n    Ok(quote! {\n        #[cfg(all(not(doc), rust_analyzer))]\n        #original\n\n        #[cfg(all(doc, not(rust_analyzer)))]\n        #doc\n        #original\n\n        #[cfg(not(any(doc, rust_analyzer)))]\n        #func\n    })\n}\n\npub fn async_bound(\n    args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream\n) -> TokenStream {\n    _async_bound(args, input).unwrap_or_else(|d| d.emit_as_item_tokens())\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/catch/mod.rs",
    "content": "mod parse;\n\nuse devise::ext::SpanDiagnosticExt;\nuse devise::{Spanned, Result};\nuse proc_macro2::{TokenStream, Span};\n\nuse crate::http_codegen::Optional;\nuse crate::syn_ext::ReturnTypeExt;\nuse crate::exports::*;\n\npub fn _catch(\n    args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream\n) -> Result<TokenStream> {\n    // Parse and validate all of the user's input.\n    let catch = parse::Attribute::parse(args.into(), input)?;\n\n    // Gather everything we'll need to generate the catcher.\n    let user_catcher_fn = &catch.function;\n    let user_catcher_fn_name = &catch.function.sig.ident;\n    let vis = &catch.function.vis;\n    let status_code = Optional(catch.status.map(|s| s.code));\n    let deprecated = catch.function.attrs.iter().find(|a| a.path().is_ident(\"deprecated\"));\n\n    // Determine the number of parameters that will be passed in.\n    if catch.function.sig.inputs.len() > 2 {\n        return Err(catch.function.sig.paren_token.span.join()\n            .error(\"invalid number of arguments: must be zero, one, or two\")\n            .help(\"catchers optionally take `&Request` or `Status, &Request`\"));\n    }\n\n    // This ensures that \"Responder not implemented\" points to the return type.\n    let return_type_span = catch.function.sig.output.ty()\n        .map(|ty| ty.span())\n        .unwrap_or_else(Span::call_site);\n\n    // Set the `req` and `status` spans to that of their respective function\n    // arguments for a more correct `wrong type` error span. `rev` to be cute.\n    let codegen_args = &[__req, __status];\n    let inputs = catch.function.sig.inputs.iter().rev()\n        .zip(codegen_args.iter())\n        .map(|(fn_arg, codegen_arg)| match fn_arg {\n            syn::FnArg::Receiver(_) => codegen_arg.respanned(fn_arg.span()),\n            syn::FnArg::Typed(a) => codegen_arg.respanned(a.ty.span())\n        }).rev();\n\n    // We append `.await` to the function call if this is `async`.\n    let dot_await = catch.function.sig.asyncness\n        .map(|a| quote_spanned!(a.span() => .await));\n\n    let catcher_response = quote_spanned!(return_type_span => {\n        let ___responder = #user_catcher_fn_name(#(#inputs),*) #dot_await;\n        #_response::Responder::respond_to(___responder, #__req)?\n    });\n\n    // Generate the catcher, keeping the user's input around.\n    Ok(quote! {\n        #user_catcher_fn\n\n        #[doc(hidden)]\n        #[allow(nonstandard_style)]\n        /// Rocket code generated proxy structure.\n        #deprecated #vis struct #user_catcher_fn_name {  }\n\n        /// Rocket code generated proxy static conversion implementations.\n        #[allow(nonstandard_style, deprecated, clippy::style)]\n        impl #user_catcher_fn_name {\n            fn into_info(self) -> #_catcher::StaticInfo {\n                fn monomorphized_function<'__r>(\n                    #__status: #Status,\n                    #__req: &'__r #Request<'_>\n                ) -> #_catcher::BoxFuture<'__r> {\n                    #_Box::pin(async move {\n                        let __response = #catcher_response;\n                        #Response::build()\n                            .status(#__status)\n                            .merge(__response)\n                            .ok()\n                    })\n                }\n\n                #_catcher::StaticInfo {\n                    name: ::core::stringify!(#user_catcher_fn_name),\n                    code: #status_code,\n                    handler: monomorphized_function,\n                    location: (::core::file!(), ::core::line!(), ::core::column!()),\n                }\n            }\n\n            #[doc(hidden)]\n            pub fn into_catcher(self) -> #Catcher {\n                self.into_info().into()\n            }\n        }\n    })\n}\n\npub fn catch_attribute(\n    args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream\n) -> TokenStream {\n    _catch(args, input).unwrap_or_else(|d| d.emit_as_item_tokens())\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/catch/parse.rs",
    "content": "use devise::ext::SpanDiagnosticExt;\nuse devise::{MetaItem, Spanned, Result, FromMeta, Diagnostic};\nuse proc_macro2::TokenStream;\n\nuse crate::{http, http_codegen};\n\n/// This structure represents the parsed `catch` attribute and associated items.\npub struct Attribute {\n    /// The status associated with the code in the `#[catch(code)]` attribute.\n    pub status: Option<http::Status>,\n    /// The function that was decorated with the `catch` attribute.\n    pub function: syn::ItemFn,\n}\n\n/// We generate a full parser for the meta-item for great error messages.\n#[derive(FromMeta)]\nstruct Meta {\n    #[meta(naked)]\n    code: Code,\n}\n\n/// `Some` if there's a code, `None` if it's `default`.\n#[derive(Debug)]\nstruct Code(Option<http::Status>);\n\nimpl FromMeta for Code {\n    fn from_meta(meta: &MetaItem) -> Result<Self> {\n        if usize::from_meta(meta).is_ok() {\n            let status = http_codegen::Status::from_meta(meta)?;\n            Ok(Code(Some(status.0)))\n        } else if let MetaItem::Path(path) = meta {\n            if path.is_ident(\"default\") {\n                Ok(Code(None))\n            } else {\n                Err(meta.span().error(\"expected `default`\"))\n            }\n        } else {\n            let msg = format!(\"expected integer or `default`, found {}\", meta.description());\n            Err(meta.span().error(msg))\n        }\n    }\n}\n\nimpl Attribute {\n    pub fn parse(args: TokenStream, input: proc_macro::TokenStream) -> Result<Self> {\n        let function: syn::ItemFn = syn::parse(input)\n            .map_err(Diagnostic::from)\n            .map_err(|diag| diag.help(\"`#[catch]` can only be used on functions\"))?;\n\n        let attr: MetaItem = syn::parse2(quote!(catch(#args)))?;\n        let status = Meta::from_meta(&attr)\n            .map(|meta| meta.code.0)\n            .map_err(|diag| diag.help(\"`#[catch]` expects a status code int or `default`: \\\n                        `#[catch(404)]` or `#[catch(default)]`\"))?;\n\n        Ok(Attribute { status, function })\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/entry/launch.rs",
    "content": "use devise::{Spanned, Result};\nuse devise::ext::SpanDiagnosticExt;\nuse proc_macro2::{TokenStream, Span};\n\nuse super::EntryAttr;\nuse crate::attribute::suppress::Lint;\nuse crate::exports::{mixed, _error, _ExitCode};\n\n/// `#[rocket::launch]`: generates a `main` function that calls the attributed\n/// function to generate a `Rocket` instance. Then calls `.launch()` on the\n/// returned instance inside of an `rocket::async_main`.\npub struct Launch;\n\n/// Determines if `f` likely spawns an async task, returning the spawn call.\nfn likely_spawns(f: &syn::ItemFn) -> Option<&syn::ExprCall> {\n    use syn::visit::{self, Visit};\n\n    struct SpawnFinder<'a>(Option<&'a syn::ExprCall>);\n\n    impl<'ast> Visit<'ast> for SpawnFinder<'ast> {\n        fn visit_expr_call(&mut self, i: &'ast syn::ExprCall) {\n            if self.0.is_some() {\n                return;\n            }\n\n            if let syn::Expr::Path(ref e) = *i.func {\n                let mut segments = e.path.segments.clone();\n                if let Some(last) = segments.pop() {\n                    if last.value().ident != \"spawn\" {\n                        return visit::visit_expr_call(self, i);\n                    }\n\n                    if let Some(prefix) = segments.pop() {\n                        if prefix.value().ident == \"tokio\" {\n                            self.0 = Some(i);\n                            return;\n                        }\n                    }\n\n                    if let Some(syn::Expr::Async(_)) = i.args.first() {\n                        self.0 = Some(i);\n                        return;\n                    }\n                }\n            };\n\n            visit::visit_expr_call(self, i);\n        }\n    }\n\n    let mut v = SpawnFinder(None);\n    v.visit_item_fn(f);\n    v.0\n}\n\nimpl EntryAttr for Launch {\n    const REQUIRES_ASYNC: bool = false;\n\n    fn function(f: &mut syn::ItemFn) -> Result<TokenStream> {\n        if f.sig.ident == \"main\" {\n            return Err(Span::call_site()\n                .error(\"attribute cannot be applied to `main` function\")\n                .note(\"this attribute generates a `main` function\")\n                .span_note(f.sig.ident.span(), \"this function cannot be `main`\"));\n        }\n\n        // Always infer the type as `Rocket<Build>`.\n        if let syn::ReturnType::Type(_, ref mut ty) = &mut f.sig.output {\n            if let syn::Type::Infer(_) = &mut **ty {\n                *ty = syn::parse_quote_spanned!(ty.span() => ::rocket::Rocket<::rocket::Build>);\n            }\n        }\n\n        let ty = match &f.sig.output {\n            syn::ReturnType::Type(_, ty) => ty,\n            _ => return Err(Span::call_site()\n                .error(\"attribute can only be applied to functions that return a value\")\n                .span_note(f.sig.span(), \"this function must return a value\"))\n        };\n\n        let block = &f.block;\n        let rocket = quote_spanned!(mixed(ty.span()) => {\n            let ___rocket: #ty = #block;\n            let ___rocket: ::rocket::Rocket<::rocket::Build> = ___rocket;\n            ___rocket\n        });\n\n        let launch = match f.sig.asyncness {\n            Some(_) => quote_spanned!(ty.span() => async move { #rocket.launch().await }),\n            None => quote_spanned!(ty.span() => #rocket.launch()),\n        };\n\n        let lint = Lint::SyncSpawn;\n        if f.sig.asyncness.is_none() && lint.enabled(f.sig.asyncness.span()) {\n            if let Some(call) = likely_spawns(f) {\n                call.span()\n                    .warning(\"task is being spawned outside an async context\")\n                    .span_help(f.sig.span(), \"declare this function as `async fn` \\\n                                              to require async execution\")\n                    .span_note(Span::call_site(), \"`#[launch]` call is here\")\n                    .note(lint.how_to_suppress())\n                    .emit_as_expr_tokens();\n            }\n        }\n\n        let (vis, mut sig) = (&f.vis, f.sig.clone());\n        sig.ident = syn::Ident::new(\"main\", f.sig.ident.span());\n        let ret_ty = _ExitCode.respanned(ty.span());\n        sig.output = syn::parse_quote_spanned!(ty.span() => -> #ret_ty);\n        sig.asyncness = None;\n\n        Ok(quote_spanned!(block.span() =>\n            #[allow(dead_code)] #f\n\n            #vis #sig {\n                #_error::Error::report(::rocket::async_main(#launch))\n            }\n        ))\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/entry/main.rs",
    "content": "use crate::attribute::suppress::Lint;\n\nuse super::EntryAttr;\n\nuse devise::{Spanned, Result};\nuse devise::ext::SpanDiagnosticExt;\nuse proc_macro2::{TokenStream, Span};\n\n/// `#[rocket::async_main]`: calls the attributed fn inside `rocket::async_main`\npub struct Main;\n\nimpl EntryAttr for Main {\n    const REQUIRES_ASYNC: bool = true;\n\n    fn function(f: &mut syn::ItemFn) -> Result<TokenStream> {\n        let (attrs, vis, block, sig) = (&f.attrs, &f.vis, &f.block, &mut f.sig);\n        let lint = Lint::ArbitraryMain;\n        if sig.ident != \"main\" && lint.enabled(sig.ident.span()) {\n            Span::call_site()\n                .warning(\"attribute is typically applied to `main` function\")\n                .span_note(sig.ident.span(), \"this function is not `main`\")\n                .note(lint.how_to_suppress())\n                .emit_as_item_tokens();\n        }\n\n        sig.asyncness = None;\n        Ok(quote_spanned!(block.span() => #(#attrs)* #vis #sig {\n            ::rocket::async_main(async move #block)\n        }))\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/entry/mod.rs",
    "content": "mod main;\nmod launch;\nmod test;\n\nuse devise::{Diagnostic, Spanned, Result};\nuse devise::ext::SpanDiagnosticExt;\nuse proc_macro2::{TokenStream, Span};\n\nuse crate::attribute::suppress::Lint;\n\n// Common trait implemented by `async` entry generating attributes.\ntrait EntryAttr {\n    /// Whether the attribute requires the attributed function to be `async`.\n    const REQUIRES_ASYNC: bool;\n\n    /// Return a new or rewritten function, using block as the main execution.\n    fn function(f: &mut syn::ItemFn) -> Result<TokenStream>;\n}\n\nfn _async_entry<A: EntryAttr>(\n    _args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream\n) -> Result<TokenStream> {\n    let mut function: syn::ItemFn = syn::parse(input)\n        .map_err(Diagnostic::from)\n        .map_err(|d| d.help(\"attribute can only be applied to functions\"))?;\n\n    Lint::suppress_attrs(&function.attrs, function.span());\n\n    if A::REQUIRES_ASYNC && function.sig.asyncness.is_none() {\n        return Err(Span::call_site()\n            .error(\"attribute can only be applied to `async` functions\")\n            .span_note(function.sig.span(), \"this function must be `async`\"));\n    }\n\n    if !function.sig.inputs.is_empty() {\n        return Err(Span::call_site()\n            .error(\"attribute can only be applied to functions without arguments\")\n            .span_note(function.sig.span(), \"this function must take no arguments\"));\n    }\n\n    A::function(&mut function)\n}\n\nmacro_rules! async_entry {\n    ($name:ident, $kind:ty, $default:expr) => (\n        pub fn $name(a: proc_macro::TokenStream, i: proc_macro::TokenStream) -> TokenStream {\n            _async_entry::<$kind>(a, i).unwrap_or_else(|d| {\n                let d = d.emit_as_item_tokens();\n                let default = $default;\n                quote!(#d #default)\n            })\n        }\n    )\n}\n\nasync_entry!(async_test_attribute, test::Test, quote!());\nasync_entry!(main_attribute, main::Main, quote!(fn main() {}));\nasync_entry!(launch_attribute, launch::Launch, quote!(fn main() {}));\n"
  },
  {
    "path": "core/codegen/src/attribute/entry/test.rs",
    "content": "use super::EntryAttr;\n\nuse devise::{Spanned, Result};\nuse proc_macro2::TokenStream;\n\n/// `#[rocket::async_test]`: calls the attributed fn inside `rocket::async_test`\npub struct Test;\n\nimpl EntryAttr for Test {\n    const REQUIRES_ASYNC: bool = true;\n\n    fn function(f: &mut syn::ItemFn) -> Result<TokenStream> {\n        let (attrs, vis, block, sig) = (&f.attrs, &f.vis, &f.block, &mut f.sig);\n        sig.asyncness = None;\n        Ok(quote_spanned!(block.span() => #(#attrs)* #[test] #vis #sig {\n            ::rocket::async_test(async move #block)\n        }))\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/mod.rs",
    "content": "pub mod entry;\npub mod catch;\npub mod route;\npub mod param;\npub mod async_bound;\npub mod suppress;\n"
  },
  {
    "path": "core/codegen/src/attribute/param/guard.rs",
    "content": "use std::hash::{Hash, Hasher};\n\nuse devise::{FromMeta, MetaItem, Result};\nuse proc_macro2::Span;\n\nuse crate::name::Name;\nuse crate::proc_macro_ext::StringLit;\nuse crate::http::uri;\n\nimpl Dynamic {\n    pub fn is_wild(&self) -> bool {\n        self.value == \"_\"\n    }\n}\n\nimpl FromMeta for Dynamic {\n    fn from_meta(meta: &MetaItem) -> Result<Self> {\n        let string = StringLit::from_meta(meta)?;\n        let span = string.subspan(1..string.len() + 1);\n\n        // We don't allow `_`. We abuse `fmt::Query` to enforce this.\n        Ok(Dynamic::parse::<fmt::Query>(&string, span)?)\n    }\n}\n\nimpl PartialEq for Dynamic {\n    fn eq(&self, other: &Dynamic) -> bool {\n        self.value == other.value\n    }\n}\n\nimpl Eq for Dynamic {}\n\nimpl Hash for Dynamic {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.value.hash(state)\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/param/mod.rs",
    "content": "mod parse;\n\nuse std::ops::Deref;\nuse std::hash::Hash;\n\nuse crate::name::Name;\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\npub enum Parameter {\n    Static(Name),\n    Ignored(Dynamic),\n    Dynamic(Dynamic),\n    Guard(Guard),\n}\n\n#[derive(Debug, Clone)]\npub struct Dynamic {\n    pub name: Name,\n    pub index: usize,\n    pub trailing: bool,\n}\n\n#[derive(Debug, Clone)]\npub struct Guard {\n    pub source: Dynamic,\n    pub fn_ident: syn::Ident,\n    pub ty: syn::Type,\n}\n\nimpl Parameter {\n    pub fn r#static(&self) -> Option<&Name> {\n        match self {\n            Parameter::Static(s) => Some(s),\n            _ => None\n        }\n    }\n\n    pub fn ignored(&self) -> Option<&Dynamic> {\n        match self {\n            Parameter::Ignored(d) => Some(d),\n            _ => None\n        }\n    }\n\n    pub fn take_dynamic(self) -> Option<Dynamic> {\n        match self {\n            Parameter::Dynamic(d) => Some(d),\n            Parameter::Guard(g) => Some(g.source),\n            _ => None\n        }\n    }\n\n    pub fn dynamic(&self) -> Option<&Dynamic> {\n        match self {\n            Parameter::Dynamic(d) => Some(d),\n            Parameter::Guard(g) => Some(&g.source),\n            _ => None\n        }\n    }\n\n    pub fn dynamic_mut(&mut self) -> Option<&mut Dynamic> {\n        match self {\n            Parameter::Dynamic(d) => Some(d),\n            Parameter::Guard(g) => Some(&mut g.source),\n            _ => None\n        }\n    }\n\n    pub fn guard(&self) -> Option<&Guard> {\n        match self {\n            Parameter::Guard(g) => Some(g),\n            _ => None\n        }\n    }\n}\n\nimpl Dynamic {\n    // This isn't public since this `Dynamic` should always be an `Ignored`.\n    pub fn is_wild(&self) -> bool {\n        &self.name == \"_\"\n    }\n}\n\nimpl Guard {\n    pub fn from(source: Dynamic, fn_ident: syn::Ident, ty: syn::Type) -> Self {\n        Guard { source, fn_ident, ty }\n    }\n}\n\nmacro_rules! impl_derived {\n    ($T:ty => $U:ty = $v:ident) => (\n        impl Deref for $T {\n            type Target = $U;\n\n            fn deref(&self) -> &Self::Target {\n                &self.$v\n            }\n        }\n\n        impl PartialEq for $T {\n            fn eq(&self, other: &Self) -> bool {\n                self.$v == other.$v\n            }\n        }\n\n        impl Eq for $T {  }\n\n        impl Hash for $T {\n            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n                self.$v.hash(state)\n            }\n        }\n    )\n}\n\nimpl_derived!(Dynamic => Name = name);\nimpl_derived!(Guard => Dynamic = source);\n"
  },
  {
    "path": "core/codegen/src/attribute/param/parse.rs",
    "content": "use unicode_xid::UnicodeXID;\nuse devise::{Diagnostic, ext::SpanDiagnosticExt};\nuse proc_macro2::Span;\n\nuse crate::name::Name;\nuse crate::proc_macro_ext::StringLit;\nuse crate::attribute::param::{Parameter, Dynamic};\nuse crate::http::uri::fmt::{Part, Kind, Path};\nuse crate::attribute::suppress::Lint;\n\n#[derive(Debug)]\npub struct Error<'a> {\n    segment: &'a str,\n    span: Span,\n    source: &'a str,\n    source_span: Span,\n    kind: ErrorKind,\n}\n\n#[derive(Debug, PartialEq, Eq, Copy, Clone)]\npub enum ErrorKind {\n    Empty,\n    BadIdent,\n    Ignored,\n    EarlyTrailing,\n    NoTrailing,\n    Static,\n}\n\nimpl Dynamic {\n    pub fn parse<P: Part>(\n        segment: &str,\n        span: Span,\n    ) -> Result<Self, Error<'_>>  {\n        match Parameter::parse::<P>(segment, span)? {\n            Parameter::Dynamic(d) | Parameter::Ignored(d) => Ok(d),\n            Parameter::Guard(g) => Ok(g.source),\n            Parameter::Static(_) => Err(Error::new(segment, span, ErrorKind::Static)),\n        }\n    }\n}\n\nimpl Parameter {\n    pub fn parse<P: Part>(\n        segment: &str,\n        source_span: Span,\n    ) -> Result<Self, Error<'_>>  {\n        let mut trailing = false;\n\n        // Check if this is a dynamic param. If so, check its well-formedness.\n        let lint = Lint::SegmentChars;\n        if segment.starts_with('<') && segment.ends_with('>') {\n            let mut name = &segment[1..(segment.len() - 1)];\n            if name.ends_with(\"..\") {\n                trailing = true;\n                name = &name[..(name.len() - 2)];\n            }\n\n            let span = subspan(name, segment, source_span);\n            if name.is_empty() {\n                return Err(Error::new(name, source_span, ErrorKind::Empty));\n            } else if !is_valid_ident(name) {\n                return Err(Error::new(name, span, ErrorKind::BadIdent));\n            }\n\n            let dynamic = Dynamic { name: Name::new(name, span), trailing, index: 0 };\n            if dynamic.is_wild() && P::KIND != Kind::Path {\n                return Err(Error::new(name, span, ErrorKind::Ignored));\n            } else if dynamic.is_wild() {\n                return Ok(Parameter::Ignored(dynamic));\n            } else {\n                return Ok(Parameter::Dynamic(dynamic));\n            }\n        } else if segment.is_empty() {\n            return Err(Error::new(segment, source_span, ErrorKind::Empty));\n        } else if segment.starts_with('<') && lint.enabled(source_span) {\n            let candidate = candidate_from_malformed(segment);\n            source_span.warning(\"`segment` starts with `<` but does not end with `>`\")\n                .help(format!(\"perhaps you meant the dynamic parameter `<{}>`?\", candidate))\n                .note(lint.how_to_suppress())\n                .emit_as_item_tokens();\n        } else if (segment.contains('>') || segment.contains('<')) && lint.enabled(source_span) {\n            source_span.warning(\"`segment` contains `<` or `>` but is not a dynamic parameter\")\n                .emit_as_item_tokens();\n        }\n\n        Ok(Parameter::Static(Name::new(segment, source_span)))\n    }\n\n    pub fn parse_many<P: Part>(\n        source: &str,\n        source_span: Span,\n    ) -> impl Iterator<Item = Result<Self, Error<'_>>> {\n        let mut trailing: Option<(&str, Span)> = None;\n\n        // We check for empty segments when we parse an `Origin` in `FromMeta`.\n        source.split(P::DELIMITER)\n            .filter(|s| !s.is_empty())\n            .enumerate()\n            .map(move |(i, segment)| {\n                if let Some((trail, span)) = trailing {\n                    let error = Error::new(trail, span, ErrorKind::EarlyTrailing)\n                        .source(source, source_span);\n\n                    return Err(error);\n                }\n\n                let segment_span = subspan(segment, source, source_span);\n                let mut parsed = Self::parse::<P>(segment, segment_span)\n                    .map_err(|e| e.source(source, source_span))?;\n\n                if let Some(ref mut d) = parsed.dynamic_mut() {\n                    if d.trailing {\n                        trailing = Some((segment, segment_span));\n                    }\n\n                    d.index = i;\n                }\n\n                Ok(parsed)\n            })\n    }\n}\n\nimpl std::fmt::Display for ErrorKind {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            ErrorKind::Empty => \"parameters cannot be empty\".fmt(f),\n            ErrorKind::BadIdent => \"invalid identifier\".fmt(f),\n            ErrorKind::Ignored => \"parameter must be named\".fmt(f),\n            ErrorKind::NoTrailing => \"parameter cannot be trailing\".fmt(f),\n            ErrorKind::EarlyTrailing => \"unexpected text after trailing parameter\".fmt(f),\n            ErrorKind::Static => \"unexpected static parameter\".fmt(f),\n        }\n    }\n}\n\nimpl<'a> Error<'a> {\n    pub fn new(segment: &str, span: Span, kind: ErrorKind) -> Error<'_> {\n        Error { segment, source: segment, span, source_span: span, kind }\n    }\n\n    pub fn source(mut self, source: &'a str, span: Span) -> Self {\n        self.source = source;\n        self.source_span = span;\n        self\n    }\n}\n\nimpl From<Error<'_>> for Diagnostic {\n    fn from(error: Error<'_>) -> Self {\n        match error.kind {\n            ErrorKind::Empty => error.span.error(error.kind.to_string()),\n            ErrorKind::BadIdent => {\n                let candidate = candidate_from_malformed(error.segment);\n                error.span.error(format!(\"{}: `{}`\", error.kind, error.segment))\n                    .help(\"dynamic parameters must be valid identifiers\")\n                    .help(format!(\"did you mean `<{}>`?\", candidate))\n            }\n            ErrorKind::Ignored => {\n                error.span.error(error.kind.to_string())\n                    .help(\"use a name such as `_guard` or `_param`\")\n            }\n            ErrorKind::EarlyTrailing => {\n                trailspan(error.segment, error.source, error.source_span)\n                    .error(error.kind.to_string())\n                    .help(\"a trailing parameter must be the final component\")\n                    .span_note(error.span, \"trailing param is here\")\n            }\n            ErrorKind::NoTrailing => {\n                let candidate = candidate_from_malformed(error.segment);\n                error.span.error(error.kind.to_string())\n                    .help(format!(\"did you mean `<{}>`?\", candidate))\n            }\n            ErrorKind::Static => {\n                let candidate = candidate_from_malformed(error.segment);\n                error.span.error(error.kind.to_string())\n                    .help(format!(\"parameter must be dynamic: `<{}>`\", candidate))\n            }\n        }\n    }\n}\n\nimpl devise::FromMeta for Dynamic {\n    fn from_meta(meta: &devise::MetaItem) -> devise::Result<Self> {\n        let string = StringLit::from_meta(meta)?;\n        let span = string.subspan(1..string.len() + 1);\n        let param = Dynamic::parse::<Path>(&string, span)?;\n\n        if param.is_wild() {\n            return Err(Error::new(&string, span, ErrorKind::Ignored).into());\n        } else if param.trailing {\n            return Err(Error::new(&string, span, ErrorKind::NoTrailing).into());\n        } else {\n            Ok(param)\n        }\n    }\n}\n\nfn subspan(needle: &str, haystack: &str, span: Span) -> Span {\n    let index = needle.as_ptr() as usize - haystack.as_ptr() as usize;\n    StringLit::new(haystack, span).subspan(index..index + needle.len())\n}\n\nfn trailspan(needle: &str, haystack: &str, span: Span) -> Span {\n    let index = needle.as_ptr() as usize - haystack.as_ptr() as usize;\n    let lit = StringLit::new(haystack, span);\n    if needle.as_ptr() as usize > haystack.as_ptr() as usize {\n        lit.subspan((index - 1)..)\n    } else {\n        lit.subspan(index..)\n    }\n}\n\nfn candidate_from_malformed(segment: &str) -> String {\n    let candidate = segment.chars().enumerate()\n        .filter(|(i, c)| *i == 0 && is_ident_start(*c) || *i != 0 && is_ident_continue(*c))\n        .map(|(_, c)| c)\n        .collect::<String>();\n\n    if candidate.is_empty() {\n        \"param\".into()\n    } else {\n        candidate\n    }\n}\n\n#[inline]\nfn is_ident_start(c: char) -> bool {\n    c.is_ascii_alphabetic()\n        || c == '_'\n        || (c > '\\x7f' && UnicodeXID::is_xid_start(c))\n}\n\n#[inline]\nfn is_ident_continue(c: char) -> bool {\n    c.is_ascii_alphanumeric()\n        || c == '_'\n        || (c > '\\x7f' && UnicodeXID::is_xid_continue(c))\n}\n\nfn is_valid_ident(string: &str) -> bool {\n    let mut chars = string.chars();\n    match chars.next() {\n        Some(c) => is_ident_start(c) && chars.all(is_ident_continue),\n        None => false\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/route/mod.rs",
    "content": "mod parse;\n\nuse std::hash::Hash;\n\nuse devise::{Spanned, SpanWrapped, Result, FromMeta, Diagnostic};\nuse devise::ext::TypeExt as _;\nuse proc_macro2::{TokenStream, Span};\n\nuse crate::proc_macro_ext::StringLit;\nuse crate::syn_ext::{IdentExt, TypeExt as _};\nuse crate::http_codegen::{Method, Optional};\nuse crate::attribute::param::Guard;\nuse crate::exports::mixed;\n\nuse self::parse::{Route, Attribute, MethodAttribute};\n\nuse super::suppress::Lint;\n\nimpl Route {\n    pub fn guards(&self) -> impl Iterator<Item = &Guard> {\n        self.param_guards()\n            .chain(self.query_guards())\n            .chain(self.data_guard.iter())\n            .chain(self.request_guards.iter())\n    }\n\n    pub fn param_guards(&self) -> impl Iterator<Item = &Guard> {\n        self.path_params.iter().filter_map(|p| p.guard())\n    }\n\n    pub fn query_guards(&self) -> impl Iterator<Item = &Guard> {\n        self.query_params.iter().filter_map(|p| p.guard())\n    }\n}\n\nfn query_decls(route: &Route) -> Option<TokenStream> {\n    use devise::ext::{Split2, Split6};\n\n    if route.query_params.is_empty() && route.query_guards().next().is_none() {\n        return None;\n    }\n\n    define_spanned_export!(Span::call_site() =>\n        __req, __data, _form, Outcome, _Ok, _Err, _Some, _None, Status\n    );\n\n    // Record all of the static parameters for later filtering.\n    let (raw_name, raw_value) = route.query_params.iter()\n        .filter_map(|s| s.r#static())\n        .map(|name| match name.find('=') {\n            Some(i) => (&name[..i], &name[i + 1..]),\n            None => (name.as_str(), \"\")\n        })\n        .split2();\n\n    // Now record all of the dynamic parameters.\n    let (name, matcher, ident, init_expr, push_expr, finalize_expr) = route.query_guards()\n        .map(|guard| {\n            let (name, ty) = (&guard.name, &guard.ty);\n            let ident = guard.fn_ident.rocketized().with_span(ty.span());\n            let matcher = match guard.trailing {\n                true => quote_spanned!(name.span() => _),\n                _ => quote!(#name)\n            };\n\n            define_spanned_export!(ty.span() => FromForm, _form);\n\n            let ty = quote_spanned!(ty.span() => <#ty as #FromForm>);\n            let init = quote_spanned!(ty.span() => #ty::init(#_form::Options::Lenient));\n            let finalize = quote_spanned!(ty.span() => #ty::finalize(#ident));\n            let push = match guard.trailing {\n                true => quote_spanned!(ty.span() => #ty::push_value(&mut #ident, _f)),\n                _ => quote_spanned!(ty.span() => #ty::push_value(&mut #ident, _f.shift())),\n            };\n\n            (name, matcher, ident, init, push, finalize)\n        })\n        .split6();\n\n    #[allow(non_snake_case)]\n    Some(quote! {\n        let (#(#ident),*) = {\n            let mut __e = #_form::Errors::new();\n            #(let mut #ident = #init_expr;)*\n\n            for _f in #__req.query_fields() {\n                let _raw = (_f.name.source().as_str(), _f.value);\n                let _key = _f.name.key_lossy().as_str();\n                match (_raw, _key) {\n                    // Skip static parameters so <param..> doesn't see them.\n                    #(((#raw_name, #raw_value), _) => { /* skip */ },)*\n                    #((_, #matcher) => #push_expr,)*\n                    _ => { /* in case we have no trailing, ignore all else */ },\n                }\n            }\n\n            #(\n                let #ident = match #finalize_expr {\n                    #_Ok(_v) => #_Some(_v),\n                    #_Err(_err) => {\n                        __e.extend(_err.with_name(#_form::NameView::new(#name)));\n                        #_None\n                    },\n                };\n            )*\n\n            if !__e.is_empty() {\n                ::rocket::trace::span_info!(\n                    \"codegen\",\n                    \"query string failed to match route declaration\" =>\n                        { for _err in __e { ::rocket::trace::info!(\n                            target: concat!(\"rocket::codegen::route::\", module_path!()),\n                            \"{_err}\"\n                        ); } }\n                );\n\n                return #Outcome::Forward((#__data, #Status::UnprocessableEntity));\n            }\n\n            (#(#ident.unwrap()),*)\n        };\n    })\n}\n\nfn request_guard_decl(guard: &Guard) -> TokenStream {\n    let (ident, ty) = (guard.fn_ident.rocketized(), &guard.ty);\n    define_spanned_export!(ty.span() =>\n        __req, __data, _request, display_hack, FromRequest, Outcome\n    );\n\n    quote_spanned! { ty.span() =>\n        let #ident: #ty = match <#ty as #FromRequest>::from_request(#__req).await {\n            #Outcome::Success(__v) => __v,\n            #Outcome::Forward(__e) => {\n                ::rocket::trace::info!(\n                    name: \"forward\",\n                    target: concat!(\"rocket::codegen::route::\", module_path!()),\n                    parameter = stringify!(#ident),\n                    type_name = stringify!(#ty),\n                    status = __e.code,\n                    \"request guard forwarding\"\n                );\n\n                return #Outcome::Forward((#__data, __e));\n            },\n            #[allow(unreachable_code)]\n            #Outcome::Error((__c, __e)) => {\n                ::rocket::trace::info!(\n                    name: \"failure\",\n                    target: concat!(\"rocket::codegen::route::\", module_path!()),\n                    parameter = stringify!(#ident),\n                    type_name = stringify!(#ty),\n                    reason = %#display_hack!(__e),\n                    \"request guard failed\"\n                );\n\n                return #Outcome::Error(__c);\n            }\n        };\n    }\n}\n\nfn param_guard_decl(guard: &Guard) -> TokenStream {\n    let (i, name, ty) = (guard.index, &guard.name, &guard.ty);\n    define_spanned_export!(ty.span() =>\n        __req, __data, _None, _Some, _Ok, _Err,\n        Outcome, FromSegments, FromParam, Status, display_hack\n    );\n\n    // Returned when a dynamic parameter fails to parse.\n    let parse_error = quote!({\n        ::rocket::trace::info!(\n            name: \"forward\",\n            target: concat!(\"rocket::codegen::route::\", module_path!()),\n            parameter = #name,\n            type_name = stringify!(#ty),\n            reason = %#display_hack!(__error),\n            \"path guard forwarding\"\n        );\n\n        #Outcome::Forward((#__data, #Status::UnprocessableEntity))\n    });\n\n    // All dynamic parameters should be found if this function is being called;\n    // that's the point of statically checking the URI parameters.\n    let expr = match guard.trailing {\n        false => quote_spanned! { ty.span() =>\n            match #__req.routed_segment(#i) {\n                #_Some(__s) => match <#ty as #FromParam>::from_param(__s) {\n                    #_Ok(__v) => __v,\n                    #[allow(unreachable_code)]\n                    #_Err(__error) => return #parse_error,\n                },\n                #_None => {\n                    ::rocket::trace::error!(\n                        target: concat!(\"rocket::codegen::route::\", module_path!()),\n                        \"Internal invariant broken: dyn param {} not found.\\n\\\n                        Please report this to the Rocket issue tracker.\\n\\\n                        https://github.com/rwf2/Rocket/issues\",\n                        #i\n                    );\n\n                    return #Outcome::Forward((#__data, #Status::InternalServerError));\n                }\n            }\n        },\n        true => quote_spanned! { ty.span() =>\n            match <#ty as #FromSegments>::from_segments(#__req.routed_segments(#i..)) {\n                #_Ok(__v) => __v,\n                #[allow(unreachable_code)]\n                #_Err(__error) => return #parse_error,\n            }\n        },\n    };\n\n    let ident = guard.fn_ident.rocketized();\n    quote!(let #ident: #ty = #expr;)\n}\n\nfn data_guard_decl(guard: &Guard) -> TokenStream {\n    let (ident, ty) = (guard.fn_ident.rocketized(), &guard.ty);\n    define_spanned_export!(ty.span() => __req, __data, display_hack, FromData, Outcome);\n\n    quote_spanned! { ty.span() =>\n        let #ident: #ty = match <#ty as #FromData>::from_data(#__req, #__data).await {\n            #Outcome::Success(__d) => __d,\n            #Outcome::Forward((__d, __e)) => {\n                ::rocket::trace::info!(\n                    name: \"forward\",\n                    target: concat!(\"rocket::codegen::route::\", module_path!()),\n                    parameter = stringify!(#ident),\n                    type_name = stringify!(#ty),\n                    status = __e.code,\n                    \"data guard forwarding\"\n                );\n\n                return #Outcome::Forward((__d, __e));\n            }\n            #[allow(unreachable_code)]\n            #Outcome::Error((__c, __e)) => {\n                ::rocket::trace::info!(\n                    name: \"failure\",\n                    target: concat!(\"rocket::codegen::route::\", module_path!()),\n                    parameter = stringify!(#ident),\n                    type_name = stringify!(#ty),\n                    reason = %#display_hack!(__e),\n                    \"data guard failed\"\n                );\n\n                return #Outcome::Error(__c);\n            }\n        };\n    }\n}\n\nfn internal_uri_macro_decl(route: &Route) -> TokenStream {\n    // FIXME: Is this the right order? Does order matter?\n    let uri_args = route.param_guards()\n        .chain(route.query_guards())\n        .map(|guard| (&guard.fn_ident, &guard.ty))\n        .map(|(ident, ty)| quote!(#ident: #ty));\n\n    // Generate a unique macro name based on the route's metadata.\n    let macro_name = route.handler.sig.ident.prepend(crate::URI_MACRO_PREFIX);\n    let inner_macro_name = macro_name.uniqueify_with(|mut hasher| {\n        route.attr.method.as_ref().map(|m| m.0.hash(&mut hasher));\n        route.attr.uri.path().hash(&mut hasher);\n        route.attr.uri.query().hash(&mut hasher);\n        route.attr.data.as_ref().map(|d| d.value.hash(&mut hasher));\n        route.attr.format.as_ref().map(|f| f.0.hash(&mut hasher));\n    });\n\n    let route_uri = route.attr.uri.to_string();\n\n    quote_spanned! { Span::call_site() =>\n        #[doc(hidden)]\n        #[allow(nonstandard_style, unused)]\n        pub mod #inner_macro_name {\n            #[doc(hidden)]\n            #[macro_export]\n            /// Rocket generated URI macro.\n            macro_rules! #inner_macro_name {\n                ($($token:tt)*) => {{\n                    ::rocket::rocket_internal_uri!(#route_uri, (#(#uri_args),*), $($token)*)\n                }};\n            }\n\n            pub use #inner_macro_name as #macro_name;\n        }\n\n        #[doc(hidden)]\n        #[allow(unused)]\n        pub use #inner_macro_name::#macro_name;\n    }\n}\n\nfn responder_outcome_expr(route: &Route) -> TokenStream {\n    let ret_span = match route.handler.sig.output {\n        syn::ReturnType::Default => route.handler.sig.ident.span(),\n        syn::ReturnType::Type(_, ref ty) => ty.span()\n    };\n\n    let user_handler_fn_name = &route.handler.sig.ident;\n    let parameter_names = route.arguments.map.values()\n        .map(|(ident, _)| ident.rocketized());\n\n    let _await = route.handler.sig.asyncness\n        .map(|a| quote_spanned!(a.span() => .await));\n\n    define_spanned_export!(ret_span => __req, _route);\n    quote_spanned! { mixed(ret_span) =>\n        let ___responder = #user_handler_fn_name(#(#parameter_names),*) #_await;\n        #_route::Outcome::from(#__req, ___responder)\n    }\n}\n\nfn sentinels_expr(route: &Route) -> TokenStream {\n    let ret_ty = match route.handler.sig.output {\n        syn::ReturnType::Default => None,\n        syn::ReturnType::Type(_, ref ty) => Some(ty.with_stripped_lifetimes())\n    };\n\n    let generic_idents: Vec<_> = route.handler.sig.generics\n        .type_params()\n        .map(|p| &p.ident)\n        .collect();\n\n    // Note: for a given route, we need to emit a valid graph of eligible\n    // sentinels. This means that we don't have broken links, where a child\n    // points to a parent that doesn't exist. The concern is that the\n    // `is_concrete()` filter will cause a break in the graph.\n    //\n    // Here's a proof by cases for why this can't happen:\n    //    1. if `is_concrete()` returns `false` for a (valid) type, it returns\n    //       false for all of its parents. we consider this an axiom; this is\n    //       the point of `is_concrete()`. the type is filtered out, so the\n    //       theorem vacuously holds\n    //    2. if `is_concrete()` returns `true`, for a type `T`, it either:\n    //      * returns `false` for the parent. by 1) it will return false for\n    //        _all_ parents of the type, so no node in the graph can consider,\n    //        directly or indirectly, `T` to be a child, and thus there are no\n    //        broken links; the theorem holds\n    //      * returns `true` for the parent, and so the type has a parent, and\n    //      the theorem holds.\n    //    3. these are all the cases. QED.\n\n    const TY_MACS: &[&str] = &[\"ReaderStream\", \"TextStream\", \"ByteStream\", \"EventStream\"];\n\n    fn ty_mac_mapper(tokens: &TokenStream) -> Option<syn::Type> {\n        use crate::bang::typed_stream::Input;\n\n        match syn::parse2(tokens.clone()).ok()? {\n            Input::Type(ty, ..) => Some(ty),\n            Input::Tokens(..) => None\n        }\n    }\n\n    let eligible_types = route.guards()\n        .map(|guard| &guard.ty)\n        .chain(ret_ty.as_ref())\n        .flat_map(|ty| ty.unfold_with_ty_macros(TY_MACS, ty_mac_mapper))\n        .filter(|ty| ty.is_concrete(&generic_idents))\n        .map(|child| (child.parent, child.ty));\n\n    let sentinel = eligible_types.map(|(parent, ty)| {\n        define_spanned_export!(ty.span() => _sentinel);\n\n        match parent {\n            Some(p) if p.is_concrete(&generic_idents) => {\n                quote_spanned!(ty.span() => #_sentinel::resolve!(#ty, #p))\n            }\n            Some(_) | None => quote_spanned!(ty.span() => #_sentinel::resolve!(#ty)),\n        }\n    });\n\n    quote!(::std::vec![#(#sentinel),*])\n}\n\nfn codegen_route(route: Route) -> Result<TokenStream> {\n    use crate::exports::*;\n\n    // Generate the declarations for all of the guards.\n    let request_guards = route.request_guards.iter().map(request_guard_decl);\n    let param_guards = route.param_guards().map(param_guard_decl);\n    let query_guards = query_decls(&route);\n    let data_guard = route.data_guard.as_ref().map(data_guard_decl);\n\n    // Extract the sentinels from the route.\n    let sentinels = sentinels_expr(&route);\n\n    // Gather info about the function.\n    let (vis, handler_fn) = (&route.handler.vis, &route.handler);\n    let deprecated = handler_fn.attrs.iter().find(|a| a.path().is_ident(\"deprecated\"));\n    let handler_fn_name = &handler_fn.sig.ident;\n    let internal_uri_macro = internal_uri_macro_decl(&route);\n    let responder_outcome = responder_outcome_expr(&route);\n\n    let method = Optional(route.attr.method.clone());\n    let uri = route.attr.uri.to_string();\n    let rank = Optional(route.attr.rank);\n    let format = Optional(route.attr.format.as_ref());\n\n    Ok(quote! {\n        #handler_fn\n\n        #[doc(hidden)]\n        #[allow(nonstandard_style)]\n        /// Rocket code generated proxy structure.\n        #deprecated #vis struct #handler_fn_name {  }\n\n        /// Rocket code generated proxy static conversion implementations.\n        #[allow(nonstandard_style, deprecated, clippy::style)]\n        impl #handler_fn_name {\n            fn into_info(self) -> #_route::StaticInfo {\n                fn monomorphized_function<'__r>(\n                    #__req: &'__r #Request<'_>,\n                    #__data: #Data<'__r>\n                ) -> #_route::BoxFuture<'__r> {\n                    #_Box::pin(async move {\n                        #(#request_guards)*\n                        #(#param_guards)*\n                        #query_guards\n                        #data_guard\n\n                        #responder_outcome\n                    })\n                }\n\n                #_route::StaticInfo {\n                    name: stringify!(#handler_fn_name),\n                    method: #method,\n                    uri: #uri,\n                    handler: monomorphized_function,\n                    format: #format,\n                    rank: #rank,\n                    sentinels: #sentinels,\n                    location: (::core::file!(), ::core::line!(), ::core::column!()),\n                }\n            }\n\n            #[doc(hidden)]\n            pub fn into_route(self) -> #Route {\n                self.into_info().into()\n            }\n        }\n\n        /// Rocket code generated wrapping URI macro.\n        #internal_uri_macro\n    })\n}\n\nfn complete_route(args: TokenStream, input: TokenStream) -> Result<TokenStream> {\n    let function: syn::ItemFn = syn::parse2(input)\n        .map_err(Diagnostic::from)\n        .map_err(|diag| diag.help(\"`#[route]` can only be used on functions\"))?;\n\n    let attr_tokens = quote!(route(#args));\n    let attribute = Attribute::from_meta(&syn::parse2(attr_tokens)?)?;\n    codegen_route(Route::from(attribute, function)?)\n}\n\nfn incomplete_route(\n    method: crate::http::Method,\n    args: TokenStream,\n    input: TokenStream\n) -> Result<TokenStream> {\n    // FIXME(proc_macro): there should be a way to get this `Span`.\n    let method_str = method.to_string().to_lowercase();\n    let method_span = StringLit::new(format!(\"#[{}]\", method), Span::call_site())\n        .subspan(2..2 + method_str.len());\n\n    let full_span = args.span().join(input.span()).unwrap_or(input.span());\n    let function: syn::ItemFn = syn::parse2(input)\n        .map_err(Diagnostic::from)\n        .map_err(|d| d.help(format!(\"#[{}] can only be used on functions\", method_str)))?;\n\n    Lint::suppress_attrs(&function.attrs, full_span);\n    let method_ident = syn::Ident::new(&method_str, method_span);\n    let full_attr = quote!(#method_ident(#args));\n    let method_attribute = MethodAttribute::from_meta(&syn::parse2(full_attr)?)?;\n\n    let attribute = Attribute {\n        method: Some(SpanWrapped {\n            full_span: method_span,\n            key_span: None,\n            span: method_span,\n            value: Method(method),\n        }),\n        uri: method_attribute.uri,\n        data: method_attribute.data,\n        format: method_attribute.format,\n        rank: method_attribute.rank,\n    };\n\n    codegen_route(Route::from(attribute, function)?)\n}\n\npub fn route_attribute<M: Into<Option<crate::http::Method>>>(\n    method: M,\n    args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream\n) -> TokenStream {\n    let result = match method.into() {\n        Some(method) => incomplete_route(method, args.into(), input.into()),\n        None => complete_route(args.into(), input.into())\n    };\n\n    result.unwrap_or_else(|diag| diag.emit_as_item_tokens())\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/route/parse.rs",
    "content": "use devise::{Spanned, SpanWrapped, Result, FromMeta};\nuse devise::ext::{SpanDiagnosticExt, TypeExt};\nuse indexmap::{IndexSet, IndexMap};\nuse proc_macro2::Span;\n\nuse crate::attribute::suppress::Lint;\nuse crate::proc_macro_ext::Diagnostics;\nuse crate::http_codegen::{Method, MediaType};\nuse crate::attribute::param::{Parameter, Dynamic, Guard};\nuse crate::syn_ext::FnArgExt;\nuse crate::name::Name;\nuse crate::http::ext::IntoOwned;\nuse crate::http::uri::{Origin, fmt};\n\n/// This structure represents the parsed `route` attribute and associated items.\n#[derive(Debug)]\npub struct Route {\n    /// The attribute: `#[get(path, ...)]`.\n    pub attr: Attribute,\n    /// The static and dynamic path parameters.\n    pub path_params: Vec<Parameter>,\n    /// The static and dynamic query parameters.\n    pub query_params: Vec<Parameter>,\n    /// The data guard, if any.\n    pub data_guard: Option<Guard>,\n    /// The request guards.\n    pub request_guards: Vec<Guard>,\n    /// The decorated function: the handler.\n    pub handler: syn::ItemFn,\n    /// The parsed arguments to the user's function.\n    pub arguments: Arguments,\n}\n\ntype ArgumentMap = IndexMap<Name, (syn::Ident, syn::Type)>;\n\n#[derive(Debug)]\npub struct Arguments {\n    pub span: Span,\n    pub map: ArgumentMap\n}\n\n/// The parsed `#[route(..)]` attribute.\n#[derive(Debug, FromMeta)]\npub struct Attribute {\n    #[meta(naked)]\n    pub uri: RouteUri,\n    pub method: Option<SpanWrapped<Method>>,\n    pub data: Option<SpanWrapped<Dynamic>>,\n    pub format: Option<MediaType>,\n    pub rank: Option<isize>,\n}\n\n/// The parsed `#[method(..)]` (e.g, `get`, `put`, etc.) attribute.\n#[derive(Debug, FromMeta)]\npub struct MethodAttribute {\n    #[meta(naked)]\n    pub uri: RouteUri,\n    pub data: Option<SpanWrapped<Dynamic>>,\n    pub format: Option<MediaType>,\n    pub rank: Option<isize>,\n}\n\n#[derive(Debug)]\npub struct RouteUri {\n    origin: Origin<'static>,\n    path_span: Span,\n    query_span: Option<Span>,\n}\n\nimpl FromMeta for RouteUri {\n    fn from_meta(meta: &devise::MetaItem) -> Result<Self> {\n        let string = crate::proc_macro_ext::StringLit::from_meta(meta)?;\n\n        let origin = Origin::parse_route(&string)\n            .map_err(|e| {\n                let span = string.subspan(e.index() + 1..(e.index() + 2));\n                span.error(format!(\"invalid route URI: {}\", e))\n                    .help(\"expected URI in origin form: \\\"/path/<param>\\\"\")\n            })?;\n\n        if !origin.is_normalized() {\n            let normalized = origin.clone().into_normalized();\n            let span = origin.path().find(\"//\")\n                .or_else(|| origin.query()\n                    .and_then(|q| q.find(\"&&\"))\n                    .map(|i| origin.path().len() + 1 + i))\n                .map(|i| string.subspan((1 + i)..(1 + i + 2)))\n                .unwrap_or_else(|| string.span());\n\n            return Err(span.error(\"route URIs cannot contain empty segments\")\n                .note(format!(\"expected \\\"{}\\\", found \\\"{}\\\"\", normalized, origin)));\n        }\n\n        let path_span = string.subspan(1..origin.path().len() + 1);\n        let query_span = origin.query().map(|q| {\n            let len_to_q = 1 + origin.path().len() + 1;\n            let end_of_q = len_to_q + q.len();\n            string.subspan(len_to_q..end_of_q)\n        });\n\n        Ok(RouteUri { origin: origin.into_owned(), path_span, query_span })\n    }\n}\n\nimpl Route {\n    pub fn upgrade_param(param: Parameter, args: &Arguments) -> Result<Parameter> {\n        if param.dynamic().is_none() {\n            return Ok(param);\n        }\n\n        let param = param.take_dynamic().expect(\"dynamic() => take_dynamic()\");\n        Route::upgrade_dynamic(param, args).map(Parameter::Guard)\n    }\n\n    pub fn upgrade_dynamic(param: Dynamic, args: &Arguments) -> Result<Guard> {\n        if let Some((ident, ty)) = args.map.get(&param.name) {\n            Ok(Guard::from(param, ident.clone(), ty.clone()))\n        } else {\n            let msg = format!(\"expected argument named `{}` here\", param.name);\n            let diag = param.span().error(\"unused parameter\").span_note(args.span, msg);\n            Err(diag)\n        }\n    }\n\n    pub fn from(attr: Attribute, handler: syn::ItemFn) -> Result<Route> {\n        // Collect diagnostics as we proceed.\n        let mut diags = Diagnostics::new();\n\n        // Emit a warning if a `data` param was supplied for non-payload methods.\n        if let Some(ref data) = attr.data {\n            let lint = Lint::DubiousPayload;\n            match attr.method.as_ref() {\n                Some(m) if m.0.allows_request_body() == Some(false) => {\n                    diags.push(data.full_span\n                        .error(\"`data` cannot be used on this route\")\n                        .span_note(m.span, \"method does not support request payloads\"))\n                },\n                Some(m) if m.0.allows_request_body().is_none() && lint.enabled(handler.span()) => {\n                    data.full_span.warning(\"`data` used with non-payload-supporting method\")\n                        .span_note(m.span, format!(\"'{}' does not typically support payloads\", m.0))\n                        .note(lint.how_to_suppress())\n                        .emit_as_item_tokens();\n                },\n                None if lint.enabled(handler.span()) => {\n                    data.full_span.warning(\"`data` used on route with wildcard method\")\n                        .note(\"some methods may not support request payloads\")\n                        .note(lint.how_to_suppress())\n                        .emit_as_item_tokens();\n                }\n                _ => { /* okay */ },\n            }\n        }\n\n        // Check the validity of function arguments.\n        let span = handler.sig.paren_token.span.join();\n        let mut arguments = Arguments { map: ArgumentMap::new(), span };\n        for arg in &handler.sig.inputs {\n            if let Some((ident, ty)) = arg.typed() {\n                let value = (ident.clone(), ty.with_stripped_lifetimes());\n                arguments.map.insert(Name::from(ident), value);\n            } else {\n                let span = arg.span();\n                let diag = if arg.wild().is_some() {\n                    span.error(\"handler arguments must be named\")\n                        .help(\"to name an ignored handler argument, use `_name`\")\n                } else {\n                    span.error(\"handler arguments must be of the form `ident: Type`\")\n                };\n\n                diags.push(diag);\n            }\n        }\n\n        // Parse and collect the path parameters.\n        let (source, span) = (attr.uri.path(), attr.uri.path_span);\n        let path_params = Parameter::parse_many::<fmt::Path>(source.as_str(), span)\n            .map(|p| Route::upgrade_param(p?, &arguments))\n            .filter_map(|p| p.map_err(|e| diags.push(e)).ok())\n            .collect::<Vec<_>>();\n\n        // Parse and collect the query parameters.\n        let query_params = match (attr.uri.query(), attr.uri.query_span) {\n            (Some(q), Some(span)) => Parameter::parse_many::<fmt::Query>(q.as_str(), span)\n                .map(|p| Route::upgrade_param(p?, &arguments))\n                .filter_map(|p| p.map_err(|e| diags.push(e)).ok())\n                .collect::<Vec<_>>(),\n            _ => vec![]\n        };\n\n        // Remove the `SpanWrapped` layer and upgrade to a guard.\n        let data_guard = attr.data.clone()\n            .map(|p| Route::upgrade_dynamic(p.value, &arguments))\n            .and_then(|p| p.map_err(|e| diags.push(e)).ok());\n\n        // Collect all of the declared dynamic route parameters.\n        let all_dyn_params = path_params.iter().filter_map(|p| p.dynamic())\n            .chain(query_params.iter().filter_map(|p| p.dynamic()))\n            .chain(data_guard.as_ref().map(|g| &g.source));\n\n        // Check for any duplicates in the dynamic route parameters.\n        let mut dyn_params: IndexSet<&Dynamic> = IndexSet::new();\n        for p in all_dyn_params {\n            if let Some(prev) = dyn_params.replace(p) {\n                diags.push(p.span().error(format!(\"duplicate parameter: `{}`\", p.name))\n                    .span_note(prev.span(), \"previous parameter with the same name here\"))\n            }\n        }\n\n        // Collect the request guards: all the arguments not already a guard.\n        let request_guards = arguments.map.iter()\n            .filter(|(name, _)| {\n                let mut all_other_guards = path_params.iter().filter_map(|p| p.guard())\n                    .chain(query_params.iter().filter_map(|p| p.guard()))\n                    .chain(data_guard.as_ref());\n\n                all_other_guards.all(|g| &g.name != *name)\n            })\n            .enumerate()\n            .map(|(index, (name, (ident, ty)))| Guard {\n                source: Dynamic { index, name: name.clone(), trailing: false },\n                fn_ident: ident.clone(),\n                ty: ty.clone(),\n            })\n            .collect();\n\n        diags.head_err_or(Route {\n            attr, path_params, query_params, data_guard, request_guards,\n            handler, arguments,\n        })\n    }\n}\n\nimpl std::ops::Deref for RouteUri {\n    type Target = Origin<'static>;\n\n    fn deref(&self) -> &Self::Target {\n        &self.origin\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/suppress/lint.rs",
    "content": "use std::cell::RefCell;\nuse std::collections::{HashMap, HashSet};\nuse std::ops::Range;\n\nuse devise::ext::PathExt;\nuse proc_macro2::{Span, TokenStream};\nuse syn::{parse::Parser, punctuated::Punctuated};\n\nmacro_rules! declare_lints {\n    ($($name:ident ( $string:literal) ),* $(,)?) => (\n        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]\n        pub enum Lint {\n            $($name),*\n        }\n\n        impl Lint {\n            fn from_str(string: &str) -> Option<Self> {\n                $(if string.eq_ignore_ascii_case($string) {\n                    return Some(Lint::$name);\n                })*\n\n                None\n            }\n\n            fn as_str(&self) -> &'static str {\n                match self {\n                    $(Lint::$name => $string),*\n                }\n            }\n\n            fn lints() -> &'static str {\n                concat!(\"[\" $(,$string,)\", \"* \"]\")\n            }\n        }\n    )\n}\n\ndeclare_lints! {\n    UnknownFormat(\"unknown_format\"),\n    DubiousPayload(\"dubious_payload\"),\n    SegmentChars(\"segment_chars\"),\n    ArbitraryMain(\"arbitrary_main\"),\n    SyncSpawn(\"sync_spawn\"),\n}\n\nthread_local! {\n    static SUPPRESSIONS: RefCell<HashMap<Lint, HashSet<Range<usize>>>> = RefCell::default();\n}\n\nfn span_to_range(span: Span) -> Option<Range<usize>> {\n    let string = format!(\"{span:?}\");\n    let i = string.find('(')?;\n    let j = string[i..].find(')')?;\n    let (start, end) = string[(i + 1)..(i + j)].split_once(\"..\")?;\n    Some(Range { start: start.parse().ok()?, end: end.parse().ok()? })\n}\n\nimpl Lint {\n    pub fn suppress_attrs(attrs: &[syn::Attribute], ctxt: Span) {\n        let _ = attrs.iter().try_for_each(|attr| Lint::suppress_attr(attr, ctxt));\n    }\n\n    pub fn suppress_attr(attr: &syn::Attribute, ctxt: Span) -> Result<(), syn::Error> {\n        let syn::Meta::List(list) = &attr.meta else {\n            return Ok(());\n        };\n\n        if !list.path.last_ident().map_or(false, |i| i == \"suppress\") {\n            return Ok(());\n        }\n\n        Self::suppress_tokens(list.tokens.clone(), ctxt)\n    }\n\n    pub fn suppress_tokens(attr_tokens: TokenStream, ctxt: Span) -> Result<(), syn::Error> {\n        let lints = Punctuated::<Lint, syn::Token![,]>::parse_terminated.parse2(attr_tokens)?;\n        lints.iter().for_each(|lint| lint.suppress(ctxt));\n        Ok(())\n    }\n\n    pub fn suppress(self, ctxt: Span) {\n        SUPPRESSIONS.with_borrow_mut(|s| {\n            let range = span_to_range(ctxt).unwrap_or_default();\n            s.entry(self).or_default().insert(range);\n        })\n    }\n\n    pub fn is_suppressed(self, ctxt: Span) -> bool {\n        SUPPRESSIONS.with_borrow(|s| {\n            let this = span_to_range(ctxt).unwrap_or_default();\n            s.get(&self).map_or(false, |set| {\n                set.iter().any(|r| this.start >= r.start && this.end <= r.end)\n            })\n        })\n    }\n\n    pub fn enabled(self, ctxt: Span) -> bool {\n        !self.is_suppressed(ctxt)\n    }\n\n    pub fn how_to_suppress(self) -> String {\n        format!(\"apply `#[suppress({})]` before the item to suppress this lint\", self.as_str())\n    }\n}\n\nimpl syn::parse::Parse for Lint {\n    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {\n        let ident: syn::Ident = input.parse()?;\n        let name = ident.to_string();\n        Lint::from_str(&name).ok_or_else(|| {\n            let msg = format!(\"invalid lint `{name}` (known lints: {})\", Lint::lints());\n            syn::Error::new(ident.span(), msg)\n        })\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/attribute/suppress/mod.rs",
    "content": "use proc_macro2::TokenStream;\nuse devise::Spanned;\n\nmod lint;\n\npub use lint::Lint;\n\npub fn suppress_attribute(\n    args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream\n) -> TokenStream {\n    let input: TokenStream = input.into();\n    match Lint::suppress_tokens(args.into(), input.span()) {\n        Ok(_) => input,\n        Err(e) => {\n            let error: TokenStream = e.to_compile_error().into();\n            quote!(#error #input)\n        }\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/bang/export.rs",
    "content": "use std::hash::Hash;\n\nuse devise::Spanned;\nuse devise::ext::SpanDiagnosticExt;\nuse proc_macro2::{TokenStream, TokenTree, Punct};\n\nuse crate::syn_ext::IdentExt;\n\npub fn _macro(input: proc_macro::TokenStream) -> devise::Result<TokenStream> {\n    let mac: syn::ItemMacro = syn::parse(input)?;\n    let macro_name = match mac.ident {\n        Some(ident) => ident,\n        None => return Err(mac.span().error(\"expected `macro_rules!`\")),\n    };\n\n    // We rename the actual `macro_export` macro so we don't accidentally use it\n    // internally from the auto-imported crate root macro namespace.\n    let (attrs, def) = (mac.attrs, mac.mac);\n    let internal_name = macro_name.prepend(\"___internal_\");\n    let mod_name = macro_name.uniqueify_with(|mut hasher| def.hash(&mut hasher));\n\n    let macro_rules_tokens = def.tokens.clone();\n    let decl_macro_tokens: TokenStream = def.tokens.into_iter()\n        .map(|t| match t {\n            TokenTree::Punct(p) if p.as_char() == ';' => {\n                let mut token = Punct::new(',', p.spacing());\n                token.set_span(p.span());\n                TokenTree::Punct(token)\n            },\n            _ => t,\n        })\n        .collect();\n\n    // Only try using the `macro` syntax on nightly/dev or when we don't know.\n    let export = match version_check::is_feature_flaggable() {\n        Some(true) | None => quote! {\n            #(#attrs)*\n            #[cfg(all(nightly, doc))]\n            pub macro #macro_name {\n                #decl_macro_tokens\n            }\n\n            #[cfg(not(all(nightly, doc)))]\n            pub use #mod_name::#internal_name as #macro_name;\n        },\n        Some(false) => quote! {\n            pub use #mod_name::#internal_name as #macro_name;\n        }\n    };\n\n    Ok(quote! {\n        #[allow(non_snake_case)]\n        mod #mod_name {\n            #[doc(hidden)]\n            #[macro_export]\n            macro_rules! #internal_name {\n                #macro_rules_tokens\n            }\n\n            pub use #internal_name;\n        }\n\n        #export\n    })\n}\n"
  },
  {
    "path": "core/codegen/src/bang/mod.rs",
    "content": "mod uri;\nmod uri_parsing;\nmod test_guide;\nmod export;\n\npub mod typed_stream;\n\nuse devise::Result;\nuse syn::{Path, punctuated::Punctuated, parse::Parser, Token};\nuse syn::spanned::Spanned;\nuse proc_macro2::TokenStream;\n\nfn struct_maker_vec(\n    input: proc_macro::TokenStream,\n    ty: TokenStream,\n    map: impl Fn(TokenStream) -> TokenStream,\n) -> Result<TokenStream> {\n    use crate::exports::_Vec;\n\n    // Parse a comma-separated list of paths.\n    let paths = <Punctuated<Path, Token![,]>>::parse_terminated.parse(input)?;\n    let exprs = paths.iter().map(|path| {\n        let expr = map(quote_spanned!(path.span() => ___struct));\n        quote_spanned!(path.span() => {\n            let ___struct = #path {};\n            let ___item: #ty = #expr;\n            ___item\n        })\n    });\n\n    Ok(quote!({\n        let ___vec: #_Vec<#ty> = vec![#(#exprs),*];\n        ___vec\n    }))\n}\n\npub fn routes_macro(input: proc_macro::TokenStream) -> TokenStream {\n    struct_maker_vec(input, quote!(::rocket::Route), |e| quote!(#e.into_route()))\n        .unwrap_or_else(|diag| diag.emit_as_expr_tokens())\n}\n\npub fn catchers_macro(input: proc_macro::TokenStream) -> TokenStream {\n    struct_maker_vec(input, quote!(::rocket::Catcher), |e| quote!(#e.into_catcher()))\n        .unwrap_or_else(|diag| diag.emit_as_expr_tokens())\n}\n\npub fn uri_macro(input: proc_macro::TokenStream) -> TokenStream {\n    uri::_uri_macro(input.into())\n        .unwrap_or_else(|diag| diag.emit_as_expr_tokens_or(quote! {\n            rocket::http::uri::Origin::root()\n        }))\n}\n\npub fn uri_internal_macro(input: proc_macro::TokenStream) -> TokenStream {\n    // TODO: Ideally we would generate a perfect `Origin::root()` so that we don't\n    // assist in propagating further errors. Alas, we can't set the span to the\n    // invocation of `uri!` without access to `span.parent()`, and\n    // `Span::call_site()` here points to the `#[route]`, immediate caller,\n    // generating a rather confusing error message when there's a type-mismatch.\n    uri::_uri_internal_macro(input.into())\n        .unwrap_or_else(|diag| diag.emit_as_expr_tokens_or(quote! {\n            rocket::http::uri::Origin::root()\n        }))\n}\n\npub fn guide_tests_internal(input: proc_macro::TokenStream) -> TokenStream {\n    test_guide::_macro(input)\n        .unwrap_or_else(|diag| diag.emit_as_item_tokens())\n}\n\npub fn export_internal(input: proc_macro::TokenStream) -> TokenStream {\n    export::_macro(input)\n        .unwrap_or_else(|diag| diag.emit_as_item_tokens())\n}\n\npub fn typed_stream(input: proc_macro::TokenStream) -> TokenStream {\n    typed_stream::_macro(input)\n        .unwrap_or_else(|diag| diag.emit_as_item_tokens())\n}\n"
  },
  {
    "path": "core/codegen/src/bang/test_guide.rs",
    "content": "use std::path::Path;\nuse std::error::Error;\n\nuse syn::{Ident, LitStr};\nuse devise::ext::SpanDiagnosticExt;\nuse proc_macro2::TokenStream;\n\npub fn _macro(input: proc_macro::TokenStream) -> devise::Result<TokenStream> {\n    let root_glob = syn::parse::<LitStr>(input)?;\n    let tests = entry_to_tests(&root_glob)\n        .map_err(|e| root_glob.span().error(format!(\"failed to read: {}\", e)))?;\n\n    Ok(quote!(#(#tests)*))\n}\n\nfn entry_to_tests(root_glob: &LitStr) -> Result<Vec<TokenStream>, Box<dyn Error>> {\n    let manifest_dir = std::env::var(\"CARGO_MANIFEST_DIR\").expect(\"MANIFEST_DIR\");\n    let full_glob = Path::new(&manifest_dir).join(root_glob.value());\n\n    let mut tests = vec![];\n    for path in glob::glob(&full_glob.to_string_lossy()).map_err(Box::new)? {\n        let path = path.map_err(Box::new)?;\n        let name = path.file_name()\n            .and_then(|f| f.to_str())\n            .map(|name| name.trim_matches(|c| char::is_numeric(c) || c == '-')\n                .replace(|c| c == '-' || c == '.', \"_\"))\n            .ok_or(\"invalid file name\")?;\n\n        let ident = Ident::new(&name.to_lowercase(), root_glob.span());\n        let full_path = Path::new(&manifest_dir).join(&path).display().to_string();\n        tests.push(quote_spanned!(root_glob.span() =>\n            #[allow(unused_doc_comments)]\n            mod #ident {\n                macro_rules! doc_comment { ($x:expr) => (#[doc = $x] extern {}); }\n                doc_comment!(include_str!(#full_path));\n            }\n        ));\n    }\n\n    if tests.is_empty() {\n        return Err(format!(\"glob '{}' evaluates to 0 files\", full_glob.display()).into());\n    }\n\n    Ok(tests)\n}\n"
  },
  {
    "path": "core/codegen/src/bang/typed_stream.rs",
    "content": "use proc_macro2::TokenStream;\nuse syn::parse::{Parse, ParseStream, discouraged::Speculative};\n\n#[derive(Debug)]\npub enum Input {\n    Type(syn::Type, Option<(syn::Token![+], syn::Lifetime)>),\n    Tokens(TokenStream)\n}\n\n#[derive(Debug)]\nstruct Invocation {\n    ty_stream_ty: syn::Path,\n    stream_mac: syn::Path,\n    stream_trait: syn::Path,\n    input: Input,\n}\n\n/// Reinterpret a `T + '_` (without the `dyn`) for `impl Stream<T> + '_`.\nfn trait_obj_recast(ty: &syn::Type) -> Option<(syn::Type, syn::Token![+], syn::Lifetime)> {\n    let bounds = match ty {\n        syn::Type::TraitObject(t) if t.dyn_token.is_none() => &t.bounds,\n        _ => return None\n    };\n\n    let mut bounds = bounds.pairs();\n    let (first, second) = (bounds.next()?, bounds.next()?);\n    let plus = **first.punct().expect(\"have two so have punct\");\n\n    let first = first.value();\n    let real_ty = syn::parse2(quote!(#first)).ok()?;\n    let lifetime = match second.value() {\n        syn::TypeParamBound::Lifetime(lt) => lt.clone(),\n        _ => return None,\n    };\n\n    Some((real_ty, plus, lifetime))\n}\n\nimpl Parse for Input {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        let fork = input.fork();\n        if let Ok(mut ty) = fork.parse() {\n            // If there's an extra + '_, use it in the reinterpretation.\n            let mut bound = match fork.parse() {\n                Ok(plus) => Some((plus, fork.parse()?)),\n                _ => None,\n            };\n\n            // We might miss `A + '_`. Check if we did.\n            if let Some((real_ty, plus, lt)) = trait_obj_recast(&ty) {\n                ty = real_ty;\n                bound = Some((plus, lt));\n            }\n\n            // If we have nothing else to parse, this must have been a type.\n            if fork.is_empty() {\n                input.advance_to(&fork);\n                Ok(Input::Type(ty, bound))\n            } else {\n                Ok(Input::Tokens(input.parse()?))\n            }\n        } else {\n            Ok(Input::Tokens(input.parse()?))\n        }\n    }\n}\n\nimpl Parse for Invocation {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        Ok(Invocation {\n            ty_stream_ty: (input.parse()?, input.parse::<syn::Token![,]>()?).0,\n            stream_mac: (input.parse()?, input.parse::<syn::Token![,]>()?).0,\n            stream_trait: (input.parse()?, input.parse::<syn::Token![,]>()?).0,\n            input: input.parse()?,\n        })\n    }\n}\n\n/// This macro exists because we want to disambiguate between input of a type\n/// and input of an expression that looks like a type. `macro_rules` matches\n/// eagerly on a single token, so something like `foo!(for x in 0..10 {})` will\n/// match a `($ty)` branch as will anything that starts with a path.\npub fn _macro(input: proc_macro::TokenStream) -> devise::Result<TokenStream> {\n    let tokens = proc_macro2::TokenStream::from(input);\n    let i: Invocation = syn::parse2(tokens)?;\n    let (s_ty, mac, s_trait) = (i.ty_stream_ty, i.stream_mac, i.stream_trait);\n    let tokens = match i.input {\n        Input::Tokens(tt) => quote!(#s_ty::from(#mac!(#tt))),\n        Input::Type(ty, Some((p, l))) => quote!(#s_ty<impl #s_trait<Item = #ty> #p #l>),\n        Input::Type(ty, None) => quote!(#s_ty<impl #s_trait<Item = #ty>>),\n    };\n\n    Ok(tokens)\n}\n"
  },
  {
    "path": "core/codegen/src/bang/uri.rs",
    "content": "use std::fmt::Display;\n\nuse devise::{Result, ext::{SpanDiagnosticExt, quote_respanned}};\nuse syn::{Expr, Ident, Type, spanned::Spanned};\nuse proc_macro2::TokenStream;\n\nuse crate::http::uri::fmt;\nuse crate::http_codegen::Optional;\nuse crate::syn_ext::IdentExt;\nuse crate::bang::uri_parsing::*;\nuse crate::attribute::param::Parameter;\nuse crate::exports::*;\nuse crate::URI_MACRO_PREFIX;\n\nmacro_rules! p {\n    (@go $num:expr, $singular:expr, $plural:expr) => (\n        if $num == 1 { $singular.into() } else { $plural }\n    );\n\n    (\"parameter\", $n:expr) => (p!(@go $n, \"parameter\", \"parameters\"));\n    ($n:expr, \"was\") => (p!(@go $n, \"1 was\", format!(\"{} were\", $n)));\n    ($n:expr, \"parameter\") => (p!(@go $n, \"1 parameter\", format!(\"{} parameters\", $n)));\n}\n\npub fn prefix_last_segment(path: &mut syn::Path, prefix: &str) {\n    let last_seg = path.segments.last_mut().expect(\"syn::Path has segments\");\n    last_seg.ident = last_seg.ident.prepend(prefix);\n}\n\npub fn _uri_macro(input: TokenStream) -> Result<TokenStream> {\n    let input2: TokenStream = input.clone();\n    match syn::parse2::<UriMacro>(input)? {\n        UriMacro::Routed(ref mut mac) => {\n            prefix_last_segment(&mut mac.route.path, URI_MACRO_PREFIX);\n            let path = &mac.route.path;\n            Ok(quote!(#path!(#input2)))\n        },\n        UriMacro::Literal(uri) => Ok(quote!(#uri)),\n    }\n}\n\nfn extract_exprs(internal: &InternalUriParams) -> Result<(\n        impl Iterator<Item = &Expr>,             // path exprs\n        impl Iterator<Item = &ArgExpr>,          // query exprs\n        impl Iterator<Item = (&Ident, &Type)>,   // types for both path || query\n    )>\n{\n    let route_name = &internal.uri_mac.route.path;\n    match internal.validate() {\n        Validation::Ok(exprs) => {\n            let path_params = internal.dynamic_path_params();\n            let path_param_count = path_params.clone().count();\n            for expr in exprs.iter().take(path_param_count) {\n                if expr.as_expr().is_none() {\n                    return Err(expr.span().error(\"path parameters cannot be ignored\"));\n                }\n            }\n\n            let query_exprs = exprs.clone().into_iter().skip(path_param_count);\n            let path_exprs = exprs.into_iter().map(|e| e.unwrap_expr()).take(path_param_count);\n            let types = internal.fn_args.iter().map(|a| (&a.ident, &a.ty));\n            Ok((path_exprs, query_exprs, types))\n        }\n        Validation::NamedIgnored(args) => {\n            let mut route_name = quote!(#route_name).to_string();\n            route_name.retain(|c| !c.is_whitespace());\n\n            let diag = internal.uri_mac.args_span()\n                .error(\"expected unnamed arguments due to ignored parameters\")\n                .note(format!(\"uri for route `{}` ignores {} path parameters: \\\"{}\\\"\",\n                        route_name, args.len(), internal.route_uri));\n\n            Err(diag)\n        }\n        Validation::Unnamed(expected, actual) => {\n            let mut route_name = quote!(#route_name).to_string();\n            route_name.retain(|c| !c.is_whitespace());\n\n            let diag = internal.uri_mac.args_span()\n                .error(format!(\"route expects {} but {} supplied\",\n                         p!(expected, \"parameter\"), p!(actual, \"was\")))\n                .note(format!(\"route `{}` has uri \\\"{}\\\"\", route_name, internal.route_uri));\n\n            Err(diag)\n        }\n        Validation::Named(missing, extra, dup) => {\n            let e = format!(\"invalid parameters for `{}` route uri\", quote!(#route_name));\n            let mut diag = internal.uri_mac.args_span().error(e)\n                .note(format!(\"uri parameters are: {}\", internal.fn_args_str()));\n\n            fn join<S: Display, T: Iterator<Item = S>>(iter: T) -> (&'static str, String) {\n                let mut items: Vec<_> = iter.map(|i| format!(\"`{}`\", i)).collect();\n                items.dedup();\n                (p!(\"parameter\", items.len()), items.join(\", \"))\n            }\n\n            if !missing.is_empty() {\n                let (ps, msg) = join(missing.iter());\n                diag = diag.help(format!(\"missing {}: {}\", ps, msg));\n            }\n\n            if !extra.is_empty() {\n                let (ps, msg) = join(extra.iter());\n                let spans: Vec<_> = extra.iter().map(|ident| ident.span()).collect();\n                diag = diag.span_help(spans, format!(\"unknown {}: {}\", ps, msg));\n            }\n\n            if !dup.is_empty() {\n                let (ps, msg) = join(dup.iter());\n                let spans: Vec<_> = dup.iter().map(|ident| ident.span()).collect();\n                diag = diag.span_help(spans, format!(\"duplicate {}: {}\", ps, msg));\n            }\n\n            Err(diag)\n        }\n    }\n}\n\nfn add_binding<P: fmt::Part>(to: &mut Vec<TokenStream>, ident: &Ident, ty: &Type, expr: &Expr) {\n    let span = expr.span();\n    let part = match P::KIND {\n        fmt::Kind::Path => quote_spanned!(span => #_fmt::Path),\n        fmt::Kind::Query  => quote_spanned!(span => #_fmt::Query),\n    };\n\n    let tmp_ident = ident.clone().with_span(expr.span());\n    let let_stmt = quote_spanned!(span => let #tmp_ident = #expr);\n\n    to.push(quote_spanned!(mixed(span) =>\n        #[allow(non_snake_case)] #let_stmt;\n        let #ident = <#ty as #_fmt::FromUriParam<#part, _>>::from_uri_param(#tmp_ident);\n    ));\n}\n\nfn explode_path<'a>(\n    internal: &InternalUriParams,\n    bindings: &mut Vec<TokenStream>,\n    mut exprs: impl Iterator<Item = &'a Expr>,\n    mut args: impl Iterator<Item = (&'a Ident, &'a Type)>,\n) -> TokenStream {\n    if internal.dynamic_path_params().count() == 0 {\n        let path = internal.route_uri.path().as_str();\n        quote!(#_fmt::UriArgumentsKind::Static(#path))\n    } else {\n        let uri_display = quote!(#_fmt::UriDisplay<#_fmt::Path>);\n        let dyn_exprs = internal.path_params.iter().map(|param| {\n            match param {\n                Parameter::Static(name) => {\n                    quote!(&#name as &dyn #uri_display)\n                },\n                Parameter::Dynamic(_) | Parameter::Guard(_) => {\n                    let (ident, ty) = args.next().expect(\"ident/ty for non-ignored\");\n                    let expr = exprs.next().expect(\"one expr per dynamic arg\");\n                    add_binding::<fmt::Path>(bindings, ident, ty, expr);\n                    quote_spanned!(expr.span() => &#ident as &dyn #uri_display)\n                }\n                Parameter::Ignored(_) => {\n                    let expr = exprs.next().expect(\"one expr per dynamic arg\");\n                    quote_spanned!(expr.span() => &#expr as &dyn #uri_display)\n                }\n            }\n        });\n\n        quote!(#_fmt::UriArgumentsKind::Dynamic(&[#(#dyn_exprs),*]))\n    }\n}\n\nfn explode_query<'a>(\n    internal: &InternalUriParams,\n    bindings: &mut Vec<TokenStream>,\n    mut arg_exprs: impl Iterator<Item = &'a ArgExpr>,\n    mut args: impl Iterator<Item = (&'a Ident, &'a Type)>,\n) -> Option<TokenStream> {\n    let query = internal.route_uri.query()?.as_str();\n    if internal.dynamic_query_params().count() == 0 {\n        return Some(quote!(#_fmt::UriArgumentsKind::Static(#query)));\n    }\n\n    let query_arg = quote!(#_fmt::UriQueryArgument);\n    let uri_display = quote!(#_fmt::UriDisplay<#_fmt::Query>);\n    let dyn_exprs = internal.query_params.iter().filter_map(|param| {\n        if let Parameter::Static(source) = param {\n            return Some(quote!(#query_arg::Raw(#source)));\n        }\n\n        let dynamic = match param {\n            Parameter::Static(source) =>  {\n                return Some(quote!(#query_arg::Raw(#source)));\n            },\n            Parameter::Dynamic(ref seg) => seg,\n            Parameter::Guard(ref seg) => seg,\n            Parameter::Ignored(_) => unreachable!(\"invariant: unignorable q\")\n        };\n\n        let (ident, ty) = args.next().expect(\"ident/ty for query\");\n        let arg_expr = arg_exprs.next().expect(\"one expr per query\");\n        let expr = match arg_expr.as_expr() {\n            Some(expr) => expr,\n            None => {\n                // Force a typecheck for the `Ignoreable` trait.\n                bindings.push(quote_respanned! { arg_expr.span() =>\n                    #_fmt::assert_ignorable::<#_fmt::Query, #ty>();\n                });\n\n                return None;\n            }\n        };\n\n        let name = &dynamic.name;\n        add_binding::<fmt::Query>(bindings, ident, ty, expr);\n        Some(match dynamic.trailing {\n            false => quote_spanned! { expr.span() =>\n                #query_arg::NameValue(#name, &#ident as &dyn #uri_display)\n            },\n            true => quote_spanned! { expr.span() =>\n                #query_arg::Value(&#ident as &dyn #uri_display)\n            },\n        })\n    });\n\n    Some(quote!(#_fmt::UriArgumentsKind::Dynamic(&[#(#dyn_exprs),*])))\n}\n\npub fn _uri_internal_macro(input: TokenStream) -> Result<TokenStream> {\n    // Parse the internal invocation and the user's URI param expressions.\n    let internal = syn::parse2::<InternalUriParams>(input)?;\n    let (path_exprs, query_exprs, mut fn_args) = extract_exprs(&internal)?;\n\n    let mut bindings = vec![];\n    let path = explode_path(&internal, &mut bindings, path_exprs, &mut fn_args);\n    let query = Optional(explode_query(&internal, &mut bindings, query_exprs, fn_args));\n\n    let prefix = internal.uri_mac.prefix.as_ref()\n        .map(|prefix| quote_spanned!(prefix.span() => .with_prefix(#prefix)));\n\n    let suffix = internal.uri_mac.suffix.as_ref()\n        .map(|suffix| quote_spanned!(suffix.span() => .with_suffix(#suffix)));\n\n     Ok(quote_spanned!(internal.uri_mac.route.path.span() =>\n         #[allow(unused_braces)] {\n             #(#bindings)*\n             let __builder = #_fmt::RouteUriBuilder::new(#path, #query);\n             __builder #prefix #suffix .render()\n         }\n     ))\n}\n"
  },
  {
    "path": "core/codegen/src/bang/uri_parsing.rs",
    "content": "use std::ops::Deref;\n\nuse indexmap::IndexMap;\nuse devise::{Spanned, ext::TypeExt};\nuse quote::{ToTokens, TokenStreamExt};\nuse syn::{Expr, Ident, LitStr, Path, Token, Type};\nuse syn::parse::{self, Parse, ParseStream, Parser};\nuse syn::punctuated::Punctuated;\nuse proc_macro2::{TokenStream, TokenTree, Span};\nuse rocket_http::uri::{Error, Reference};\n\nuse crate::http::uri::{Uri, Origin, Absolute, fmt};\nuse crate::http::ext::IntoOwned;\nuse crate::proc_macro_ext::StringLit;\nuse crate::attribute::param::{Parameter, Dynamic};\nuse crate::name::Name;\n\n// TODO(diag): Use 'Diagnostic' in place of syn::Error.\n\n#[derive(Debug)]\npub enum ArgExpr {\n    Expr(Expr),\n    Ignored(Token![_]),\n}\n\n#[derive(Debug)]\npub enum Arg {\n    Unnamed(ArgExpr),\n    Named(Name, Ident, Token![=], ArgExpr),\n}\n\n#[derive(Debug)]\npub enum Args {\n    Unnamed(Punctuated<Arg, Token![,]>),\n    Named(Punctuated<Arg, Token![,]>),\n}\n\n/// A string literal parsed as a URI.\n#[derive(Debug)]\npub struct UriLit(Uri<'static>, Span);\n\n/// An expression in a URI slot (prefix, suffix, or literal).\n#[derive(Debug)]\npub enum UriExpr {\n    /// A string literal parsed as a URI.\n    Uri(UriLit),\n    /// An expression that will be typechecked to be some URI kind.\n    Expr(Expr),\n}\n\n/// See `UriMacro` for what each field represents.\n#[derive(Debug)]\npub struct RouteInvocation {\n    pub path: Path,\n    pub args: Args,\n}\n\n/// See `UriMacro` for what each field represents.\n#[derive(Debug)]\npub struct RoutedUri {\n    pub prefix: Option<UriExpr>,\n    pub route: RouteInvocation,\n    pub suffix: Option<UriExpr>,\n}\n\n// The macro can be invoked with 1, 2, or 3 arguments.\n//\n// As a `Literal`, with a single argument:\n//  uri!(\"/mount/point\");\n//       ^-------------|\n//                 literal.0\n//\n// As `Routed`, with 1, 2, or 3 arguments: prefix/suffix optional.\n//  uri!(\"/mount/point\", this::route(e1, e2, e3), \"?some#suffix\");\n//       ^-------------| ^---------|^----------|  |-----|------|\n//              routed.prefix      |           |   routed.suffix\n//                                 |   route.route.args\n//                        routed.route.path\n#[derive(Debug)]\npub enum UriMacro {\n    Literal(UriLit),\n    Routed(RoutedUri),\n}\n\n#[derive(Debug)]\npub enum Validation<'a> {\n    // Parameters that were ignored in a named argument setting.\n    NamedIgnored(Vec<&'a Dynamic>),\n    // Number expected, what we actually got.\n    Unnamed(usize, usize),\n    // (Missing, Extra, Duplicate)\n    Named(Vec<&'a Name>, Vec<&'a Ident>, Vec<&'a Ident>),\n    // Everything is okay; here are the expressions in the route decl order.\n    Ok(Vec<&'a ArgExpr>)\n}\n\n// This is invoked by Rocket itself. The `uri!` macro expands to a call to a\n// route-specific macro which in-turn expands to a call to `internal_uri!`,\n// passing along the user's invocation (`uri_mac`) from the original `uri!`\n// call. This is necessary so that we can converge the type information in the\n// route (from the route-specific macro) with the user's parameters (by\n// forwarding them to the internal_uri! call).\n//\n// `fn_args` are the URI arguments (excluding request guards) from the original\n// handler in the order they were declared in the URI (`<first>/<second>`).\n// `route_uri` is the full route URI itself.\n//\n// The syntax of `uri_mac` is that of `UriMacro`.\n//\n//  internal_uri!(\"/<one>/<_>?lang=en&<two>\", (one: ty, two: ty), $($tt)*);\n//                ^----/----^ ^-----\\-----^    ^-------/------^   ^-----|\n//               path_params    query_params       fn_args          uri_mac\n//                ^------ route_uri ------^\n#[derive(Debug)]\npub struct InternalUriParams {\n    pub route_uri: Origin<'static>,\n    pub path_params: Vec<Parameter>,\n    pub query_params: Vec<Parameter>,\n    pub fn_args: Vec<FnArg>,\n    pub uri_mac: RoutedUri,\n}\n\n#[derive(Debug)]\npub struct FnArg {\n    pub ident: Ident,\n    pub ty: Type,\n}\n\nfn err<T, S: AsRef<str>>(span: Span, s: S) -> parse::Result<T> {\n    Err(parse::Error::new(span, s.as_ref()))\n}\n\nimpl Parse for ArgExpr {\n    fn parse(input: ParseStream<'_>) -> parse::Result<Self> {\n        if input.peek(Token![_]) {\n            return Ok(ArgExpr::Ignored(input.parse::<Token![_]>()?));\n        }\n\n        input.parse::<Expr>().map(ArgExpr::Expr)\n    }\n}\n\nimpl Parse for Arg {\n    fn parse(input: ParseStream<'_>) -> parse::Result<Self> {\n        let has_key = input.peek2(Token![=]);\n        if has_key {\n            let ident = input.parse::<Ident>()?;\n            let eq_token = input.parse::<Token![=]>()?;\n            let expr = input.parse::<ArgExpr>()?;\n            Ok(Arg::Named(Name::from(&ident), ident, eq_token, expr))\n        } else {\n            let expr = input.parse::<ArgExpr>()?;\n            Ok(Arg::Unnamed(expr))\n        }\n    }\n}\n\nimpl Parse for Args {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        // If there are no arguments, finish early.\n        if input.cursor().eof() {\n            return Ok(Args::Unnamed(Punctuated::new()));\n        }\n\n        // Parse arguments. Ensure both types of args were not used at once.\n        let args = input.parse_terminated(Arg::parse, Token![,])?;\n        let mut first_is_named = None;\n        for arg in &args {\n            if let Some(first_is_named) = first_is_named {\n                if first_is_named != arg.is_named() {\n                    return err(args.span(), \"named and unnamed parameters cannot be mixed\");\n                }\n            } else {\n                first_is_named = Some(arg.is_named());\n            }\n        }\n\n        // Create the `Args` enum, which properly record one-kind-of-argument-ness.\n        match first_is_named {\n            Some(true) => Ok(Args::Named(args)),\n            _ => Ok(Args::Unnamed(args))\n        }\n    }\n}\n\nimpl Parse for RouteInvocation {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        let path = input.parse()?;\n        let args = if input.peek(syn::token::Paren) {\n            let args;\n            syn::parenthesized!(args in input);\n            args.parse()?\n        } else {\n            Args::Unnamed(Punctuated::new())\n        };\n\n        Ok(RouteInvocation { path, args })\n    }\n}\n\nimpl Parse for UriLit {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        let string = input.parse::<StringLit>()?;\n        let uri = match Uri::parse_any(&string) {\n            Ok(uri) => uri.into_owned(),\n            Err(e) => {\n                let span = string.subspan(e.index() + 1..(e.index() + 2));\n                return err(span, format!(\"invalid URI: {}\", e));\n            }\n        };\n\n        Ok(UriLit(uri, string.span()))\n    }\n}\n\nimpl UriMacro {\n    fn unary(input: ParseStream<'_>) -> parse::Result<Self> {\n        if input.peek(LitStr) {\n            Ok(UriMacro::Literal(input.parse()?))\n        } else {\n            Ok(UriMacro::Routed(RoutedUri {\n                prefix: None,\n                route: input.parse()?,\n                suffix: None,\n            }))\n        }\n    }\n\n    fn binary(prefix: TokenStream, middle: TokenStream) -> parse::Result<Self> {\n        Ok(UriMacro::Routed(RoutedUri {\n            prefix: UriExpr::parse_prefix.parse2(prefix)?,\n            route: syn::parse2(middle)?,\n            suffix: None,\n        }))\n    }\n\n    fn ternary(prefix: TokenStream, mid: TokenStream, suffix: TokenStream) -> parse::Result<Self> {\n        Ok(UriMacro::Routed(RoutedUri {\n            prefix: UriExpr::parse_prefix.parse2(prefix)?,\n            route: syn::parse2(mid)?,\n            suffix: UriExpr::parse_suffix.parse2(suffix)?\n        }))\n    }\n}\n\nimpl Parse for UriMacro {\n    fn parse(input: ParseStream<'_>) -> parse::Result<Self> {\n        use syn::buffer::Cursor;\n        use parse::{StepCursor, Result};\n\n        fn stream<'c>(cursor: StepCursor<'c, '_>) -> Result<(Option<TokenStream>, Cursor<'c>)> {\n            let mut stream = TokenStream::new();\n            let mut cursor = *cursor;\n            while let Some((tt, next)) = cursor.token_tree() {\n                cursor = next;\n                match tt {\n                    TokenTree::Punct(p) if p.as_char() == ',' => break,\n                    _ =>  stream.append(tt)\n                }\n            }\n\n            stream.is_empty()\n                .then(|| Ok((None, cursor)))\n                .unwrap_or(Ok((Some(stream), cursor)))\n        }\n\n        let mut args = vec![];\n        while let Some(tokens) = input.step(stream)? {\n            args.push(tokens);\n        }\n\n        let (arg_count, mut iter) = (args.len(), args.into_iter());\n        let mut next = || iter.next().unwrap();\n        match arg_count {\n            0 => err(Span::call_site(), \"expected at least 1 argument, found none\"),\n            1 => UriMacro::unary.parse2(next()),\n            2 => UriMacro::binary(next(), next()),\n            3 => UriMacro::ternary(next(), next(), next()),\n            n => err(iter.nth(3).unwrap().span(),\n                format!(\"expected 1, 2, or 3 arguments, found {}\", n))\n        }\n    }\n}\n\nimpl Parse for RoutedUri {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        match UriMacro::parse(input)? {\n            UriMacro::Routed(route) => Ok(route),\n            UriMacro::Literal(uri) => err(uri.span(), \"expected route URI, found literal\")\n        }\n    }\n}\n\nimpl Parse for FnArg {\n    fn parse(input: ParseStream<'_>) -> parse::Result<FnArg> {\n        let ident = input.parse::<Ident>()?;\n        input.parse::<Token![:]>()?;\n        let mut ty = input.parse::<Type>()?;\n        ty.strip_lifetimes();\n        Ok(FnArg { ident, ty })\n    }\n}\n\nimpl Parse for InternalUriParams {\n    fn parse(input: ParseStream<'_>) -> parse::Result<InternalUriParams> {\n        let route_uri_str = input.parse::<StringLit>()?;\n        input.parse::<Token![,]>()?;\n\n        // Validation should always succeed since this macro can only be called\n        // if the route attribute succeeded, implying a valid route URI.\n        let route_uri = Origin::parse_route(&route_uri_str)\n            .map(|o| o.into_normalized().into_owned())\n            .map_err(|_| input.error(\"internal error: invalid route URI\"))?;\n\n        let content;\n        syn::parenthesized!(content in input);\n        let fn_args = content.parse_terminated(FnArg::parse, Token![,])?;\n        let fn_args = fn_args.into_iter().collect();\n\n        input.parse::<Token![,]>()?;\n        let uri_mac = input.parse::<RoutedUri>()?;\n\n        let span = route_uri_str.subspan(1..route_uri.path().len() + 1);\n        let path_params = Parameter::parse_many::<fmt::Path>(route_uri.path().as_str(), span)\n            .map(|p| p.expect(\"internal error: invalid path parameter\"))\n            .collect::<Vec<_>>();\n\n        let query = route_uri.query();\n        let query_params = query.map(|query| {\n            let i = route_uri.path().len() + 2;\n            let span = route_uri_str.subspan(i..(i + query.len()));\n            Parameter::parse_many::<fmt::Query>(query.as_str(), span)\n                .map(|p| p.expect(\"internal error: invalid query parameter\"))\n                .collect::<Vec<_>>()\n        }).unwrap_or_default();\n\n        Ok(InternalUriParams { route_uri, path_params, query_params, fn_args, uri_mac })\n    }\n}\n\nimpl InternalUriParams {\n    pub fn fn_args_str(&self) -> String {\n        self.fn_args.iter()\n            .map(|FnArg { ident, ty }| {\n                let ty = ty.with_stripped_lifetimes();\n                let ty_str = quote!(#ty).to_string();\n                let ty_str: String = ty_str.chars().filter(|c| !c.is_whitespace()).collect();\n                format!(\"{}: {}\", ident, ty_str)\n            })\n            .collect::<Vec<_>>()\n            .join(\", \")\n    }\n\n    pub fn dynamic_path_params(&self) -> impl Iterator<Item = &Dynamic> + Clone {\n        self.path_params.iter()\n            .filter_map(|p| p.dynamic().or_else(|| p.ignored()))\n    }\n\n    pub fn dynamic_query_params(&self) -> impl Iterator<Item = &Dynamic> + Clone {\n        self.query_params.iter().filter_map(|p| p.dynamic())\n    }\n\n    pub fn validate(&self) -> Validation<'_> {\n        let args = &self.uri_mac.route.args;\n        let all_params = self.dynamic_path_params().chain(self.dynamic_query_params());\n        match args {\n            Args::Unnamed(args) => {\n                let (expected, actual) = (all_params.count(), args.len());\n                let unnamed_args = args.iter().map(|arg| arg.unnamed());\n                match expected == actual {\n                    true => Validation::Ok(unnamed_args.collect()),\n                    false => Validation::Unnamed(expected, actual)\n                }\n            },\n            Args::Named(args) => {\n                let ignored = all_params.clone().filter(|p| p.is_wild());\n                if ignored.clone().count() > 0 {\n                    return Validation::NamedIgnored(ignored.collect());\n                }\n\n                let mut params = all_params.map(|p| (&p.name, None))\n                    .collect::<IndexMap<&Name, Option<&ArgExpr>>>();\n\n                let (mut extra, mut dup) = (vec![], vec![]);\n                let named_args = args.iter().map(|arg| arg.named());\n                for (name, ident, expr) in named_args {\n                    match params.get_mut(name) {\n                        Some(ref entry) if entry.is_some() => dup.push(ident),\n                        Some(entry) => *entry = Some(expr),\n                        None => extra.push(ident),\n                    }\n                }\n\n                let (mut missing, mut exprs) = (vec![], vec![]);\n                for (name, expr) in params {\n                    match expr {\n                        Some(expr) => exprs.push(expr),\n                        None => missing.push(name)\n                    }\n                }\n\n                if (extra.len() + dup.len() + missing.len()) == 0 {\n                    Validation::Ok(exprs)\n                } else {\n                    Validation::Named(missing, extra, dup)\n                }\n            }\n        }\n    }\n}\n\nimpl RoutedUri {\n    /// The Span to use when referring to all of the arguments.\n    pub fn args_span(&self) -> Span {\n        match self.route.args.num() {\n            0 => self.route.path.span(),\n            _ => self.route.args.span()\n        }\n    }\n}\n\nimpl Arg {\n    fn is_named(&self) -> bool {\n        matches!(self, Arg::Named(..))\n    }\n\n    fn unnamed(&self) -> &ArgExpr {\n        match self {\n            Arg::Unnamed(expr) => expr,\n            _ => panic!(\"Called Arg::unnamed() on an Arg::Named!\"),\n        }\n    }\n\n    fn named(&self) -> (&Name, &Ident, &ArgExpr) {\n        match self {\n            Arg::Named(name, ident, _, expr) => (name, ident, expr),\n            _ => panic!(\"Called Arg::named() on an Arg::Unnamed!\"),\n        }\n    }\n}\n\nimpl Args {\n    fn num(&self) -> usize {\n        match self {\n            Args::Named(inner) | Args::Unnamed(inner) => inner.len(),\n        }\n    }\n}\n\nimpl ArgExpr {\n    pub fn as_expr(&self) -> Option<&Expr> {\n        match self {\n            ArgExpr::Expr(expr) => Some(expr),\n            _ => None\n        }\n    }\n\n    pub fn unwrap_expr(&self) -> &Expr {\n        match self {\n            ArgExpr::Expr(expr) => expr,\n            _ => panic!(\"Called ArgExpr::expr() on ArgExpr::Ignored!\"),\n        }\n    }\n}\n\nfn uri_err<T>(lit: &StringLit, error: Error<'_>) -> parse::Result<T> {\n    let span = lit.subspan(error.index() + 1..(error.index() + 2));\n    err(span, format!(\"invalid URI: {}\", error))\n}\n\nimpl UriExpr {\n    fn parse_prefix(input: ParseStream<'_>) -> syn::Result<Option<Self>> {\n        if input.parse::<Token![_]>().is_ok() {\n            return Ok(None);\n        }\n\n        if !input.peek(LitStr) {\n            return input.parse::<Expr>().map(|e| Some(UriExpr::Expr(e)));\n        }\n\n        let lit = input.parse::<StringLit>()?;\n        let uri = Uri::parse::<Origin<'_>>(&lit)\n            .or_else(|e| Uri::parse::<Absolute<'_>>(&lit).map_err(|e2| (e, e2)))\n            .map_err(|(e1, e2)| if lit.starts_with('/') { e1 } else { e2 })\n            .or_else(|e| uri_err(&lit, e))?;\n\n        if matches!(&uri, Uri::Origin(o) if o.query().is_some())\n            || matches!(&uri, Uri::Absolute(a) if a.query().is_some())\n        {\n            return err(lit.span(), \"URI prefix cannot contain query part\");\n        }\n\n        Ok(Some(UriExpr::Uri(UriLit(uri.into_owned(), lit.span()))))\n    }\n\n    fn parse_suffix(input: ParseStream<'_>) -> syn::Result<Option<Self>> {\n        if input.parse::<Token![_]>().is_ok() {\n            return Ok(None);\n        }\n\n        if !input.peek(LitStr) {\n            return input.parse::<Expr>().map(|e| Some(UriExpr::Expr(e)));\n        }\n\n        let lit = input.parse::<StringLit>()?;\n        let uri = Reference::parse(&lit).or_else(|e| uri_err(&lit, e))?;\n        if uri.scheme().is_some() || uri.authority().is_some() || !uri.path().is_empty() {\n            return err(lit.span(), \"URI suffix must contain only query and/or fragment\");\n        }\n\n        // This is a bit of finagling to get the types to match up how we'd\n        // like. A URI like `?foo` will parse as a `Reference`, since that's\n        // what it is. But if we left this as is, we'd convert Origins and\n        // Absolutes to References on suffix appendage when we don't need to.\n        // This is because anything + a Reference _must_ result in a Reference\n        // since the resulting URI could have a fragment. Since here we know\n        // that's not the case, we lie and say it's Absolute since an Absolute\n        // can't contain a fragment, so an Origin + Absolute suffix is still an\n        // Origin, and likewise for an Absolute.\n        let uri = match uri.fragment() {\n            None => {\n                let query = uri.query().map(|q| q.as_str());\n                Uri::Absolute(Absolute::const_new(\"\", None, \"\", query))\n            }\n            Some(_) => Uri::Reference(uri)\n        };\n\n        Ok(Some(UriExpr::Uri(UriLit(uri.into_owned(), lit.span()))))\n    }\n}\n\nimpl Deref for UriLit {\n    type Target = Uri<'static>;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl ToTokens for UriLit {\n    fn to_tokens(&self, t: &mut TokenStream) {\n        use crate::http_codegen::*;\n\n        let (uri, span) = (&self.0, self.1);\n        match uri {\n            Uri::Origin(o) => Origin(o, span).to_tokens(t),\n            Uri::Absolute(o) => Absolute(o, span).to_tokens(t),\n            Uri::Authority(o) => Authority(o, span).to_tokens(t),\n            Uri::Reference(r) => Reference(r, span).to_tokens(t),\n            Uri::Asterisk(a) => Asterisk(*a, span).to_tokens(t),\n        }\n    }\n}\n\nimpl ToTokens for UriExpr {\n    fn to_tokens(&self, t: &mut TokenStream) {\n        match self {\n            UriExpr::Uri(uri) => uri.to_tokens(t),\n            UriExpr::Expr(e) => e.to_tokens(t),\n        }\n    }\n}\n\nimpl ToTokens for ArgExpr {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            ArgExpr::Expr(e) => e.to_tokens(tokens),\n            ArgExpr::Ignored(e) => e.to_tokens(tokens)\n        }\n    }\n}\n\nimpl ToTokens for Arg {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            Arg::Unnamed(e) => e.to_tokens(tokens),\n            Arg::Named(_, ident, eq, expr) => {\n                ident.to_tokens(tokens);\n                eq.to_tokens(tokens);\n                expr.to_tokens(tokens);\n            }\n        }\n    }\n}\n\nimpl ToTokens for Args {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            Args::Unnamed(e) | Args::Named(e) => e.to_tokens(tokens)\n        }\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/derive/form_field.rs",
    "content": "use std::collections::HashSet;\n\nuse devise::{*, ext::{TypeExt, SpanDiagnosticExt}};\n\nuse syn::{visit_mut::VisitMut, visit::Visit};\nuse proc_macro2::{TokenStream, TokenTree, Span};\nuse quote::{ToTokens, TokenStreamExt};\n\nuse crate::syn_ext::IdentExt;\nuse crate::name::Name;\n\nmacro_rules! quote_spanned {\n    ($span:expr => $($token:tt)*) => (\n        quote::quote_spanned!(\n            proc_macro2::Span::call_site().located_at($span) => $($token)*\n        )\n    )\n}\n\n#[derive(Debug)]\npub enum FieldName {\n    Cased(Name),\n    Uncased(Name),\n}\n\n#[derive(FromMeta)]\npub struct FieldAttr {\n    pub name: Option<FieldName>,\n    pub validate: Option<SpanWrapped<syn::Expr>>,\n    pub default: Option<syn::Expr>,\n    pub default_with: Option<syn::Expr>,\n}\n\nimpl FieldAttr {\n    const NAME: &'static str = \"field\";\n}\n\npub(crate) trait FieldExt {\n    fn ident(&self) -> Option<&syn::Ident>;\n    fn member(&self) -> syn::Member;\n    fn context_ident(&self) -> syn::Ident;\n    fn field_names(&self) -> Result<Vec<FieldName>>;\n    fn first_field_name(&self) -> Result<Option<FieldName>>;\n    fn stripped_ty(&self) -> syn::Type;\n    fn name_buf_opt(&self) -> Result<TokenStream>;\n}\n\n#[derive(FromMeta)]\npub struct VariantAttr {\n    pub value: Name,\n}\n\nimpl VariantAttr {\n    const NAME: &'static str = \"field\";\n}\n\npub(crate) trait VariantExt {\n    fn first_form_field_value(&self) -> Result<FieldName>;\n    fn form_field_values(&self) -> Result<Vec<FieldName>>;\n}\n\nimpl VariantExt for Variant<'_> {\n    fn first_form_field_value(&self) -> Result<FieldName> {\n        let value = VariantAttr::from_attrs(VariantAttr::NAME, &self.attrs)?\n            .into_iter()\n            .next()\n            .map(|attr| FieldName::Uncased(attr.value))\n            .unwrap_or_else(|| FieldName::Uncased(Name::from(&self.ident)));\n\n        Ok(value)\n    }\n\n    fn form_field_values(&self) -> Result<Vec<FieldName>> {\n        let attr_values = VariantAttr::from_attrs(VariantAttr::NAME, &self.attrs)?\n            .into_iter()\n            .map(|attr| FieldName::Uncased(attr.value))\n            .collect::<Vec<_>>();\n\n        if attr_values.is_empty() {\n            return Ok(vec![FieldName::Uncased(Name::from(&self.ident))]);\n        }\n\n        Ok(attr_values)\n    }\n}\n\nimpl FromMeta for FieldName {\n    fn from_meta(meta: &MetaItem) -> Result<Self> {\n        // These are used during parsing.\n        const CONTROL_CHARS: &[char] = &['&', '=', '?', '.', '[', ']'];\n\n        fn is_valid_field_name(s: &str) -> bool {\n            // The HTML5 spec (4.10.18.1) says 'isindex' is not allowed.\n            if s == \"isindex\" || s.is_empty() {\n                return false\n            }\n\n            // We allow all visible ASCII characters except `CONTROL_CHARS`.\n            s.chars().all(|c| c.is_ascii_graphic() && !CONTROL_CHARS.contains(&c))\n        }\n\n        let field_name = match Name::from_meta(meta) {\n            Ok(name) => FieldName::Cased(name),\n            Err(_) => {\n                #[derive(FromMeta)]\n                struct Inner {\n                    #[meta(naked)]\n                    uncased: Name\n                }\n\n                let expr = meta.expr()?;\n                let item: MetaItem = syn::parse2(quote!(#expr))?;\n                let inner = Inner::from_meta(&item)?;\n                FieldName::Uncased(inner.uncased)\n            }\n        };\n\n        if !is_valid_field_name(field_name.as_str()) {\n            let chars = CONTROL_CHARS.iter()\n                .map(|c| format!(\"{:?}\", c))\n                .collect::<Vec<_>>()\n                .join(\", \");\n\n            return Err(meta.value_span()\n                .error(\"invalid form field name\")\n                .help(format!(\"field name cannot be `isindex` or contain {}\", chars)));\n        }\n\n        Ok(field_name)\n    }\n}\n\nimpl std::ops::Deref for FieldName {\n    type Target = Name;\n\n    fn deref(&self) -> &Self::Target {\n        match self {\n            FieldName::Cased(n) | FieldName::Uncased(n) => n,\n        }\n    }\n}\n\nimpl ToTokens for FieldName {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        (self as &Name).to_tokens(tokens)\n    }\n}\n\nimpl PartialEq for FieldName {\n    fn eq(&self, other: &Self) -> bool {\n        use FieldName::*;\n\n        match (self, other) {\n            (Cased(a), Cased(b)) => a == b,\n            (Cased(a), Uncased(u)) | (Uncased(u), Cased(a)) => a == u.as_uncased_str(),\n            (Uncased(u1), Uncased(u2)) => u1.as_uncased_str() == u2.as_uncased_str(),\n        }\n    }\n}\n\nfn member_to_ident(member: syn::Member) -> syn::Ident {\n    match member {\n        syn::Member::Named(ident) => ident,\n        syn::Member::Unnamed(i) => format_ident!(\"__{}\", i.index, span = i.span),\n    }\n}\n\nimpl FieldExt for Field<'_> {\n    fn ident(&self) -> Option<&syn::Ident> {\n        self.ident.as_ref()\n    }\n\n    fn member(&self) -> syn::Member {\n        match self.ident().cloned() {\n            Some(ident) => syn::Member::Named(ident),\n            None => syn::Member::Unnamed(syn::Index {\n                index: self.index as u32,\n                span: self.ty.span()\n            })\n        }\n    }\n\n    /// Returns the ident used by the context generated for the `FromForm` impl.\n    /// This is _not_ the field's ident and should not be used as such.\n    fn context_ident(&self) -> syn::Ident {\n        member_to_ident(self.member())\n    }\n\n    // With named existentials, this could return an `impl Iterator`...\n    fn field_names(&self) -> Result<Vec<FieldName>> {\n        let attr_names = FieldAttr::from_attrs(FieldAttr::NAME, &self.attrs)?\n            .into_iter()\n            .filter_map(|attr| attr.name)\n            .collect::<Vec<_>>();\n\n        if attr_names.is_empty() {\n            if let Some(ident) = self.ident() {\n                return Ok(vec![FieldName::Cased(Name::from(ident))]);\n            }\n        }\n\n        Ok(attr_names)\n    }\n\n    fn first_field_name(&self) -> Result<Option<FieldName>> {\n        Ok(self.field_names()?.into_iter().next())\n    }\n\n    fn stripped_ty(&self) -> syn::Type {\n        self.ty.with_stripped_lifetimes()\n    }\n\n    fn name_buf_opt(&self) -> Result<TokenStream> {\n        let (span, field_names) = (self.span(), self.field_names()?);\n        define_spanned_export!(span => _form);\n\n        Ok(field_names.first()\n            .map(|name| quote_spanned!(span => Some(#_form::NameBuf::from((__c.__parent, #name)))))\n            .unwrap_or_else(|| quote_spanned!(span => None::<#_form::NameBuf>)))\n    }\n}\n\n#[derive(Default)]\nstruct RecordMemberAccesses {\n    reference: bool,\n    accesses: HashSet<(syn::Ident, bool)>,\n}\n\nimpl<'a> Visit<'a> for RecordMemberAccesses {\n    fn visit_expr_reference(&mut self, i: &'a syn::ExprReference) {\n        self.reference = true;\n        syn::visit::visit_expr_reference(self, i);\n        self.reference = false;\n    }\n\n    fn visit_expr_field(&mut self, i: &syn::ExprField) {\n        if let syn::Expr::Path(e) = &*i.base {\n            if e.path.is_ident(\"self\") {\n                let ident = member_to_ident(i.member.clone());\n                self.accesses.insert((ident, self.reference));\n            }\n        }\n\n        syn::visit::visit_expr_field(self, i);\n    }\n}\n\nstruct ValidationMutator<'a> {\n    field: Field<'a>,\n    visited: bool,\n}\n\nimpl ValidationMutator<'_> {\n    fn visit_token_stream(&mut self, tt: TokenStream) -> TokenStream {\n        use TokenTree::*;\n\n        let mut iter = tt.into_iter();\n        let mut stream = TokenStream::new();\n        while let Some(tt) = iter.next() {\n            match tt {\n                Ident(s3lf) if s3lf == \"self\" => {\n                    match (iter.next(), iter.next()) {\n                        (Some(Punct(p)), Some(Ident(i))) if p.as_char() == '.' => {\n                            let field = syn::parse_quote!(#s3lf #p #i);\n                            let mut expr = syn::Expr::Field(field);\n                            self.visit_expr_mut(&mut expr);\n                            expr.to_tokens(&mut stream);\n                        },\n                        (tt1, tt2) => stream.append_all(&[Some(Ident(s3lf)), tt1, tt2]),\n                    }\n                },\n                TokenTree::Group(group) => {\n                    let tt = self.visit_token_stream(group.stream());\n                    let mut new = proc_macro2::Group::new(group.delimiter(), tt);\n                    new.set_span(group.span());\n                    let group = TokenTree::Group(new);\n                    stream.append(group);\n                }\n                tt => stream.append(tt),\n            }\n        }\n\n        stream\n    }\n}\n\nimpl VisitMut for ValidationMutator<'_> {\n    fn visit_expr_call_mut(&mut self, call: &mut syn::ExprCall) {\n        // Only modify the first call we see.\n        if self.visited {\n            return syn::visit_mut::visit_expr_call_mut(self, call);\n        }\n\n        self.visited = true;\n        let accessor = self.field.context_ident().with_span(self.field.ty.span());\n        call.args.insert(0, syn::parse_quote!(#accessor));\n        syn::visit_mut::visit_expr_call_mut(self, call);\n    }\n\n    fn visit_macro_mut(&mut self, mac: &mut syn::Macro) {\n        mac.tokens = self.visit_token_stream(mac.tokens.clone());\n        syn::visit_mut::visit_macro_mut(self, mac);\n    }\n\n    fn visit_ident_mut(&mut self, i: &mut syn::Ident) {\n        // replace `self` with the context ident\n        if i == \"self\" {\n            *i = self.field.context_ident().with_span(self.field.ty.span());\n        }\n    }\n\n    fn visit_expr_mut(&mut self, i: &mut syn::Expr) {\n        fn inner_field(i: &syn::Expr) -> Option<syn::Expr> {\n            if let syn::Expr::Field(e) = i {\n                if let syn::Expr::Path(p) = &*e.base {\n                    if p.path.is_ident(\"self\") {\n                        let member = &e.member;\n                        return Some(syn::parse_quote!(#member));\n                    }\n                }\n            }\n\n            None\n        }\n\n        // replace `self.field` and `&self.field` with `field`\n        if let syn::Expr::Reference(r) = i {\n            if let Some(expr) = inner_field(&r.expr) {\n                if let Some(ref m) = r.mutability {\n                    m.span()\n                        .warning(\"`mut` has no effect in FromForm` validation\")\n                        .note(\"`mut` is being discarded\")\n                        .emit_as_item_tokens();\n                }\n\n                *i = expr;\n            }\n        } else if let Some(expr) = inner_field(i) {\n            *i = expr;\n        }\n\n        syn::visit_mut::visit_expr_mut(self, i);\n    }\n}\n\npub fn validators(field: Field<'_>) -> Result<impl Iterator<Item = syn::Expr> + '_> {\n    Ok(FieldAttr::from_attrs(FieldAttr::NAME, &field.attrs)?\n        .into_iter()\n        .chain(FieldAttr::from_attrs(FieldAttr::NAME, field.parent.attrs())?)\n        .filter_map(|a| a.validate)\n        .map(move |mut expr| {\n            let mut record = RecordMemberAccesses::default();\n            record.accesses.insert((field.context_ident(), true));\n            record.visit_expr(&expr);\n\n            let mut v = ValidationMutator { field, visited: false };\n            v.visit_expr_mut(&mut expr);\n\n            let span = expr.key_span.unwrap_or(field.ty.span());\n            let matchers = record.accesses.iter().map(|(member, _)| member);\n            let values = record.accesses.iter()\n                .map(|(member, is_ref)| {\n                    if *is_ref { quote_spanned!(span => &#member) }\n                    else { quote_spanned!(span => #member) }\n                });\n\n            let matchers = quote_spanned!(span => (#(Some(#matchers)),*));\n            let values = quote_spanned!(span => (#(#values),*));\n            let name_opt = field.name_buf_opt().unwrap();\n\n            define_spanned_export!(span => _form);\n            let expr: syn::Expr = syn::parse_quote_spanned!(span => {\n                #[allow(unused_parens)]\n                let __result: #_form::Result<'_, ()> = match #values {\n                    #matchers => #expr,\n                    _ => Ok(()),\n                };\n\n                let __e_name = #name_opt;\n                __result.map_err(|__e| match __e_name {\n                    Some(__name) => __e.with_name(__name),\n                    None => __e\n                })\n            });\n\n            expr\n        }))\n}\n\n/// Take an $expr in `default = $expr` and turn it into a `Some($expr.into())`.\n///\n/// As a result of calling `into()`, type inference fails for two common\n/// expressions: integer literals and the bare `None`. As a result, we cheat: if\n/// the expr matches either condition, we pass them through unchanged.\nfn default_expr(expr: &syn::Expr) -> TokenStream {\n    use syn::{Expr, Lit, ExprLit};\n\n    if matches!(expr, Expr::Path(e) if e.path.is_ident(\"None\")) {\n        quote!(#expr)\n    } else if matches!(expr, Expr::Lit(ExprLit { lit: Lit::Int(_), .. })) {\n        quote_spanned!(expr.span() => Some(#expr))\n    } else {\n        quote_spanned!(expr.span() => Some({ #expr }.into()))\n    }\n}\n\npub fn default(field: Field<'_>) -> Result<Option<TokenStream>> {\n    let field_attrs = FieldAttr::from_attrs(FieldAttr::NAME, &field.attrs)?;\n    let parent_attrs = FieldAttr::from_attrs(FieldAttr::NAME, field.parent.attrs())?;\n\n    // Expressions in `default = `, except for `None`, are wrapped in `Some()`.\n    let mut expr = field_attrs.iter()\n        .chain(parent_attrs.iter())\n        .filter_map(|a| a.default.as_ref()).map(default_expr);\n\n    // Expressions in `default_with` are passed through directly.\n    let mut expr_with = field_attrs.iter()\n        .chain(parent_attrs.iter())\n        .filter_map(|a| a.default_with.as_ref())\n        .map(|e| e.to_token_stream());\n\n    // Pull the first `default` and `default_with` expressions.\n    let (default, default_with) = (expr.next(), expr_with.next());\n\n    // If there are any more of either, emit an error.\n    if let (Some(e), _) | (_, Some(e)) = (expr.next(), expr_with.next()) {\n        return Err(e.span()\n            .error(\"duplicate default field expression\")\n            .help(\"at most one `default` or `default_with` is allowed\"));\n    }\n\n    // Emit the final expression of type `Option<#ty>` unless both `default` and\n    // `default_with` were provided in which case we error.\n    let ty = field.stripped_ty();\n    match (default, default_with) {\n        (Some(e1), Some(e2)) => {\n            Err(e1.span()\n                .error(\"duplicate default expressions\")\n                .help(\"only one of `default` or `default_with` must be used\")\n                .span_note(e2.span(), \"other default expression is here\"))\n        },\n        (Some(e), None) | (None, Some(e)) => {\n            Ok(Some(quote_spanned!(e.span() => {\n                let __default: Option<#ty> = if __opts.strict {\n                    None\n                } else {\n                    #e\n                };\n\n                __default\n            })))\n        },\n        (None, None) => Ok(None)\n    }\n}\n\ntype Dup = (usize, Span, Span);\n\npub fn first_duplicate<K: Spanned, V: PartialEq + Spanned>(\n    keys: impl Iterator<Item = K> + Clone,\n    values: impl Fn(&K) -> Result<Vec<V>>,\n) -> Result<Option<(Dup, Dup)>> {\n    let (mut all_values, mut key_map) = (vec![], vec![]);\n    for key in keys {\n        all_values.append(&mut values(&key)?);\n        key_map.push((all_values.len(), key));\n    }\n\n    // get the key corresponding to all_value index `k`.\n    let key = |k| key_map.iter().find(|(i, _)| k < *i).expect(\"k < *i\");\n\n    for (i, a) in all_values.iter().enumerate() {\n        let mut rest = all_values.iter().enumerate().skip(i + 1);\n        if let Some((j, b)) = rest.find(|(_, b)| *b == a) {\n            let (a_i, key_a) = key(i);\n            let (b_i, key_b) = key(j);\n\n            let a = (*a_i, key_a.span(), a.span());\n            let b = (*b_i, key_b.span(), b.span());\n            return Ok(Some((a, b)));\n        }\n    }\n\n    Ok(None)\n}\n"
  },
  {
    "path": "core/codegen/src/derive/from_form.rs",
    "content": "use proc_macro2::TokenStream;\nuse devise::ext::{TypeExt, SpanDiagnosticExt, GenericsExt, quote_respanned};\nuse syn::parse::Parser;\nuse devise::*;\n\nuse crate::exports::*;\nuse crate::derive::form_field::FieldName::*;\nuse crate::derive::form_field::{FieldExt, default, first_duplicate, validators};\nuse crate::syn_ext::{GenericsExt as _, TypeExt as _};\n\ntype WherePredicates = syn::punctuated::Punctuated<syn::WherePredicate, syn::Token![,]>;\n\nmacro_rules! quote_spanned {\n    ($span:expr => $($token:tt)*) => (\n        quote::quote_spanned!(\n            proc_macro2::Span::call_site().located_at($span) => $($token)*\n        )\n    )\n}\n\n// F: fn(field_ty: Ty, field_context: Expr)\nfn fields_map<F>(fields: Fields<'_>, map_f: F) -> Result<TokenStream>\n    where F: Fn(&syn::Type, &syn::Expr) -> TokenStream\n{\n    let mut matchers = vec![];\n    for field in fields.iter() {\n        let (ident, ty) = (field.context_ident(), field.stripped_ty());\n        let field_context: syn::Expr = syn::parse2(quote_spanned!(ty.span() => {\n            let __o = __c.__opts;\n            __c.#ident.get_or_insert_with(|| <#ty as #_form::FromForm<'r>>::init(__o))\n        })).expect(\"form context expression\");\n\n        let push = map_f(&ty, &field_context);\n        if fields.are_unnamed() {\n            // If we have unnamed fields, then we have exactly one by virtue of\n            // the earlier validation. Push directly to it and return.\n            return Ok(quote_spanned!(ident.span() =>\n                __c.__parent = __f.name.parent();\n                 #push\n            ));\n        }\n\n        matchers.extend(field.field_names()?.into_iter().map(|f| match f {\n            Cased(f) => quote_spanned!(ty.span() => #f => { #push }),\n            Uncased(f) => quote_spanned!(ty.span() => __n if __n.as_uncased() == #f => { #push }),\n        }));\n    }\n\n    Ok(quote! {\n        __c.__parent = __f.name.parent();\n\n        match __f.name.key_lossy().as_str() {\n            #(#matchers,)*\n            __k if __k == \"_method\" || !__c.__opts.strict => { /* ok */ },\n            _ => __c.__errors.push(__f.unexpected()),\n        }\n    })\n}\n\nfn generic_bounds_tokens(input: Input<'_>) -> Result<TokenStream> {\n    MapperBuild::new()\n        .try_enum_map(|m, e| mapper::enum_null(m, e))\n        .try_fields_map(|_, fields| {\n            let generic_idents = fields.parent.input().generics().type_idents();\n\n            let bounds = fields.iter()\n                .filter(|f| !f.ty.is_concrete(&generic_idents))\n                .map(|f| f.ty.with_replaced_lifetimes(syn::Lifetime::new(\"'r\", f.ty.span())))\n                .map(|ty| quote_spanned!(ty.span() => #ty: #_form::FromForm<'r>));\n\n            Ok(quote!(#(#bounds),*))\n        })\n        .map_input(input)\n}\n\nfn generic_bounds(input: Input<'_>) -> Result<WherePredicates> {\n    Ok(WherePredicates::parse_terminated.parse2(generic_bounds_tokens(input)?)?)\n}\n\nfn context_type(input: Input<'_>) -> Result<(TokenStream, syn::Generics)> {\n    let mut gen = input.generics().clone();\n\n    let lifetime = syn::parse_quote!('r);\n    if !gen.replace_lifetime(0, &lifetime) {\n        gen.insert_lifetime(syn::LifetimeParam::new(lifetime.clone()));\n    }\n\n    gen.add_where_predicates(generic_bounds(input)?);\n    let ty = quote_spanned!(input.ident().span() => FromFormGeneratedContext);\n    Ok((ty, gen))\n}\n\npub fn derive_from_form(input: proc_macro::TokenStream) -> TokenStream {\n    DeriveGenerator::build_for(input, quote!(impl<'r> #_form::FromForm<'r>))\n        .support(Support::Struct | Support::Lifetime | Support::Type)\n        .replace_generic(0, 0)\n        .type_bound_mapper(MapperBuild::new().try_input_map(|_, i| generic_bounds_tokens(i)))\n        .validator(ValidatorBuild::new()\n            .input_validate(|_, i| match i.generics().lifetimes().enumerate().last() {\n                Some((i, lt)) if i >= 1 => Err(lt.span().error(\"only one lifetime is supported\")),\n                _ => Ok(())\n            })\n            .fields_validate(|_, fields| {\n                if fields.is_empty() {\n                    return Err(fields.span().error(\"at least one field is required\"));\n                } else if fields.are_unnamed() && fields.count() != 1 {\n                    return Err(fields.span().error(\"tuple struct must have exactly one field\"));\n                } else if let Some(d) = first_duplicate(fields.iter(), |f| f.field_names())? {\n                    let (field_a_i, field_a, name_a) = d.0;\n                    let (field_b_i, field_b, name_b) = d.1;\n\n                    if field_a_i == field_b_i {\n                        return Err(field_a.error(\"field has conflicting names\")\n                            .span_note(name_a, \"this field name...\")\n                            .span_note(name_b, \"...conflicts with this field name\"));\n                    }\n\n                    return Err(name_b.error(\"field name conflicts with previous name\")\n                        .span_help(field_b, \"declared in this field\")\n                        .span_note(field_a, \"previous field with conflicting name\"));\n                }\n\n                Ok(())\n            })\n        )\n        .outer_mapper(MapperBuild::new()\n            .try_input_map(|mapper, input|  {\n                let vis = input.vis();\n                let (ctxt_ty, gen) = context_type(input)?;\n                let (impl_gen, _, where_clause)  = gen.split_for_impl();\n                let output = mapper::input_default(mapper, input)?;\n                Ok(quote_spanned! { mixed(input.span())=>\n                    /// Rocket generated FormForm context.\n                    #[doc(hidden)]\n                    #[allow(private_bounds)]\n                    #vis struct #ctxt_ty #impl_gen #where_clause {\n                        __opts: #_form::Options,\n                        __errors: #_form::Errors<'r>,\n                        __parent: #_Option<&'r #_form::Name>,\n                        #output\n                    }\n                })\n            })\n            .try_fields_map(|m, f| mapper::fields_null(m, f))\n            .field_map(|_, field| {\n                let ident = field.context_ident();\n                let mut ty = field.stripped_ty();\n                ty.replace_lifetimes(syn::parse_quote!('r));\n                let field_ty = quote_respanned!(ty.span() =>\n                    #_Option<<#ty as #_form::FromForm<'r>>::Context>\n                );\n\n                quote_spanned!(ty.span() => #ident: #field_ty,)\n            })\n        )\n        .outer_mapper(quote! {\n            #[allow(unused_imports)]\n            use #_http::uncased::AsUncased;\n        })\n        .outer_mapper(quote!(#[allow(clippy::all, clippy::pedantic, clippy::nursery)]))\n        .outer_mapper(quote!(#[allow(renamed_and_removed_lints)]))\n        .outer_mapper(quote!(#[allow(private_in_public)]))\n        .outer_mapper(quote!(#[rocket::async_trait]))\n        .inner_mapper(MapperBuild::new()\n            .try_input_map(|mapper, input| {\n                let (ctxt_ty, gen) = context_type(input)?;\n                let (_, ty_gen, _) = gen.split_for_impl();\n                let output = mapper::input_default(mapper, input)?;\n                Ok(quote! {\n                    type Context = #ctxt_ty #ty_gen;\n\n                    fn init(__opts: #_form::Options) -> Self::Context {\n                        Self::Context {\n                            __opts,\n                            __errors: #_form::Errors::new(),\n                            __parent: #_None,\n                            #output\n                        }\n                    }\n                })\n            })\n            .try_fields_map(|m, f| mapper::fields_null(m, f))\n            .field_map(|_, field| {\n                let ident = field.context_ident();\n                let ty = field.ty.with_stripped_lifetimes();\n                quote_spanned!(ty.span() => #ident: #_None,)\n            })\n        )\n        .inner_mapper(MapperBuild::new()\n            .with_output(|_, output| quote! {\n                fn push_value(__c: &mut Self::Context, __f: #_form::ValueField<'r>) {\n                    #output\n                }\n            })\n            .try_fields_map(|_, f| fields_map(f, |ty, ctxt| quote_spanned!(ty.span() => {\n                <#ty as #_form::FromForm<'r>>::push_value(#ctxt, __f.shift());\n            })))\n        )\n        .inner_mapper(MapperBuild::new()\n            .try_input_map(|mapper, input| {\n                let (ctxt_ty, gen) = context_type(input)?;\n                let (_, ty_gen, _) = gen.split_for_impl();\n                let output = mapper::input_default(mapper, input)?;\n                Ok(quote_spanned! { ctxt_ty.span() =>\n                    async fn push_data(\n                        __c: &mut #ctxt_ty #ty_gen,\n                        __f: #_form::DataField<'r, '_>\n                    ) {\n                        #output\n                    }\n                })\n            })\n            // Without the `let _fut`, we get a wild lifetime error. It don't\n            // make no sense, Rust async/await: it don't make no sense.\n            .try_fields_map(|_, f| fields_map(f, |ty, ctxt| quote_spanned!(ty.span() => {\n                let __fut = <#ty as #_form::FromForm<'r>>::push_data(#ctxt, __f.shift());\n                __fut.await;\n            })))\n        )\n        .inner_mapper(MapperBuild::new()\n            .with_output(|_, _| quote! {\n                fn push_error(__c: &mut Self::Context, __e: #_form::Error<'r>) {\n                    __c.__errors.push(__e);\n                }\n            }))\n        .inner_mapper(MapperBuild::new()\n            .with_output(|_, output| quote! {\n                fn finalize(mut __c: Self::Context) -> #_Result<Self, #_form::Errors<'r>> {\n                    #[allow(unused_imports)]\n                    use #_form::validate::*;\n\n                    #output\n                }\n            })\n            .try_fields_map(|mapper, fields| {\n                // This validates the attributes so we can `unwrap()` later.\n                let finalize_field = fields.iter()\n                    .map(|f| mapper.map_field(f))\n                    .collect::<Result<Vec<TokenStream>>>()?;\n\n                let (_ok, _some, _err, _none) = (_Ok, _Some, _Err, _None);\n                let validator = fields.iter().flat_map(|f| validators(f).unwrap());\n                let ident = fields.iter().map(|f| f.context_ident());\n                let builder = fields.builder(|f| {\n                    let ident = f.context_ident();\n                    quote_spanned!(ident.span() => #ident.unwrap())\n                });\n\n                Ok(quote_spanned!(fields.span() =>\n                    #(\n                        let #ident = match #finalize_field {\n                            #_ok(#ident) => #_some(#ident),\n                            #_err(__e) => { __c.__errors.extend(__e); #_none }\n                        };\n                    )*\n\n                    #(\n                        if let #_err(__e) = #validator {\n                            __c.__errors.extend(__e);\n                        }\n                    )*\n\n                    if !__c.__errors.is_empty() {\n                        return #_Err(__c.__errors);\n                    }\n\n                    Ok(#builder)\n                ))\n            })\n            .try_field_map(|_, f| {\n                let (ident, ty) = (f.context_ident(), f.stripped_ty());\n                let name_buf_opt = f.name_buf_opt()?;\n                let default = default(f)?\n                    .unwrap_or_else(|| quote_spanned!(ty.span() => {\n                        <#ty as #_form::FromForm<'r>>::default(__opts)\n                    }));\n\n                Ok(quote_spanned! { ty.span() => {\n                    let __opts = __c.__opts;\n                    let __name = #name_buf_opt;\n                    __c.#ident\n                        .map_or_else(\n                            || #default.ok_or_else(|| #_form::ErrorKind::Missing.into()),\n                            <#ty as #_form::FromForm<'r>>::finalize\n                        )\n                        .map_err(|__e| match __name {\n                            #_Some(__name) => __e.with_name(__name),\n                            #_None => __e,\n                        })\n                        .map_err(|__e| __e.is_empty()\n                            .then(|| #_form::ErrorKind::Unknown.into())\n                            .unwrap_or(__e))\n                }})\n            })\n        )\n        .to_tokens()\n}\n"
  },
  {
    "path": "core/codegen/src/derive/from_form_field.rs",
    "content": "use devise::{*, ext::SpanDiagnosticExt};\nuse proc_macro2::TokenStream;\n\nuse crate::exports::*;\nuse crate::derive::form_field::{VariantExt, first_duplicate};\n\npub fn derive_from_form_field(input: proc_macro::TokenStream) -> TokenStream {\n    DeriveGenerator::build_for(input, quote!(impl<'__v> #_form::FromFormField<'__v>))\n        .support(Support::Enum)\n        .validator(ValidatorBuild::new()\n            // We only accept C-like enums with at least one variant.\n            .fields_validate(|_, fields| {\n                if !fields.is_empty() {\n                    return Err(fields.span().error(\"variants cannot have fields\"));\n                }\n\n                Ok(())\n            })\n            .enum_validate(|_, data| {\n                if data.variants.is_empty() {\n                    return Err(data.span().error(\"enum must have at least one variant\"));\n                }\n\n                if let Some(d) = first_duplicate(data.variants(), |v| v.form_field_values())? {\n                    let (variant_a_i, variant_a, value_a) = d.0;\n                    let (variant_b_i, variant_b, value_b) = d.1;\n\n                    if variant_a_i == variant_b_i {\n                        return Err(variant_a.error(\"variant has conflicting values\")\n                            .span_note(value_a, \"this value...\")\n                            .span_note(value_b, \"...conflicts with this value\"));\n                    }\n\n                    return Err(value_b.error(\"field value conflicts with previous value\")\n                        .span_help(variant_b, \"...declared in this variant\")\n                        .span_note(variant_a, \"previous field with conflicting name\"));\n                }\n\n                Ok(())\n            })\n        )\n        .outer_mapper(quote! {\n            #[allow(unused_imports)]\n            use #_http::uncased::AsUncased;\n        })\n        .inner_mapper(MapperBuild::new()\n            .with_output(|_, output| quote! {\n                fn from_value(\n                    __f: #_form::ValueField<'__v>\n                ) -> #_Result<Self, #_form::Errors<'__v>> {\n\n                    #output\n                }\n            })\n            .try_enum_map(|mapper, data| {\n                let mut variant_value = vec![];\n                for v in data.variants().map(|v| v.form_field_values()) {\n                    variant_value.append(&mut v?);\n                }\n\n                let variant_condition = data.variants()\n                    .map(|v| mapper.map_variant(v))\n                    .collect::<Result<Vec<_>>>()?;\n\n                let (_ok, _cow) = (std::iter::repeat(_Ok), std::iter::repeat(_Cow));\n                Ok(quote! {\n                    #(#variant_condition)*\n\n                    const OPTS: &'static [#_Cow<'static, str>] =\n                        &[#(#_cow::Borrowed(#variant_value)),*];\n\n                    let _error = #_form::Error::from(OPTS)\n                        .with_name(__f.name)\n                        .with_value(__f.value);\n\n                    #_Err(_error)?\n                })\n            })\n            .try_variant_map(|_, variant| {\n                let builder = variant.builder(|_| unreachable!(\"fieldless\"));\n                let value = variant.form_field_values()?;\n\n                Ok(quote_spanned! { variant.span() =>\n                    if #(__f.value.as_uncased() == #value)||* {\n                        return #_Ok(#builder);\n                    }\n                })\n            })\n        )\n        .to_tokens()\n}\n"
  },
  {
    "path": "core/codegen/src/derive/from_param.rs",
    "content": "use devise::*;\nuse devise::ext::SpanDiagnosticExt;\n\nuse quote::quote;\nuse proc_macro2::TokenStream;\nuse syn::ext::IdentExt;\n\nuse crate::exports::*;\n\npub fn derive_from_param(input: proc_macro::TokenStream) -> TokenStream {\n    DeriveGenerator::build_for(input, quote!(impl<'a> #_request::FromParam<'a>))\n        .support(Support::Enum)\n        .validator(ValidatorBuild::new().fields_validate(|_, fields| {\n            if !fields.is_empty() {\n                return Err(fields.span().error(\"variants with data fields are not supported\"));\n            }\n\n            Ok(())\n        }))\n        .inner_mapper(MapperBuild::new().enum_map(|_, data| {\n            let matches = data.variants().map(|field| {\n                let field_name = field.ident.unraw();\n                quote!(stringify!(#field_name) => Ok(Self::#field))\n            });\n\n            let names = data.variants().map(|field| {\n                let field_name = field.ident.unraw();\n                quote!(stringify!(#field_name))\n            });\n\n            quote! {\n                type Error = #_error::InvalidOption<'a>;\n\n                fn from_param(param: &'a str) -> Result<Self, Self::Error> {\n                    match param {\n                        #(#matches,)*\n                        _ => Err(#_error::InvalidOption::new(param, &[#(#names),*])),\n                    }\n                }\n            }\n        }))\n        .to_tokens()\n}\n"
  },
  {
    "path": "core/codegen/src/derive/mod.rs",
    "content": "mod form_field;\npub mod from_form;\npub mod from_form_field;\npub mod responder;\npub mod uri_display;\npub mod from_param;\n"
  },
  {
    "path": "core/codegen/src/derive/responder.rs",
    "content": "use quote::ToTokens;\nuse devise::{*, ext::{TypeExt, SpanDiagnosticExt}};\nuse proc_macro2::TokenStream;\n\nuse crate::exports::*;\nuse crate::syn_ext::{TypeExt as _, GenericsExt as _};\nuse crate::http_codegen::{ContentType, Status};\n\n#[derive(Debug, Default, FromMeta)]\nstruct ItemAttr {\n    content_type: Option<SpanWrapped<ContentType>>,\n    status: Option<SpanWrapped<Status>>,\n}\n\n#[derive(Default, FromMeta)]\nstruct FieldAttr {\n    ignore: bool,\n}\n\npub fn derive_responder(input: proc_macro::TokenStream) -> TokenStream {\n    let impl_tokens = quote!(impl<'r, 'o: 'r> #_response::Responder<'r, 'o>);\n    DeriveGenerator::build_for(input, impl_tokens)\n        .support(Support::Struct | Support::Enum | Support::Lifetime | Support::Type)\n        .replace_generic(1, 0)\n        .type_bound_mapper(MapperBuild::new()\n            .try_enum_map(|m, e| mapper::enum_null(m, e))\n            .try_fields_map(|_, fields| {\n                let generic_idents = fields.parent.input().generics().type_idents();\n                let lifetime = |ty: &syn::Type| syn::Lifetime::new(\"'o\", ty.span());\n                let mut types = fields.iter()\n                    .map(|f| (f, &f.field.inner.ty))\n                    .map(|(f, ty)| (f, ty.with_replaced_lifetimes(lifetime(ty))));\n\n                let mut bounds = vec![];\n                if let Some((_, ty)) = types.next() {\n                    if !ty.is_concrete(&generic_idents) {\n                        let span = ty.span();\n                        bounds.push(quote_spanned!(span => #ty: #_response::Responder<'r, 'o>));\n                    }\n                }\n\n                for (f, ty) in types {\n                    let attr = FieldAttr::one_from_attrs(\"response\", &f.attrs)?.unwrap_or_default();\n                    if ty.is_concrete(&generic_idents) || attr.ignore {\n                        continue;\n                    }\n\n                    bounds.push(quote_spanned! { ty.span() =>\n                        #ty: ::std::convert::Into<#_http::Header<'o>>\n                    });\n                }\n\n                Ok(quote!(#(#bounds,)*))\n            })\n        )\n        .validator(ValidatorBuild::new()\n            .input_validate(|_, i| match i.generics().lifetimes().count() > 1 {\n                true => Err(i.generics().span().error(\"only one lifetime is supported\")),\n                false => Ok(())\n            })\n            .fields_validate(|_, fields| match fields.is_empty() {\n                true => Err(fields.span().error(\"need at least one field\")),\n                false => Ok(())\n            })\n        )\n        .inner_mapper(MapperBuild::new()\n            .with_output(|_, output| quote! {\n                fn respond_to(self, __req: &'r #Request<'_>) -> #_response::Result<'o> {\n                    #output\n                }\n            })\n            .try_fields_map(|_, fields| {\n                fn set_header_tokens<T: ToTokens + Spanned>(item: T) -> TokenStream {\n                    quote_spanned!(item.span() => __res.set_header(#item);)\n                }\n\n                let attr = ItemAttr::one_from_attrs(\"response\", fields.parent.attrs())?\n                    .unwrap_or_default();\n\n                let responder = fields.iter().next().map(|f| {\n                    let (accessor, ty) = (f.accessor(), f.ty.with_stripped_lifetimes());\n                    quote_spanned! { f.span() =>\n                        let mut __res = <#ty as #_response::Responder>::respond_to(\n                            #accessor, __req\n                        )?;\n                    }\n                }).expect(\"have at least one field\");\n\n                let mut headers = vec![];\n                for field in fields.iter().skip(1) {\n                    let attr = FieldAttr::one_from_attrs(\"response\", &field.attrs)?\n                        .unwrap_or_default();\n\n                    if !attr.ignore {\n                        headers.push(set_header_tokens(field.accessor()));\n                    }\n                }\n\n                let content_type = attr.content_type.map(set_header_tokens);\n                let status = attr.status.map(|status| {\n                    quote_spanned!(status.span() => __res.set_status(#status);)\n                });\n\n                Ok(quote! {\n                    #responder\n                    #(#headers)*\n                    #content_type\n                    #status\n                    #_Ok(__res)\n                })\n            })\n        )\n        .to_tokens()\n}\n"
  },
  {
    "path": "core/codegen/src/derive/uri_display.rs",
    "content": "use proc_macro2::TokenStream;\nuse devise::{*, ext::SpanDiagnosticExt};\n\nuse crate::exports::*;\nuse crate::derive::form_field::{FieldExt, VariantExt};\nuse crate::syn_ext::{GenericsExt as _, TypeExt as _};\nuse crate::http::uri::fmt;\n\nconst NO_EMPTY_FIELDS: &str = \"fieldless structs are not supported\";\nconst NO_NULLARY: &str = \"nullary items are not supported\";\nconst NO_EMPTY_ENUMS: &str = \"empty enums are not supported\";\nconst ONLY_ONE_UNNAMED: &str = \"tuple structs or variants must have exactly one field\";\nconst EXACTLY_ONE_FIELD: &str = \"struct must have exactly one field\";\n\nconst Q_URI_DISPLAY: StaticTokens = quote_static!(#_fmt::UriDisplay<#_fmt::Query>);\nconst Q_FORMATTER: StaticTokens = quote_static!(#_fmt::Formatter<#_fmt::Query>);\n\nconst P_URI_DISPLAY: StaticTokens = quote_static!(#_fmt::UriDisplay<#_fmt::Path>);\nconst P_FORMATTER: StaticTokens = quote_static!(#_fmt::Formatter<#_fmt::Path>);\n\nfn generic_bounds_mapper(bound: StaticTokens) -> MapperBuild {\n    MapperBuild::new()\n        .try_enum_map(|m, e| mapper::enum_null(m, e))\n        .try_fields_map(move |_, fields| {\n            let generic_idents = fields.parent.input().generics().type_idents();\n\n            let bounds = fields.iter()\n                .filter(|f| !f.ty.is_concrete(&generic_idents))\n                .map(|f| &f.field.inner.ty)\n                .map(move |ty| quote_spanned!(ty.span() => #ty: #bound));\n\n            Ok(quote!(#(#bounds,)*))\n        })\n}\n\npub fn derive_uri_display_query(input: proc_macro::TokenStream) -> TokenStream {\n    let uri_display = DeriveGenerator::build_for(input.clone(), quote!(impl #Q_URI_DISPLAY))\n        .support(Support::Struct | Support::Enum | Support::Type | Support::Lifetime)\n        .validator(ValidatorBuild::new()\n            .enum_validate(|_, data| {\n                if data.variants().count() == 0 {\n                    Err(data.brace_token.span.join().error(NO_EMPTY_ENUMS))\n                } else {\n                    Ok(())\n                }\n            })\n            .struct_validate(|_, data| {\n                let fields = data.fields();\n                if fields.is_empty() {\n                    Err(data.span().error(NO_EMPTY_FIELDS))\n                } else if fields.are_unit() {\n                    Err(data.span().error(NO_NULLARY))\n                } else {\n                    Ok(())\n                }\n            })\n            .fields_validate(|_, fields| {\n                if fields.are_unnamed() && fields.count() > 1 {\n                    Err(fields.span().error(ONLY_ONE_UNNAMED))\n                } else {\n                    Ok(())\n                }\n            })\n        )\n        .type_bound_mapper(generic_bounds_mapper(Q_URI_DISPLAY))\n        .inner_mapper(MapperBuild::new()\n            .with_output(|_, output| quote! {\n                fn fmt(&self, f: &mut #Q_FORMATTER) -> ::std::fmt::Result {\n                    #output\n                    Ok(())\n                }\n            })\n            .try_variant_map(|mapper, variant| {\n                if !variant.fields().is_empty() {\n                    return mapper::variant_default(mapper, variant);\n                }\n\n                let value = variant.first_form_field_value()?;\n                Ok(quote_spanned! { variant.span() =>\n                    f.write_value(#value)?;\n                })\n            })\n            .try_field_map(|_, field| {\n                let span = field.span();\n                let accessor = field.accessor();\n                let tokens = if let Some(name) = field.first_field_name()? {\n                    quote_spanned!(span => f.write_named_value(#name, &#accessor)?;)\n                } else {\n                    quote_spanned!(span => f.write_value(&#accessor)?;)\n                };\n\n                Ok(tokens)\n            })\n        )\n        .try_to_tokens::<TokenStream>();\n\n    let uri_display = match uri_display {\n        Ok(tokens) => tokens,\n        Err(diag) => return diag.emit_as_item_tokens()\n    };\n\n    let from_self = from_uri_param::<fmt::Query>(input.clone(), quote!(Self));\n    let from_ref = from_uri_param::<fmt::Query>(input.clone(), quote!(&'__r Self));\n    let from_mut = from_uri_param::<fmt::Query>(input, quote!(&'__r mut Self));\n\n    let mut ts = uri_display;\n    ts.extend(from_self);\n    ts.extend(from_ref);\n    ts.extend(from_mut);\n    ts\n}\n\npub fn derive_uri_display_path(input: proc_macro::TokenStream) -> TokenStream {\n    let uri_display = DeriveGenerator::build_for(input.clone(), quote!(impl #P_URI_DISPLAY))\n        .support(Support::TupleStruct | Support::Type | Support::Lifetime)\n        .type_bound_mapper(generic_bounds_mapper(P_URI_DISPLAY))\n        .validator(ValidatorBuild::new()\n            .fields_validate(|_, fields| match fields.count() {\n                1 => Ok(()),\n                _ => Err(fields.span().error(EXACTLY_ONE_FIELD))\n            })\n        )\n        .inner_mapper(MapperBuild::new()\n            .with_output(|_, output| quote! {\n                fn fmt(&self, f: &mut #P_FORMATTER) -> ::std::fmt::Result {\n                    #output\n                    Ok(())\n                }\n            })\n            .field_map(|_, field| {\n                let accessor = field.accessor();\n                quote_spanned!(field.span() => f.write_value(&#accessor)?;)\n            })\n        )\n        .try_to_tokens::<TokenStream>();\n\n    let uri_display = match uri_display {\n        Ok(tokens) => tokens,\n        Err(diag) => return diag.emit_as_item_tokens()\n    };\n\n    let from_self = from_uri_param::<fmt::Path>(input.clone(), quote!(Self));\n    let from_ref = from_uri_param::<fmt::Path>(input.clone(), quote!(&'__r Self));\n    let from_mut = from_uri_param::<fmt::Path>(input, quote!(&'__r mut Self));\n\n    let mut ts = uri_display;\n    ts.extend(from_self);\n    ts.extend(from_ref);\n    ts.extend(from_mut);\n    ts\n}\n\nfn from_uri_param<P: fmt::Part>(input: proc_macro::TokenStream, ty: TokenStream) -> TokenStream {\n    let part = match P::KIND {\n        fmt::Kind::Path => quote!(#_fmt::Path),\n        fmt::Kind::Query => quote!(#_fmt::Query),\n    };\n\n    let display_trait = match P::KIND {\n        fmt::Kind::Path => P_URI_DISPLAY,\n        fmt::Kind::Query => Q_URI_DISPLAY,\n    };\n\n    let ty: syn::Type = syn::parse2(ty).expect(\"valid type\");\n    let gen = match ty {\n        syn::Type::Reference(ref r) => r.lifetime.as_ref().map(|l| quote!(<#l>)),\n        _ => None\n    };\n\n    let param_trait = quote!(impl #gen #_fmt::FromUriParam<#part, #ty>);\n    DeriveGenerator::build_for(input, param_trait)\n        .support(Support::All)\n        .type_bound_mapper(generic_bounds_mapper(display_trait))\n        .inner_mapper(MapperBuild::new()\n            .with_output(move |_, _| quote! {\n                type Target = #ty;\n                #[inline(always)] fn from_uri_param(_p: #ty) -> #ty { _p }\n            })\n        )\n        .to_tokens()\n}\n"
  },
  {
    "path": "core/codegen/src/exports.rs",
    "content": "use proc_macro2::{Span, TokenStream};\nuse quote::{ToTokens, TokenStreamExt};\n\n#[derive(Debug, Copy, Clone)]\npub struct StaticPath(pub Option<Span>, pub &'static str);\n\n#[derive(Debug, Copy, Clone)]\npub struct StaticTokens(pub fn() -> TokenStream);\n\nmacro_rules! quote_static {\n    ($($token:tt)*) => {\n        $crate::exports::StaticTokens(|| quote!($($token)*))\n    }\n}\n\nimpl ToTokens for StaticTokens {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        tokens.append_all((self.0)());\n    }\n}\n\nimpl StaticPath {\n    pub fn respanned(mut self, span: Span) -> Self {\n        self.0 = Some(span);\n        self\n    }\n}\n\nimpl ToTokens for StaticPath {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let path: syn::Path = syn::parse_str(self.1).unwrap();\n        if let Some(span) = self.0 {\n            let new_tokens = path.into_token_stream()\n                .into_iter()\n                .map(|mut t| { t.set_span(span); t });\n\n            tokens.append_all(new_tokens);\n        } else {\n            path.to_tokens(tokens)\n        }\n    }\n}\n\nmacro_rules! define_exported_paths {\n    ($($name:ident => $path:path),* $(,)?) => {\n        $(\n            #[allow(dead_code)]\n            #[allow(non_upper_case_globals)]\n            pub const $name: StaticPath = $crate::exports::StaticPath(None, stringify!($path));\n        )*\n\n        macro_rules! define {\n            // Note: the `i` is to capture the input's span.\n            $(($span:expr => $i:ident $name) => {\n                #[allow(non_snake_case)]\n                let $i = $crate::exports::StaticPath(Some($span), stringify!($path));\n            };)*\n        }\n    };\n}\n\ndefine_exported_paths! {\n    __req => __req,\n    __status => __status,\n    __catcher => __catcher,\n    __data => __data,\n    __error => __error,\n    __trail => __trail,\n    _request => ::rocket::request,\n    _response => ::rocket::response,\n    _route => ::rocket::route,\n    _error => ::rocket::error,\n    _catcher => ::rocket::catcher,\n    _sentinel => ::rocket::sentinel,\n    _form => ::rocket::form::prelude,\n    _http => ::rocket::http,\n    _uri => ::rocket::http::uri,\n    _fmt => ::rocket::http::uri::fmt,\n    _Option => ::std::option::Option,\n    _Result => ::std::result::Result,\n    _Some => ::std::option::Option::Some,\n    _None => ::std::option::Option::None,\n    _Ok => ::std::result::Result::Ok,\n    _Err => ::std::result::Result::Err,\n    _Box => ::std::boxed::Box,\n    _Vec => ::std::vec::Vec,\n    _Cow => ::std::borrow::Cow,\n    _ExitCode => ::std::process::ExitCode,\n    display_hack => ::rocket::error::display_hack,\n    BorrowMut => ::std::borrow::BorrowMut,\n    Outcome => ::rocket::outcome::Outcome,\n    FromForm => ::rocket::form::FromForm,\n    FromRequest => ::rocket::request::FromRequest,\n    FromData => ::rocket::data::FromData,\n    FromSegments => ::rocket::request::FromSegments,\n    FromParam => ::rocket::request::FromParam,\n    Request => ::rocket::request::Request,\n    Response => ::rocket::response::Response,\n    Data => ::rocket::data::Data,\n    StaticRouteInfo => ::rocket::StaticRouteInfo,\n    StaticCatcherInfo => ::rocket::StaticCatcherInfo,\n    Route => ::rocket::Route,\n    Catcher => ::rocket::Catcher,\n    Status => ::rocket::http::Status,\n}\n\nmacro_rules! define_spanned_export {\n    ($span:expr => $($name:ident),*) => ($(define!($span => $name $name);)*)\n}\n\n/// Convenience: returns a \"mixed site\" span located at `span`.\n#[inline(always)]\npub fn mixed(span: Span) -> Span {\n    Span::mixed_site().located_at(span)\n}\n"
  },
  {
    "path": "core/codegen/src/http_codegen.rs",
    "content": "use quote::ToTokens;\nuse devise::{FromMeta, MetaItem, Result, ext::{Split2, SpanDiagnosticExt}};\nuse proc_macro2::{TokenStream, Span};\n\nuse crate::{http, attribute::suppress::Lint};\n\n#[derive(Debug)]\npub struct ContentType(pub http::ContentType);\n\n#[derive(Debug)]\npub struct Status(pub http::Status);\n\n#[derive(Debug)]\npub struct MediaType(pub http::MediaType);\n\n#[derive(Debug, Clone)]\npub struct Method(pub http::Method);\n\n#[derive(Clone, Debug)]\npub struct Optional<T>(pub Option<T>);\n\n#[derive(Debug)]\npub struct Origin<'a>(pub &'a http::uri::Origin<'a>, pub Span);\n\n#[derive(Debug)]\npub struct Absolute<'a>(pub &'a http::uri::Absolute<'a>, pub Span);\n\n#[derive(Debug)]\npub struct Authority<'a>(pub &'a http::uri::Authority<'a>, pub Span);\n\n#[derive(Debug)]\npub struct Reference<'a>(pub &'a http::uri::Reference<'a>, pub Span);\n\n#[derive(Debug)]\npub struct Asterisk(pub http::uri::Asterisk, pub Span);\n\nimpl FromMeta for Status {\n    fn from_meta(meta: &MetaItem) -> Result<Self> {\n        let num = usize::from_meta(meta)?;\n        if num < 100 || num >= 600 {\n            return Err(meta.value_span().error(\"status must be in range [100, 599]\"));\n        }\n\n        Ok(Status(http::Status::new(num as u16)))\n    }\n}\n\nimpl ToTokens for Status {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let code = self.0.code;\n        tokens.extend(quote!(rocket::http::Status { code: #code }));\n    }\n}\n\nimpl FromMeta for ContentType {\n    fn from_meta(meta: &MetaItem) -> Result<Self> {\n        http::ContentType::parse_flexible(&String::from_meta(meta)?)\n            .map(ContentType)\n            .ok_or_else(|| meta.value_span().error(\"invalid or unknown content type\"))\n    }\n}\n\nimpl ToTokens for ContentType {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let http_media_type = self.0.media_type().clone();\n        let media_type = MediaType(http_media_type);\n        tokens.extend(quote!(::rocket::http::ContentType(#media_type)));\n    }\n}\n\nimpl FromMeta for MediaType {\n    fn from_meta(meta: &MetaItem) -> Result<Self> {\n        let mt = http::MediaType::parse_flexible(&String::from_meta(meta)?)\n            .ok_or_else(|| meta.value_span().error(\"invalid or unknown media type\"))?;\n\n        let lint = Lint::UnknownFormat;\n        if !mt.is_known() && lint.enabled(meta.value_span()) {\n            meta.value_span()\n                .warning(format!(\"'{}' is not a known format or media type\", mt))\n                .note(lint.how_to_suppress())\n                .emit_as_item_tokens();\n        }\n\n        Ok(MediaType(mt))\n    }\n}\n\nimpl ToTokens for MediaType {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let (top, sub) = (self.0.top().as_str(), self.0.sub().as_str());\n        let (keys, values) = self.0.params().map(|(k, v)| (k.as_str(), v)).split2();\n        let http = quote!(::rocket::http);\n\n        tokens.extend(quote! {\n            #http::MediaType::const_new(#top, #sub, &[#((#keys, #values)),*])\n        });\n    }\n}\n\nimpl FromMeta for Method {\n    fn from_meta(meta: &MetaItem) -> Result<Self> {\n        let span = meta.value_span();\n        let help = format!(\"known methods: {}\", http::Method::ALL.join(\", \"));\n\n        let string = meta.path().ok()\n            .and_then(|p| p.get_ident().cloned())\n            .map(|ident| (ident.span(), ident.to_string()))\n            .or_else(|| match meta.lit() {\n                Ok(syn::Lit::Str(s)) => Some((s.span(), s.value())),\n                _ => None\n            });\n\n        if let Some((span, string)) = string {\n            string.to_ascii_uppercase()\n                .parse()\n                .map(Method)\n                .map_err(|_| span.error(\"invalid or unknown HTTP method\").help(help))\n        } else {\n            let err = format!(\"expected method ident or string, found {}\", meta.description());\n            Err(span.error(err).help(help))\n        }\n    }\n}\n\nimpl ToTokens for Method {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let variant = syn::Ident::new(self.0.variant_str(), Span::call_site());\n        tokens.extend(quote!(::rocket::http::Method::#variant));\n    }\n}\n\nimpl<T: ToTokens> ToTokens for Optional<T> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        use crate::exports::{_Some, _None};\n        use devise::Spanned;\n\n        let opt_tokens = match self.0 {\n            Some(ref val) => quote_spanned!(val.span() => #_Some(#val)),\n            None => quote!(#_None)\n        };\n\n        tokens.extend(opt_tokens);\n    }\n}\n\nimpl ToTokens for Origin<'_> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let (origin, span) = (self.0, self.1);\n        let origin = origin.clone().into_normalized();\n        define_spanned_export!(span => _uri);\n\n        let path = origin.path().as_str();\n        let query = Optional(origin.query().map(|q| q.as_str()));\n        tokens.extend(quote_spanned! { span =>\n            #_uri::Origin::const_new(#path, #query)\n        });\n    }\n}\n\nimpl ToTokens for Absolute<'_> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let (absolute, span) = (self.0, self.1);\n        define_spanned_export!(span => _uri);\n        let absolute = absolute.clone().into_normalized();\n\n        let scheme = absolute.scheme();\n        let auth = Optional(absolute.authority().map(|a| Authority(a, span)));\n        let path = absolute.path().as_str();\n        let query = Optional(absolute.query().map(|q| q.as_str()));\n        tokens.extend(quote_spanned! { span =>\n            #_uri::Absolute::const_new(#scheme, #auth, #path, #query)\n        });\n    }\n}\n\nimpl ToTokens for Authority<'_> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let (authority, span) = (self.0, self.1);\n        define_spanned_export!(span => _uri);\n\n        let user_info = Optional(authority.user_info());\n        let host = authority.host();\n        let port = Optional(authority.port());\n        tokens.extend(quote_spanned! { span =>\n            #_uri::Authority::const_new(#user_info, #host, #port)\n        });\n    }\n}\n\nimpl ToTokens for Reference<'_> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let (reference, span) = (self.0, self.1);\n        define_spanned_export!(span => _uri);\n        let reference = reference.clone().into_normalized();\n\n        let scheme = Optional(reference.scheme());\n        let auth = Optional(reference.authority().map(|a| Authority(a, span)));\n        let path = reference.path().as_str();\n        let query = Optional(reference.query().map(|q| q.as_str()));\n        let frag = Optional(reference.fragment().map(|f| f.as_str()));\n        tokens.extend(quote_spanned! { span =>\n            #_uri::Reference::const_new(#scheme, #auth, #path, #query, #frag)\n        });\n    }\n}\n\nimpl ToTokens for Asterisk {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        define_spanned_export!(self.1 => _uri);\n        tokens.extend(quote_spanned!(self.1 => #_uri::Asterisk));\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/lib.rs",
    "content": "#![recursion_limit=\"128\"]\n\n#![doc(html_root_url = \"https://api.rocket.rs/master\")]\n#![doc(html_favicon_url = \"https://rocket.rs/images/favicon.ico\")]\n#![doc(html_logo_url = \"https://rocket.rs/images/logo-boxed.png\")]\n\n#![warn(rust_2018_idioms, missing_docs)]\n\n//! # Rocket - Code Generation\n//!\n//! This crate implements the code generation portions of Rocket. This includes\n//! custom derives, custom attributes, and procedural macros. The documentation\n//! here is purely technical. The code generation facilities are documented\n//! thoroughly in the [Rocket programming guide](https://rocket.rs/master/guide).\n//!\n//! # Usage\n//!\n//! You **_should not_** directly depend on this library. To use the macros,\n//! attributes, and derives in this crate, it suffices to depend on `rocket` in\n//! `Cargo.toml`:\n//!\n//! ```toml\n//! [dependencies]\n//! rocket = \"0.6.0-dev\"\n//! ```\n//!\n//! And to import all macros, attributes, and derives via `#[macro_use]` in the\n//! crate root:\n//!\n//! ```rust\n//! #[macro_use] extern crate rocket;\n//! # #[get(\"/\")] fn hello() { }\n//! # fn main() { rocket::build().mount(\"/\", routes![hello]); }\n//! ```\n//!\n//! Or, alternatively, selectively import from the top-level scope:\n//!\n//! ```rust\n//! # extern crate rocket;\n//!\n//! use rocket::{get, routes};\n//! # #[get(\"/\")] fn hello() { }\n//! # fn main() { rocket::build().mount(\"/\", routes![hello]); }\n//! ```\n//!\n//! # Debugging Codegen\n//!\n//! When the `ROCKET_CODEGEN_DEBUG` environment variable is set, this crate\n//! logs, at compile-time and to the console, the items it generates. For\n//! example, you might run the following to build a Rocket application with\n//! codegen debug logging enabled:\n//!\n//! ```sh\n//! ROCKET_CODEGEN_DEBUG=1 cargo build\n//! ```\n\n#[macro_use] extern crate quote;\n\nuse rocket_http as http;\n\n#[macro_use]\nmod exports;\nmod proc_macro_ext;\nmod derive;\nmod attribute;\nmod bang;\nmod http_codegen;\nmod syn_ext;\nmod name;\n\nuse crate::http::Method;\nuse proc_macro::TokenStream;\n\nstatic URI_MACRO_PREFIX: &str = \"rocket_uri_macro_\";\nstatic ROCKET_IDENT_PREFIX: &str = \"__rocket_\";\n\nmacro_rules! emit {\n    ($tokens:expr) => ({\n        use devise::ext::SpanDiagnosticExt;\n\n        let mut tokens = $tokens;\n        if std::env::var_os(\"ROCKET_CODEGEN_DEBUG\").is_some() {\n            let debug_tokens = proc_macro2::Span::call_site()\n                .note(\"emitting Rocket code generation debug output\")\n                .note(tokens.to_string())\n                .emit_as_item_tokens();\n\n            tokens.extend(debug_tokens);\n        }\n\n        tokens.into()\n    })\n}\n\nmacro_rules! route_attribute {\n    ($name:ident => $method:expr) => (\n        /// Attribute to generate a [`Route`] and associated metadata.\n        ///\n        /// This and all other route attributes can only be applied to free\n        /// functions:\n        ///\n        /// ```rust\n        /// # #[macro_use] extern crate rocket;\n        /// #\n        /// #[get(\"/\")]\n        /// fn index() -> &'static str {\n        ///     \"Hello, world!\"\n        /// }\n        /// ```\n        ///\n        /// There are 7 method-specific route attributes:\n        ///\n        ///   * [`get`] - `GET` specific route\n        ///   * [`put`] - `PUT` specific route\n        ///   * [`post`] - `POST` specific route\n        ///   * [`delete`] - `DELETE` specific route\n        ///   * [`head`] - `HEAD` specific route\n        ///   * [`options`] - `OPTIONS` specific route\n        ///   * [`patch`] - `PATCH` specific route\n        ///\n        /// Additionally, [`route`] allows the method and uri to be explicitly\n        /// specified, and for the method to be omitted entirely, to match any\n        /// method:\n        ///\n        /// ```rust\n        /// # #[macro_use] extern crate rocket;\n        ///\n        /// #[route(\"/\", method = GET)]\n        /// fn get_index() { /* ... */ }\n        ///\n        /// #[route(\"/\", method = \"VERSION-CONTROL\")]\n        /// fn versioned_index() { /* ... */ }\n        ///\n        /// #[route(\"/\")]\n        /// fn index() { /* ... */ }\n        /// ```\n        ///\n        /// [`get`]: attr.get.html\n        /// [`put`]: attr.put.html\n        /// [`post`]: attr.post.html\n        /// [`delete`]: attr.delete.html\n        /// [`head`]: attr.head.html\n        /// [`options`]: attr.options.html\n        /// [`patch`]: attr.patch.html\n        /// [`route`]: attr.route.html\n        ///\n        /// # Grammar\n        ///\n        /// The grammar for all method-specific route attributes is defined as:\n        ///\n        /// ```text\n        /// route := '\"' uri ('?' query)? '\"' (',' parameter)*\n        ///\n        /// uri := ('/' segment)*\n        ///\n        /// query := segment ('&' segment)*\n        ///\n        /// segment := URI_SEG\n        ///          | SINGLE_PARAM\n        ///          | TRAILING_PARAM\n        ///\n        /// parameter := 'rank' '=' INTEGER\n        ///            | 'format' '=' '\"' MEDIA_TYPE '\"'\n        ///            | 'data' '=' '\"' SINGLE_PARAM '\"'\n        ///\n        /// SINGLE_PARAM := '<' IDENT '>'\n        /// TRAILING_PARAM := '<' IDENT '..>'\n        ///\n        /// URI_SEG := valid, non-percent-encoded HTTP URI segment\n        /// MEDIA_TYPE := valid HTTP media type or known shorthand\n        ///\n        /// INTEGER := unsigned integer, as defined by Rust\n        /// IDENT := valid identifier, as defined by Rust\n        /// ```\n        ///\n        /// The generic route attribute is defined as:\n        ///\n        /// ```text\n        /// generic-route := route (',' method)?\n        ///\n        /// method := 'method' '=' METHOD\n        /// ```\n        ///\n        /// # Typing Requirements\n        ///\n        /// Every identifier, except for `_`, that appears in a dynamic\n        /// parameter (`SINGLE_PARAM` or `TRAILING_PARAM`) must appear as an\n        /// argument to the function. For example, the following route requires\n        /// the decorated function to have the arguments `foo`, `baz`, `msg`,\n        /// `rest`, and `form`:\n        ///\n        /// ```rust\n        /// # #[macro_use] extern crate rocket;\n        /// # use rocket::form::Form;\n        /// # use std::path::PathBuf;\n        /// # #[derive(FromForm)] struct F { a: usize }\n        /// #[get(\"/<foo>/bar/<baz..>?<msg>&closed&<rest..>\", data = \"<form>\")]\n        /// # fn f(foo: usize, baz: PathBuf, msg: String, rest: F, form: Form<F>) {  }\n        /// ```\n        ///\n        /// The type of each function argument corresponding to a dynamic\n        /// parameter is required to implement one of Rocket's guard traits. The\n        /// exact trait that is required to be implemented depends on the kind\n        /// of dynamic parameter (`SINGLE` or `TRAILING`) and where in the route\n        /// attribute the parameter appears. The table below summarizes trait\n        /// requirements:\n        ///\n        /// | position | kind        | trait             |\n        /// |----------|-------------|-------------------|\n        /// | path     | `<ident>`   | [`FromParam`]     |\n        /// | path     | `<ident..>` | [`FromSegments`]  |\n        /// | query    | `<ident>`   | [`FromForm`]      |\n        /// | query    | `<ident..>` | [`FromForm`]      |\n        /// | data     | `<ident>`   | [`FromData`]      |\n        ///\n        /// The type of each function argument that _does not_ have a\n        /// corresponding dynamic parameter is required to implement the\n        /// [`FromRequest`] trait.\n        ///\n        /// A route argument declared a `_` must _not_ appear in the function\n        /// argument list and has no typing requirements.\n        ///\n        /// The return type of the decorated function must implement the\n        /// [`Responder`] trait.\n        ///\n        /// [`FromParam`]: ../rocket/request/trait.FromParam.html\n        /// [`FromSegments`]: ../rocket/request/trait.FromSegments.html\n        /// [`FromFormField`]: ../rocket/request/trait.FromFormField.html\n        /// [`FromForm`]: ../rocket/form/trait.FromForm.html\n        /// [`FromData`]: ../rocket/data/trait.FromData.html\n        /// [`FromRequest`]: ../rocket/request/trait.FromRequest.html\n        /// [`Route`]: ../rocket/struct.Route.html\n        /// [`Responder`]: ../rocket/response/trait.Responder.html\n        ///\n        /// # Semantics\n        ///\n        /// The attribute generates three items:\n        ///\n        ///   1. A route [`Handler`].\n        ///\n        ///      The generated handler validates and generates all arguments for\n        ///      the generated function according to the trait that their type\n        ///      must implement. The order in which arguments are processed is:\n        ///\n        ///         1. Request guards from left to right.\n        ///\n        ///            If a request guard fails, the request is forwarded if the\n        ///            [`Outcome`] is `Forward` or failed if the [`Outcome`] is\n        ///            `Error`. See [`FromRequest` Outcomes] for further detail.\n        ///\n        ///         2. Path and query guards in an unspecified order. If a path\n        ///            or query guard fails, the request is forwarded.\n        ///\n        ///         3. Data guard, if any.\n        ///\n        ///            If a data guard fails, the request is forwarded if the\n        ///            [`Outcome`] is `Forward` or failed if the [`Outcome`] is\n        ///            `Error`. See [`FromData`] for further detail.\n        ///\n        ///      If all validation succeeds, the decorated function is called.\n        ///      The returned value is used to generate a [`Response`] via the\n        ///      type's [`Responder`] implementation.\n        ///\n        ///   2. A static structure used by [`routes!`] to generate a [`Route`].\n        ///\n        ///      The static structure (and resulting [`Route`]) is populated\n        ///      with the name (the function's name), path, query, rank, and\n        ///      format from the route attribute. The handler is set to the\n        ///      generated handler.\n        ///\n        ///   3. A macro used by [`uri!`] to type-check and generate an\n        ///      [`Origin`].\n        ///\n        /// [`Handler`]: ../rocket/route/trait.Handler.html\n        /// [`routes!`]: macro.routes.html\n        /// [`uri!`]: macro.uri.html\n        /// [`Origin`]: ../rocket/http/uri/struct.Origin.html\n        /// [`Outcome`]: ../rocket/outcome/enum.Outcome.html\n        /// [`Response`]: ../rocket/struct.Response.html\n        /// [`FromRequest` Outcomes]: ../rocket/request/trait.FromRequest.html#outcomes\n        #[proc_macro_attribute]\n        pub fn $name(args: TokenStream, input: TokenStream) -> TokenStream {\n            emit!(attribute::route::route_attribute($method, args, input))\n        }\n    )\n}\n\nroute_attribute!(route => None);\nroute_attribute!(get => Method::Get);\nroute_attribute!(put => Method::Put);\nroute_attribute!(post => Method::Post);\nroute_attribute!(delete => Method::Delete);\nroute_attribute!(head => Method::Head);\nroute_attribute!(patch => Method::Patch);\nroute_attribute!(options => Method::Options);\n\n/// Attribute to generate a [`Catcher`] and associated metadata.\n///\n/// This attribute can only be applied to free functions:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// use rocket::Request;\n/// use rocket::http::Status;\n///\n/// #[catch(404)]\n/// fn not_found(req: &Request) -> String {\n///     format!(\"Sorry, {} does not exist.\", req.uri())\n/// }\n///\n/// #[catch(default)]\n/// fn default(status: Status, req: &Request) -> String {\n///     format!(\"{} ({})\", status, req.uri())\n/// }\n/// ```\n///\n/// # Grammar\n///\n/// The grammar for the `#[catch]` attributes is defined as:\n///\n/// ```text\n/// catch := STATUS | 'default'\n///\n/// STATUS := valid HTTP status code (integer in [200, 599])\n/// ```\n///\n/// # Typing Requirements\n///\n/// The decorated function may take zero, one, or two arguments. It's type\n/// signature must be one of the following, where `R:`[`Responder`]:\n///\n///   * `fn() -> R`\n///   * `fn(`[`&Request`]`) -> R`\n///   * `fn(`[`Status`]`, `[`&Request`]`) -> R`\n///\n/// # Semantics\n///\n/// The attribute generates two items:\n///\n///   1. An error [`Handler`].\n///\n///      The generated handler calls the decorated function, passing in the\n///      [`Status`] and [`&Request`] values if requested. The returned value is\n///      used to generate a [`Response`] via the type's [`Responder`]\n///      implementation.\n///\n///   2. A static structure used by [`catchers!`] to generate a [`Catcher`].\n///\n///      The static structure (and resulting [`Catcher`]) is populated with the\n///      name (the function's name) and status code from the route attribute or\n///      `None` if `default`. The handler is set to the generated handler.\n///\n/// [`&Request`]: ../rocket/struct.Request.html\n/// [`Status`]: ../rocket/http/struct.Status.html\n/// [`Handler`]: ../rocket/catcher/trait.Handler.html\n/// [`catchers!`]: macro.catchers.html\n/// [`Catcher`]: ../rocket/struct.Catcher.html\n/// [`Response`]: ../rocket/struct.Response.html\n/// [`Responder`]: ../rocket/response/trait.Responder.html\n#[proc_macro_attribute]\npub fn catch(args: TokenStream, input: TokenStream) -> TokenStream {\n    emit!(attribute::catch::catch_attribute(args, input))\n}\n\n/// Suppress a warning generated by a Rocket lint.\n///\n/// Lints:\n///   * `unknown_format`\n///   * `dubious_payload`\n///   * `segment_chars`\n///   * `arbitrary_main`\n///   * `sync_spawn`\n///\n/// # Example\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n///\n/// #[suppress(dubious_payload)]\n/// #[get(\"/\", data = \"<_a>\")]\n/// fn _f(_a: String) { }\n///\n/// #[get(\"/\", data = \"<_a>\", format = \"foo/bar\")]\n/// #[suppress(dubious_payload, unknown_format)]\n/// fn _g(_a: String) { }\n/// ```\n#[proc_macro_attribute]\npub fn suppress(args: TokenStream, input: TokenStream) -> TokenStream {\n    emit!(attribute::suppress::suppress_attribute(args, input))\n}\n\n/// Retrofits supports for `async fn` in unit tests.\n///\n/// Simply decorate a test `async fn` with `#[async_test]` instead of `#[test]`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[cfg(test)]\n/// mod tests {\n///     #[async_test]\n///     async fn test() {\n///         /* .. */\n///     }\n/// }\n/// ```\n///\n/// The attribute rewrites the function to execute inside of a Rocket-compatible\n/// async runtime.\n#[proc_macro_attribute]\npub fn async_test(args: TokenStream, input: TokenStream) -> TokenStream {\n    emit!(attribute::entry::async_test_attribute(args, input))\n}\n\n/// Retrofits `async fn` support in `main` functions.\n///\n/// A `main` `async fn` function decorated with `#[rocket::main]` is transformed\n/// into a regular `main` function that internally initializes a Rocket-specific\n/// tokio runtime and runs the attributed `async fn` inside of it:\n///\n/// ```rust,no_run\n/// #[rocket::main]\n/// async fn main() -> Result<(), rocket::Error> {\n///     let _rocket = rocket::build()\n///         .ignite().await?\n///         .launch().await?;\n///\n///     Ok(())\n/// }\n/// ```\n///\n/// It should be used only when the return values of `ignite()` or `launch()`\n/// are to be inspected:\n///\n/// ```rust,no_run\n/// #[rocket::main]\n/// async fn main() -> Result<(), rocket::Error> {\n///     let rocket = rocket::build().ignite().await?;\n///     println!(\"Hello, Rocket: {:?}\", rocket);\n///\n///     let rocket = rocket.launch().await?;\n///     println!(\"Welcome back, Rocket: {:?}\", rocket);\n///\n///     Ok(())\n/// }\n/// ```\n///\n/// For all other cases, use [`#[launch]`](launch) instead.\n///\n/// The function attributed with `#[rocket::main]` _must_ be `async` and _must_\n/// be called `main`. Violation of either results in a compile-time error.\n#[proc_macro_attribute]\npub fn main(args: TokenStream, input: TokenStream) -> TokenStream {\n    emit!(attribute::entry::main_attribute(args, input))\n}\n\n/// Generates a `main` function that launches a returned `Rocket<Build>`.\n///\n/// When applied to a function that returns a `Rocket<Build>` instance,\n/// `#[launch]` automatically initializes an `async` runtime and\n/// launches the function's returned instance:\n///\n/// ```rust,no_run\n/// # use rocket::launch;\n/// use rocket::{Rocket, Build};\n///\n/// #[launch]\n/// fn rocket() -> Rocket<Build> {\n///     rocket::build()\n/// }\n/// ```\n///\n/// This generates code equivalent to the following:\n///\n/// ```rust,no_run\n/// # use rocket::{Rocket, Build};\n/// # fn rocket() -> Rocket<Build> {\n/// #     rocket::build()\n/// # }\n/// #\n/// #[rocket::main]\n/// async fn main() {\n///     // Recall that an uninspected `Error` will cause a pretty-printed panic,\n///     // so rest assured errors do not go undetected when using `#[launch]`.\n///     let _ = rocket().launch().await;\n/// }\n/// ```\n///\n/// To avoid needing to import _any_ items in the common case, the `launch`\n/// attribute will infer a return type written as `_` as `Rocket<Build>`:\n///\n/// ```rust,no_run\n/// # use rocket::launch;\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build()\n/// }\n/// ```\n///\n/// The attributed function may be `async`:\n///\n/// ```rust,no_run\n/// # use rocket::launch;\n/// # async fn some_async_work() {}\n/// #[launch]\n/// async fn rocket() -> _ {\n///     some_async_work().await;\n///     rocket::build()\n/// }\n/// ```\n#[proc_macro_attribute]\npub fn launch(args: TokenStream, input: TokenStream) -> TokenStream {\n    emit!(attribute::entry::launch_attribute(args, input))\n}\n\n/// Derive for the [`FromFormField`] trait.\n///\n/// The [`FromFormField`] derive can be applied to enums with nullary\n/// (zero-length) fields:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// #[derive(FromFormField)]\n/// enum MyValue {\n///     First,\n///     Second,\n///     Third,\n/// }\n/// ```\n///\n/// The derive generates an implementation of the [`FromFormField`] trait for\n/// the decorated `enum`. The implementation returns successfully when the form\n/// value matches, case insensitively, the stringified version of a variant's\n/// name, returning an instance of said variant. If there is no match, an error\n/// recording all of the available options is returned.\n///\n/// As an example, for the `enum` above, the form values `\"first\"`, `\"FIRST\"`,\n/// `\"fiRSt\"`, and so on would parse as `MyValue::First`, while `\"second\"` and\n/// `\"third\"` (in any casing) would parse as `MyValue::Second` and\n/// `MyValue::Third`, respectively.\n///\n/// The `field` field attribute can be used to change the string value that is\n/// compared against for a given variant:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// #[derive(FromFormField)]\n/// enum MyValue {\n///     First,\n///     Second,\n///     #[field(value = \"fourth\")]\n///     #[field(value = \"fifth\")]\n///     Third,\n/// }\n/// ```\n///\n/// When more than one `value` is specified, matching _any_ value will result in\n/// parsing the decorated variant. Declaring any two values that are\n/// case-insensitively equal to any other value or variant name is a\n/// compile-time error.\n///\n/// The `#[field]` attribute's grammar is:\n///\n/// ```text\n/// field := 'value' '=' STRING_LIT\n///\n/// STRING_LIT := any valid string literal, as defined by Rust\n/// ```\n///\n/// The attribute accepts a single string parameter of name `value`\n/// corresponding to the string to use to match against for the decorated\n/// variant. In the example above, the the strings `\"fourth\"`, `\"FOUrth\"`,\n/// `\"fiFTH\"` and so on would parse as `MyValue::Third`.\n///\n/// [`FromFormField`]: ../rocket/form/trait.FromFormField.html\n#[proc_macro_derive(FromFormField, attributes(field))]\npub fn derive_from_form_field(input: TokenStream) -> TokenStream {\n    emit!(derive::from_form_field::derive_from_form_field(input))\n}\n\n/// Derive for the [`FromForm`] trait.\n///\n/// The [`FromForm`] derive can be applied to structures with named or unnamed\n/// fields:\n///\n/// ```rust\n/// use rocket::form::FromForm;\n///\n/// #[derive(FromForm)]\n/// struct MyStruct<'r> {\n///     field: usize,\n///     #[field(name = \"renamed_field\")]\n///     #[field(name = uncased(\"RenamedField\"))]\n///     other: &'r str,\n///     #[field(validate = range(1..), default = 3)]\n///     r#type: usize,\n///     #[field(default = None)]\n///     is_nice: bool,\n/// }\n///\n/// #[derive(FromForm)]\n/// #[field(validate = len(6..))]\n/// #[field(validate = neq(\"password\"))]\n/// struct Password<'r>(&'r str);\n/// ```\n///\n/// Each field type is required to implement [`FromForm`].\n///\n/// The derive generates an implementation of the [`FromForm`] trait.\n///\n/// **Named Fields**\n///\n/// If the structure has named fields, the implementation parses a form whose\n/// field names match the field names of the structure on which the derive was\n/// applied. Each field's value is parsed with the [`FromForm`] implementation\n/// of the field's type. The `FromForm` implementation succeeds only when all\n/// fields parse successfully or return a default. Errors are collected into a\n/// [`form::Errors`] and returned if non-empty after parsing all fields.\n///\n/// **Unnamed Fields**\n///\n/// If the structure is a tuple struct, it must have exactly one field. The\n/// implementation parses a form exactly when the internal field parses a form\n/// _and_ any `#[field]` validations succeed.\n///\n/// ## Syntax\n///\n/// The derive accepts one field attribute: `field`, and one container\n/// attribute, `form`, with the following syntax:\n///\n/// ```text\n/// field := name? default? validate*\n///\n/// name := 'name' '=' name_val ','?\n/// name_val :=  '\"' FIELD_NAME '\"'\n///          | 'uncased(' '\"' FIELD_NAME '\"' ')\n///\n/// default := 'default' '=' EXPR ','?\n///          | 'default_with' '=' EXPR ','?\n///\n/// validate := 'validate' '=' EXPR ','?\n///\n/// FIELD_NAME := valid field name, according to the HTML5 spec\n/// EXPR := valid expression, as defined by Rust\n/// ```\n///\n/// `#[field]` can be applied any number of times on a field. `default` and\n/// `default_with` are mutually exclusive: at most _one_ of `default` or\n/// `default_with` can be present per field.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[derive(FromForm)]\n/// struct MyStruct {\n///     #[field(name = uncased(\"number\"))]\n///     #[field(default = 42)]\n///     field: usize,\n///     #[field(name = \"renamed_field\")]\n///     #[field(name = uncased(\"anotherName\"))]\n///     #[field(validate = eq(\"banana\"))]\n///     #[field(validate = neq(\"orange\"))]\n///     other: String\n/// }\n/// ```\n///\n/// For tuples structs, the `field` attribute can be applied to the structure\n/// itself:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[derive(FromForm)]\n/// #[field(default = 42, validate = eq(42))]\n/// struct Meaning(usize);\n/// ```\n///\n/// ## Field Attribute Parameters\n///\n///   * **`name`**\n///\n///     A `name` attribute changes the name to match against when parsing the\n///     form field. The value is either an exact string to match against\n///     (`\"foo\"`), or `uncased(\"foo\")`, which causes the match to be\n///     case-insensitive but case-preserving. When more than one `name`\n///     attribute is applied, the field will match against _any_ of the names.\n///\n///   * **`validate = expr`**\n///\n///     The validation `expr` is run if the field type parses successfully. The\n///     expression must return a value of type `Result<(), form::Errors>`. On\n///     `Err`, the errors are added to the thus-far collected errors. If more\n///     than one `validate` attribute is applied, _all_ validations are run.\n///\n///   * **`default = expr`**\n///\n///     If `expr` is not literally `None`, the parameter sets the default value\n///     of the field to be `expr.into()`. If `expr` _is_ `None`, the parameter\n///     _unsets_ the default value of the field, if any. The expression is only\n///     evaluated if the attributed field is missing in the incoming form.\n///\n///     Except when `expr` is `None`, `expr` must be of type `T: Into<F>` where\n///     `F` is the field's type.\n///\n///   * **`default_with = expr`**\n///\n///     The parameter sets the default value of the field to be exactly `expr`\n///     which must be of type `Option<F>` where `F` is the field's type. If the\n///     expression evaluates to `None`, there is no default. Otherwise the value\n///     wrapped in `Some` is used. The expression is only evaluated if the\n///     attributed field is missing in the incoming form.\n///\n///     ```rust\n///     # #[macro_use] extern crate rocket;\n///     use std::num::NonZeroUsize;\n///\n///     #[derive(FromForm)]\n///     struct MyForm {\n///         // `NonZeroUsize::new()` return an `Option<NonZeroUsize>`.\n///         #[field(default_with = NonZeroUsize::new(42))]\n///         num: NonZeroUsize,\n///     }\n///     ```\n///\n/// [`FromForm`]: ../rocket/form/trait.FromForm.html\n/// [`form::Errors`]: ../rocket/form/struct.Errors.html\n///\n/// # Generics\n///\n/// The derive accepts any number of type generics and at most one lifetime\n/// generic. If a type generic is present, the generated implementation will\n/// require a bound of `FromForm<'r>` for the field type containing the generic.\n/// For example, for a struct `struct Foo<T>(Json<T>)`, the bound `Json<T>:\n/// FromForm<'r>` will be added to the generated implementation.\n///\n/// ```rust\n/// use rocket::form::FromForm;\n/// use rocket::serde::json::Json;\n///\n/// // The bounds `A: FromForm<'r>`, `B: FromForm<'r>` will be required.\n/// #[derive(FromForm)]\n/// struct FancyForm<A, B> {\n///     first: A,\n///     second: B,\n/// };\n///\n/// // The bound `Json<T>: FromForm<'r>` will be required.\n/// #[derive(FromForm)]\n/// struct JsonToken<T> {\n///     token: Json<T>,\n///     id: usize,\n/// }\n/// ```\n///\n/// If a lifetime generic is present, it is replaced with `'r` in the\n/// generated implementation `impl FromForm<'r>`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// // Generates `impl<'r> FromForm<'r> for MyWrapper<'r>`.\n/// #[derive(FromForm)]\n/// struct MyWrapper<'a>(&'a str);\n/// ```\n///\n/// Both type generics and one lifetime generic may be used:\n///\n/// ```rust\n/// use rocket::form::{self, FromForm};\n///\n/// // The bound `form::Result<'r, T>: FromForm<'r>` will be required.\n/// #[derive(FromForm)]\n/// struct SomeResult<'o, T>(form::Result<'o, T>);\n/// ```\n///\n/// The special bounds on `Json` and `Result` are required due to incomplete and\n/// incorrect support for lifetime generics in `async` blocks in Rust. See\n/// [rust-lang/#64552](https://github.com/rust-lang/rust/issues/64552) for\n/// further details.\n#[proc_macro_derive(FromForm, attributes(form, field))]\npub fn derive_from_form(input: TokenStream) -> TokenStream {\n    emit!(derive::from_form::derive_from_form(input))\n}\n\n/// Derive for the [`FromParam`] trait.\n///\n/// This [`FromParam`] derive can be applied to C-like enums whose variants have\n/// no fields. The generated implementation case-sensitively matches each\n/// variant to its stringified field name. If there is no match, an error\n/// of type [`InvalidOption`] is returned.\n///\n/// [`FromParam`]: ../rocket/request/trait.FromParam.html\n/// [`InvalidOption`]: ../rocket/error/struct.InvalidOption.html\n///\n/// # Example\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::request::FromParam;\n///\n/// #[derive(FromParam, Debug, PartialEq)]\n/// enum MyParam {\n///     A,\n///     Bob,\n/// }\n///\n/// assert_eq!(MyParam::from_param(\"A\").unwrap(), MyParam::A);\n/// assert_eq!(MyParam::from_param(\"Bob\").unwrap(), MyParam::Bob);\n/// assert!(MyParam::from_param(\"a\").is_err());\n/// assert!(MyParam::from_param(\"bob\").is_err());\n/// assert!(MyParam::from_param(\"c\").is_err());\n/// assert!(MyParam::from_param(\"C\").is_err());\n///\n/// // Now `MyParam` can be used in an route to accept either `A` or `B`.\n/// #[get(\"/<param>\")]\n/// fn index(param: MyParam) -> &'static str {\n///     match param {\n///         MyParam::A => \"A\",\n///         MyParam::Bob => \"Bob\",\n///     }\n/// }\n#[proc_macro_derive(FromParam)]\npub fn derive_from_param(input: TokenStream) -> TokenStream {\n    emit!(derive::from_param::derive_from_param(input))\n}\n\n/// Derive for the [`Responder`] trait.\n///\n/// The [`Responder`] derive can be applied to enums and structs with named\n/// fields. When applied to enums, variants must have at least one field. When\n/// applied to structs, the struct must have at least one field.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use std::fs::File;\n/// # use rocket::http::ContentType;\n/// # type OtherResponder = MyResponderA;\n/// #\n/// #[derive(Responder)]\n/// enum MyResponderA {\n///     A(String),\n///     B(File, ContentType),\n/// }\n///\n/// #[derive(Responder)]\n/// struct MyResponderB {\n///     inner: OtherResponder,\n///     header: ContentType,\n/// }\n/// ```\n///\n/// # Semantics\n///\n/// The derive generates an implementation of the [`Responder`] trait for the\n/// decorated enum or structure. The derive uses the _first_ field of a variant\n/// or structure to generate a [`Response`]. As such, the type of the first\n/// field must implement [`Responder`]. The remaining fields of a variant or\n/// structure are set as headers in the produced [`Response`] using\n/// [`Response::set_header()`]. As such, every other field (unless explicitly\n/// ignored, explained next) must implement `Into<Header>`.\n///\n/// Except for the first field, fields decorated with `#[response(ignore)]` are\n/// ignored by the derive:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use std::fs::File;\n/// # use rocket::http::ContentType;\n/// # use rocket::fs::NamedFile;\n/// # type Other = usize;\n/// #\n/// #[derive(Responder)]\n/// enum MyResponder {\n///     A(String),\n///     B(File, ContentType, #[response(ignore)] Other),\n/// }\n///\n/// #[derive(Responder)]\n/// struct MyOtherResponder {\n///     inner: NamedFile,\n///     header: ContentType,\n///     #[response(ignore)]\n///     other: Other,\n/// }\n/// ```\n///\n/// Decorating the first field with `#[response(ignore)]` has no effect.\n///\n/// # Field Attribute\n///\n/// Additionally, the `response` attribute can be used on named structures and\n/// enum variants to override the status and/or content-type of the [`Response`]\n/// produced by the generated implementation. The `response` attribute used in\n/// these positions has the following grammar:\n///\n/// ```text\n/// response := parameter (',' parameter)?\n///\n/// parameter := 'status' '=' STATUS\n///            | 'content_type' '=' CONTENT_TYPE\n///\n/// STATUS := unsigned integer >= 100 and < 600\n/// CONTENT_TYPE := string literal, as defined by Rust, identifying a valid\n///                 Content-Type, as defined by Rocket\n/// ```\n///\n/// It can be used as follows:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use rocket::http::ContentType;\n/// # use rocket::fs::NamedFile;\n/// # type Other = usize;\n/// # type InnerResponder = String;\n/// #\n/// #[derive(Responder)]\n/// enum Error {\n///     #[response(status = 500, content_type = \"json\")]\n///     A(String),\n///     #[response(status = 404)]\n///     B(NamedFile, ContentType),\n/// }\n///\n/// #[derive(Responder)]\n/// #[response(status = 400)]\n/// struct MyResponder {\n///     inner: InnerResponder,\n///     header: ContentType,\n///     #[response(ignore)]\n///     other: Other,\n/// }\n/// ```\n///\n/// The attribute accepts two key/value pairs: `status` and `content_type`. The\n/// value of `status` must be an unsigned integer representing a valid status\n/// code. The [`Response`] produced from the generated implementation will have\n/// its status overridden to this value.\n///\n/// The value of `content_type` must be a valid media-type in `top/sub` form or\n/// `shorthand` form. Examples include:\n///\n///   * `\"text/html\"`\n///   * `\"application/x-custom\"`\n///   * `\"html\"`\n///   * `\"json\"`\n///   * `\"plain\"`\n///   * `\"binary\"`\n///\n/// See [`ContentType::parse_flexible()`] for a full list of available\n/// shorthands. The [`Response`] produced from the generated implementation will\n/// have its content-type overridden to this value.\n///\n/// [`Responder`]: ../rocket/response/trait.Responder.html\n/// [`Response`]: ../rocket/struct.Response.html\n/// [`Response::set_header()`]: ../rocket/response/struct.Response.html#method.set_header\n/// [`ContentType::parse_flexible()`]: ../rocket/http/struct.ContentType.html#method.parse_flexible\n///\n/// # Generics\n///\n/// The derive accepts any number of type generics and at most one lifetime\n/// generic. If a type generic is present and the generic is used in the first\n/// field of a structure, the generated implementation will require a bound of\n/// `Responder<'r, 'o>` for the field type containing the generic. In all other\n/// fields, unless ignores, a bound of `Into<Header<'o>` is added.\n///\n/// For example, for a struct `struct Foo<T, H>(Json<T>, H)`, the derive adds:\n///\n///   * `Json<T>: Responder<'r, 'o>`\n///   * `H: Into<Header<'o>>`\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::serde::Serialize;\n/// use rocket::serde::json::Json;\n/// use rocket::http::ContentType;\n/// use rocket::response::Responder;\n///\n/// // The bound `T: Responder` will be added.\n/// #[derive(Responder)]\n/// #[response(status = 404, content_type = \"html\")]\n/// struct NotFoundHtml<T>(T);\n///\n/// // The bound `Json<T>: Responder` will be added.\n/// #[derive(Responder)]\n/// struct NotFoundJson<T>(Json<T>);\n///\n/// // The bounds `Json<T>: Responder, E: Responder` will be added.\n/// #[derive(Responder)]\n/// enum MyResult<T, E> {\n///     Ok(Json<T>),\n///     #[response(status = 404)]\n///     Err(E, ContentType)\n/// }\n/// ```\n///\n/// If a lifetime generic is present, it will be replaced with `'o` in the\n/// generated implementation `impl Responder<'r, 'o>`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// // Generates `impl<'r, 'o> Responder<'r, 'o> for NotFoundHtmlString<'o>`.\n/// #[derive(Responder)]\n/// #[response(status = 404, content_type = \"html\")]\n/// struct NotFoundHtmlString<'a>(&'a str);\n/// ```\n///\n/// Both type generics and lifetime generic may be used:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use rocket::response::Responder;\n/// #[derive(Responder)]\n/// struct SomeResult<'o, T>(Result<T, &'o str>);\n/// ```\n#[proc_macro_derive(Responder, attributes(response))]\npub fn derive_responder(input: TokenStream) -> TokenStream {\n    emit!(derive::responder::derive_responder(input))\n}\n\n/// Derive for the [`UriDisplay<Query>`] trait.\n///\n/// The [`UriDisplay<Query>`] derive can be applied to enums and structs. When\n/// applied to an enum, the enum must have at least one variant. When applied to\n/// a struct, the struct must have at least one field.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[derive(UriDisplayQuery)]\n/// enum Kind {\n///     A(String),\n///     B(usize),\n/// }\n///\n/// #[derive(UriDisplayQuery)]\n/// struct MyStruct {\n///     name: String,\n///     id: usize,\n///     kind: Kind,\n/// }\n/// ```\n///\n/// Each field's type is required to implement [`UriDisplay<Query>`].\n///\n/// The derive generates an implementation of the [`UriDisplay<Query>`] trait.\n/// The implementation calls [`Formatter::write_named_value()`] for every named\n/// field, using the field's name (unless overridden, explained next) as the\n/// `name` parameter, and [`Formatter::write_value()`] for every unnamed field\n/// in the order the fields are declared.\n///\n/// The derive accepts one field attribute: `field`, with the following syntax:\n///\n/// ```text\n/// field := 'name' '=' '\"' FIELD_NAME '\"'\n///        | 'value' '=' '\"' FIELD_VALUE '\"'\n///\n/// FIELD_NAME := valid HTTP field name\n/// FIELD_VALUE := valid HTTP field value\n/// ```\n///\n/// When applied to a struct, the attribute can only contain `name` and looks\n/// as follows:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[derive(UriDisplayQuery)]\n/// # struct Kind(String);\n/// #[derive(UriDisplayQuery)]\n/// struct MyStruct {\n///     name: String,\n///     id: usize,\n///     #[field(name = \"type\")]\n///     #[field(name = \"kind\")]\n///     kind: Kind,\n/// }\n/// ```\n///\n/// The field attribute directs that a different field name be used when calling\n/// [`Formatter::write_named_value()`] for the given field. The value of the\n/// `name` attribute is used instead of the structure's actual field name. If\n/// more than one `field` attribute is applied to a field, the _first_ name is\n/// used. In the example above, the field `MyStruct::kind` is rendered with a\n/// name of `type`.\n///\n/// The attribute can also be applied to variants of C-like enums; it may only\n/// contain `value` and looks as follows:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[derive(UriDisplayQuery)]\n/// enum Kind {\n///     File,\n///     #[field(value = \"str\")]\n///     #[field(value = \"string\")]\n///     String,\n///     Other\n/// }\n/// ```\n///\n/// The field attribute directs that a different value be used when calling\n/// [`Formatter::write_named_value()`] for the given variant. The value of the\n/// `value` attribute is used instead of the variant's actual name. If more than\n/// one `field` attribute is applied to a variant, the _first_ value is used. In\n/// the example above, the variant `Kind::String` will render with a value of\n/// `str`.\n///\n/// [`UriDisplay<Query>`]: ../rocket/http/uri/fmt/trait.UriDisplay.html\n/// [`Formatter::write_named_value()`]: ../rocket/http/uri/fmt/struct.Formatter.html#method.write_named_value\n/// [`Formatter::write_value()`]: ../rocket/http/uri/fmt/struct.Formatter.html#method.write_value\n#[proc_macro_derive(UriDisplayQuery, attributes(field))]\npub fn derive_uri_display_query(input: TokenStream) -> TokenStream {\n    emit!(derive::uri_display::derive_uri_display_query(input))\n}\n\n/// Derive for the [`UriDisplay<Path>`] trait.\n///\n/// The [`UriDisplay<Path>`] derive can only be applied to tuple structs with\n/// one field.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[derive(UriDisplayPath)]\n/// struct Name(String);\n///\n/// #[derive(UriDisplayPath)]\n/// struct Age(usize);\n/// ```\n///\n/// The field's type is required to implement [`UriDisplay<Path>`].\n///\n/// The derive generates an implementation of the [`UriDisplay<Path>`] trait.\n/// The implementation calls [`Formatter::write_value()`] for the field.\n///\n/// [`UriDisplay<Path>`]: ../rocket/http/uri/fmt/trait.UriDisplay.html\n/// [`Formatter::write_value()`]: ../rocket/http/uri/fmt/struct.Formatter.html#method.write_value\n#[proc_macro_derive(UriDisplayPath)]\npub fn derive_uri_display_path(input: TokenStream) -> TokenStream {\n    emit!(derive::uri_display::derive_uri_display_path(input))\n}\n\n/// Generates a `Vec` of [`Route`]s from a set of route paths.\n///\n/// The `routes!` macro expands a list of route paths into a `Vec` of their\n/// corresponding [`Route`] structures. For example, given the following routes:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// #[get(\"/\")]\n/// fn index() { /* .. */ }\n///\n/// mod person {\n///     #[post(\"/hi/<person>\")]\n///     pub fn hello(person: String) { /* .. */ }\n/// }\n/// ```\n///\n/// The `routes!` macro can be used as:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// # use rocket::http::Method;\n/// #\n/// # #[get(\"/\")] fn index() { /* .. */ }\n/// # mod person {\n/// #   #[post(\"/hi/<person>\")] pub fn hello(person: String) { /* .. */ }\n/// # }\n/// let my_routes = routes![index, person::hello];\n/// assert_eq!(my_routes.len(), 2);\n///\n/// let index_route = &my_routes[0];\n/// assert_eq!(index_route.method, Some(Method::Get));\n/// assert_eq!(index_route.name.as_ref().unwrap(), \"index\");\n/// assert_eq!(index_route.uri.path(), \"/\");\n///\n/// let hello_route = &my_routes[1];\n/// assert_eq!(hello_route.method, Some(Method::Post));\n/// assert_eq!(hello_route.name.as_ref().unwrap(), \"hello\");\n/// assert_eq!(hello_route.uri.path(), \"/hi/<person>\");\n/// ```\n///\n/// The grammar for `routes!` is defined as:\n///\n/// ```text\n/// routes := PATH (',' PATH)*\n///\n/// PATH := a path, as defined by Rust\n/// ```\n///\n/// [`Route`]: ../rocket/struct.Route.html\n#[proc_macro]\npub fn routes(input: TokenStream) -> TokenStream {\n    emit!(bang::routes_macro(input))\n}\n\n/// Generates a `Vec` of [`Catcher`]s from a set of catcher paths.\n///\n/// The `catchers!` macro expands a list of catcher paths into a `Vec` of\n/// their corresponding [`Catcher`] structures. For example, given the following\n/// catchers:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// #[catch(404)]\n/// fn not_found() { /* .. */ }\n///\n/// mod inner {\n///     #[catch(400)]\n///     pub fn unauthorized() { /* .. */ }\n/// }\n///\n/// #[catch(default)]\n/// fn default_catcher() { /* .. */ }\n/// ```\n///\n/// The `catchers!` macro can be used as:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// # #[catch(404)] fn not_found() { /* .. */ }\n/// # #[catch(default)] fn default_catcher() { /* .. */ }\n/// # mod inner {\n/// #     #[catch(400)] pub fn unauthorized() { /* .. */ }\n/// # }\n/// let my_catchers = catchers![not_found, inner::unauthorized, default_catcher];\n/// assert_eq!(my_catchers.len(), 3);\n///\n/// let not_found = &my_catchers[0];\n/// assert_eq!(not_found.code, Some(404));\n///\n/// let unauthorized = &my_catchers[1];\n/// assert_eq!(unauthorized.code, Some(400));\n///\n/// let default = &my_catchers[2];\n/// assert_eq!(default.code, None);\n/// ```\n///\n/// The grammar for `catchers!` is defined as:\n///\n/// ```text\n/// catchers := PATH (',' PATH)*\n///\n/// PATH := a path, as defined by Rust\n/// ```\n///\n/// [`Catcher`]: ../rocket/struct.Catcher.html\n#[proc_macro]\npub fn catchers(input: TokenStream) -> TokenStream {\n    emit!(bang::catchers_macro(input))\n}\n\n/// Type-safe, encoding-safe route and non-route URI generation.\n///\n/// The `uri!` macro creates type-safe, URL-safe URIs given a route and concrete\n/// parameters for its URI or a URI string literal.\n///\n/// # String Literal Parsing\n///\n/// Given a string literal as input, `uri!` parses the string using\n/// [`Uri::parse_any()`] and emits a `'static`, `const` value whose type is one\n/// of [`Asterisk`], [`Origin`], [`Authority`], [`Absolute`], or [`Reference`],\n/// reflecting the parsed value. If the type allows normalization, the value is\n/// normalized before being emitted. Parse errors are caught and emitted at\n/// compile-time.\n///\n/// The grammar for this variant of `uri!` is:\n///\n/// ```text\n/// uri := STRING\n///\n/// STRING := an uncooked string literal, as defined by Rust (example: `\"/hi\"`)\n/// ```\n///\n/// `STRING` is expected to be an undecoded URI of any variant.\n///\n/// ## Examples\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::http::uri::Absolute;\n///\n/// // Values returned from `uri!` are `const` and `'static`.\n/// const ROOT_CONST: Absolute<'static> = uri!(\"https://rocket.rs\");\n/// static ROOT_STATIC: Absolute<'static> = uri!(\"https://rocket.rs?root\");\n///\n/// // Any variant can be parsed, but beware of ambiguities.\n/// let asterisk = uri!(\"*\");\n/// let origin = uri!(\"/foo/bar/baz\");\n/// let authority = uri!(\"rocket.rs:443\");\n/// let absolute = uri!(\"https://rocket.rs:443\");\n/// let reference = uri!(\"foo?bar#baz\");\n///\n/// # use rocket::http::uri::{Asterisk, Origin, Authority, Reference};\n/// # // Ensure we get the types we expect.\n/// # let asterisk: Asterisk = asterisk;\n/// # let origin: Origin<'static> = origin;\n/// # let authority: Authority<'static> = authority;\n/// # let absolute: Absolute<'static> = absolute;\n/// # let reference: Reference<'static> = reference;\n/// ```\n///\n/// # Type-Safe Route URIs\n///\n/// A URI to a route name `foo` is generated using `uri!(foo(v1, v2, v3))` or\n/// `uri!(foo(a = v1, b = v2, c = v3))`, where `v1`, `v2`, `v3` are the values\n/// to fill in for route parameters named `a`, `b`, and `c`. If the named\n/// parameter syntax is used (`a = v1`, etc.), parameters can appear in any\n/// order.\n///\n/// More concretely, for the route `person` defined below:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[get(\"/person/<name>?<age>\")]\n/// fn person(name: &str, age: Option<u8>) { }\n/// ```\n///\n/// ...a URI can be created as follows:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[get(\"/person/<name>?<age>\")]\n/// # fn person(name: &str, age: Option<u8>) { }\n/// // with unnamed parameters, in route path declaration order\n/// let mike = uri!(person(\"Mike Smith\", Some(28)));\n/// assert_eq!(mike.to_string(), \"/person/Mike%20Smith?age=28\");\n///\n/// // with named parameters, order irrelevant\n/// let mike = uri!(person(name = \"Mike\", age = Some(28)));\n/// let mike = uri!(person(age = Some(28), name = \"Mike\"));\n/// assert_eq!(mike.to_string(), \"/person/Mike?age=28\");\n///\n/// // with unnamed values, explicitly `None`.\n/// let mike = uri!(person(\"Mike\", None::<u8>));\n/// assert_eq!(mike.to_string(), \"/person/Mike\");\n///\n/// // with named values, explicitly `None`\n/// let option: Option<u8> = None;\n/// let mike = uri!(person(name = \"Mike\", age = None::<u8>));\n/// assert_eq!(mike.to_string(), \"/person/Mike\");\n/// ```\n///\n/// For optional query parameters, those of type `Option` or `Result`, a `_` can\n/// be used in-place of `None` or `Err`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[get(\"/person/<name>?<age>\")]\n/// # fn person(name: &str, age: Option<u8>) { }\n/// // with named values ignored\n/// let mike = uri!(person(name = \"Mike\", age = _));\n/// assert_eq!(mike.to_string(), \"/person/Mike\");\n///\n/// // with named values ignored\n/// let mike = uri!(person(age = _, name = \"Mike\"));\n/// assert_eq!(mike.to_string(), \"/person/Mike\");\n///\n/// // with unnamed values ignored\n/// let mike = uri!(person(\"Mike\", _));\n/// assert_eq!(mike.to_string(), \"/person/Mike\");\n/// ```\n///\n/// It is a type error to attempt to ignore query parameters that are neither\n/// `Option` or `Result`. Path parameters can never be ignored. A path parameter\n/// of type `Option<T>` or `Result<T, E>` must be filled by a value that can\n/// target a type of `T`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[get(\"/person/<name>\")]\n/// fn maybe(name: Option<&str>) { }\n///\n/// let bob1 = uri!(maybe(name = \"Bob\"));\n/// let bob2 = uri!(maybe(\"Bob Smith\"));\n/// assert_eq!(bob1.to_string(), \"/person/Bob\");\n/// assert_eq!(bob2.to_string(), \"/person/Bob%20Smith\");\n///\n/// #[get(\"/person/<age>\")]\n/// fn ok(age: Result<u8, std::num::ParseIntError>) { }\n///\n/// let kid1 = uri!(ok(age = 10));\n/// let kid2 = uri!(ok(12));\n/// assert_eq!(kid1.to_string(), \"/person/10\");\n/// assert_eq!(kid2.to_string(), \"/person/12\");\n/// ```\n///\n/// Values for ignored route segments can be of any type as long as the type\n/// implements [`UriDisplay`] for the appropriate URI part. If a route URI\n/// contains ignored segments, the route URI invocation cannot use named\n/// arguments.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[get(\"/ignore/<_>/<other>\")]\n/// fn ignore(other: &str) { }\n///\n/// let bob = uri!(ignore(\"Bob Hope\", \"hello\"));\n/// let life = uri!(ignore(42, \"cat&dog\"));\n/// assert_eq!(bob.to_string(), \"/ignore/Bob%20Hope/hello\");\n/// assert_eq!(life.to_string(), \"/ignore/42/cat%26dog\");\n/// ```\n///\n/// ## Prefixes and Suffixes\n///\n/// A route URI can be be optionally prefixed and/or suffixed by a URI generated\n/// from a string literal or an arbitrary expression. This takes the form\n/// `uri!(prefix, foo(v1, v2, v3), suffix)`, where both `prefix` and `suffix`\n/// are optional, and either `prefix` or `suffix` may be `_` to specify the\n/// value as empty.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[get(\"/person/<name>?<age>\")]\n/// fn person(name: &str, age: Option<u8>) { }\n///\n/// // with a specific mount-point of `/api`.\n/// let bob = uri!(\"/api\", person(\"Bob\", Some(28)));\n/// assert_eq!(bob.to_string(), \"/api/person/Bob?age=28\");\n///\n/// // with an absolute URI as a prefix\n/// let bob = uri!(\"https://rocket.rs\", person(\"Bob\", Some(28)));\n/// assert_eq!(bob.to_string(), \"https://rocket.rs/person/Bob?age=28\");\n///\n/// // with another absolute URI as a prefix\n/// let bob = uri!(\"https://rocket.rs/foo\", person(\"Bob\", Some(28)));\n/// assert_eq!(bob.to_string(), \"https://rocket.rs/foo/person/Bob?age=28\");\n///\n/// // with an expression as a prefix\n/// let host = uri!(\"http://bob.me\");\n/// let bob = uri!(host, person(\"Bob\", Some(28)));\n/// assert_eq!(bob.to_string(), \"http://bob.me/person/Bob?age=28\");\n///\n/// // with a suffix but no prefix\n/// let bob = uri!(_, person(\"Bob\", Some(28)), \"#baz\");\n/// assert_eq!(bob.to_string(), \"/person/Bob?age=28#baz\");\n///\n/// // with both a prefix and suffix\n/// let bob = uri!(\"https://rocket.rs/\", person(\"Bob\", Some(28)), \"#woo\");\n/// assert_eq!(bob.to_string(), \"https://rocket.rs/person/Bob?age=28#woo\");\n///\n/// // with an expression suffix. if the route URI already has a query, the\n/// // query part is ignored. otherwise it is added.\n/// let suffix = uri!(\"?woo#bam\");\n/// let bob = uri!(_, person(\"Bob\", Some(28)), suffix.clone());\n/// assert_eq!(bob.to_string(), \"/person/Bob?age=28#bam\");\n///\n/// let bob = uri!(_, person(\"Bob\", None::<u8>), suffix.clone());\n/// assert_eq!(bob.to_string(), \"/person/Bob?woo#bam\");\n/// ```\n///\n/// ## Grammar\n///\n/// The grammar for this variant of the `uri!` macro is:\n///\n/// ```text\n/// uri := (prefix ',')? route\n///      | prefix ',' route ',' suffix\n///\n/// prefix := STRING | expr                     ; `Origin` or `Absolute`\n/// suffix := STRING | expr                     ; `Reference` or `Absolute`\n///\n/// route := PATH '(' (named | unnamed) ')'\n///\n/// named := IDENT = expr (',' named)? ','?\n/// unnamed := expr (',' unnamed)? ','?\n///\n/// expr := EXPR | '_'\n///\n/// EXPR := a valid Rust expression (examples: `foo()`, `12`, `\"hey\"`)\n/// IDENT := a valid Rust identifier (examples: `name`, `age`)\n/// STRING := an uncooked string literal, as defined by Rust (example: `\"hi\"`)\n/// PATH := a path, as defined by Rust (examples: `route`, `my_mod::route`)\n/// ```\n///\n/// ## Dynamic Semantics\n///\n/// The returned value is that of the prefix (minus any query part) concatenated\n/// with the route URI concatenated with the query (if the route has no query\n/// part) and fragment parts of the suffix. The route URI is generated by\n/// interpolating the declared route URI with the URL-safe version of the route\n/// values in `uri!()`. The generated URI is guaranteed to be URI-safe.\n///\n/// Each route value is rendered in its appropriate place in the URI using the\n/// [`UriDisplay`] implementation for the value's type. The `UriDisplay`\n/// implementation ensures that the rendered value is URL-safe.\n///\n/// A `uri!()` invocation allocated at-most once.\n///\n/// ## Static Semantics\n///\n/// The `uri!` macro returns one of [`Origin`], [`Absolute`], or [`Reference`],\n/// depending on the types of the prefix and suffix, if any. The table below\n/// specifies all combinations:\n///\n/// | Prefix     | Suffix      | Output      |\n/// |------------|-------------|-------------|\n/// | None       | None        | `Origin`    |\n/// | None       | `Absolute`  | `Origin`    |\n/// | None       | `Reference` | `Reference` |\n/// | `Origin`   | None        | `Origin`    |\n/// | `Origin`   | `Absolute`  | `Origin`    |\n/// | `Origin`   | `Reference` | `Reference` |\n/// | `Absolute` | None        | `Absolute`  |\n/// | `Absolute` | `Absolute`  | `Absolute`  |\n/// | `Absolute` | `Reference` | `Reference` |\n///\n/// A `uri!` invocation only typechecks if the type of every route URI value in\n/// the invocation matches the type declared for the parameter in the given\n/// route, after conversion with [`FromUriParam`], or if a value is ignored\n/// using `_` and the corresponding route type implements [`Ignorable`].\n///\n/// ### Conversion\n///\n/// The [`FromUriParam`] trait is used to typecheck and perform a conversion for\n/// each value passed to `uri!`. If a `FromUriParam<P, S> for T` implementation\n/// exists for a type `T` for part URI part `P`, then a value of type `S` can be\n/// used in `uri!` macro for a route URI parameter declared with a type of `T`\n/// in part `P`. For example, the following implementation, provided by Rocket,\n/// allows an `&str` to be used in a `uri!` invocation for route URI parameters\n/// declared as `String`:\n///\n/// ```rust,ignore\n/// impl<P: Part, 'a> FromUriParam<P, &'a str> for String { .. }\n/// ```\n///\n/// ### Ignorables\n///\n/// Query parameters can be ignored using `_` in place of an expression. The\n/// corresponding type in the route URI must implement [`Ignorable`]. Ignored\n/// parameters are not interpolated into the resulting `Origin`. Path parameters\n/// are not ignorable.\n///\n/// [`Uri`]: ../rocket/http/uri/enum.Uri.html\n/// [`Uri::parse_any()`]: ../rocket/http/uri/enum.Uri.html#method.parse_any\n/// [`Origin`]: ../rocket/http/uri/struct.Origin.html\n/// [`Asterisk`]: ../rocket/http/uri/struct.Asterisk.html\n/// [`Authority`]: ../rocket/http/uri/struct.Authority.html\n/// [`Absolute`]: ../rocket/http/uri/struct.Absolute.html\n/// [`Reference`]: ../rocket/http/uri/struct.Reference.html\n/// [`FromUriParam`]: ../rocket/http/uri/fmt/trait.FromUriParam.html\n/// [`UriDisplay`]: ../rocket/http/uri/fmt/trait.UriDisplay.html\n/// [`Ignorable`]: ../rocket/http/uri/fmt/trait.Ignorable.html\n#[proc_macro]\npub fn uri(input: TokenStream) -> TokenStream {\n    emit!(bang::uri_macro(input))\n}\n\n/// Internal macro: `rocket_internal_uri!`.\n#[proc_macro]\n#[doc(hidden)]\npub fn rocket_internal_uri(input: TokenStream) -> TokenStream {\n    emit!(bang::uri_internal_macro(input))\n}\n\n/// Internal macro: `__typed_stream!`.\n#[proc_macro]\n#[doc(hidden)]\npub fn __typed_stream(input: TokenStream) -> TokenStream {\n    emit!(bang::typed_stream(input))\n}\n\n/// Private Rocket internal macro: `internal_guide_tests!`.\n#[proc_macro]\n#[doc(hidden)]\npub fn internal_guide_tests(input: TokenStream) -> TokenStream {\n    emit!(bang::guide_tests_internal(input))\n}\n\n/// Private Rocket internal macro: `export!`.\n#[proc_macro]\n#[doc(hidden)]\npub fn export(input: TokenStream) -> TokenStream {\n    emit!(bang::export_internal(input))\n}\n\n/// Private Rocket attribute: `async_bound(Bounds + On + Returned + Future)`.\n#[doc(hidden)]\n#[proc_macro_attribute]\npub fn async_bound(args: TokenStream, input: TokenStream) -> TokenStream {\n    emit!(attribute::async_bound::async_bound(args, input))\n}\n"
  },
  {
    "path": "core/codegen/src/name.rs",
    "content": "use crate::http::uncased::UncasedStr;\n\nuse syn::{Ident, ext::IdentExt};\nuse proc_macro2::{Span, TokenStream};\n\n/// A \"name\" read by codegen, which may or may not be an identifier. A `Name` is\n/// typically constructed indirectly via FromMeta, or From<Ident> or directly\n/// from a string via `Name::new()`. A name is tokenized as a string.\n///\n/// Some \"names\" in Rocket include:\n///   * Dynamic parameter: `name` in `<name>`\n///   * Renamed fields: `foo` in #[field(name = \"foo\")].\n///\n/// `Name` implements Hash, PartialEq, and Eq, and additionally PartialEq<S> for\n/// all types `S: PartialEq<str>`. These implementations all compare the value\n/// of `as_str()` only.\n#[derive(Debug, Clone)]\npub struct Name {\n    value: String,\n    span: Span,\n}\n\nimpl Name {\n    /// Creates a new `Name` from the string `name` and span `span`. If\n    /// `name` is a valid ident, the ident is stored as well.\n    pub fn new<S: Into<String>>(name: S, span: Span) -> Self {\n        Name { value: name.into(), span }\n    }\n\n    /// Returns the name as a string. Notably, if `self` was constructed from an\n    /// Ident this method returns a name *without* an `r#` prefix.\n    pub fn as_str(&self) -> &str {\n        &self.value\n    }\n\n    /// Like `as_str()` but into an `&UncasedStr`.\n    pub fn as_uncased_str(&self) -> &UncasedStr {\n        UncasedStr::new(self.as_str())\n    }\n\n    pub fn span(&self) -> Span {\n        self.span\n    }\n}\n\nimpl devise::FromMeta for Name {\n    fn from_meta(meta: &devise::MetaItem) -> devise::Result<Self> {\n        use devise::ext::SpanDiagnosticExt;\n\n        if let syn::Lit::Str(s) = meta.lit()? {\n            return Ok(Name::new(s.value(), s.span()));\n        }\n\n        Err(meta.value_span().error(\"invalid value: expected string literal\"))\n    }\n}\n\nimpl quote::ToTokens for Name {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        syn::LitStr::new(self.as_str(), self.span()).to_tokens(tokens)\n    }\n}\n\nimpl From<&Ident> for Name {\n    fn from(ident: &Ident) -> Self {\n        Name::new(ident.unraw().to_string(), ident.span())\n    }\n}\n\nimpl AsRef<str> for Name {\n    fn as_ref(&self) -> &str {\n        self.as_str()\n    }\n}\n\nimpl std::hash::Hash for Name {\n    fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {\n        self.as_str().hash(hasher)\n    }\n}\n\nimpl std::ops::Deref for Name {\n    type Target = str;\n\n    fn deref(&self) -> &Self::Target {\n        self.as_str()\n    }\n}\n\nimpl Eq for Name { }\n\nimpl<S: PartialEq<str> + ?Sized> PartialEq<S> for Name {\n    fn eq(&self, other: &S) -> bool {\n        other == self.as_str()\n    }\n}\n\nimpl std::fmt::Display for Name {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.as_str().fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/proc_macro_ext.rs",
    "content": "use std::ops::RangeBounds;\n\nuse devise::Diagnostic;\nuse proc_macro2::{Span, Literal};\n\n// An experiment.\npub struct Diagnostics(Vec<Diagnostic>);\n\nimpl Diagnostics {\n    pub fn new() -> Self {\n        Diagnostics(vec![])\n    }\n\n    pub fn push(&mut self, diag: Diagnostic) {\n        self.0.push(diag);\n    }\n\n    pub fn emit_head(self) -> Diagnostic {\n        let mut iter = self.0.into_iter();\n        let mut last = iter.next().expect(\"Diagnostic::emit_head empty\");\n        for diag in iter {\n            // FIXME(diag: emit, can there be errors here?)\n            last.emit_as_item_tokens();\n            last = diag;\n        }\n\n        last\n    }\n\n    pub fn head_err_or<T>(self, ok: T) -> devise::Result<T> {\n        match self.0.is_empty() {\n            true => Ok(ok),\n            false => Err(self.emit_head())\n        }\n    }\n}\n\nimpl From<Diagnostic> for Diagnostics {\n    fn from(diag: Diagnostic) -> Self {\n        Diagnostics(vec![diag])\n    }\n}\n\nimpl From<Vec<Diagnostic>> for Diagnostics {\n    fn from(diags: Vec<Diagnostic>) -> Self {\n        Diagnostics(diags)\n    }\n}\n\npub struct StringLit(pub String, pub Literal);\n\nimpl StringLit {\n    pub fn new<S: Into<String>>(string: S, span: Span) -> Self {\n        let string = string.into();\n        let mut lit = Literal::string(&string);\n        lit.set_span(span);\n        StringLit(string, lit)\n    }\n\n    pub fn span(&self) -> Span {\n        self.1.span()\n    }\n\n    /// Attempt to obtain a subspan, or, failing that, produce the full span.\n    /// This will create suboptimal diagnostics, but better than failing to\n    /// build entirely.\n    pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Span {\n        self.1.subspan(range).unwrap_or_else(|| self.span())\n    }\n}\n\nimpl syn::parse::Parse for StringLit {\n    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {\n        let lit = input.parse::<syn::LitStr>()?;\n        Ok(StringLit::new(lit.value(), lit.span()))\n    }\n}\n\nimpl devise::FromMeta for StringLit {\n    fn from_meta(meta: &devise::MetaItem) -> devise::Result<Self> {\n        Ok(StringLit::new(String::from_meta(meta)?, meta.value_span()))\n    }\n}\n\nimpl std::ops::Deref for StringLit {\n    type Target = str;\n\n    fn deref(&self) -> &str {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "core/codegen/src/syn_ext.rs",
    "content": "//! Extensions to `syn` types.\n\nuse std::ops::Deref;\nuse std::hash::{Hash, Hasher};\nuse std::borrow::Cow;\n\nuse syn::{Ident, ext::IdentExt as _, visit::Visit};\nuse proc_macro2::{Span, TokenStream};\nuse devise::ext::{PathExt, TypeExt as _};\nuse rocket_http::ext::IntoOwned;\n\npub trait IdentExt {\n    fn prepend(&self, string: &str) -> syn::Ident;\n    fn append(&self, string: &str) -> syn::Ident;\n    fn with_span(self, span: Span) -> syn::Ident;\n    fn rocketized(&self) -> syn::Ident;\n    fn uniqueify_with<F: FnMut(&mut dyn Hasher)>(&self, f: F) -> syn::Ident;\n}\n\npub trait ReturnTypeExt {\n    fn ty(&self) -> Option<&syn::Type>;\n}\n\npub trait FnArgExt {\n    fn typed(&self) -> Option<(&syn::Ident, &syn::Type)>;\n    fn wild(&self) -> Option<&syn::PatWild>;\n}\n\npub trait TypeExt {\n    fn unfold_with_ty_macros(&self, names: &[&str], mapper: MacTyMapFn) -> Vec<Child<'_>>;\n    fn is_concrete(&self, generic_ident: &[&Ident]) -> bool;\n}\n\npub trait GenericsExt {\n    fn type_idents(&self) -> Vec<&Ident>;\n}\n\n#[derive(Debug)]\npub struct Child<'a> {\n    pub parent: Option<Cow<'a, syn::Type>>,\n    pub ty: Cow<'a, syn::Type>,\n}\n\nimpl Deref for Child<'_> {\n    type Target = syn::Type;\n\n    fn deref(&self) -> &Self::Target {\n        &self.ty\n    }\n}\n\nimpl IntoOwned for Child<'_> {\n    type Owned = Child<'static>;\n\n    fn into_owned(self) -> Self::Owned {\n        Child {\n            parent: self.parent.into_owned(),\n            ty: Cow::Owned(self.ty.into_owned()),\n        }\n    }\n}\n\ntype MacTyMapFn = fn(&TokenStream) -> Option<syn::Type>;\n\nimpl IdentExt for syn::Ident {\n    fn prepend(&self, string: &str) -> syn::Ident {\n        syn::Ident::new(&format!(\"{}{}\", string, self.unraw()), self.span())\n    }\n\n    fn append(&self, string: &str) -> syn::Ident {\n        syn::Ident::new(&format!(\"{}{}\", self, string), self.span())\n    }\n\n    fn with_span(mut self, span: Span) -> syn::Ident {\n        self.set_span(span);\n        self\n    }\n\n    fn rocketized(&self) -> syn::Ident {\n        self.prepend(crate::ROCKET_IDENT_PREFIX)\n    }\n\n    /// Create a unique version of the ident `self` based on the hash of `self`,\n    /// its span, the current call site, and any additional information provided\n    /// by the closure `f`.\n    ///\n    /// Span::source_file() / line / col are not stable, but the byte span and\n    /// some kind of scope identifier do appear in the `Debug` representation\n    /// for `Span`. And they seem to be consistent across compilations: \"#57\n    /// bytes(106..117)\" at the time of writing. So we use that.\n    fn uniqueify_with<F: FnMut(&mut dyn Hasher)>(&self, mut f: F) -> syn::Ident {\n        use std::collections::hash_map::DefaultHasher;\n\n        let mut hasher = DefaultHasher::new();\n        self.hash(&mut hasher);\n        format!(\"{:?}\", self.span()).hash(&mut hasher);\n        format!(\"{:?}\", Span::call_site()).hash(&mut hasher);\n        f(&mut hasher);\n\n        self.append(&format!(\"_{}\", hasher.finish()))\n    }\n}\n\nimpl ReturnTypeExt for syn::ReturnType {\n    fn ty(&self) -> Option<&syn::Type> {\n        match self {\n            syn::ReturnType::Default => None,\n            syn::ReturnType::Type(_, ty) => Some(ty),\n        }\n    }\n}\n\nimpl FnArgExt for syn::FnArg {\n    fn typed(&self) -> Option<(&Ident, &syn::Type)> {\n        match self {\n            syn::FnArg::Typed(arg) => match *arg.pat {\n                syn::Pat::Ident(ref pat) => Some((&pat.ident, &arg.ty)),\n                _ => None\n            }\n            _ => None,\n        }\n    }\n\n    fn wild(&self) -> Option<&syn::PatWild> {\n        match self {\n            syn::FnArg::Typed(arg) => match *arg.pat {\n                syn::Pat::Wild(ref pat) => Some(pat),\n                _ => None\n            }\n            _ => None,\n        }\n    }\n}\n\nfn macro_inner_ty(t: &syn::TypeMacro, names: &[&str], m: MacTyMapFn) -> Option<syn::Type> {\n    if !names.iter().any(|k| t.mac.path.last_ident().map_or(false, |i| i == k)) {\n        return None;\n    }\n\n    let mut ty = m(&t.mac.tokens)?;\n    ty.strip_lifetimes();\n    Some(ty)\n}\n\nimpl TypeExt for syn::Type {\n    fn unfold_with_ty_macros(&self, names: &[&str], mapper: MacTyMapFn) -> Vec<Child<'_>> {\n        struct Visitor<'a, 'm> {\n            parents: Vec<Cow<'a, syn::Type>>,\n            children: Vec<Child<'a>>,\n            names: &'m [&'m str],\n            mapper: MacTyMapFn,\n        }\n\n        impl<'m> Visitor<'_, 'm> {\n            fn new(names: &'m [&'m str], mapper: MacTyMapFn) -> Self {\n                Visitor { parents: vec![], children: vec![], names, mapper }\n            }\n        }\n\n        impl<'a> Visit<'a> for Visitor<'a, '_> {\n            fn visit_type(&mut self, ty: &'a syn::Type) {\n                let parent = self.parents.last().cloned();\n\n                if let syn::Type::Macro(t) = ty {\n                    if let Some(inner_ty) = macro_inner_ty(t, self.names, self.mapper) {\n                        let mut visitor = Visitor::new(self.names, self.mapper);\n                        if let Some(parent) = parent.clone().into_owned() {\n                            visitor.parents.push(parent);\n                        }\n\n                        visitor.visit_type(&inner_ty);\n                        let mut children = visitor.children.into_owned();\n                        self.children.append(&mut children);\n                        return;\n                    }\n                }\n\n                self.children.push(Child { parent, ty: Cow::Borrowed(ty) });\n                self.parents.push(Cow::Borrowed(ty));\n                syn::visit::visit_type(self, ty);\n                self.parents.pop();\n            }\n        }\n\n        let mut visitor = Visitor::new(names, mapper);\n        visitor.visit_type(self);\n        visitor.children\n    }\n\n    fn is_concrete(&self, generics: &[&Ident]) -> bool {\n        struct ConcreteVisitor<'i>(bool, &'i [&'i Ident]);\n\n        impl<'a> Visit<'a> for ConcreteVisitor<'_> {\n            fn visit_type(&mut self, ty: &'a syn::Type) {\n                use syn::Type::*;\n\n                match ty {\n                    Path(t) if self.1.iter().any(|i| t.path.is_ident(*i)) => {\n                        self.0 = false;\n                    }\n                    ImplTrait(_) | Infer(_) | Macro(_) => {\n                        self.0 = false;\n                    }\n                    BareFn(_) | Never(_) => {\n                        self.0 = true;\n                    },\n                    _ => syn::visit::visit_type(self, ty),\n                }\n            }\n        }\n\n        let mut visitor = ConcreteVisitor(true, generics);\n        visitor.visit_type(self);\n        visitor.0\n    }\n}\n\nimpl GenericsExt for syn::Generics {\n    fn type_idents(&self) -> Vec<&Ident> {\n        self.type_params().map(|p| &p.ident).collect()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #[test]\n    fn test_type_unfold_is_generic() {\n        use super::TypeExt;\n\n        let ty: syn::Type = syn::parse_quote!(A<B, C<impl Foo>, Box<dyn Foo>, Option<T>>);\n        let children = ty.unfold_with_ty_macros(&[], |_| None);\n        assert_eq!(children.len(), 8);\n\n        let gen_ident = format_ident!(\"T\");\n        let gen = &[&gen_ident];\n        assert_eq!(children.iter().filter(|c| c.ty.is_concrete(gen)).count(), 3);\n    }\n}\n"
  },
  {
    "path": "core/codegen/tests/async-entry.rs",
    "content": "#![allow(dead_code, unused_variables)]\n\nmod a {\n    // async launch that is async.\n    #[rocket::launch]\n    async fn rocket() -> rocket::Rocket<rocket::Build> {\n        let _ = rocket::build().launch().await;\n        rocket::build()\n    }\n\n    async fn use_it() {\n        let rocket: rocket::Rocket<rocket::Build> = rocket().await;\n    }\n}\n\nmod b {\n    // async launch that isn't async.\n    #[rocket::launch]\n    async fn main2() -> _ {\n        rocket::build()\n    }\n\n    async fn use_it() {\n        let rocket: rocket::Rocket<_> = main2().await;\n    }\n}\n\nmod b_inferred {\n    #[rocket::launch]\n    async fn main2() -> _ { rocket::build() }\n\n    async fn use_it() {\n        let rocket: rocket::Rocket<_> = main2().await;\n    }\n}\n\nmod c {\n    // non-async launch.\n    #[rocket::launch]\n    fn rocket() -> _ {\n        rocket::build()\n    }\n\n    fn use_it() {\n        let rocket: rocket::Rocket<_> = rocket();\n    }\n}\n\nmod c_inferred {\n    #[rocket::launch]\n    fn rocket() -> _ { rocket::build() }\n\n    fn use_it() {\n        let rocket: rocket::Rocket<_> = rocket();\n    }\n}\n\nmod d {\n    // main with async, is async.\n    #[rocket::main]\n    async fn main() {\n        let _ = rocket::build().launch().await;\n    }\n}\n\nmod e {\n    // main with async, isn't async.\n    #[rocket::main]\n    async fn main() { }\n}\n\nmod f {\n    // main with async, is async, with termination return.\n    #[rocket::main]\n    async fn main() -> Result<(), rocket::Error> {\n        let _: rocket::Rocket<rocket::Ignite> = rocket::build().launch().await?;\n        Ok(())\n    }\n}\n\nmod g {\n    // main with async, isn't async, with termination return.\n    #[rocket::main]\n    async fn main() -> Result<(), String> {\n        Ok(())\n    }\n}\n\n// main with async, is async, with termination return.\n#[rocket::main]\nasync fn main() -> Result<(), String> {\n    let result = rocket::build().launch().await;\n    let _: rocket::Rocket<rocket::Ignite> = result.map_err(|e| e.to_string())?;\n    Ok(())\n}\n"
  },
  {
    "path": "core/codegen/tests/async-routes.rs",
    "content": "#![allow(dead_code)]\n\n#[macro_use] extern crate rocket;\nuse rocket::http::uri::Origin;\nuse rocket::request::Request;\n\nasync fn noop() { }\n\n#[get(\"/\")]\nasync fn hello(_origin: &Origin<'_>) -> &'static str {\n    noop().await;\n    \"Hello, world!\"\n}\n\n#[get(\"/repeated_query?<sort>\")]\nasync fn repeated_query(sort: Vec<&str>) -> &str {\n    noop().await;\n    sort[0]\n}\n\n#[catch(404)]\nasync fn not_found(req: &Request<'_>) -> String {\n    noop().await;\n    format!(\"{} not found\", req.uri())\n}\n"
  },
  {
    "path": "core/codegen/tests/catcher.rs",
    "content": "// Rocket sometimes generates mangled identifiers that activate the\n// non_snake_case lint. We deny the lint in this test to ensure that\n// code generation uses #[allow(non_snake_case)] in the appropriate places.\n#![deny(non_snake_case)]\n\n#[macro_use] extern crate rocket;\n\nuse rocket::{Request, Rocket, Build};\nuse rocket::local::blocking::Client;\nuse rocket::http::Status;\n\n#[catch(404)] fn not_found_0() -> &'static str { \"404-0\" }\n#[catch(404)] fn not_found_1(_: &Request<'_>) -> &'static str { \"404-1\" }\n#[catch(404)] fn not_found_2(_: Status, _: &Request<'_>) -> &'static str { \"404-2\" }\n#[catch(default)] fn all(_: Status, r: &Request<'_>) -> String { r.uri().to_string() }\n\n#[test]\nfn test_simple_catchers() {\n    fn rocket() -> Rocket<Build> {\n        rocket::build()\n            .register(\"/0\", catchers![not_found_0])\n            .register(\"/1\", catchers![not_found_1])\n            .register(\"/2\", catchers![not_found_2])\n            .register(\"/\", catchers![all])\n    }\n\n    let client = Client::debug(rocket()).unwrap();\n    for i in 0..6 {\n        let response = client.get(format!(\"/{}\", i)).dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n\n        match i {\n            0..=2 => assert_eq!(response.into_string().unwrap(), format!(\"404-{}\", i)),\n            _ => assert_eq!(response.into_string().unwrap(), format!(\"/{}\", i)),\n        }\n    }\n}\n\n#[get(\"/<code>\")] fn forward(code: u16) -> Status { Status::new(code) }\n#[catch(400)] fn forward_400(status: Status, _: &Request<'_>) -> String { status.code.to_string() }\n#[catch(404)] fn forward_404(status: Status, _: &Request<'_>) -> String { status.code.to_string() }\n#[catch(444)] fn forward_444(status: Status, _: &Request<'_>) -> String { status.code.to_string() }\n#[catch(500)] fn forward_500(status: Status, _: &Request<'_>) -> String { status.code.to_string() }\n\n#[test]\nfn test_status_param() {\n    fn rocket() -> Rocket<Build> {\n        rocket::build()\n            .mount(\"/\", routes![forward])\n            .register(\"/\", catchers![forward_400, forward_404, forward_444, forward_500])\n    }\n\n    let client = Client::debug(rocket()).unwrap();\n    for code in &[400, 404, 444, 400, 800, 3480] {\n        let response = client.get(uri!(forward(*code))).dispatch();\n        let code = std::cmp::min(*code, 500);\n        assert_eq!(response.status(), Status::new(code));\n        assert_eq!(response.into_string().unwrap(), code.to_string());\n    }\n}\n"
  },
  {
    "path": "core/codegen/tests/expansion.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::local::blocking::Client;\n\n#[get(\"/easy/<id>\")]\nfn easy(id: i32) -> String {\n    format!(\"easy id: {}\", id)\n}\n\nmacro_rules! make_handler {\n    () => {\n        #[get(\"/hard/<id>\")]\n        fn hard(id: i32) -> String {\n            format!(\"hard id: {}\", id)\n        }\n    }\n}\n\nmake_handler!();\n\n\nmacro_rules! foo {\n    ($addr:expr, $name:ident) => {\n        #[get($addr)]\n        fn hi($name: String) -> String {\n            $name\n        }\n    };\n}\n\n// regression test for `#[get] panicking if used inside a macro\nfoo!(\"/hello/<name>\", name);\n\n#[test]\nfn test_reexpansion() {\n    let rocket = rocket::build().mount(\"/\", routes![easy, hard, hi]);\n    let client = Client::debug(rocket).unwrap();\n\n    let response = client.get(\"/easy/327\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"easy id: 327\");\n\n    let response = client.get(\"/hard/72\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"hard id: 72\");\n\n    let response = client.get(\"/hello/fish\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"fish\");\n}\n\nmacro_rules! index {\n    ($type:ty) => {\n        #[get(\"/\")]\n        fn index(thing: &rocket::State<$type>) -> String {\n            format!(\"Thing: {}\", thing)\n        }\n    }\n}\n\nindex!(i32);\n\n#[test]\nfn test_index() {\n    let rocket = rocket::build().mount(\"/\", routes![index]).manage(100i32);\n    let client = Client::debug(rocket).unwrap();\n\n    let response = client.get(\"/\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"Thing: 100\");\n}\n"
  },
  {
    "path": "core/codegen/tests/from_form.rs",
    "content": "use std::net::{IpAddr, SocketAddr};\nuse std::collections::{BTreeMap, HashMap};\n\nuse pretty_assertions::assert_eq;\n\nuse rocket::UriDisplayQuery;\nuse rocket::http::uri::fmt::{UriDisplay, Query};\nuse rocket::form::{self, Form, Strict, FromForm, FromFormField, Errors};\nuse rocket::form::error::{ErrorKind, Entity};\nuse rocket::serde::json::Json;\n\nfn strict<'f, T: FromForm<'f>>(string: &'f str) -> Result<T, Errors<'f>> {\n    Form::<Strict<T>>::parse(string).map(|s| s.into_inner())\n}\n\nfn lenient<'f, T: FromForm<'f>>(string: &'f str) -> Result<T, Errors<'f>> {\n    Form::<T>::parse(string)\n}\n\nfn strict_encoded<T: 'static>(string: &str) -> Result<T, Errors<'static>>\n    where for<'a> T: FromForm<'a>\n{\n    Form::<Strict<T>>::parse_encoded(string.into()).map(|s| s.into_inner())\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct TodoTask {\n    description: String,\n    completed: bool\n}\n\n#[test]\nfn simple() {\n    // Same number of arguments: simple case.\n    let task: Option<TodoTask> = strict(\"description=Hello&completed=on\").ok();\n    assert_eq!(task, Some(TodoTask {\n        description: \"Hello\".to_string(),\n        completed: true\n    }));\n\n    // Argument in string but not in form.\n    let task: Option<TodoTask> = strict(\"other=a&description=Hello&completed=on\").ok();\n    assert!(task.is_none());\n\n    let task: Option<TodoTask> = lenient(\"other=a&description=Hello&completed=on\").ok();\n    assert_eq!(task, Some(TodoTask {\n        description: \"Hello\".to_string(),\n        completed: true\n    }));\n\n    // Ensure _method isn't required.\n    let task: Option<TodoTask> = strict(\"_method=patch&description=Hello&completed=off\").ok();\n    assert_eq!(task, Some(TodoTask {\n        description: \"Hello\".to_string(),\n        completed: false\n    }));\n}\n\n#[derive(Debug, PartialEq, FromFormField)]\nenum FormOption {\n    A, B, C\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct FormInput<'r> {\n    checkbox: bool,\n    number: usize,\n    radio: FormOption,\n    password: &'r str,\n    textarea: String,\n    select: FormOption,\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct DefaultInput<'r> {\n    arg: Option<&'r str>,\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct ManualMethod<'r> {\n    _method: Option<&'r str>,\n    done: bool\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct UnpresentCheckbox {\n    checkbox: bool\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct UnpresentCheckboxTwo<'r> {\n    checkbox: bool,\n    something: &'r str\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct FieldNamedV<'r> {\n    v: &'r str,\n}\n\n#[test]\nfn base_conditions() {\n    let form_string = &[\n        \"password=testing\", \"checkbox=off\", \"number=10\", \"textarea=\",\n        \"select=a\", \"radio=c\",\n    ].join(\"&\");\n\n    let input: Result<FormInput<'_>, _> = strict(&form_string);\n    assert_eq!(input, Ok(FormInput {\n        checkbox: false,\n        number: 10,\n        radio: FormOption::C,\n        password: \"testing\".into(),\n        textarea: \"\".to_string(),\n        select: FormOption::A,\n    }));\n\n    // Argument not in string with default in form.\n    let default: Option<DefaultInput<'_>> = strict(\"\").ok();\n    assert_eq!(default, Some(DefaultInput {\n        arg: None\n    }));\n\n    // Ensure _method can be captured if desired.\n    let manual: Option<ManualMethod<'_>> = strict(\"_method=put&done=true\").ok();\n    assert_eq!(manual, Some(ManualMethod {\n        _method: Some(\"put\".into()),\n        done: true\n    }));\n\n    let manual: Option<ManualMethod<'_>> = lenient(\"_method=put&done=true\").ok();\n    assert_eq!(manual, Some(ManualMethod {\n        _method: Some(\"put\".into()),\n        done: true\n    }));\n\n    // And ignored when not present.\n    let manual: Option<ManualMethod<'_>> = strict(\"done=true\").ok();\n    assert_eq!(manual, Some(ManualMethod {\n        _method: None,\n        done: true\n    }));\n\n    // Check that a `bool` value that isn't in the form is marked as `false`.\n    let manual: Option<UnpresentCheckbox> = lenient(\"\").ok();\n    assert_eq!(manual, Some(UnpresentCheckbox {\n        checkbox: false\n    }));\n\n    // Check that a `bool` value that isn't in the form is marked as `false`.\n    let manual: Option<UnpresentCheckboxTwo<'_>> = lenient(\"something=hello\").ok();\n    assert_eq!(manual, Some(UnpresentCheckboxTwo {\n        checkbox: false,\n        something: \"hello\".into()\n    }));\n\n    // Check that a structure with one field `v` parses correctly.\n    let manual: Option<FieldNamedV<'_>> = strict(\"v=abc\").ok();\n    assert_eq!(manual, Some(FieldNamedV {\n        v: \"abc\".into()\n    }));\n}\n\n#[test]\nfn lenient_parsing() {\n    // Check that a structure with one field `v` parses correctly (lenient).\n    let manual: Option<FieldNamedV<'_>> = lenient(\"v=abc\").ok();\n    assert_eq!(manual, Some(FieldNamedV { v: \"abc\".into() }));\n\n    let manual: Option<FieldNamedV<'_>> = lenient(\"v=abc&a=123\").ok();\n    assert_eq!(manual, Some(FieldNamedV { v: \"abc\".into() }));\n\n    let manual: Option<FieldNamedV<'_>> = lenient(\"c=abcddef&v=abc&a=123\").ok();\n    assert_eq!(manual, Some(FieldNamedV { v: \"abc\".into() }));\n\n    // Check default values (bool) with lenient parsing.\n    let manual: Option<UnpresentCheckboxTwo<'_>> = lenient(\"something=hello\").ok();\n    assert_eq!(manual, Some(UnpresentCheckboxTwo {\n        checkbox: false,\n        something: \"hello\".into()\n    }));\n\n    let manual: Option<UnpresentCheckboxTwo<'_>> = lenient(\"hi=hi&something=hello\").ok();\n    assert_eq!(manual, Some(UnpresentCheckboxTwo {\n        checkbox: false,\n        something: \"hello\".into()\n    }));\n\n    // Check that a missing field doesn't parse, even leniently.\n    let manual: Option<FieldNamedV<'_>> = lenient(\"a=abc\").ok();\n    assert!(manual.is_none());\n\n    let manual: Option<FieldNamedV<'_>> = lenient(\"_method=abc\").ok();\n    assert!(manual.is_none());\n}\n\n#[test]\nfn field_renaming() {\n    #[derive(Debug, PartialEq, FromForm)]\n    struct RenamedForm {\n        single: usize,\n        #[field(name = \"camelCase\")]\n        camel_case: String,\n        #[field(name = \"TitleCase\")]\n        title_case: String,\n        #[field(name = \"type\")]\n        field_type: isize,\n        #[field(name = \"DOUBLE\")]\n        double: String,\n        #[field(name = \"a:b\")]\n        colon: isize,\n    }\n\n    let form_string = &[\n        \"single=100\", \"camelCase=helloThere\", \"TitleCase=HiHi\", \"type=-2\",\n        \"DOUBLE=bing_bong\", \"a:b=123\"\n    ].join(\"&\");\n\n    let form: Option<RenamedForm> = strict(&form_string).ok();\n    assert_eq!(form, Some(RenamedForm {\n        single: 100,\n        camel_case: \"helloThere\".into(),\n        title_case: \"HiHi\".into(),\n        field_type: -2,\n        double: \"bing_bong\".into(),\n        colon: 123,\n    }));\n\n    let form_string = &[\n        \"single=100\", \"camel_case=helloThere\", \"TitleCase=HiHi\", \"type=-2\",\n        \"DOUBLE=bing_bong\", \"colon=123\"\n    ].join(\"&\");\n\n    let form: Option<RenamedForm> = strict(&form_string).ok();\n    assert!(form.is_none());\n\n    #[derive(Debug, PartialEq, FromForm)]\n    struct MultiName<'r> {\n        single: usize,\n        #[field(name = \"SomeCase\")]\n        #[field(name = \"some_case\")]\n        some_case: &'r str,\n    }\n\n    let form_string = &[\"single=123\", \"some_case=hi_im_here\"].join(\"&\");\n    let form: Option<MultiName<'_>> = strict(&form_string).ok();\n    assert_eq!(form, Some(MultiName { single: 123, some_case: \"hi_im_here\", }));\n\n    let form_string = &[\"single=123\", \"SomeCase=HiImHere\"].join(\"&\");\n    let form: Option<MultiName<'_>> = strict(&form_string).ok();\n    assert_eq!(form, Some(MultiName { single: 123, some_case: \"HiImHere\", }));\n\n    let form_string = &[\"single=123\", \"some_case=hi_im_here\", \"SomeCase=HiImHere\"].join(\"&\");\n    let form: Option<MultiName<'_>> = strict(&form_string).ok();\n    assert!(form.is_none());\n\n    let form_string = &[\"single=123\", \"some_case=hi_im_here\", \"SomeCase=HiImHere\"].join(\"&\");\n    let form: Option<MultiName<'_>> = lenient(&form_string).ok();\n    assert_eq!(form, Some(MultiName { single: 123, some_case: \"hi_im_here\", }));\n\n    let form_string = &[\"single=123\", \"SomeCase=HiImHere\", \"some_case=hi_im_here\"].join(\"&\");\n    let form: Option<MultiName<'_>> = lenient(&form_string).ok();\n    assert_eq!(form, Some(MultiName { single: 123, some_case: \"HiImHere\", }));\n\n    #[derive(Debug, PartialEq, FromForm)]\n    struct CaseInsensitive<'r> {\n        #[field(name = uncased(\"SomeCase\"))]\n        #[field(name = \"some_case\")]\n        some_case: &'r str,\n\n        #[field(name = uncased(\"hello\"))]\n        hello: usize,\n    }\n\n    let form_string = &[\"HeLLO=123\", \"sOMECASe=hi_im_here\"].join(\"&\");\n    let form: Option<CaseInsensitive<'_>> = strict(&form_string).ok();\n    assert_eq!(form, Some(CaseInsensitive { hello: 123, some_case: \"hi_im_here\", }));\n\n    let form_string = &[\"hello=456\", \"SomeCase=HiImHere\"].join(\"&\");\n    let form: Option<CaseInsensitive<'_>> = strict(&form_string).ok();\n    assert_eq!(form, Some(CaseInsensitive { hello: 456, some_case: \"HiImHere\", }));\n\n    let form_string = &[\"helLO=789\", \"some_case=hi_there\"].join(\"&\");\n    let form: Option<CaseInsensitive<'_>> = strict(&form_string).ok();\n    assert_eq!(form, Some(CaseInsensitive { hello: 789, some_case: \"hi_there\", }));\n\n    let form_string = &[\"hello=123\", \"SOme_case=hi_im_here\"].join(\"&\");\n    let form: Option<CaseInsensitive<'_>> = strict(&form_string).ok();\n    assert!(form.is_none());\n}\n\n#[test]\nfn generics() {\n    #[derive(FromForm, Debug, PartialEq)]\n    struct Oops<A, B, C> {\n        base: String,\n        a: A,\n        b: B,\n        c: C,\n    }\n\n    #[derive(FromForm, Debug, PartialEq)]\n    struct YetOneMore<'f, T> {\n        string: &'f str,\n        other: T,\n    }\n\n    let form_string = &[\n        \"string=hello\", \"other=00128\"\n    ].join(\"&\");\n\n    let form: Option<YetOneMore<'_, usize>> = strict(&form_string).ok();\n    assert_eq!(form, Some(YetOneMore {\n        string: \"hello\".into(),\n        other: 128,\n    }));\n\n    let form: Option<YetOneMore<'_, u8>> = strict(&form_string).ok();\n    assert_eq!(form, Some(YetOneMore {\n        string: \"hello\".into(),\n        other: 128,\n    }));\n\n    let form: Option<YetOneMore<'_, i8>> = strict(&form_string).ok();\n    assert!(form.is_none());\n\n    let form_string = \"base=just%20a%20test&a=hey%20there&b=a&c=811\";\n    let form: Option<Oops<String, FormOption, usize>> = strict_encoded(&form_string).ok();\n    assert_eq!(form, Some(Oops {\n        base: \"just a test\".into(),\n        a: \"hey there\".into(),\n        b: FormOption::A,\n        c: 811,\n    }));\n}\n\n#[test]\nfn form_errors() {\n    #[derive(Debug, PartialEq, FromForm)]\n    struct WhoopsForm {\n        complete: bool,\n        other: usize,\n    }\n\n    let form: Result<WhoopsForm, _> = strict(\"complete=true&other=781\");\n    assert_eq!(form, Ok(WhoopsForm { complete: true, other: 781 }));\n\n    let errors = strict::<WhoopsForm>(\"complete=true&other=unknown\").unwrap_err();\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"other\"\n            && e.value.as_deref() == Some(\"unknown\")\n            && matches!(e.kind, ErrorKind::Int(..))\n    }));\n\n    let errors = strict::<WhoopsForm>(\"complete=unknown&other=unknown\").unwrap_err();\n    assert!(errors.iter().any(|e| {\n        \"complete\" == e.name.as_ref().unwrap()\n            && e.value.as_deref() == Some(\"unknown\")\n            && matches!(e.kind, ErrorKind::Bool(..))\n    }));\n\n    let errors = strict::<WhoopsForm>(\"complete=true&other=1&extra=foo\").unwrap_err();\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"extra\"\n            && e.value.as_deref() == Some(\"foo\")\n            && matches!(e.kind, ErrorKind::Unexpected)\n    }));\n\n    let errors = strict::<WhoopsForm>(\"complete=unknown&unknown=!\").unwrap_err();\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"complete\"\n            && e.value.as_deref() == Some(\"unknown\")\n            && matches!(e.kind, ErrorKind::Bool(..))\n    }));\n\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"unknown\"\n            && e.value.as_deref() == Some(\"!\")\n            && matches!(e.kind, ErrorKind::Unexpected)\n    }));\n\n    let errors = strict::<WhoopsForm>(\"unknown=!\").unwrap_err();\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"unknown\"\n            && e.value.as_deref() == Some(\"!\")\n            && matches!(e.kind, ErrorKind::Unexpected)\n    }));\n\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"complete\"\n            && e.value.is_none()\n            && e.entity == Entity::Field\n            && matches!(e.kind, ErrorKind::Missing)\n    }));\n\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"other\"\n            && e.value.is_none()\n            && e.entity == Entity::Field\n            && matches!(e.kind, ErrorKind::Missing)\n    }));\n\n    let errors = strict::<WhoopsForm>(\"complete=true\").unwrap_err();\n    assert!(errors.iter().any(|e| {\n        e.name.as_ref().unwrap() == \"other\"\n            && e.value.is_none()\n            && e.entity == Entity::Field\n            && matches!(e.kind, ErrorKind::Missing)\n    }));\n}\n\n#[test]\nfn form_validate_error_return_correct_field_name() {\n    fn evaluate_other<'v>(_other: &str, _check: &bool) -> form::Result<'v, ()> {\n        Err(form::Error::validation(\"\"))?\n    }\n\n    #[derive(Debug, PartialEq, FromForm)]\n    struct WhoopsForm {\n        name: String,\n        check: bool,\n        // in the error context this is returned as \"name\" but should be \"other\"\n        // the problem is dependent on an argument existing for evaluate_other\n        #[field(validate = evaluate_other(&self.check))]\n        other: String,\n    }\n\n    let errors = strict::<WhoopsForm>(\"name=test&check=true&other=\").unwrap_err();\n    assert!(errors.iter().any(|e| e.name.as_ref().unwrap() == \"other\"));\n}\n\n#[test]\nfn form_validate_contains_all_errors() {\n    fn evaluate<'v>(_value: &str) -> form::Result<'v, ()> {\n        Err(form::Error::validation(\"\"))?\n    }\n\n    fn evaluate_with_argument<'v>(_value: &str, _check: bool) -> form::Result<'v, ()> {\n        Err(form::Error::validation(\"lastname failed\"))?\n    }\n\n    #[derive(Debug, PartialEq, FromForm)]\n    struct WhoopsForm {\n        #[field(validate = evaluate())]\n        firstname: String,\n        check: bool,\n        // this validator is hardcoded to return an error but it doesn't\n        #[field(validate = evaluate_with_argument(self.check))]\n        lastname: String,\n    }\n\n    let errors = strict::<WhoopsForm>(\"firstname=&check=true&lastname=\").unwrap_err();\n    assert!(errors.iter().any(|e| e.name.as_ref().unwrap() == \"lastname\"));\n    assert!(errors.iter().any(|e| e.name.as_ref().unwrap() == \"firstname\"));\n}\n\n#[test]\nfn raw_ident_form() {\n    #[derive(Debug, PartialEq, FromForm)]\n    struct RawIdentForm {\n        r#type: String,\n    }\n\n    let form: Result<RawIdentForm, _> = strict(\"type=a\");\n    assert_eq!(form, Ok(RawIdentForm { r#type: \"a\".into() }));\n}\n\n#[test]\nfn test_multi() {\n    use std::collections::HashMap;\n\n    #[derive(Debug, PartialEq, FromForm)]\n    struct Multi<'r> {\n        checks: Vec<bool>,\n        names: Vec<&'r str>,\n        news: Vec<String>,\n        dogs: HashMap<String, Dog>,\n        #[field(name = \"more:dogs\")]\n        more_dogs: HashMap<&'r str, Dog>,\n    }\n\n    let multi: Multi<'_> = strict(\"checks=true&checks=false&checks=false\\\n        &names=Sam&names[]=Smith&names[]=Bob\\\n        &news[]=Here&news[]=also here\\\n        &dogs[fido].barks=true&dogs[George].barks=false\\\n        &dogs[fido].trained=on&dogs[George].trained=yes\\\n        &dogs[bob boo].trained=no&dogs[bob boo].barks=off\\\n        &more:dogs[k:0]=My Dog&more:dogs[v:0].barks=true&more:dogs[v:0].trained=yes\\\n    \").unwrap();\n    assert_eq!(multi, Multi {\n        checks: vec![true, false, false],\n        names: vec![\"Sam\".into(), \"Smith\".into(), \"Bob\".into()],\n        news: vec![\"Here\".into(), \"also here\".into()],\n        dogs: {\n            let mut map = HashMap::new();\n            map.insert(\"fido\".into(), Dog { barks: true, trained: true });\n            map.insert(\"George\".into(), Dog { barks: false, trained: true });\n            map.insert(\"bob boo\".into(), Dog { barks: false, trained: false });\n            map\n        },\n        more_dogs: {\n            let mut map = HashMap::new();\n            map.insert(\"My Dog\".into(), Dog { barks: true, trained: true });\n            map\n        }\n    });\n\n    #[derive(Debug, PartialEq, FromForm)]\n    struct MultiOwned {\n        names: Vec<String>,\n    }\n\n    let raw = \"names=Sam&names%5B%5D=Smith&names%5B%5D=Bob%20Smith%3F\";\n    let multi: MultiOwned = strict_encoded(raw).unwrap();\n    assert_eq!(multi, MultiOwned {\n        names: vec![\"Sam\".into(), \"Smith\".into(), \"Bob Smith?\".into()],\n    });\n}\n\n#[derive(Debug, FromForm, PartialEq)]\nstruct Dog {\n    barks: bool,\n    trained: bool,\n}\n\n#[derive(Debug, FromForm, PartialEq)]\nstruct Cat<'r> {\n    nip: &'r str,\n    meows: bool\n}\n\n#[derive(Debug, FromForm, PartialEq)]\nstruct Pet<'r, T> {\n    pet: T,\n    name: &'r str,\n    age: u8\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct Person<'r> {\n    dogs: Vec<Pet<'r, Dog>>,\n    cats: Vec<Pet<'r, Cat<'r>>>,\n    sitting: Dog,\n}\n\n#[test]\nfn test_nested_multi() {\n    let person: Person<'_> = lenient(\"sitting.barks=true&sitting.trained=true\").unwrap();\n    assert_eq!(person, Person {\n        sitting: Dog { barks: true, trained: true },\n        cats: vec![],\n        dogs: vec![],\n    });\n\n    let person = strict::<Person<'_>>(\"sitting.barks=true&sitting.trained=true\");\n    assert!(person.is_err());\n\n    let person: Person<'_> = lenient(\"sitting.barks=true&sitting.trained=true\\\n        &dogs[0].name=fido&dogs[0].pet.trained=yes&dogs[0].age=7&dogs[0].pet.barks=no\\\n    \").unwrap();\n    assert_eq!(person, Person {\n        sitting: Dog { barks: true, trained: true },\n        cats: vec![],\n        dogs: vec![Pet {\n            pet: Dog { barks: false, trained: true },\n            name: \"fido\".into(),\n            age: 7\n        }]\n    });\n\n    let person = strict::<Person<'_>>(\"sitting.barks=true&sitting.trained=true\\\n        &dogs[0].name=fido&dogs[0].pet.trained=yes&dogs[0].age=7&dogs[0].pet.barks=no\");\n    assert!(person.is_err());\n\n    let person: Person<'_> = lenient(\"sitting.trained=no&sitting.barks=true\\\n        &dogs[0].name=fido&dogs[0].pet.trained=yes&dogs[0].age=7&dogs[0].pet.barks=no\\\n        &dogs[1].pet.barks=true&dogs[1].name=Bob&dogs[1].pet.trained=no&dogs[1].age=1\\\n    \").unwrap();\n    assert_eq!(person, Person {\n        sitting: Dog { barks: true, trained: false },\n        cats: vec![],\n        dogs: vec![\n            Pet {\n                pet: Dog { barks: false, trained: true },\n                name: \"fido\".into(),\n                age: 7\n            },\n            Pet {\n                pet: Dog { barks: true, trained: false },\n                name: \"Bob\".into(),\n                age: 1\n            },\n        ]\n    });\n\n    let person: Person<'_> = strict(\"sitting.barks=true&sitting.trained=no\\\n        &dogs[0].name=fido&dogs[0].pet.trained=yes&dogs[0].age=7&dogs[0].pet.barks=no\\\n        &dogs[1].pet.barks=true&dogs[1].name=Bob&dogs[1].pet.trained=no&dogs[1].age=1\\\n        &cats[george].pet.nip=paws&cats[george].name=George&cats[george].age=2\\\n        &cats[george].pet.meows=yes\\\n    \").unwrap();\n    assert_eq!(person, Person {\n        sitting: Dog { barks: true, trained: false },\n        cats: vec![\n            Pet {\n                pet: Cat { nip: \"paws\".into(), meows: true },\n                name: \"George\".into(),\n                age: 2\n            }\n        ],\n        dogs: vec![\n            Pet {\n                pet: Dog { barks: false, trained: true },\n                name: \"fido\".into(),\n                age: 7\n            },\n            Pet {\n                pet: Dog { barks: true, trained: false },\n                name: \"Bob\".into(),\n                age: 1\n            },\n        ]\n    });\n}\n\n#[test]\nfn test_multipart() {\n    use rocket::http::ContentType;\n    use rocket::local::blocking::Client;\n    use rocket::fs::TempFile;\n\n    #[derive(FromForm)]\n    struct MyForm<'r> {\n        names: Vec<&'r str>,\n        file: TempFile<'r>,\n    }\n\n    #[rocket::post(\"/\", data = \"<form>\")]\n    fn form(form: Form<MyForm<'_>>) {\n        assert_eq!(form.names, &[\"abcd\", \"123\"]);\n        assert_eq!(form.file.name(), Some(\"foo\"));\n    }\n\n    let client = Client::debug_with(rocket::routes![form]).unwrap();\n    let ct = \"multipart/form-data; boundary=X-BOUNDARY\"\n        .parse::<ContentType>()\n        .unwrap();\n\n    let body = &[\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"names[]\"\"#,\n        \"\",\n        \"abcd\",\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"names[]\"\"#,\n        \"\",\n        \"123\",\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"file\"; filename=\"foo.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"hi there\",\n        \"--X-BOUNDARY--\",\n        \"\",\n    ].join(\"\\r\\n\");\n\n    let response = client.post(\"/\")\n        .header(ct)\n        .body(body)\n        .dispatch();\n\n    assert!(response.status().class().is_success());\n}\n\n#[test]\nfn test_default_removed() {\n    #[derive(FromForm, PartialEq, Debug)]\n    struct FormNoDefault {\n        #[field(default = None)]\n        field1: bool,\n        #[field(default = None)]\n        field2: Option<usize>,\n        #[field(default = None)]\n        field3: Option<Option<usize>>,\n        #[field(default_with = None)]\n        field4: bool,\n    }\n\n    let form_string = &[\"field1=false\", \"field2=10\", \"field3=23\", \"field4\"].join(\"&\");\n    let form1: Option<FormNoDefault> = lenient(&form_string).ok();\n    assert_eq!(form1, Some(FormNoDefault {\n        field1: false,\n        field2: Some(10),\n        field3: Some(Some(23)),\n        field4: true,\n    }));\n\n    let form_string = &[\"field1=true\", \"field2=10\", \"field3=23\", \"field4\"].join(\"&\");\n    let form1: Option<FormNoDefault> = lenient(&form_string).ok();\n    assert_eq!(form1, Some(FormNoDefault {\n        field1: true,\n        field2: Some(10),\n        field3: Some(Some(23)),\n        field4: true,\n    }));\n\n    // Field 1 missing.\n    let form_string = &[\"field2=20\", \"field3=10\", \"field4\"].join(\"&\");\n    assert!(lenient::<FormNoDefault>(&form_string).is_err());\n\n    // Field 2 missing.\n    let form_string = &[\"field1=true\", \"field3=10\", \"field4\"].join(\"&\");\n    assert!(lenient::<FormNoDefault>(&form_string).is_err());\n\n    // Field 3 missing.\n    let form_string = &[\"field1=true\", \"field2=10\", \"field4=false\"].join(\"&\");\n    assert!(lenient::<FormNoDefault>(&form_string).is_err());\n\n    // Field 4 missing.\n    let form_string = &[\"field1=true\", \"field2=10\", \"field3=23\"].join(\"&\");\n    assert!(lenient::<FormNoDefault>(&form_string).is_err());\n}\n\n#[test]\nfn test_defaults() {\n    fn test_hashmap() -> HashMap<&'static str, &'static str> {\n        let mut map = HashMap::new();\n        map.insert(\"key\", \"value\");\n        map.insert(\"one-more\", \"good-value\");\n        map\n    }\n\n    fn test_btreemap() -> BTreeMap<Vec<usize>, &'static str> {\n        let mut map = BTreeMap::new();\n        map.insert(vec![1], \"empty\");\n        map.insert(vec![1, 2], \"one-and-two\");\n        map.insert(vec![3, 7, 9], \"prime\");\n        map\n    }\n\n    #[derive(FromForm, UriDisplayQuery, PartialEq, Debug)]\n    struct FormWithDefaults<'a> {\n        field2: i128,\n        field5: bool,\n\n        #[field(default = 100)]\n        field1: usize,\n        #[field(default = true)]\n        field3: bool,\n        #[field(default = false)]\n        field4: bool,\n        #[field(default = 254 + 1)]\n        field6: u8,\n        #[field(default = Some(true))]\n        opt1: Option<bool>,\n        #[field(default = false)]\n        opt2: Option<bool>,\n        #[field(default = Ok(\"hello\".into()))]\n        res: form::Result<'a, String>,\n        #[field(default = Ok(\"hello\"))]\n        res2: form::Result<'a, &'a str>,\n        #[field(default = vec![1, 2, 3])]\n        vec_num: Vec<usize>,\n        #[field(default = vec![\"wow\", \"a\", \"string\", \"nice\"])]\n        vec_str: Vec<&'a str>,\n        #[field(default = test_hashmap())]\n        hashmap: HashMap<&'a str, &'a str>,\n        #[field(default = test_btreemap())]\n        btreemap: BTreeMap<Vec<usize>, &'a str>,\n        #[field(default_with = Some(false))]\n        boolean: bool,\n        #[field(default_with = (|| Some(777))())]\n        unsigned: usize,\n        #[field(default = std::num::NonZeroI32::new(3).unwrap())]\n        nonzero: std::num::NonZeroI32,\n        #[field(default_with = std::num::NonZeroI32::new(9001))]\n        nonzero2: std::num::NonZeroI32,\n        #[field(default = 3.0)]\n        float: f64,\n        #[field(default = \"wow\")]\n        str_ref: &'a str,\n        #[field(default = \"wowie\")]\n        string: String,\n        #[field(default = [192u8, 168, 1, 0])]\n        ip: IpAddr,\n        #[field(default = ([192u8, 168, 1, 0], 20))]\n        addr: SocketAddr,\n        #[field(default = time::macros::date!(2021-05-27))]\n        date: time::Date,\n        #[field(default = time::macros::time!(01:15:00))]\n        time: time::Time,\n        #[field(default = time::PrimitiveDateTime::new(\n            time::macros::date!(2021-05-27),\n            time::macros::time!(01:15:00),\n        ))]\n        datetime: time::PrimitiveDateTime,\n    }\n\n    // `field2` has no default.\n    assert!(lenient::<FormWithDefaults<'_>>(\"\").is_err());\n\n    // every other field should.\n    let form_string = &[\"field2=102\"].join(\"&\");\n    let form1: Option<FormWithDefaults<'_>> = lenient(&form_string).ok();\n    assert_eq!(form1, Some(FormWithDefaults {\n        field1: 100,\n        field2: 102,\n        field3: true,\n        field4: false,\n        field5: false,\n        field6: 255,\n        opt1: Some(true),\n        opt2: Some(false),\n        res: Ok(\"hello\".into()),\n        res2: Ok(\"hello\"),\n        vec_num: vec![1, 2, 3],\n        vec_str: vec![\"wow\", \"a\", \"string\", \"nice\"],\n        hashmap: test_hashmap(),\n        btreemap: test_btreemap(),\n        boolean: false,\n        unsigned: 777,\n        nonzero: std::num::NonZeroI32::new(3).unwrap(),\n        nonzero2: std::num::NonZeroI32::new(9001).unwrap(),\n        float: 3.0,\n        str_ref: \"wow\",\n        string: \"wowie\".to_string(),\n        ip: [192u8, 168, 1, 0].into(),\n        addr: ([192u8, 168, 1, 0], 20).into(),\n        date: time::macros::date!(2021-05-27),\n        time: time::macros::time!(01:15:00),\n        datetime: time::PrimitiveDateTime::new(\n            time::macros::date!(2021-05-27),\n            time::macros::time!(01:15:00)\n        ),\n    }));\n\n    let form2: Option<FormWithDefaults<'_>> = strict(&form_string).ok();\n    assert!(form2.is_none());\n\n    // Ensure actual form field values take precedence.\n    let form_string = &[\"field1=101\", \"field2=102\", \"field3=true\", \"field5=true\"].join(\"&\");\n    let form3: Option<FormWithDefaults<'_>> = lenient(&form_string).ok();\n    assert_eq!(form3, Some(FormWithDefaults {\n        field1: 101,\n        field2: 102,\n        field3: true,\n        field4: false,\n        field5: true,\n        ..form1.unwrap()\n    }));\n\n    // And that strict parsing still works.\n    let form = form3.unwrap();\n    let form_string = format!(\"{}\", &form as &dyn UriDisplay<Query>);\n    let form4: form::Result<'_, FormWithDefaults<'_>> = strict(&form_string);\n    assert_eq!(form4, Ok(form), \"parse from {}\", form_string);\n\n    #[derive(FromForm, UriDisplayQuery, PartialEq, Debug)]\n    struct OwnedFormWithDefaults {\n        #[field(default = {\n            let mut map = BTreeMap::new();\n            map.insert(vec![], \"empty!/!? neat\".into());\n            map.insert(vec![1, 2], \"one/ and+two\".into());\n            map.insert(vec![3, 7, 9], \"prime numbers\".into());\n            map\n        })]\n        btreemap: BTreeMap<Vec<usize>, String>,\n    }\n\n    let form5: Option<OwnedFormWithDefaults> = lenient(\"\").ok();\n    assert_eq!(form5, Some(OwnedFormWithDefaults {\n        btreemap: {\n            let mut map = BTreeMap::new();\n            map.insert(vec![3, 7, 9], \"prime numbers\".into());\n            map.insert(vec![1, 2], \"one/ and+two\".into());\n            map.insert(vec![], \"empty!/!? neat\".into());\n            map\n        }\n    }));\n\n    // And that strict parsing still works even when encoded. We add one value\n    // to the empty vec because it would not parse as `strict` otherwise.\n    let mut form = form5.unwrap();\n    form.btreemap.remove(&vec![]);\n    let form_string = format!(\"{}\", &form as &dyn UriDisplay<Query>);\n    let form6: form::Result<'_, OwnedFormWithDefaults> = strict_encoded(&form_string);\n    assert_eq!(form6, Ok(form));\n}\n\n#[test]\nfn test_lazy_default() {\n    use std::sync::atomic::{AtomicUsize, Ordering};\n\n    static VAL: AtomicUsize = AtomicUsize::new(40);\n\n    fn f() -> usize {\n        VAL.fetch_add(1, Ordering::Relaxed)\n    }\n\n    fn opt_f() -> Option<usize> {\n        Some(f())\n    }\n\n    #[derive(Debug, PartialEq, FromForm)]\n    struct MyForm {\n        #[field(default = f())]\n        missing0: usize,\n        #[field(default = VAL.load(Ordering::Relaxed))]\n        missing1: usize,\n        #[field(default_with = opt_f())]\n        missing2: usize,\n        #[field(default_with = opt_f())]\n        a: usize,\n        #[field(default = f())]\n        b: usize,\n        #[field(default = VAL.load(Ordering::Relaxed))]\n        missing3: usize,\n    }\n\n    // Ensure actual form field values take precedence.\n    let form_string = &[\"a=100\", \"b=300\"].join(\"&\");\n    let form3: Option<MyForm> = lenient(&form_string).ok();\n    assert_eq!(form3, Some(MyForm {\n        missing0: 40,\n        missing1: 41,\n        missing2: 41,\n        a: 100,\n        b: 300,\n        missing3: 42\n    }));\n}\n\n#[derive(Debug, PartialEq, FromForm, UriDisplayQuery)]\n#[field(validate = len(3..), default = \"some default hello\")]\nstruct Token<'r>(&'r str);\n\n#[derive(Debug, PartialEq, FromForm, UriDisplayQuery)]\n#[field(validate = try_with(|s| s.parse::<usize>()), default = \"123456\")]\nstruct TokenOwned(String);\n\n#[test]\nfn wrapper_works() {\n    let form: Option<Token<'_>> = lenient(\"\").ok();\n    assert_eq!(form, Some(Token(\"some default hello\")));\n\n    let form: Option<TokenOwned> = lenient(\"\").ok();\n    assert_eq!(form, Some(TokenOwned(\"123456\".into())));\n\n    let errors = strict::<Token<'_>>(\"\").unwrap_err();\n    assert!(errors.iter().any(|e| matches!(e.kind, ErrorKind::Missing)));\n\n    let form: Option<Token<'_>> = lenient(\"=hi there\").ok();\n    assert_eq!(form, Some(Token(\"hi there\")));\n\n    let form: Option<TokenOwned> = strict_encoded(\"=2318\").ok();\n    assert_eq!(form, Some(TokenOwned(\"2318\".into())));\n\n    let errors = lenient::<Token<'_>>(\"=hi\").unwrap_err();\n    assert!(errors.iter().any(|e| matches!(e.kind, ErrorKind::InvalidLength { .. })));\n\n    let errors = lenient::<TokenOwned>(\"=hellothere\").unwrap_err();\n    assert!(errors.iter().any(|e| matches!(e.kind, ErrorKind::Validation { .. })));\n}\n\n#[derive(Debug, PartialEq, FromForm, UriDisplayQuery)]\nstruct JsonToken<T>(Json<T>);\n\n#[test]\nfn json_wrapper_works() {\n    let form: JsonToken<String> = lenient(\"=\\\"hello\\\"\").unwrap();\n    assert_eq!(form, JsonToken(Json(\"hello\".into())));\n\n    let form: JsonToken<usize> = lenient(\"=10\").unwrap();\n    assert_eq!(form, JsonToken(Json(10)));\n\n    let form: JsonToken<()> = lenient(\"=null\").unwrap();\n    assert_eq!(form, JsonToken(Json(())));\n\n    let form: JsonToken<Vec<usize>> = lenient(\"=[1, 4, 3, 9]\").unwrap();\n    assert_eq!(form, JsonToken(Json(vec![1, 4, 3, 9])));\n\n    let string = String::from(\"=\\\"foo bar\\\"\");\n    let form: JsonToken<&str> = lenient(&string).unwrap();\n    assert_eq!(form, JsonToken(Json(\"foo bar\")));\n}\n\n#[allow(renamed_and_removed_lints)]\n#[allow(private_in_public)]\nstruct Q<T>(T);\n\n// This is here to ensure we don't warn, which we can't test with trybuild.\n#[derive(FromForm)]\npub struct JsonTokenBad<T>(Q<T>);\n\n#[test]\nfn range() {\n    use std::ops::{Range, RangeFrom, RangeTo, RangeToInclusive};\n\n    let range: Range<usize> = strict(\"start=1&end=2\").unwrap();\n    assert_eq!(range, Range { start: 1, end: 2 });\n\n    let range: Range<isize> = strict_encoded(\"start=-1&end=2\").unwrap();\n    assert_eq!(range, Range { start: -1, end: 2 });\n\n    let range: Range<isize> = strict(\"start=-1&end=-95\").unwrap();\n    assert_eq!(range, Range { start: -1, end: -95 });\n\n    let range: Range<isize> = strict_encoded(\"start=-1&end=-95\").unwrap();\n    assert_eq!(range, Range { start: -1, end: -95 });\n\n    let range: RangeFrom<char> = strict(\"start=a\").unwrap();\n    assert_eq!(range, RangeFrom { start: 'a' });\n\n    let range: RangeTo<char> = strict(\"end=z\").unwrap();\n    assert_eq!(range, RangeTo { end: 'z' });\n\n    let range: RangeToInclusive<u8> = strict(\"end=255\").unwrap();\n    assert_eq!(range, RangeToInclusive { end: 255 });\n\n    // now with compound, non-Step values\n    let form_string = &[\"start.start=0\", \"start.end=1\", \"end.start=1\", \"end.end=2\"].join(\"&\");\n    let range: Range<Range<usize>> = strict(&form_string).unwrap();\n    assert_eq!(range, Range {\n        start: Range { start: 0, end : 1},\n        end: Range { start: 1, end : 2 }\n    });\n\n    let form_string = &[\n        \"start.description=some%20task\",\n        \"start.completed=false\",\n        \"end.description=yet%20more%20work\",\n        \"end.completed=true\",\n    ].join(\"&\");\n\n    let range: Range<TodoTask> = strict_encoded(form_string).unwrap();\n    assert_eq!(range, Range {\n        start: TodoTask { description: \"some task\".into(), completed: false, },\n        end: TodoTask { description: \"yet more work\".into(), completed: true, },\n    });\n}\n"
  },
  {
    "path": "core/codegen/tests/from_form_field.rs",
    "content": "use rocket::form::{FromFormField, ValueField, FromForm, Options, Errors};\n\nfn parse<'v, T: FromForm<'v>>(value: &'v str) -> Result<T, Errors<'v>> {\n    let mut context = T::init(Options::Lenient);\n    T::push_value(&mut context, ValueField::from_value(value));\n    T::finalize(context)\n}\n\nmacro_rules! assert_parse {\n    ($($string:expr),* => $item:ident :: $variant:ident) => ($(\n        match parse::<$item>($string) {\n            Ok($item::$variant) => { /* okay */ },\n            Ok(item) => panic!(\"Failed to parse {} as {:?}. Got {:?} instead.\",\n                               $string, $item::$variant, item),\n            Err(e) => panic!(\"Failed to parse {} as {}: {}\",\n                             $string, stringify!($item), e),\n\n        }\n    )*)\n}\n\nmacro_rules! assert_no_parse {\n    ($($string:expr),* => $item:ident) => ($(\n        match parse::<$item>($string) {\n            Err(_) => { /* okay */ },\n            Ok(item) => panic!(\"Unexpectedly parsed {} as {:?}\", $string, item)\n        }\n    )*)\n}\n\n#[test]\nfn from_form_value_simple() {\n    #[derive(Debug, FromFormField)]\n    enum Foo { A, B, C, }\n\n    assert_parse!(\"a\", \"A\" => Foo::A);\n    assert_parse!(\"b\", \"B\" => Foo::B);\n    assert_parse!(\"c\", \"C\" => Foo::C);\n}\n\n#[test]\nfn from_form_value_weirder() {\n    #[allow(non_camel_case_types)]\n    #[derive(Debug, FromFormField)]\n    enum Foo { Ab_Cd, OtherA }\n\n    assert_parse!(\"ab_cd\", \"ab_CD\", \"Ab_CD\" => Foo::Ab_Cd);\n    assert_parse!(\"othera\", \"OTHERA\", \"otherA\", \"OtherA\" => Foo::OtherA);\n}\n\n#[test]\nfn from_form_value_no_parse() {\n    #[derive(Debug, FromFormField)]\n    enum Foo { A, B, C, }\n\n    assert_no_parse!(\"abc\", \"ab\", \"bc\", \"ca\" => Foo);\n    assert_no_parse!(\"b \", \"a \", \"c \", \"a b\" => Foo);\n}\n\n#[test]\nfn from_form_value_renames() {\n    #[derive(Debug, FromFormField)]\n    enum Foo {\n        #[field(value = \"foo\")]\n        #[field(value = \"bark\")]\n        Bar,\n        #[field(value = \":book\")]\n        Book\n    }\n\n    assert_parse!(\"foo\", \"FOO\", \"FoO\", \"bark\", \"BARK\", \"BaRk\" => Foo::Bar);\n    assert_parse!(\":book\", \":BOOK\", \":bOOk\", \":booK\" => Foo::Book);\n    assert_no_parse!(\"book\", \"bar\" => Foo);\n}\n\n#[test]\nfn from_form_value_raw() {\n    #[allow(non_camel_case_types)]\n    #[derive(Debug, FromFormField)]\n    enum Keyword {\n        r#type,\n        this,\n    }\n\n    assert_parse!(\"type\", \"tYpE\" => Keyword::r#type);\n    assert_parse!(\"this\" => Keyword::this);\n    assert_no_parse!(\"r#type\" => Keyword);\n}\n\n#[test]\nfn form_value_errors() {\n    use rocket::form::error::{ErrorKind, Entity};\n\n    #[derive(Debug, FromFormField)]\n    enum Foo { Bar, Bob }\n\n    let errors = parse::<Foo>(\"blob\").unwrap_err();\n    assert!(errors.iter().any(|e| {\n        && \"blob\" == &e.value.as_ref().unwrap()\n        && e.entity == Entity::Value\n        && match &e.kind {\n            ErrorKind::InvalidChoice { choices } => &choices[..] == &[\"Bar\", \"Bob\"],\n            _ => false\n        }\n    }));\n}\n"
  },
  {
    "path": "core/codegen/tests/from_param.rs",
    "content": "use rocket::request::FromParam;\n\n#[allow(non_camel_case_types)]\n#[derive(Debug, FromParam, PartialEq)]\nenum Test {\n    Test1,\n    Test2,\n    r#for,\n}\n\n#[test]\nfn derive_from_param() {\n    assert_eq!(Test::from_param(\"Test1\").unwrap(), Test::Test1);\n    assert_eq!(Test::from_param(\"Test2\").unwrap(), Test::Test2);\n    assert_eq!(Test::from_param(\"for\").unwrap(), Test::r#for);\n\n    let err = Test::from_param(\"For\").unwrap_err();\n    assert_eq!(err.value, \"For\");\n    assert_eq!(err.options, &[\"Test1\", \"Test2\", \"for\"]);\n\n    let err = Test::from_param(\"not_test\").unwrap_err();\n    assert_eq!(err.value, \"not_test\");\n    assert_eq!(err.options, &[\"Test1\", \"Test2\", \"for\"]);\n\n}\n"
  },
  {
    "path": "core/codegen/tests/responder.rs",
    "content": "use rocket::local::asynchronous::Client;\nuse rocket::http::{Status, ContentType, Cookie};\nuse rocket::response::Responder;\nuse rocket::serde::json::Json;\nuse rocket::http::Accept;\n\n#[derive(Responder)]\npub enum Foo<'r> {\n    First(String),\n    #[response(status = 500)]\n    Second(Vec<u8>),\n    #[response(status = 404, content_type = \"html\")]\n    Third {\n        responder: &'r str,\n        ct: rocket::http::ContentType,\n    },\n    #[response(status = 105)]\n    Fourth {\n        string: &'r str,\n        ct: rocket::http::ContentType,\n    },\n}\n\n#[rocket::async_test]\nasync fn responder_foo() {\n    let client = Client::debug_with(vec![]).await.expect(\"valid rocket\");\n    let local_req = client.get(\"/\");\n    let req = local_req.inner();\n\n    let mut r = Foo::First(\"hello\".into())\n        .respond_to(req)\n        .expect(\"response okay\");\n\n    assert_eq!(r.status(), Status::Ok);\n    assert_eq!(r.content_type(), Some(ContentType::Plain));\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"hello\");\n\n    let mut r = Foo::Second(\"just a test\".into())\n        .respond_to(req)\n        .expect(\"response okay\");\n\n    assert_eq!(r.status(), Status::InternalServerError);\n    assert_eq!(r.content_type(), Some(ContentType::Binary));\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"just a test\");\n\n    let mut r = Foo::Third { responder: \"well, hi\", ct: ContentType::JSON }\n        .respond_to(req)\n        .expect(\"response okay\");\n\n    assert_eq!(r.status(), Status::NotFound);\n    assert_eq!(r.content_type(), Some(ContentType::HTML));\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"well, hi\");\n\n    let mut r = Foo::Fourth { string: \"goodbye\", ct: ContentType::JSON }\n        .respond_to(req)\n        .expect(\"response okay\");\n\n    assert_eq!(r.status().code, 105);\n    assert_eq!(r.content_type(), Some(ContentType::JSON));\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"goodbye\");\n}\n\n#[derive(Responder)]\n#[response(content_type = \"plain\")]\npub struct Bar<'r> {\n    responder: Foo<'r>,\n    other: ContentType,\n    third: Cookie<'static>,\n    #[response(ignore)]\n    _yet_another: String,\n}\n\n#[rocket::async_test]\nasync fn responder_bar() {\n    let client = Client::debug_with(vec![]).await.expect(\"valid rocket\");\n    let local_req = client.get(\"/\");\n    let req = local_req.inner();\n\n    let mut r = Bar {\n        responder: Foo::Second(\"foo foo\".into()),\n        other: ContentType::HTML,\n        third: Cookie::new(\"cookie\", \"here!\"),\n        _yet_another: \"uh..hi?\".into()\n    }.respond_to(req).expect(\"response okay\");\n\n    assert_eq!(r.status(), Status::InternalServerError);\n    assert_eq!(r.content_type(), Some(ContentType::Plain));\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"foo foo\");\n    assert_eq!(r.headers().get_one(\"Set-Cookie\"), Some(\"cookie=here!\"));\n}\n\n#[derive(Responder)]\n#[response(content_type = \"application/x-custom\")]\npub struct Baz {\n    responder: &'static str,\n}\n\n#[rocket::async_test]\nasync fn responder_baz() {\n    let client = Client::debug_with(vec![]).await.expect(\"valid rocket\");\n    let local_req = client.get(\"/\");\n    let req = local_req.inner();\n\n    let mut r = Baz { responder: \"just a custom\" }\n        .respond_to(req)\n        .expect(\"response okay\");\n\n    assert_eq!(r.status(), Status::Ok);\n    assert_eq!(r.content_type(), Some(ContentType::new(\"application\", \"x-custom\")));\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"just a custom\");\n}\n\n// The bounds `Json<T>: Responder, E: Responder` will be added to the generated\n// implementation. This would fail to compile otherwise.\n#[derive(Responder)]\nenum MyResult<'a, T, E, H1, H2> {\n    Ok(Json<T>),\n    #[response(status = 404)]\n    Err(E, H1, H2),\n    #[response(status = 500)]\n    Other(&'a str),\n}\n\n#[rocket::async_test]\nasync fn generic_responder() {\n    let client = Client::debug_with(vec![]).await.expect(\"valid rocket\");\n    let local_req = client.get(\"/\");\n    let req = local_req.inner();\n\n    let v: MyResult<'_, _, (), ContentType, Cookie<'static>> = MyResult::Ok(Json(\"hi\"));\n    let mut r = v.respond_to(req).unwrap();\n    assert_eq!(r.status(), Status::Ok);\n    assert_eq!(r.content_type().unwrap(), ContentType::JSON);\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"\\\"hi\\\"\");\n\n    let bytes = &[7, 13, 23];\n    let v: MyResult<'_, (), &[u8], _, _> = MyResult::Err(bytes, ContentType::JPEG, Accept::Text);\n    let mut r = v.respond_to(req).unwrap();\n    assert_eq!(r.status(), Status::NotFound);\n    assert_eq!(r.content_type().unwrap(), ContentType::JPEG);\n    assert_eq!(r.body_mut().to_bytes().await.unwrap(), bytes);\n\n    let v: MyResult<'_, (), &[u8], ContentType, Accept> = MyResult::Other(\"beep beep\");\n    let mut r = v.respond_to(req).unwrap();\n    assert_eq!(r.status(), Status::InternalServerError);\n    assert_eq!(r.content_type().unwrap(), ContentType::Text);\n    assert_eq!(r.body_mut().to_string().await.unwrap(), \"beep beep\");\n}\n"
  },
  {
    "path": "core/codegen/tests/route-data.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::{Request, Data};\nuse rocket::local::blocking::Client;\nuse rocket::data::{self, FromData};\nuse rocket::http::ContentType;\nuse rocket::form::Form;\n\n// Test that the data parameters works as expected.\n\n#[derive(FromForm)]\nstruct Inner<'r> {\n    field: &'r str\n}\n\nstruct Simple<'r>(&'r str);\n\n#[async_trait]\nimpl<'r> FromData<'r> for Simple<'r> {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {\n        <&'r str>::from_data(req, data).await.map(Simple)\n    }\n}\n\n#[post(\"/f\", data = \"<form>\")]\nfn form<'r>(form: Form<Inner<'r>>) -> &'r str { form.into_inner().field }\n\n#[post(\"/s\", data = \"<simple>\")]\nfn simple<'r>(simple: Simple<'r>) -> &'r str { simple.0 }\n\n#[test]\nfn test_data() {\n    let rocket = rocket::build().mount(\"/\", routes![form, simple]);\n    let client = Client::debug(rocket).unwrap();\n\n    let response = client.post(\"/f\")\n        .header(ContentType::Form)\n        .body(\"field=this%20is%20here\")\n        .dispatch();\n\n    assert_eq!(response.into_string().unwrap(), \"this is here\");\n\n    let response = client.post(\"/s\").body(\"this is here\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"this is here\");\n\n    let response = client.post(\"/s\").body(\"this%20is%20here\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"this%20is%20here\");\n}\n"
  },
  {
    "path": "core/codegen/tests/route-format.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::local::blocking::Client;\nuse rocket::http::{ContentType, MediaType, Accept, Status};\n\n// Test that known formats work as expected, including not colliding.\n\n#[post(\"/\", format = \"json\")]\nfn json() -> &'static str { \"json\" }\n\n#[post(\"/\", format = \"xml\")]\nfn xml() -> &'static str { \"xml\" }\n\n// Unreachable. Written for codegen.\n#[post(\"/\", format = \"application/json\", rank = 2)]\nfn json_long() -> &'static str { \"json_long\" }\n\n#[post(\"/\", format = \"application/msgpack\")]\nfn msgpack_long() -> &'static str { \"msgpack_long\" }\n\n// Unreachable. Written for codegen.\n#[post(\"/\", format = \"msgpack\", rank = 2)]\nfn msgpack() -> &'static str { \"msgpack\" }\n\n#[get(\"/\", format = \"plain\")]\nfn plain() -> &'static str { \"plain\" }\n\n#[get(\"/\", format = \"binary\", rank = 2)]\nfn binary() -> &'static str { \"binary\" }\n\n#[get(\"/\", rank = 3)]\nfn other() -> &'static str { \"other\" }\n\n#[test]\nfn test_formats() {\n    let rocket = rocket::build()\n        .mount(\"/\", routes![json, xml, json_long, msgpack_long, msgpack,\n               plain, binary, other]);\n\n    let client = Client::debug(rocket).unwrap();\n\n    let response = client.post(\"/\").header(ContentType::JSON).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"json\");\n\n    let response = client.post(\"/\").header(ContentType::MsgPack).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"msgpack_long\");\n\n    let response = client.post(\"/\").header(ContentType::XML).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"xml\");\n\n    let response = client.get(\"/\").header(Accept::Plain).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"plain\");\n\n    let response = client.get(\"/\").header(Accept::Binary).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"binary\");\n\n    let response = client.get(\"/\").header(ContentType::JSON).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"plain\");\n\n    let response = client.get(\"/\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"plain\");\n\n    let response = client.put(\"/\").header(ContentType::HTML).dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n}\n\n// Test custom formats.\n\n#[suppress(unknown_format)]\n#[get(\"/\", format = \"application/foo\")]\nfn get_foo() -> &'static str { \"get_foo\" }\n\n#[suppress(unknown_format)]\n#[post(\"/\", format = \"application/foo\")]\nfn post_foo() -> &'static str { \"post_foo\" }\n\n#[suppress(unknown_format)]\n#[get(\"/\", format = \"bar/baz\", rank = 2)]\nfn get_bar_baz() -> &'static str { \"get_bar_baz\" }\n\n#[suppress(unknown_format)]\n#[put(\"/\", format = \"bar/baz\")]\nfn put_bar_baz() -> &'static str { \"put_bar_baz\" }\n\n#[test]\nfn test_custom_formats() {\n    let rocket = rocket::build()\n        .mount(\"/\", routes![get_foo, post_foo, get_bar_baz, put_bar_baz]);\n\n    let client = Client::debug(rocket).unwrap();\n\n    let foo_a = Accept::new([MediaType::new(\"application\", \"foo\")]);\n    let foo_ct = ContentType::new(\"application\", \"foo\");\n    let bar_baz_ct = ContentType::new(\"bar\", \"baz\");\n    let bar_baz_a = Accept::new([MediaType::new(\"bar\", \"baz\")]);\n\n    let response = client.get(\"/\").header(foo_a).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"get_foo\");\n\n    let response = client.post(\"/\").header(foo_ct).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"post_foo\");\n\n    let response = client.get(\"/\").header(bar_baz_a).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"get_bar_baz\");\n\n    let response = client.put(\"/\").header(bar_baz_ct).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"put_bar_baz\");\n\n    let response = client.get(\"/\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"get_foo\");\n\n    let response = client.put(\"/\").header(ContentType::HTML).dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n\n    let response = client.post(\"/\").header(ContentType::HTML).dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n}\n"
  },
  {
    "path": "core/codegen/tests/route-ranking.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::local::blocking::Client;\n\n// Test that manual/auto ranking works as expected.\n\n#[get(\"/<_number>\")]\nfn get0(_number: u8) -> &'static str { \"0\" }\n\n#[get(\"/<_number>\", rank = 1)]\nfn get1(_number: u16) -> &'static str { \"1\" }\n\n#[get(\"/<_number>\", rank = 2)]\nfn get2(_number: u32) -> &'static str { \"2\" }\n\n#[get(\"/<_number>\", rank = 3)]\nfn get3(_number: u64) -> &'static str { \"3\" }\n\n#[test]\nfn test_ranking() {\n    let rocket = rocket::build().mount(\"/\", routes![get0, get1, get2, get3]);\n    let client = Client::debug(rocket).unwrap();\n\n    let response = client.get(\"/0\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"0\");\n\n    let response = client.get(format!(\"/{}\", 1 << 8)).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"1\");\n\n    let response = client.get(format!(\"/{}\", 1 << 16)).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"2\");\n\n    let response = client.get(format!(\"/{}\", 1u64 << 32)).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"3\");\n}\n\n// Test a collision due to same auto rank.\n\n#[get(\"/<_n>\")]\nfn get0b(_n: u8) {  }\n\n#[test]\nfn test_rank_collision() {\n    use rocket::error::ErrorKind;\n\n    let rocket = rocket::build().mount(\"/\", routes![get0, get0b]);\n    let client_result = Client::debug(rocket);\n    match client_result.as_ref().map_err(|e| e.kind()) {\n        Err(ErrorKind::Collisions { .. }) => { /* o.k. */ },\n        Ok(_) => panic!(\"client succeeded unexpectedly\"),\n        Err(e) => panic!(\"expected collision, got {}\", e)\n    }\n}\n"
  },
  {
    "path": "core/codegen/tests/route-raw.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::local::blocking::Client;\n\n// Test that raw idents can be used for route parameter names\n\n#[get(\"/<enum>?<type>\")]\nfn get(r#enum: String, r#type: i32) -> String {\n    format!(\"{} is {}\", r#enum, r#type)\n}\n\n#[get(\"/swap/<raw>/<bare>\")]\nfn swap(r#raw: String, bare: String) -> String {\n    format!(\"{}, {}\", raw, bare)\n}\n\n#[catch(400)]\nfn catch(r#raw: &rocket::Request<'_>) -> String {\n    format!(\"{}\", raw.method())\n}\n\n#[test]\nfn test_raw_ident() {\n    let rocket = rocket::build()\n        .mount(\"/\", routes![get, swap])\n        .register(\"/\", catchers![catch]);\n\n    let client = Client::debug(rocket).unwrap();\n\n    let response = client.get(\"/example?type=1\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"example is 1\");\n\n    let uri_named = uri!(get(r#enum = \"test_named\", r#type = 1));\n    assert_eq!(uri_named.to_string(), \"/test_named?type=1\");\n\n    let uri_unnamed = uri!(get(\"test_unnamed\", 2));\n    assert_eq!(uri_unnamed.to_string(), \"/test_unnamed?type=2\");\n\n    let uri_raws = uri!(swap(r#raw = \"1\", r#bare = \"2\"));\n    assert_eq!(uri_raws.to_string(), \"/swap/1/2\");\n    let uri_bare = uri!(swap(raw = \"1\", bare = \"2\"));\n    assert_eq!(uri_bare.to_string(), \"/swap/1/2\");\n}\n"
  },
  {
    "path": "core/codegen/tests/route-uniqueness.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[get(\"/\")]\nfn index() { }\n\nmod module {\n    // This one has all the same macro inputs, and we need it to\n    // generate a crate-wide unique identifier for the macro it\n    // defines.\n    #[get(\"/\")]\n    pub fn index() { }\n}\n\n// Makes sure that the hashing of the proc macro's call site span\n// is enough, even if we're inside a declarative macro\nmacro_rules! gen_routes {\n    () => {\n        #[get(\"/\")]\n        pub fn index() { }\n\n        pub mod two {\n            #[get(\"/\")]\n            pub fn index() { }\n        }\n    }\n}\n\nmod module2 {\n    gen_routes!();\n\n    pub mod module3 {\n        gen_routes!();\n    }\n}\n\n#[test]\nfn test_uri_reachability() {\n    use rocket::http::Status;\n    use rocket::local::blocking::Client;\n\n    let rocket = rocket::build()\n        .mount(\"/\", routes![index])\n        .mount(\"/module\", routes![module::index])\n        .mount(\"/module2\", routes![module2::index])\n        .mount(\"/module2/two\", routes![module2::two::index])\n        .mount(\"/module2/module3\", routes![module2::module3::index])\n        .mount(\"/module2/module3/two\", routes![module2::module3::two::index]);\n\n    let uris = rocket.routes()\n        .map(|r| r.uri.base().to_string())\n        .collect::<Vec<_>>();\n\n    let client = Client::debug(rocket).unwrap();\n    for uri in uris {\n        let response = client.get(uri).dispatch();\n        assert_eq!(response.status(), Status::Ok);\n    }\n}\n\n#[test]\nfn test_uri_calls() {\n    let uris = [\n        uri!(index()),\n        uri!(module::index()),\n        uri!(module2::index()),\n        uri!(module2::two::index()),\n        uri!(module2::module3::index()),\n        uri!(module2::module3::two::index()),\n    ];\n\n    assert!(uris.iter().all(|uri| uri == \"/\"));\n}\n"
  },
  {
    "path": "core/codegen/tests/route.rs",
    "content": "// Rocket sometimes generates mangled identifiers that activate the\n// non_snake_case lint. We deny the lint in this test to ensure that\n// code generation uses #[allow(non_snake_case)] in the appropriate places.\n#![deny(non_snake_case)]\n\n#[macro_use] extern crate rocket;\n\nuse std::path::PathBuf;\n\nuse rocket::request::Request;\nuse rocket::http::ext::Normalize;\nuse rocket::local::blocking::Client;\nuse rocket::data::{self, Data, FromData};\nuse rocket::http::{Status, RawStr, ContentType, uri::fmt::Path};\n\n// Use all of the code generation available at once.\n\n#[derive(FromForm, UriDisplayQuery)]\nstruct Inner<'r> {\n    field: &'r str\n}\n\nstruct Simple(String);\n\n#[async_trait]\nimpl<'r> FromData<'r> for Simple {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {\n        String::from_data(req, data).await.map(Simple)\n    }\n}\n\n#[post(\n    \"/<a>/<name>/name/<path..>?sky=blue&<sky>&<query..>\",\n    format = \"json\",\n    data = \"<simple>\",\n    rank = 138\n)]\nfn post1(\n    sky: usize,\n    name: &str,\n    a: String,\n    query: Inner<'_>,\n    path: PathBuf,\n    simple: Simple,\n) -> String {\n    let string = format!(\"{}, {}, {}, {}, {}, {}\",\n        sky, name, a, query.field, path.normalized_str(), simple.0);\n\n    let uri = uri!(post1(a, name, path, sky, query));\n\n    format!(\"({}) ({})\", string, uri.to_string())\n}\n\n#[route(\n    \"/<a>/<name>/name/<path..>?sky=blue&<sky>&<query..>\",\n    method = POST,\n    format = \"json\",\n    data = \"<simple>\",\n    rank = 138\n)]\nfn post2(\n    sky: usize,\n    name: &str,\n    a: String,\n    query: Inner<'_>,\n    path: PathBuf,\n    simple: Simple,\n) -> String {\n    let string = format!(\"{}, {}, {}, {}, {}, {}\",\n        sky, name, a, query.field, path.normalized_str(), simple.0);\n\n    let uri = uri!(post2(a, name, path, sky, query));\n\n    format!(\"({}) ({})\", string, uri.to_string())\n}\n\n#[allow(dead_code)]\n#[post(\"/<_unused_param>?<_unused_query>\", data=\"<_unused_data>\")]\nfn test_unused_params(_unused_param: String, _unused_query: String, _unused_data: Data<'_>) {\n}\n\n#[test]\nfn test_full_route() {\n    let rocket = rocket::build()\n        .mount(\"/1\", routes![post1])\n        .mount(\"/2\", routes![post2]);\n\n    let client = Client::debug(rocket).unwrap();\n\n    let a = RawStr::new(\"A%20A\");\n    let name = RawStr::new(\"Bob%20McDonald\");\n    let path = \"this/path/here\";\n    let sky = 777;\n    let query = \"field=inside\";\n    let simple = \"data internals\";\n\n    let path_part = format!(\"/{}/{}/name/{}\", a, name, path);\n    let query_part = format!(\"?sky={}&sky=blue&{}\", sky, query);\n    let uri = format!(\"{}{}\", path_part, query_part);\n    let expected_uri = format!(\"{}?sky=blue&sky={}&{}\", path_part, sky, query);\n\n    let response = client.post(&uri).body(simple).dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n\n    let response = client.post(format!(\"/1{}\", uri)).body(simple).dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n\n    let response = client\n        .post(format!(\"/1{}\", uri))\n        .header(ContentType::JSON)\n        .body(simple)\n        .dispatch();\n\n    assert_eq!(response.into_string().unwrap(), format!(\"({}, {}, {}, {}, {}, {}) ({})\",\n            sky, name.percent_decode().unwrap(), \"A A\", \"inside\", path, simple, expected_uri));\n\n    let response = client.post(format!(\"/2{}\", uri)).body(simple).dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n\n    let response = client\n        .post(format!(\"/2{}\", uri))\n        .header(ContentType::JSON)\n        .body(simple)\n        .dispatch();\n\n    assert_eq!(response.into_string().unwrap(), format!(\"({}, {}, {}, {}, {}, {}) ({})\",\n            sky, name.percent_decode().unwrap(), \"A A\", \"inside\", path, simple, expected_uri));\n}\n\nmod scopes {\n    #![allow(dead_code)]\n\n    mod other {\n        #[get(\"/world\")]\n        pub fn world() -> &'static str {\n            \"Hello, world!\"\n        }\n    }\n\n    #[get(\"/hello\")]\n    pub fn hello() -> &'static str {\n        \"Hello, outside world!\"\n    }\n\n    use other::world;\n\n    fn _rocket() -> rocket::Rocket<rocket::Build> {\n        rocket::build().mount(\"/\", rocket::routes![hello, world, other::world])\n    }\n}\n\nuse rocket::form::Contextual;\n\n#[derive(Default, Debug, PartialEq, FromForm)]\nstruct Filtered<'r> {\n    bird: Option<&'r str>,\n    color: Option<&'r str>,\n    cat: Option<&'r str>,\n    rest: Option<&'r str>,\n}\n\n#[get(\"/?bird=1&color=blue&<bird>&<color>&cat=bob&<rest..>\")]\nfn filtered_raw_query(bird: usize, color: &str, rest: Contextual<'_, Filtered<'_>>) -> String {\n    assert_ne!(bird, 1);\n    assert_ne!(color, \"blue\");\n    assert_eq!(rest.value.unwrap(), Filtered::default());\n\n    format!(\"{} - {}\", bird, color)\n}\n\n#[test]\nfn test_filtered_raw_query() {\n    let rocket = rocket::build().mount(\"/\", routes![filtered_raw_query]);\n    let client = Client::debug(rocket).unwrap();\n\n    #[track_caller]\n    fn run(client: &Client, birds: &[&str], colors: &[&str], cats: &[&str]) -> (Status, String) {\n        let join = |slice: &[&str], name: &str| slice.iter()\n            .map(|v| format!(\"{}={}\", name, v))\n            .collect::<Vec<_>>()\n            .join(\"&\");\n\n        let q = format!(\"{}&{}&{}\",\n            join(birds, \"bird\"),\n            join(colors, \"color\"),\n            join(cats, \"cat\"));\n\n        let response = client.get(format!(\"/?{}\", q)).dispatch();\n        let status = response.status();\n        let body = response.into_string().unwrap();\n\n        (status, body)\n    }\n\n    let birds = &[\"2\", \"3\"];\n    let colors = &[\"red\", \"blue\", \"green\"];\n    let cats = &[\"bob\", \"bob\"];\n    assert_eq!(run(&client, birds, colors, cats).0, Status::NotFound);\n\n    let birds = &[\"2\", \"1\", \"3\"];\n    let colors = &[\"red\", \"green\"];\n    let cats = &[\"bob\", \"bob\"];\n    assert_eq!(run(&client, birds, colors, cats).0, Status::NotFound);\n\n    let birds = &[\"2\", \"1\", \"3\"];\n    let colors = &[\"red\", \"blue\", \"green\"];\n    let cats = &[];\n    assert_eq!(run(&client, birds, colors, cats).0, Status::NotFound);\n\n    let birds = &[\"2\", \"1\", \"3\"];\n    let colors = &[\"red\", \"blue\", \"green\"];\n    let cats = &[\"bob\", \"bob\"];\n    assert_eq!(run(&client, birds, colors, cats).1, \"2 - red\");\n\n    let birds = &[\"1\", \"2\", \"1\", \"3\"];\n    let colors = &[\"blue\", \"red\", \"blue\", \"green\"];\n    let cats = &[\"bob\"];\n    assert_eq!(run(&client, birds, colors, cats).1, \"2 - red\");\n\n    let birds = &[\"5\", \"1\"];\n    let colors = &[\"blue\", \"orange\", \"red\", \"blue\", \"green\"];\n    let cats = &[\"bob\"];\n    assert_eq!(run(&client, birds, colors, cats).1, \"5 - orange\");\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct Dog<'r> {\n    name: &'r str,\n    age: usize\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct Q<'r> {\n    dog: Dog<'r>\n}\n\n#[get(\"/?<color>&color=red&<q..>\")]\nfn query_collection(color: Vec<&str>, q: Q<'_>) -> String {\n    format!(\"{} - {} - {}\", color.join(\"&\"), q.dog.name, q.dog.age)\n}\n\n#[get(\"/?<color>&color=red&<dog>\")]\nfn query_collection_2(color: Vec<&str>, dog: Dog<'_>) -> String {\n    format!(\"{} - {} - {}\", color.join(\"&\"), dog.name, dog.age)\n}\n\n#[test]\nfn test_query_collection() {\n    #[track_caller]\n    fn run(client: &Client, colors: &[&str], dog: &[&str]) -> (Status, String) {\n        let join = |slice: &[&str], prefix: &str| slice.iter()\n            .map(|v| format!(\"{}{}\", prefix, v))\n            .collect::<Vec<_>>()\n            .join(\"&\");\n\n        let q = format!(\"{}&{}\", join(colors, \"color=\"), join(dog, \"dog.\"));\n        let response = client.get(format!(\"/?{}\", q)).dispatch();\n        (response.status(), response.into_string().unwrap())\n    }\n\n    fn run_tests(rocket: rocket::Rocket<rocket::Build>) {\n        let client = Client::debug(rocket).unwrap();\n\n        let colors = &[\"blue\", \"green\"];\n        let dog = &[\"name=Fido\", \"age=10\"];\n        assert_eq!(run(&client, colors, dog).0, Status::NotFound);\n\n        let colors = &[\"red\"];\n        let dog = &[\"name=Fido\"];\n        assert_eq!(run(&client, colors, dog).0, Status::UnprocessableEntity);\n\n        let colors = &[\"red\"];\n        let dog = &[\"name=Fido\", \"age=2\"];\n        assert_eq!(run(&client, colors, dog).1, \" - Fido - 2\");\n\n        let colors = &[\"red\", \"blue\", \"green\"];\n        let dog = &[\"name=Fido\", \"age=10\"];\n        assert_eq!(run(&client, colors, dog).1, \"blue&green - Fido - 10\");\n\n        let colors = &[\"red\", \"blue\", \"green\"];\n        let dog = &[\"name=Fido\", \"age=10\", \"toy=yes\"];\n        assert_eq!(run(&client, colors, dog).1, \"blue&green - Fido - 10\");\n\n        let colors = &[\"blue\", \"red\", \"blue\"];\n        let dog = &[\"name=Fido\", \"age=10\"];\n        assert_eq!(run(&client, colors, dog).1, \"blue&blue - Fido - 10\");\n\n        let colors = &[\"blue\", \"green\", \"red\", \"blue\"];\n        let dog = &[\"name=Max+Fido\", \"age=10\"];\n        assert_eq!(run(&client, colors, dog).1, \"blue&green&blue - Max Fido - 10\");\n    }\n\n    let rocket = rocket::build().mount(\"/\", routes![query_collection]);\n    run_tests(rocket);\n\n    let rocket = rocket::build().mount(\"/\", routes![query_collection_2]);\n    run_tests(rocket);\n}\n\nuse rocket::request::FromSegments;\nuse rocket::http::uri::Segments;\n\nstruct PathString(String);\n\nimpl FromSegments<'_> for PathString {\n    type Error = std::convert::Infallible;\n\n    fn from_segments(segments: Segments<'_, Path>) -> Result<Self, Self::Error> {\n        Ok(PathString(segments.collect::<Vec<_>>().join(\"/\")))\n    }\n\n}\n\n#[get(\"/<_>/b/<path..>\", rank = 1)]\nfn segments(path: PathString) -> String {\n    format!(\"nonempty+{}\", path.0)\n}\n\n#[get(\"/<path..>\", rank = 2)]\nfn segments_empty(path: PathString) -> String {\n    format!(\"empty+{}\", path.0)\n}\n\n#[test]\nfn test_inclusive_segments() {\n    let rocket = rocket::build()\n        .mount(\"/\", routes![segments])\n        .mount(\"/\", routes![segments_empty]);\n\n    let client = Client::debug(rocket).unwrap();\n    let get = |uri| client.get(uri).dispatch().into_string().unwrap();\n\n    assert_eq!(get(\"/\"), \"empty+\");\n    assert_eq!(get(\"//\"), \"empty+\");\n    assert_eq!(get(\"//a\"), \"empty+a\");\n    assert_eq!(get(\"//a/\"), \"empty+a/\");\n    assert_eq!(get(\"//a//\"), \"empty+a/\");\n    assert_eq!(get(\"//a//c/d\"), \"empty+a/c/d\");\n    assert_eq!(get(\"//a/b\"), \"empty+a/b\");\n\n    assert_eq!(get(\"//a/b/\"), \"nonempty+\");\n    assert_eq!(get(\"//a/b/c\"), \"nonempty+c\");\n    assert_eq!(get(\"//a/b//c\"), \"nonempty+c\");\n    assert_eq!(get(\"//a//b////c\"), \"nonempty+c\");\n    assert_eq!(get(\"//a//b////c/d/e\"), \"nonempty+c/d/e\");\n    assert_eq!(get(\"//a//b////c/d/e/\"), \"nonempty+c/d/e/\");\n}\n"
  },
  {
    "path": "core/codegen/tests/segment-ignore.rs",
    "content": "#[macro_use]\nextern crate rocket;\n\n#[get(\"/<_>\", rank = 1)] fn ig_1() -> &'static str { \"1\" }\n\n#[get(\"/static\")] fn just_static() -> &'static str { \"static\" }\n\n#[get(\"/<_>/<_>\", rank = 1)] fn ig_2() -> &'static str { \"2\" }\n\n#[get(\"/static/<_>\")] fn ig_1_static() -> &'static str { \"static_1\" }\n\n#[get(\"/<_>/<_>/<_>\", rank = 1)] fn ig_3() -> &'static str { \"3\" }\n\n#[get(\"/static/<_>/static\")] fn ig_1_static_static() -> &'static str { \"static_1_static\" }\n\n#[get(\"/<a>/<_>/<_>/<b>\")] fn wrapped(a: String, b: String) -> String { a + &b }\n\n#[test]\nfn test_ignored_segments() {\n    use rocket::local::blocking::Client;\n\n    fn get_string(client: &Client, url: &str) -> String {\n        client.get(url).dispatch().into_string().unwrap()\n    }\n\n    let rocket = rocket::build().mount(\"/\", routes![\n        ig_1, just_static, ig_2, ig_3, ig_1_static, ig_1_static_static, wrapped\n    ]);\n\n    let client = Client::debug(rocket).unwrap();\n    assert_eq!(get_string(&client, \"/foo\"), \"1\");\n    assert_eq!(get_string(&client, \"/bar\"), \"1\");\n    assert_eq!(get_string(&client, \"/static\"), \"static\");\n\n    assert_eq!(get_string(&client, \"/foo/bar\"), \"2\");\n    assert_eq!(get_string(&client, \"/bar/foo\"), \"2\");\n    assert_eq!(get_string(&client, \"/a/b\"), \"2\");\n    assert_eq!(get_string(&client, \"/foo/static\"), \"2\");\n    assert_eq!(get_string(&client, \"/static/foo\"), \"static_1\");\n\n    assert_eq!(get_string(&client, \"/foo/bar/baz\"), \"3\");\n    assert_eq!(get_string(&client, \"/bar/static/bam\"), \"3\");\n    assert_eq!(get_string(&client, \"/static/static/static\"), \"static_1_static\");\n    assert_eq!(get_string(&client, \"/static/foo/bam\"), \"3\");\n\n    assert_eq!(get_string(&client, \"/a/b/c/d\"), \"ad\");\n    assert_eq!(get_string(&client, \"/static/b/c/static\"), \"staticstatic\");\n    assert_eq!(get_string(&client, \"/a/b/c/static\"), \"astatic\");\n    assert_eq!(get_string(&client, \"/ec/b/c/static\"), \"ecstatic\");\n}\n"
  },
  {
    "path": "core/codegen/tests/typed-uris.rs",
    "content": "#![allow(dead_code, unused_variables)]\n\n#[macro_use] extern crate rocket;\n\nuse std::path::PathBuf;\n\nuse rocket::http::CookieJar;\nuse rocket::http::uri::fmt::{FromUriParam, Query};\nuse rocket::form::{Form, error::{Errors, ErrorKind}};\n\nmacro_rules! assert_uri_eq {\n    ($($uri:expr => $expected:expr,)+) => {\n        $(\n            let actual = $uri;\n            let expected = rocket::http::uri::Uri::parse_any($expected).expect(\"valid URI\");\n            if actual != expected {\n                panic!(\"\\nURI mismatch: got {}, expected {}\\nGot) {:?}\\nExpected) {:?}\\n\",\n                    actual, expected, actual, expected);\n            }\n        )+\n    };\n}\n\n#[derive(FromForm, UriDisplayQuery)]\nstruct User<'a> {\n    name: &'a str,\n    nickname: String,\n}\n\nimpl<'a, 'b> FromUriParam<Query, (&'a str, &'b str)> for User<'a> {\n    type Target = User<'a>;\n    fn from_uri_param((name, nickname): (&'a str, &'b str)) -> User<'a> {\n        User { name: name.into(), nickname: nickname.to_string() }\n    }\n}\n\n// This one has no `UriDisplay`. It exists to ensure that this file still\n// compiles even though it's used a URI parameter's type. As long as a user\n// doesn't request a URI from that route, things should be okay.\n#[derive(FromForm)]\nstruct Second {\n    nickname: String,\n}\n\n#[post(\"/\")]\nfn index() { }\n\n#[post(\"/<id>\")]\nfn simple(id: i32) { }\n\n#[post(\"/<id>/<name>\")]\nfn simple2(id: i32, name: String) { }\n\n#[post(\"/<id>/<name>\")]\nfn simple2_flipped(name: String, id: i32) { }\n\n#[post(\"/?<id>\")]\nfn simple3(id: i32) { }\n\n#[post(\"/?<id>&<name>\")]\nfn simple4(id: i32, name: String) { }\n\n#[post(\"/?<id>&<name>\")]\nfn simple4_flipped(name: String, id: i32) { }\n\n#[post(\"/<used>/<_unused>\")]\nfn unused_param(used: i32, _unused: i32) { }\n\n#[post(\"/<id>\")]\nfn guard_1(cookies: &CookieJar<'_>, id: i32) { }\n\n#[post(\"/<id>/<name>\")]\nfn guard_2(name: String, cookies: &CookieJar<'_>, id: i32) { }\n\n#[post(\"/a/<id>/hi/<name>/hey\")]\nfn guard_3(id: i32, name: String, cookies: &CookieJar<'_>) { }\n\n#[post(\"/<id>\", data = \"<form>\")]\nfn no_uri_display_okay(id: i32, form: Form<Second>) { }\n\n#[post(\"/name/<name>?<foo>&type=10&<type>&<query..>\", data = \"<user>\", rank = 2)]\nfn complex<'r>(\n    foo: usize,\n    name: &str,\n    query: User<'r>,\n    user: Form<User<'r>>,\n    r#type: &str,\n    cookies: &CookieJar<'_>\n) {  }\n\n#[post(\"/a/<path..>\")]\nfn segments(path: PathBuf) { }\n\n#[post(\"/a/<id>/then/<path..>\")]\nfn param_and_segments(path: PathBuf, id: usize) { }\n\n#[post(\"/a/<id>/then/<path..>\")]\nfn guarded_segments(cookies: &CookieJar<'_>, path: PathBuf, id: usize) { }\n\n#[test]\nfn check_simple_unnamed() {\n    assert_uri_eq! {\n        uri!(simple(100)) => \"/100\",\n        uri!(simple(-23)) => \"/-23\",\n        uri!(unused_param(1, 2)) => \"/1/2\",\n    }\n\n    // The \"flipped\" test ensures that the order of parameters depends on the\n    // route's URI, not on the order in the function signature.\n    assert_uri_eq! {\n        uri!(simple2(100, \"hello\".to_string())) => \"/100/hello\",\n        uri!(simple2(1349, \"hey\".to_string())) => \"/1349/hey\",\n        uri!(simple2_flipped(100, \"hello\".to_string())) => \"/100/hello\",\n    }\n\n    // Ensure that `.from_uri_param()` is called.\n    assert_uri_eq! {\n        uri!(simple2(100, \"hello\")) => \"/100/hello\",\n        uri!(simple2_flipped(1349, \"hey\")) => \"/1349/hey\",\n    }\n\n    // Ensure that the `UriDisplay` trait is being used.\n    assert_uri_eq! {\n        uri!(simple2(100, \"hello there\")) => \"/100/hello%20there\",\n        uri!(simple2_flipped(100, \"hello there\")) => \"/100/hello%20there\",\n    }\n\n    // Ensure that query parameters are handled properly.\n    assert_uri_eq! {\n        uri!(simple3(100)) => \"/?id=100\",\n        uri!(simple3(1349)) => \"/?id=1349\",\n        uri!(simple4(100, \"bob\")) => \"/?id=100&name=bob\",\n        uri!(simple4(1349, \"Bob Anderson\")) => \"/?id=1349&name=Bob%20Anderson\",\n        uri!(simple4(-2, \"@M+s&OU=\")) => \"/?id=-2&name=@M%2Bs%26OU%3D\",\n        uri!(simple4_flipped(100, \"bob\")) => \"/?id=100&name=bob\",\n        uri!(simple4_flipped(1349, \"Bob Anderson\")) => \"/?id=1349&name=Bob%20Anderson\",\n    }\n}\n\n#[test]\nfn check_simple_named() {\n    assert_uri_eq! {\n        uri!(simple(id = 100)) => \"/100\",\n        uri!(simple(id = -23)) => \"/-23\",\n        uri!(unused_param(used = 1, _unused = 2)) => \"/1/2\",\n    }\n\n    assert_uri_eq! {\n        uri!(simple2(id = 100, name = \"hello\".to_string())) => \"/100/hello\",\n        uri!(simple2(name = \"hi\".to_string(), id = 123)) => \"/123/hi\",\n        uri!(simple2_flipped(id = 1349, name = \"hey\".to_string())) => \"/1349/hey\",\n        uri!(simple2_flipped(name = \"hello\".to_string(), id = 100)) => \"/100/hello\",\n    }\n\n    // Ensure that `.from_uri_param()` is called.\n    assert_uri_eq! {\n        uri!(simple2(id = 100, name = \"hello\")) => \"/100/hello\",\n        uri!(simple2(id = 100, name = \"hi\")) => \"/100/hi\",\n        uri!(simple2(id = 1349, name = \"hey\")) => \"/1349/hey\",\n        uri!(simple2(name = \"hello\", id = 100)) => \"/100/hello\",\n        uri!(simple2(name = \"hi\", id = 100)) => \"/100/hi\",\n        uri!(simple2_flipped(id = 1349, name = \"hey\")) => \"/1349/hey\",\n    }\n\n    // Ensure that the `UriDisplay` trait is being used.\n    assert_uri_eq! {\n        uri!(simple2(id = 100, name = \"hello there\")) => \"/100/hello%20there\",\n        uri!(simple2(name = \"hello there\", id = 100)) => \"/100/hello%20there\",\n        uri!(simple2_flipped(id = 100, name = \"hello there\")) => \"/100/hello%20there\",\n        uri!(simple2_flipped(name = \"hello there\", id = 100)) => \"/100/hello%20there\",\n    }\n\n    // Ensure that query parameters are handled properly.\n    assert_uri_eq! {\n        uri!(simple3(id = 100)) => \"/?id=100\",\n        uri!(simple3(id = 1349)) => \"/?id=1349\",\n        uri!(simple4(id = 100, name = \"bob\")) => \"/?id=100&name=bob\",\n        uri!(simple4(id = 1349, name = \"Bob A\")) => \"/?id=1349&name=Bob%20A\",\n        uri!(simple4(name = \"Bob A\", id = 1349)) => \"/?id=1349&name=Bob%20A\",\n        uri!(simple4_flipped(id = 1349, name = \"Bob A\")) => \"/?id=1349&name=Bob%20A\",\n        uri!(simple4_flipped(name = \"Bob A\", id = 1349)) => \"/?id=1349&name=Bob%20A\",\n    }\n}\n\n#[test]\nfn check_route_prefix_suffix() {\n    assert_uri_eq! {\n        uri!(index) => \"/\",\n        uri!(\"/\") => \"/\",\n        uri!(\"/\", index) => \"/\",\n        uri!(\"/hi\", index) => \"/hi\",\n        uri!(\"/foo\", index) => \"/foo\",\n        uri!(\"/hi/\", index) => \"/hi/\",\n        uri!(\"/foo/\", index) => \"/foo/\",\n        uri!(\"/\", simple3(10)) => \"/?id=10\",\n        uri!(\"/hi\", simple3(11)) => \"/hi?id=11\",\n        uri!(\"/hi/\", simple3(11)) => \"/hi/?id=11\",\n        uri!(\"/mount\", simple(100)) => \"/mount/100\",\n        uri!(\"/mount\", simple(id = 23)) => \"/mount/23\",\n        uri!(\"/mount/\", simple(100)) => \"/mount/100\",\n        uri!(\"/mount/\", simple(id = 23)) => \"/mount/23\",\n        uri!(\"/another\", simple(100)) => \"/another/100\",\n        uri!(\"/another\", simple(id = 23)) => \"/another/23\",\n        uri!(\"/foo\") => \"/foo\",\n        uri!(\"/foo/\") => \"/foo/\",\n        uri!(\"/foo///\") => \"/foo/\",\n        uri!(\"/foo/bar/\") => \"/foo/bar/\",\n    }\n\n    assert_uri_eq! {\n        uri!(\"http://rocket.rs\", index) => \"http://rocket.rs\",\n        uri!(\"http://rocket.rs/\", index) => \"http://rocket.rs/\",\n        uri!(\"http://rocket.rs///\", index) => \"http://rocket.rs/\",\n        uri!(\"http://rocket.rs/foo\", index) => \"http://rocket.rs/foo\",\n        uri!(\"http://rocket.rs/foo/\", index) => \"http://rocket.rs/foo/\",\n        uri!(\"http://\", index) => \"http://\",\n        uri!(\"http:///\", index) => \"http:///\",\n        uri!(\"http:////\", index) => \"http:///\",\n        uri!(\"ftp:/\", index) => \"ftp:/\",\n    }\n\n    assert_uri_eq! {\n        uri!(\"http://rocket.rs\", index, \"?foo\") => \"http://rocket.rs?foo\",\n        uri!(\"http://rocket.rs\", index, \"?\") => \"http://rocket.rs?\",\n        uri!(\"http://rocket.rs\", index, \"#\") => \"http://rocket.rs#\",\n        uri!(\"http://rocket.rs\", index, \"#bar\") => \"http://rocket.rs#bar\",\n        uri!(\"http://rocket.rs\", index, \"?bar#baz\") => \"http://rocket.rs?bar#baz\",\n        uri!(\"http://rocket.rs/\", index, \"?foo\") => \"http://rocket.rs/?foo\",\n        uri!(\"http://rocket.rs/\", index, \"?\") => \"http://rocket.rs/?\",\n        uri!(\"http://rocket.rs/\", index, \"#\") => \"http://rocket.rs/#\",\n        uri!(\"http://rocket.rs/\", index, \"#bar\") => \"http://rocket.rs/#bar\",\n        uri!(\"http://rocket.rs/\", index, \"?bar#baz\") => \"http://rocket.rs/?bar#baz\",\n        uri!(\"http://\", index, \"?foo\") => \"http://?foo\",\n        uri!(\"http://rocket.rs\", simple3(id = 100), \"?foo\") => \"http://rocket.rs?id=100\",\n        uri!(\"http://rocket.rs\", simple3(id = 100), \"?foo#bar\") => \"http://rocket.rs?id=100#bar\",\n        uri!(\"http://rocket.rs/\", simple3(id = 100), \"?foo\") => \"http://rocket.rs/?id=100\",\n        uri!(\"http://rocket.rs/\", simple3(id = 100), \"?foo#bar\") => \"http://rocket.rs/?id=100#bar\",\n        uri!(_, simple3(id = 100), \"?foo#bar\") => \"/?id=100#bar\",\n    }\n\n    let dyn_origin = uri!(\"/a/b/c\");\n    let dyn_origin2 = uri!(\"/a/b/c?foo-bar\");\n    let dyn_origin_slash = uri!(\"/a/b/c/\");\n    assert_uri_eq! {\n        uri!(dyn_origin.clone(), index) => \"/a/b/c\",\n        uri!(dyn_origin2.clone(), index) => \"/a/b/c\",\n        uri!(dyn_origin.clone(), simple3(10)) => \"/a/b/c?id=10\",\n        uri!(dyn_origin2.clone(), simple3(10)) => \"/a/b/c?id=10\",\n        uri!(dyn_origin.clone(), simple(100)) => \"/a/b/c/100\",\n        uri!(dyn_origin2.clone(), simple(100)) => \"/a/b/c/100\",\n        uri!(dyn_origin.clone(), simple2(100, \"hey\")) => \"/a/b/c/100/hey\",\n        uri!(dyn_origin2.clone(), simple2(100, \"hey\")) => \"/a/b/c/100/hey\",\n        uri!(dyn_origin.clone(), simple2(id = 23, name = \"hey\")) => \"/a/b/c/23/hey\",\n        uri!(dyn_origin2.clone(), simple2(id = 23, name = \"hey\")) => \"/a/b/c/23/hey\",\n\n        uri!(dyn_origin_slash.clone(), index) => \"/a/b/c/\",\n        uri!(dyn_origin_slash.clone(), simple3(10)) => \"/a/b/c/?id=10\",\n        uri!(dyn_origin_slash.clone(), simple(100)) => \"/a/b/c/100\",\n    }\n\n    let dyn_absolute = uri!(\"http://rocket.rs\");\n    let dyn_absolute_slash = uri!(\"http://rocket.rs/\");\n    assert_uri_eq! {\n        uri!(dyn_absolute.clone(), index) => \"http://rocket.rs\",\n        uri!(dyn_absolute.clone(), simple(100)) => \"http://rocket.rs/100\",\n        uri!(dyn_absolute.clone(), simple3(123)) => \"http://rocket.rs?id=123\",\n        uri!(dyn_absolute_slash.clone(), index) => \"http://rocket.rs/\",\n        uri!(dyn_absolute_slash.clone(), simple(100)) => \"http://rocket.rs/100\",\n        uri!(dyn_absolute_slash.clone(), simple3(123)) => \"http://rocket.rs/?id=123\",\n        uri!(uri!(\"http://rocket.rs/a/b\"), index) => \"http://rocket.rs/a/b\",\n        uri!(\"http://rocket.rs/a/b\") => \"http://rocket.rs/a/b\",\n        uri!(uri!(\"http://rocket.rs/a/b\"), index) => \"http://rocket.rs/a/b\",\n        uri!(\"http://rocket.rs/a/b\") => \"http://rocket.rs/a/b\",\n    }\n\n    let dyn_abs = uri!(\"http://rocket.rs?foo\");\n    assert_uri_eq! {\n        uri!(_, index, dyn_abs.clone()) => \"/?foo\",\n        uri!(\"http://rocket.rs\", index, dyn_abs.clone()) => \"http://rocket.rs?foo\",\n        uri!(\"http://rocket.rs/\", index, dyn_abs.clone()) => \"http://rocket.rs/?foo\",\n        uri!(\"http://\", index, dyn_abs.clone()) => \"http://?foo\",\n        uri!(_, simple3(id = 123), dyn_abs) => \"/?id=123\",\n    }\n\n    let dyn_abs = uri!(\"http://rocket.rs/?foo\");\n    assert_uri_eq! {\n        uri!(_, index, dyn_abs.clone()) => \"/?foo\",\n        uri!(\"http://rocket.rs\", index, dyn_abs.clone()) => \"http://rocket.rs?foo\",\n        uri!(\"http://rocket.rs/\", index, dyn_abs.clone()) => \"http://rocket.rs/?foo\",\n        uri!(\"http://\", index, dyn_abs.clone()) => \"http://?foo\",\n        uri!(\"http:///\", index, dyn_abs.clone()) => \"http:///?foo\",\n        uri!(_, simple3(id = 123), dyn_abs) => \"/?id=123\",\n    }\n\n    let dyn_ref = uri!(\"?foo#bar\");\n    assert_uri_eq! {\n        uri!(_, index, dyn_ref.clone()) => \"/?foo#bar\",\n        uri!(\"http://rocket.rs\", index, dyn_ref.clone()) => \"http://rocket.rs?foo#bar\",\n        uri!(\"http://rocket.rs/\", index, dyn_ref.clone()) => \"http://rocket.rs/?foo#bar\",\n        uri!(\"http://\", index, dyn_ref.clone()) => \"http://?foo#bar\",\n        uri!(\"http:///\", index, dyn_ref.clone()) => \"http:///?foo#bar\",\n        uri!(_, simple3(id = 123), dyn_ref) => \"/?id=123#bar\",\n    }\n}\n\n#[test]\nfn check_guards_ignored() {\n    assert_uri_eq! {\n        uri!(\"/mount\", guard_1(100)) => \"/mount/100\",\n        uri!(\"/mount\", guard_2(2938, \"boo\")) => \"/mount/2938/boo\",\n        uri!(\"/mount\", guard_3(340, \"Bob\")) => \"/mount/a/340/hi/Bob/hey\",\n        uri!(guard_1(100)) => \"/100\",\n        uri!(guard_2(2938, \"boo\")) => \"/2938/boo\",\n        uri!(guard_3(340, \"Bob\")) => \"/a/340/hi/Bob/hey\",\n        uri!(\"/mount\", guard_1(id = 100)) => \"/mount/100\",\n        uri!(\"/mount\", guard_2(id = 2938, name = \"boo\")) => \"/mount/2938/boo\",\n        uri!(\"/mount\", guard_3(id = 340, name = \"Bob\")) => \"/mount/a/340/hi/Bob/hey\",\n        uri!(guard_1(id = 100)) => \"/100\",\n        uri!(guard_2(name = \"boo\", id = 2938)) => \"/2938/boo\",\n        uri!(guard_3(name = \"Bob\", id = 340)) => \"/a/340/hi/Bob/hey\",\n    }\n}\n\n#[test]\nfn check_with_segments() {\n    assert_uri_eq! {\n        uri!(segments(PathBuf::from(\"one/two/three\"))) => \"/a/one/two/three\",\n        uri!(segments(path = PathBuf::from(\"one/two/three\"))) => \"/a/one/two/three\",\n        uri!(\"/c\", segments(PathBuf::from(\"one/tw o/\"))) => \"/c/a/one/tw%20o\",\n        uri!(\"/c\", segments(path = PathBuf::from(\"one/tw o/\"))) => \"/c/a/one/tw%20o\",\n        uri!(segments(PathBuf::from(\"one/ tw?o/\"))) => \"/a/one/%20tw%3Fo\",\n        uri!(param_and_segments(10, PathBuf::from(\"a/b\"))) => \"/a/10/then/a/b\",\n        uri!(param_and_segments(id = 10, path = PathBuf::from(\"a/b\"))) => \"/a/10/then/a/b\",\n        uri!(guarded_segments(10, PathBuf::from(\"a/b\"))) => \"/a/10/then/a/b\",\n        uri!(guarded_segments(id = 10, path = PathBuf::from(\"a/b\"))) => \"/a/10/then/a/b\",\n    }\n\n    // Now check the `from_uri_param()` conversions for `PathBuf`.\n    assert_uri_eq! {\n        uri!(segments(\"one/two/three\")) => \"/a/one/two/three\",\n        uri!(\"/\", segments(path = \"one/two/three\")) => \"/a/one/two/three\",\n        uri!(\"/oh\", segments(path = \"one/two/three\")) => \"/oh/a/one/two/three\",\n        uri!(segments(\"one/ tw?o/\")) => \"/a/one/%20tw%3Fo\",\n        uri!(param_and_segments(id = 10, path = \"a/b\")) => \"/a/10/then/a/b\",\n        uri!(guarded_segments(10, \"a/b\")) => \"/a/10/then/a/b\",\n        uri!(guarded_segments(id = 10, path = \"a/b\")) => \"/a/10/then/a/b\",\n    }\n}\n\n#[test]\nfn check_complex() {\n    assert_uri_eq! {\n        uri!(complex(\"no idea\", 10, \"high\", (\"A B C\", \"a c\"))) =>\n            \"/name/no%20idea?foo=10&type=10&type=high&name=A%20B%20C&nickname=a%20c\",\n        uri!(complex(\"Bob\", 248, \"?\", User { name: \"Robert\".into(), nickname: \"Bob\".into() })) =>\n            \"/name/Bob?foo=248&type=10&type=%3F&name=Robert&nickname=Bob\",\n        uri!(complex(\"Bob\", 248, \"a a\", &User { name: \"Robert\".into(), nickname: \"B\".into() })) =>\n            \"/name/Bob?foo=248&type=10&type=a%20a&name=Robert&nickname=B\",\n        uri!(complex(\"no idea\", 248, \"\", &User { name: \"A B\".into(), nickname: \"A\".into() })) =>\n            \"/name/no%20idea?foo=248&type=10&type=&name=A%20B&nickname=A\",\n        uri!(complex(\"hi\", 3, \"b\", &User { name: \"A B C\".into(), nickname: \"a b\".into() })) =>\n            \"/name/hi?foo=3&type=10&type=b&name=A%20B%20C&nickname=a%20b\",\n        uri!(complex(name = \"no idea\", foo = 10, r#type = \"high\", query = (\"A B C\", \"a c\"))) =>\n            \"/name/no%20idea?foo=10&type=10&type=high&name=A%20B%20C&nickname=a%20c\",\n        uri!(complex(foo = 10, name = \"no idea\", r#type = \"high\", query = (\"A B C\", \"a c\"))) =>\n            \"/name/no%20idea?foo=10&type=10&type=high&name=A%20B%20C&nickname=a%20c\",\n        uri!(complex(query = (\"A B C\", \"a c\"), foo = 10, name = \"no idea\", r#type = \"high\", )) =>\n            \"/name/no%20idea?foo=10&type=10&type=high&name=A%20B%20C&nickname=a%20c\",\n        uri!(complex(query = (\"A B C\", \"a c\"), foo = 10, name = \"no idea\", r#type = \"high\")) =>\n            \"/name/no%20idea?foo=10&type=10&type=high&name=A%20B%20C&nickname=a%20c\",\n        uri!(complex(query = *&(\"A B C\", \"a c\"), foo = 10, name = \"no idea\", r#type = \"high\")) =>\n            \"/name/no%20idea?foo=10&type=10&type=high&name=A%20B%20C&nickname=a%20c\",\n        uri!(complex(foo = 3, name = \"hi\", r#type = \"b\",\n                query = &User { name: \"A B C\".into(), nickname: \"a b\".into() })) =>\n                \"/name/hi?foo=3&type=10&type=b&name=A%20B%20C&nickname=a%20b\",\n        uri!(complex(query = &User { name: \"A B C\".into(), nickname: \"a b\".into() },\n                foo = 3, name = \"hi\", r#type = \"b\")) =>\n                \"/name/hi?foo=3&type=10&type=b&name=A%20B%20C&nickname=a%20b\",\n    }\n\n    // Ensure variables are correctly processed.\n    let user = User { name: \"Robert\".into(), nickname: \"Bob\".into() };\n    assert_uri_eq! {\n        uri!(complex(\"complex\", 0, \"high\", &user)) =>\n            \"/name/complex?foo=0&type=10&type=high&name=Robert&nickname=Bob\",\n        uri!(complex(\"complex\", 0, \"high\", &user)) =>\n            \"/name/complex?foo=0&type=10&type=high&name=Robert&nickname=Bob\",\n        uri!(complex(\"complex\", 0, \"high\", user)) =>\n            \"/name/complex?foo=0&type=10&type=high&name=Robert&nickname=Bob\",\n    }\n}\n\n#[test]\nfn check_location_promotion() {\n    struct S1(String);\n    struct S2 { name: String }\n\n    let s1 = S1(\"Bob\".into());\n    let s2 = S2 { name: \"Bob\".into() };\n\n    assert_uri_eq! {\n        uri!(simple2(1, &S1(\"A\".into()).0)) => \"/1/A\",\n        uri!(simple2(1, &mut S1(\"A\".into()).0)) => \"/1/A\",\n        uri!(simple2(1, S1(\"A\".into()).0)) => \"/1/A\",\n        uri!(simple2(1, &S2 { name: \"A\".into() }.name)) => \"/1/A\",\n        uri!(simple2(1, &mut S2 { name: \"A\".into() }.name)) => \"/1/A\",\n        uri!(simple2(1, S2 { name: \"A\".into() }.name)) => \"/1/A\",\n        uri!(simple2(1, &s1.0)) => \"/1/Bob\",\n        uri!(simple2(1, &s2.name)) => \"/1/Bob\",\n        uri!(simple2(2, &s1.0)) => \"/2/Bob\",\n        uri!(simple2(2, &s2.name)) => \"/2/Bob\",\n        uri!(simple2(2, s1.0)) => \"/2/Bob\",\n        uri!(simple2(2, s2.name)) => \"/2/Bob\",\n    }\n\n    let mut s1 = S1(\"Bob\".into());\n    let mut s2 = S2 { name: \"Bob\".into() };\n    assert_uri_eq! {\n        uri!(simple2(1, &mut S1(\"A\".into()).0)) => \"/1/A\",\n        uri!(simple2(1, S1(\"A\".into()).0)) => \"/1/A\",\n        uri!(simple2(1, &mut S2 { name: \"A\".into() }.name)) => \"/1/A\",\n        uri!(simple2(1, S2 { name: \"A\".into() }.name)) => \"/1/A\",\n        uri!(simple2(1, &mut s1.0)) => \"/1/Bob\",\n        uri!(simple2(1, &mut s2.name)) => \"/1/Bob\",\n        uri!(simple2(2, &mut s1.0)) => \"/2/Bob\",\n        uri!(simple2(2, &mut s2.name)) => \"/2/Bob\",\n        uri!(simple2(2, s1.0)) => \"/2/Bob\",\n        uri!(simple2(2, s2.name)) => \"/2/Bob\",\n    }\n}\n\n#[test]\nfn check_scoped() {\n    assert_uri_eq!{\n        uri!(typed_uris::simple(100)) => \"/typed_uris/100\",\n        uri!(typed_uris::simple(id = 100)) => \"/typed_uris/100\",\n        uri!(typed_uris::deeper::simple(100)) => \"/typed_uris/deeper/100\",\n    }\n}\n\nmod typed_uris {\n    #[post(\"/typed_uris/<id>\")]\n    fn simple(id: i32) { }\n\n    #[test]\n    fn check_simple_scoped() {\n        assert_uri_eq! {\n            uri!(simple(id = 100)) => \"/typed_uris/100\",\n            uri!(crate::simple(id = 100)) => \"/100\",\n            uri!(\"/mount\", crate::simple(id = 100)) => \"/mount/100\",\n            uri!(crate::simple2(id = 100, name = \"hello\")) => \"/100/hello\",\n        }\n    }\n\n    pub mod deeper {\n        #[post(\"/typed_uris/deeper/<id>\")]\n        fn simple(id: i32) { }\n\n        #[test]\n        fn check_deep_scoped() {\n            assert_uri_eq! {\n                uri!(super::simple(id = 100)) => \"/typed_uris/100\",\n                uri!(crate::simple(id = 100)) => \"/100\",\n            }\n        }\n    }\n}\n\n#[derive(FromForm, UriDisplayQuery)]\nstruct Third<'r> {\n    one: String,\n    two: &'r str,\n}\n\n#[post(\"/<foo>/<bar>?<q1>&<rest..>\")]\nfn optionals(\n    foo: Option<usize>,\n    bar: Option<String>,\n    q1: Result<usize, Errors<'_>>,\n    rest: Option<Third<'_>>\n) { }\n\n#[test]\nfn test_optional_uri_parameters() {\n    let mut some_10 = Some(10);\n    let mut third = Third { one: \"hi there\".into(), two: \"a b\".into() };\n    assert_uri_eq! {\n        uri!(optionals(\n            foo = 10,\n            bar = &\"hi there\",\n            q1 = Some(10),\n            rest = Some(Third { one: \"hi there\".into(), two: \"a b\".into() }),\n        )) => \"/10/hi%20there?q1=10&one=hi%20there&two=a%20b\",\n\n        uri!(optionals(\n            foo = &10,\n            bar = &\"hi there\",\n            q1 = Some(&10),\n            rest = Some(&third),\n        )) => \"/10/hi%20there?q1=10&one=hi%20there&two=a%20b\",\n\n        uri!(optionals(\n            foo = &mut 10,\n            bar = &mut \"hi there\",\n            q1 = some_10.as_mut(),\n            rest = Some(&mut third),\n        )) => \"/10/hi%20there?q1=10&one=hi%20there&two=a%20b\",\n\n        uri!(optionals(\n            foo = 10,\n            bar = &\"hi there\",\n            q1 = _,\n            rest = Some(Third { one: \"hi there\".into(), two: \"a b\".into() }),\n        )) => \"/10/hi%20there?one=hi%20there&two=a%20b\",\n\n        uri!(optionals(\n            foo = 10,\n            bar = &\"hi there\",\n            q1 = Some(10),\n            rest = _,\n        )) => \"/10/hi%20there?q1=10\",\n\n        uri!(optionals(\n            foo = 10,\n            bar = &\"hi there\",\n            q1 = Err(ErrorKind::Missing.into()) as Result<usize, _>,\n            rest = _,\n        )) => \"/10/hi%20there\",\n\n        uri!(optionals(\n            foo = 10,\n            bar = &\"hi there\",\n            q1 = None as Option<usize>,\n            rest = _\n        )) => \"/10/hi%20there\",\n\n        uri!(optionals(\n            foo = 10,\n            bar = &\"hi there\",\n            q1 = _,\n            rest = None as Option<Third<'_>>,\n        )) => \"/10/hi%20there\",\n\n        uri!(optionals(\n            foo = 10,\n            bar = &\"hi there\",\n            q1 = _,\n            rest = _,\n        )) => \"/10/hi%20there\",\n    }\n}\n\n#[test]\nfn test_simple_ignored() {\n    #[get(\"/<_>\")] fn ignore_one() { }\n    assert_uri_eq! {\n        uri!(ignore_one(100)) => \"/100\",\n        uri!(ignore_one(\"hello\")) => \"/hello\",\n        uri!(ignore_one(\"cats r us\")) => \"/cats%20r%20us\",\n    }\n\n    #[get(\"/<_>/<_>\")] fn ignore_two() { }\n    assert_uri_eq! {\n        uri!(ignore_two(100, \"boop\")) => \"/100/boop\",\n        uri!(ignore_two(&\"hi\", \"bop\")) => \"/hi/bop\",\n    }\n\n    #[get(\"/<_>/foo/<_>\")] fn ignore_inner_two() { }\n    #[get(\"/hi/<_>/foo\")] fn ignore_inner_one_a() { }\n    #[get(\"/hey/hi/<_>/foo/<_>\")] fn ignore_inner_two_b() { }\n\n    assert_uri_eq! {\n        uri!(ignore_inner_two(100, \"boop\")) => \"/100/foo/boop\",\n        uri!(ignore_inner_one_a(\"!?\")) => \"/hi/!%3F/foo\",\n        uri!(ignore_inner_two_b(&mut 5, \"boo\")) => \"/hey/hi/5/foo/boo\",\n    }\n\n    #[get(\"/<_>/foo/<_>?hi\")] fn ignore_with_q() { }\n    #[get(\"/hi/<_>/foo/<_>?hi&<hey>\")] fn ignore_with_q2(hey: Option<usize>) { }\n    #[get(\"/hi/<_>/foo/<_>?<hi>&<hey>\")] fn ignore_with_q3(hi: &str, hey: &str) { }\n\n    assert_uri_eq! {\n        uri!(ignore_with_q(100, \"boop\")) => \"/100/foo/boop?hi\",\n        uri!(ignore_with_q2(\"!?\", \"bop\", Some(3usize))) => \"/hi/!%3F/foo/bop?hi&hey=3\",\n        uri!(ignore_with_q3(&mut 5, \"boo\", \"hi b\", \"ho\")) => \"/hi/5/foo/boo?hi=hi%20b&hey=ho\",\n    }\n}\n\n#[test]\nfn test_maps() {\n    use std::collections::{HashMap, BTreeMap};\n    use rocket::figment::util::map;\n\n    #[get(\"/?<bar>\")] fn hmap(mut bar: HashMap<String, usize>) {\n        let _ = uri!(bmap(&bar));\n        let _ = uri!(bmap(&mut bar));\n        let _ = uri!(bmap(bar));\n    }\n\n    assert_uri_eq! {\n        uri!(hmap(map![\"foo\" => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(hmap(map![\"foo\".to_string() => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(hmap(&map![\"foo\".to_string() => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(hmap(&mut map![\"foo\".to_string() => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(hmap(&map![\"foo\" => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n    }\n\n    #[get(\"/?<bar>\")] fn bmap(mut bar: BTreeMap<&str, usize>) {\n        let _ = uri!(hmap(&bar));\n        let _ = uri!(hmap(&mut bar));\n        let _ = uri!(hmap(bar));\n    }\n\n    assert_uri_eq! {\n        uri!(bmap(map![\"foo\" => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(bmap(map![\"foo\".to_string() => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(bmap(&map![\"foo\".to_string() => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(bmap(&mut map![\"foo\".to_string() => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n        uri!(bmap(&map![\"foo\" => 10])) => \"/?bar.k:0=foo&bar.v:0=10\",\n    }\n}\n\n#[test]\nfn test_json() {\n    use rocket::serde::{Serialize, Deserialize, json::Json};\n\n    #[derive(Serialize, Deserialize, Copy, Clone)]\n    #[serde(crate = \"rocket::serde\")]\n    struct Inner<T> {\n        foo: Option<T>\n    }\n\n    #[get(\"/?<json>\")] fn foo(json: Json<Inner<usize>>) { }\n\n    let mut inner = Inner { foo: Some(10) };\n    assert_uri_eq! {\n        uri!(foo(inner)) => \"/?json=%7B%22foo%22:10%7D\",\n        uri!(foo(&inner)) => \"/?json=%7B%22foo%22:10%7D\",\n        uri!(foo(&mut inner)) => \"/?json=%7B%22foo%22:10%7D\",\n        uri!(foo(Json(inner))) => \"/?json=%7B%22foo%22:10%7D\",\n        uri!(foo(&Json(inner))) => \"/?json=%7B%22foo%22:10%7D\",\n        uri!(foo(&mut Json(inner))) => \"/?json=%7B%22foo%22:10%7D\",\n    }\n\n    #[get(\"/?<json>\")] fn bar(json: Json<Inner<Inner<&str>>>) { }\n\n    let mut inner = Inner { foo: Some(Inner { foo: Some(\"hi\") }) };\n    assert_uri_eq! {\n        uri!(bar(inner)) => \"/?json=%7B%22foo%22:%7B%22foo%22:%22hi%22%7D%7D\",\n        uri!(bar(&inner)) => \"/?json=%7B%22foo%22:%7B%22foo%22:%22hi%22%7D%7D\",\n        uri!(bar(&mut inner)) => \"/?json=%7B%22foo%22:%7B%22foo%22:%22hi%22%7D%7D\",\n        uri!(bar(Json(inner))) => \"/?json=%7B%22foo%22:%7B%22foo%22:%22hi%22%7D%7D\",\n        uri!(bar(&Json(inner))) => \"/?json=%7B%22foo%22:%7B%22foo%22:%22hi%22%7D%7D\",\n        uri!(bar(&mut Json(inner))) => \"/?json=%7B%22foo%22:%7B%22foo%22:%22hi%22%7D%7D\",\n    }\n}\n\n#[test]\nfn test_route_uri_normalization_with_prefix() {\n    #[get(\"/world\")] fn world() {}\n\n    assert_uri_eq! {\n        uri!(\"/\", index()) => \"/\",\n        uri!(\"/foo\", index()) => \"/foo\",\n        uri!(\"/bar/\", index()) => \"/bar/\",\n        uri!(\"/foo/bar\", index()) => \"/foo/bar\",\n        uri!(\"/foo/bar/\", index()) => \"/foo/bar/\",\n\n        uri!(\"/\", world()) => \"/world\",\n        uri!(\"/foo\", world()) => \"/foo/world\",\n        uri!(\"/bar/\", world()) => \"/bar/world\",\n        uri!(\"/foo/bar\", world()) => \"/foo/bar/world\",\n        uri!(\"/foo/bar/\", world()) => \"/foo/bar/world\",\n    }\n}\n\n#[test]\nfn test_vec_in_query() {\n    #[post(\"/?<v>\")]\n    fn f(v: Vec<usize>) { }\n\n    #[post(\"/?<v>\")]\n    fn g(v: Vec<String>) { }\n\n    #[post(\"/?<v>\")]\n    fn h(v: &[u8]) { }\n\n    let bytes = vec![0u8, 1, 2];\n    assert_uri_eq! {\n        uri!(f(v = vec![1, 2, 3])) => \"/?v=1&v=2&v=3\",\n        uri!(f(v = &vec![1, 2, 3])) => \"/?v=1&v=2&v=3\",\n        uri!(f(v = &[1, 2, 3])) => \"/?v=1&v=2&v=3\",\n        uri!(f(v = [1, 2, 3])) => \"/?v=1&v=2&v=3\",\n\n        uri!(f(vec![1, 2, 3])) => \"/?v=1&v=2&v=3\",\n        uri!(f(&vec![1, 2, 3])) => \"/?v=1&v=2&v=3\",\n        uri!(f(&[1, 2, 3])) => \"/?v=1&v=2&v=3\",\n        uri!(f([1, 2, 3])) => \"/?v=1&v=2&v=3\",\n\n        // TODO: Introduce `RawBytes` + FromUriParam + UriDisplay impls.\n        // uri!(f(v = &[1, 2, 3][..])) => \"/?v=1&v=2&v=3\",\n\n        uri!(g(v = vec![\"a\", \"b=c\", \"d\"])) => \"/?v=a&v=b%3Dc&v=d\",\n        uri!(g(v = &vec![\"a\", \"b=c\", \"d\"])) => \"/?v=a&v=b%3Dc&v=d\",\n        uri!(g(v = [\"a\", \"b=c\", \"d\"])) => \"/?v=a&v=b%3Dc&v=d\",\n        uri!(g(v = &[\"a\", \"b=c\", \"d\"])) => \"/?v=a&v=b%3Dc&v=d\",\n\n        uri!(h(v = bytes.as_slice())) => \"/?v=%00%01%02\",\n        uri!(h(v = &[1, 2, 3][..])) => \"/?v=%01%02%03\",\n    }\n}\n\n#[test]\nfn test_either() {\n    use rocket::either::{Either, Left, Right};\n\n    #[get(\"/<_foo>\")]\n    fn f(_foo: Either<usize, &str>) { }\n\n    assert_uri_eq! {\n        uri!(f(Left::<usize, &str>(123))) => \"/123\",\n        uri!(f(_foo = Left::<usize, &str>(710))) => \"/710\",\n\n        uri!(f(Right::<usize, &str>(\"hello world\"))) => \"/hello%20world\",\n        uri!(f(_foo = Right::<usize, &str>(\"bye?\"))) => \"/bye%3F\",\n    }\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/async-entry.rs",
    "content": "#![allow(dead_code)]\n\nmod main_a {\n    #[rocket::main]\n    fn foo() { }\n\n}\n\nmod main_b {\n    #[rocket::main]\n    async fn foo() { }\n\n}\n\nmod main_d {\n    #[rocket::main]\n    fn main() {\n        let _ = rocket::build().launch().await;\n    }\n}\n\nmod main_f {\n    #[rocket::main]\n    async fn main() {\n        rocket::build()\n    }\n}\n\n// launch\n\nmod launch_a {\n    #[rocket::launch]\n    async fn rocket() -> String {\n        let _ = rocket::build().launch().await;\n        rocket::build()\n\n    }\n}\n\nmod launch_b {\n    #[rocket::launch]\n    async fn rocket() -> _ {\n        let _ = rocket::build().launch().await;\n        \"hi\".to_string()\n    }\n}\n\nmod launch_c {\n    #[rocket::launch]\n    fn main() -> rocket::Rocket<rocket::Build> {\n        rocket::build()\n    }\n}\n\nmod launch_d {\n    #[rocket::launch]\n    async fn rocket() {\n        let _ = rocket::build().launch().await;\n        rocket::build()\n    }\n}\n\nmod launch_e {\n    #[rocket::launch]\n    fn rocket() {\n        rocket::build()\n    }\n}\n\nmod launch_f {\n    #[rocket::launch]\n    fn rocket() -> _ {\n        let _ = rocket::build().launch().await;\n        rocket::build()\n    }\n}\n\nmod launch_g {\n    #[rocket::launch]\n    fn main() -> &'static str {\n        let _ = rocket::build().launch().await;\n        \"hi\"\n    }\n}\n\nmod launch_h {\n    #[rocket::launch]\n    async fn main() -> _ {\n        rocket::build()\n    }\n}\n\n#[rocket::main]\nasync fn main() -> rocket::Rocket<rocket::Build> {\n    rocket::build()\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/bad-ignored-segments.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[get(\"/<_>\")]\nfn i0() {}\n\n#[get(\"/c?<_>\")]\nfn i1() {}\n\n#[post(\"/d\", data = \"<_>\")]\nfn i2() {}\n\nfn main() {  }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/catch.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::Request;\n\n#[catch(404)]\nstruct Catcher(String);\n\n#[catch(404)]\nconst CATCH: &str = \"Catcher\";\n\n#[catch(\"404\")]\nfn e1(_request: &Request) { }\n\n#[catch(code = \"404\")]\nfn e2(_request: &Request) { }\n\n#[catch(code = 404)]\nfn e3(_request: &Request) { }\n\n#[catch(99)]\nfn e4(_request: &Request) { }\n\n#[catch(600)]\nfn e5(_request: &Request) { }\n\n#[catch(400, message = \"foo\")]\nfn e5(_request: &Request) { }\n\n#[catch(404)]\nfn f3(_request: &Request, _other: bool) { }\n\nfn main() { }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/catch_type_errors.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::Request;\n\n#[catch(404)]\nfn f1(_request: &Request) -> usize {\n    10\n}\n\n#[catch(404)]\nfn f2(_request: &Request) -> bool {\n    false\n}\n\n#[catch(404)]\nfn f3(_request: bool) -> usize {\n    10\n}\n\n#[catch(404)]\nfn f4() -> usize {\n    10\n}\n\nfn main() {  }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/catchers.rs",
    "content": "#[macro_use] extern crate rocket;\n\nfn main() {\n    let _ = catchers![a b];\n    let _ = catchers![];\n    let _ = catchers![a::, ];\n    let _ = catchers![a::];\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/from_form.rs",
    "content": "use rocket::form::FromForm;\n\n#[derive(FromForm)]\nenum Thing { }\n\n#[derive(FromForm)]\nstruct Foo1;\n\n#[derive(FromForm)]\nstruct Foo2 {  }\n\n#[derive(FromForm)]\nstruct Foo3(usize);\n\n#[derive(FromForm)]\nstruct Foo4(usize, usize, usize);\n\n#[derive(FromForm)]\nstruct NextTodoTask<'f, 'a> {\n    description: String,\n    raw_description: &'f str,\n    other: &'a str,\n    completed: bool,\n}\n\n#[derive(FromForm)]\nstruct BadName1 {\n    #[field(name = \"isindex\")]\n    field: String,\n}\n\n#[derive(FromForm)]\nstruct Demo2 {\n    #[field(name = \"foo\")]\n    field: String,\n    foo: usize,\n}\n\n#[derive(FromForm)]\nstruct MyForm9 {\n    #[field(name = \"hello\")]\n    first: String,\n    #[field(name = \"hello\")]\n    other: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm10 {\n    first: String,\n    #[field(name = \"first\")]\n    other: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm {\n    #[field(name = \"blah\", field = \"bloo\")]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm1 {\n    #[field]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm2 {\n    #[field(\"blah\")]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm3 {\n    #[field(123)]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm4 {\n    #[field(beep = \"bop\")]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm5 {\n    #[field(name = \"blah\")]\n    #[field(name = \"blah\")]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm6 {\n    #[field(name = true)]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm7 {\n    #[field(name)]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm8 {\n    #[field(name = 123)]\n    my_field: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm11 {\n    #[field(name = \"hello&world\")]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm12 {\n    #[field(name = \"!@#$%^&*()_\")]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm13 {\n    #[field(name = \"?\")]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct MyForm14 {\n    #[field(name = \"\")]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct BadName2 {\n    #[field(name = \"a&b\")]\n    field: String,\n}\n\n#[derive(FromForm)]\nstruct BadName3 {\n    #[field(name = \"a=\")]\n    field: String,\n}\n\n#[derive(FromForm)]\nstruct Validate0 {\n    #[field(validate = 123)]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct Validate1 {\n    #[field(validate = unknown())]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct Validate2 {\n    #[field(validate = ext(rocket::http::ContentType::HTML))]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct Validate3 {\n    #[field(validate = ext(\"hello\"))]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct Default0 {\n    #[field(default = 123)]\n    first: String,\n}\n\n#[derive(FromForm)]\nstruct Default1 {\n    #[field(default = 1, default = 2)]\n    double_default: usize,\n}\n\n#[derive(FromForm)]\nstruct Default2 {\n    #[field(default = 1)]\n    #[field(default = 2)]\n    double_default: usize,\n}\n\n#[derive(FromForm)]\nstruct Default3 {\n    #[field(default = 1, default_with = None)]\n    double_default: usize,\n}\n\n#[derive(FromForm)]\nstruct Default4 {\n    #[field(default_with = None)]\n    #[field(default = 1)]\n    double_default: usize,\n}\n\n#[derive(FromForm)]\nstruct Default5 {\n    #[field(default_with = Some(\"hi\"))]\n    no_conversion_from_with: String,\n}\n\n#[derive(FromForm)]\nstruct Default6 {\n    #[field(default = \"no conversion\")]\n    first: bool,\n}\n\n#[derive(FromForm)] // NO ERROR\nstruct Another<T> {\n    _foo: T,\n    _bar: T,\n}\n\n#[derive(FromForm)] // NO ERROR\nstruct AnotherOne<T> { // NO ERROR\n    _foo: T,\n    _bar: T,\n}\n\nfn main() { }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/from_form_field.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[derive(FromFormField)]\nstruct Foo1;\n\n#[derive(FromFormField)]\nstruct Foo2(usize);\n\n#[derive(FromFormField)]\nstruct Foo3 {\n    foo: usize,\n}\n\n#[derive(FromFormField)]\nenum Foo4 {\n    A(usize),\n}\n\n#[derive(FromFormField)]\nenum Foo5 { }\n\n#[derive(FromFormField)]\nenum Foo6<T> {\n    A(T),\n}\n\n#[derive(FromFormField)]\nenum Bar1 {\n    #[field(value = 123)]\n    A,\n}\n\n#[derive(FromFormField)]\nenum Bar2 {\n    #[field(value)]\n    A,\n}\n\n#[derive(FromFormField)]\nenum Dup1 {\n    #[field(value = \"bar\")]\n    #[field(value = \"bar\")]\n    A,\n}\n\n#[derive(FromFormField)]\nenum Dup2 {\n    #[field(value = \"bar\")]\n    A,\n    #[field(value = \"BAr\")]\n    B,\n}\n\n#[derive(FromFormField)]\nenum Dup3 {\n    A,\n    #[field(value = \"a\")]\n    B,\n}\n\n#[derive(FromFormField)]\nenum Dup4 {\n    A,\n    #[field(value = \"c\")] // this shouldn't error\n    B,\n    #[field(value = \"b\")] // this shouldn't error\n    C,\n}\n\n#[derive(FromFormField)]\nenum Dup5 {\n    #[field(value = \"a\")] // this shouldn't error\n    A,\n    B,\n    C,\n}\n\n#[derive(FromFormField)]\nenum Dup6 {\n    #[field(value = \"FoO\")]\n    #[field(value = \"foo\")]\n    A,\n}\n\n#[derive(FromForm)]\nstruct Renamed0 {\n    #[field(name = \"foo\")]\n    #[field(name = uncased(\"FOO\"))]\n    single: usize,\n}\n\n#[derive(FromForm)]\nstruct Renamed1 {\n    #[field(name = \"foo\")]\n    single: usize,\n    #[field(name = \"foo\")]\n    other: usize,\n}\n\n#[derive(FromForm)]\nstruct Renamed2 {\n    #[field(name = uncased(\"HELLO_THERE\"))]\n    single: usize,\n    hello_there: usize,\n}\n\n#[derive(FromForm)]\nstruct Renamed3 {\n    #[field(name = \"hello_there\")]\n    single: usize,\n    hello_there: usize,\n}\n\nfn main() { }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/from_form_type_errors.rs",
    "content": "#[macro_use] extern crate rocket;\n\nstruct Unknown;\n\n#[derive(FromForm)]\nstruct BadType3 {\n    field: Unknown,\n}\n\nstruct Foo<T>(T);\n\n#[derive(FromForm)]\nstruct Other {\n    field: Foo<usize>,\n}\n\nfn main() {  }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/from_param.rs",
    "content": "use rocket::request::FromParam;\n\n#[derive(FromParam)]\nstruct Foo1 {\n    a: String\n}\n\n#[derive(FromParam)]\nstruct Foo2 {}\n\n#[derive(FromParam)]\nenum Foo3 {\n    A(String),\n    B(String)\n}\n\n#[derive(FromParam)]\nstruct Foo4(usize);\n\nfn main() {}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/responder-types.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[derive(Responder)]\nstruct Thing1 {\n    thing: u8,\n}\n\n#[derive(Responder)]\nstruct Thing2 {\n    thing: String,\n    other: u8,\n}\n\n#[derive(Responder)]\nstruct Thing3 {\n    thing: u8,\n    other: u8,\n}\n\n#[derive(Responder)]\nstruct Thing4 {\n    thing: String,\n    other: rocket::http::ContentType,\n    then: String,\n}\n\n#[get(\"/\")]\nfn foo() -> usize { 0 }\n\nfn main() {  }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/responder.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[derive(Responder)]\nstruct Thing1;\n\n#[derive(Responder)]\nstruct Thing2();\n\n#[derive(Responder)]\nenum Bar { } // NO ERROR\n\n#[derive(Responder)]\nenum Foo { Bark, }\n\n#[derive(Responder)]\nstruct Thing4<'a, 'b>(&'a str, &'b str);\n\n#[derive(Responder)]\nstruct Thing5<T>(T); // NO ERROR\n\n#[derive(Responder)]\nstruct Thing6<T, E>(T, E);\n\n#[derive(Responder)]\n#[response(content_type = \"\")]\nstruct Thing7(());\n\n#[derive(Responder)]\n#[response(content_type = \"idk\")]\nstruct Thing8(());\n\n#[derive(Responder)]\n#[response(content_type = 100)]\nstruct Thing9(());\n\n#[derive(Responder)]\n#[response(status = 8)]\nstruct Thing10(());\n\n#[derive(Responder)]\n#[response(status = \"404\")]\nstruct Thing11(());\n\n#[derive(Responder)]\n#[response(status = \"404\", content_type = \"html\")]\nstruct Thing12(());\n\n#[derive(Responder)]\n#[response(status = 404, content_type = 120)]\nstruct Thing13(());\n\n#[derive(Responder)] // NO ERROR\nenum Error<'r, T> {\n    #[response(status = 400)]\n    Unauthorized(T),\n    #[response(status = 404)]\n    NotFound(rocket::fs::NamedFile),\n    #[response(status = 500)]\n    A(&'r str, rocket::http::ContentType),\n}\n\n#[derive(Responder)] // NO ERROR\nenum Error2<'r, T> {\n    Unauthorized(&'r T),\n}\n\nfn main() {}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/route-attribute-general-syntax.rs",
    "content": "#[macro_use] extern crate rocket;\n\n// Check a path is supplied, at least.\n#[get()]\nfn a0() {}\n\n// Check that it only works on functions.\n#[get(\"/\")]\nstruct S;\n\n#[get(\"/\")]\nenum A {  }\n\n#[get(\"/\")]\ntrait Foo {  }\n\n#[get(\"/\")]\nimpl S {  }\n\n// Check that additional parameter weirdness is caught.\n#[get(\"/\", 123)]\nfn b0() {}\n\n#[get(\"/\", \"/\")]\nfn b1() {}\n\n#[get(data = \"<foo>\", \"/\")]\nfn b2(foo: usize) {}\n\n#[get(\"/\", unknown = \"foo\")]\nfn b3() {}\n\n#[get(\"/\", ...)]\nfn b4() {}\n\n// Check that all identifiers are named\n\n#[get(\"/\")]\nfn c1(_: usize) {}\n\n// Check that the path is a string, rank is an integer.\n\n#[get(100)]\nfn d0() {}\n\n#[get('/')]\nfn d1() {}\n\n#[get(\"/\", rank = \"1\")]\nfn d2() {}\n\n#[get(\"/\", rank = '1')]\nfn d3() {}\n\n// Check that formats are valid media-type strings.\n\n#[get(\"/\", format = \"applicationx-custom\")]\nfn e0() {}\n\n#[get(\"/\", format = \"\")]\nfn e1() {}\n\n#[get(\"/\", format = \"//\")]\nfn e2() {}\n\n#[get(\"/\", format = \"/\")]\nfn e3() {}\n\n#[get(\"/\", format = \"a/\")]\nfn e4() {}\n\n#[get(\"/\", format = \"/a\")]\nfn e5() {}\n\n#[get(\"/\", format = \"/a/\")]\nfn e6() {}\n\n#[get(\"/\", format = \"a/b/\")]\nfn e7() {}\n\n#[get(\"/\", format = \"unknown\")]\nfn e8() {}\n\n#[get(\"/\", format = 12)]\nfn e9() {}\n\n#[get(\"/\", format = 'j')]\nfn e10() {}\n\n#[get(\"/\", format = \"text//foo\")]\nfn e12() {}\n\n// Check that route methods are validated properly.\n\n#[route(CONNECT, \"/\")]\nfn f0() {}\n\n#[route(FIX, \"/\")]\nfn f1() {}\n\n#[route(\"hi\", \"/\")]\nfn f2() {}\n\n#[route(\"GET\", \"/\")]\nfn f3() {}\n\n#[route(120, \"/\")]\nfn f4() {}\n\nfn main() {}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/route-path-bad-syntax.rs",
    "content": "#[macro_use] extern crate rocket;\n\n// Check that route paths are absolute and normalized.\n\n#[get(\"a\")]\nfn f0() {}\n\n#[get(\"\")]\nfn f1() {}\n\n#[get(\"a/b/c\")]\nfn f2() {}\n\n#[get(\"/a///b\")]\nfn f3() {}\n\n#[get(\"/?bat&&\")]\nfn f4() {}\n\n#[get(\"/?bat&&\")]\nfn f5() {}\n\n#[get(\"/a/b//\")]\nfn f6() {}\n\n// Check that paths contain only valid URI characters\n\n#[get(\"/!@#$%^&*()\")]\nfn g1() {}\n\n#[get(\"/a%20b\")]\nfn g2() {}\n\n#[get(\"/a?a%20b\")]\nfn g3() {}\n\n#[get(\"/a?a+b\")]\nfn g4() {}\n\n// Check that all declared parameters are accounted for\n\n#[get(\"/<name>\")]\nfn h0(_name: usize) {}\n\n#[get(\"/a?<r>\")]\nfn h1() {}\n\n#[post(\"/a\", data = \"<test>\")]\nfn h2() {}\n\n#[get(\"/<_r>\")]\nfn h3() {}\n\n#[get(\"/<_r>/<b>\")]\nfn h4() {}\n\n//\n// Check dynamic parameters are valid idents\n\n#[get(\"/<foo_.>\")]\nfn i0() {}\n\n#[get(\"/<foo*>\")]\nfn i1() {}\n\n#[get(\"/<!>\")]\nfn i2() {}\n\n#[get(\"/<name>:<id>\")]\nfn i3() {}\n\n// Check that a data parameter is exactly `<param>`\n\n#[get(\"/\", data = \"foo\")]\nfn j0() {}\n\n#[get(\"/\", data = \"<foo..>\")]\nfn j1() {}\n\n#[get(\"/\", data = \"<foo\")]\nfn j2() {}\n\n#[get(\"/\", data = \"<test >\")]\nfn j3() {}\n\n// Check that all identifiers are named\n\n#[get(\"/<_>\")]\nfn k0(_: usize) {}\n\n// Check that strange dynamic syntax is caught.\n\n#[get(\"/<>\")]\nfn m0() {}\n\n#[get(\"/<id><\")]\nfn m1() {}\n\n#[get(\"/<<<<id><\")]\nfn m2() {}\n\n#[get(\"/<>name><\")]\nfn m3() {}\n\n// New additions for trailing paths, which we artificially disallow.\n\n#[get(\"/a/\")]\nfn n1() {}\n\n#[get(\"/a/b/\")]\nfn n2() {}\n\n#[get(\"/a/b/c/\")]\nfn n3() {}\n\nfn main() {  }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/route-type-errors.rs",
    "content": "#[macro_use] extern crate rocket;\n\nstruct Q;\n\n#[get(\"/<_foo>\")]\nfn f0(_foo: Q) {}\n\n#[get(\"/<_foo..>\")]\nfn f1(_foo: Q) {}\n\n#[get(\"/?<_foo>\")]\nfn f2(_foo: Q) {}\n\n#[get(\"/?<_foo..>\")]\nfn f3(_foo: Q) {}\n\n#[post(\"/\", data = \"<_foo>\")]\nfn f4(_foo: Q) {}\n\n#[get(\"/<_foo>\")]\nfn f5(_a: Q, _foo: Q) {}\n\n#[get(\"/<_foo>/other/<_bar>/<_good>/okay\")]\nfn f6(_a: Q, _foo: Q, _good: usize, _bar: Q) {}\n\nfn main() {  }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/route-warnings.rs",
    "content": "// must-compile-successfully\n\n#[macro_use] extern crate rocket;\n\n// Check for unknown media types.\n\n#[get(\"/\", format = \"application/x-custom\")]\nfn f0() {}\n\n#[get(\"/\", format = \"x-custom/plain\")]\nfn f1() {}\n\n#[get(\"/\", format = \"x-custom/x-custom\")]\nfn f2() {}\n\n#[suppress(unknown_format)]\n#[get(\"/\", format = \"x-custom/x-custom\")]\nfn f3() {}\n\n// Check if a data argument is used with a usually non-payload bearing method.\n\n#[get(\"/\", data = \"<_foo>\")]\nfn g0(_foo: rocket::Data<'_>) {}\n\n#[head(\"/\", data = \"<_foo>\")]\nfn g1(_foo: rocket::Data<'_>) {}\n\n#[suppress(dubious_payload)]\n#[head(\"/\", data = \"<_foo>\")]\nfn g2(_foo: rocket::Data<'_>) {}\n\nfn main() {\n    compile_error!(\"checking for warnings!\")\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/routes.rs",
    "content": "#[macro_use] extern crate rocket;\n\nfn main() {\n    let _ = routes![a b];\n    let _ = routes![];\n    let _ = routes![a::, ];\n    let _ = routes![a::];\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/synchronize.sh",
    "content": "#!/usr/bin/env bash\nset -e\n\n# Symlinks all of the tests in this directory with those in sibling\n# `ui-fail-stable` and `ui-fail-nightly` directories.\n\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nstable=\"${SCRIPT_DIR}/../ui-fail-stable\"\nnightly=\"${SCRIPT_DIR}/../ui-fail-nightly\"\nanchor=\"$(basename ${SCRIPT_DIR})\"\n\necho \":: Synchronizing...\"\necho \"   stable: ${stable}\"\necho \"   nightly: ${nightly}\"\necho \"   anchor: ${anchor}\"\n\nfor dir in \"${stable}\" \"${nightly}\"; do\n  find \"${dir}\" -type l -delete\n\n  for file in \"${SCRIPT_DIR}\"/*.rs; do\n    ln -s \"../${anchor}/$(basename $file)\" \"${dir}/\"\n  done\ndone\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/typed-uri-bad-type.rs",
    "content": "#![allow(unused_variables)]\n\n#[macro_use] extern crate rocket;\n\nuse rocket::request::FromParam;\n\nstruct S;\n\nimpl<'a> FromParam<'a> for S {\n    type Error = ();\n    fn from_param(param: &'a str) -> Result<Self, Self::Error> { Ok(S) }\n}\n\n#[post(\"/<id>\")]\nfn simple(id: usize) {  }\n\n#[post(\"/<id>/<name>\")]\nfn not_uri_display(id: i32, name: S) {  }\n\n#[post(\"/<id>/<name>\")]\nfn not_uri_display_but_unused(id: i32, name: S) {  }\n\n#[post(\"/<id>/<name>\")]\nfn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n\nuse rocket::form::{FromFormField, Errors, ValueField, DataField};\n\n#[rocket::async_trait]\nimpl<'v> FromFormField<'v> for S {\n    fn default() -> Option<Self> { None }\n\n    fn from_value(_: ValueField<'v>) -> Result<Self, Errors<'v>> { Ok(S) }\n\n    async fn from_data(_: DataField<'v, '_>) -> Result<Self, Errors<'v>> { Ok(S) }\n}\n\n#[post(\"/?<id>\")]\nfn simple_q(id: isize) {  }\n\n#[post(\"/?<id>&<rest..>\")]\nfn other_q(id: usize, rest: S) {  }\n\n#[post(\"/?<id>&<name>\")]\nfn optionals_q(id: Option<i32>, name: Result<String, Errors<'_>>) {  }\n\nfn main() {\n    uri!(simple(id = \"hi\"));\n\n    uri!(simple(\"hello\"));\n\n    uri!(simple(id = 239239i64));\n\n    uri!(not_uri_display(10, S));\n\n    // This one is okay. In paths, a value _must_ be supplied.\n    uri!(optionals(id = 10, name = \"bob\".to_string()));\n\n    uri!(optionals(id = Some(10), name = Ok(\"bob\".into())));\n\n    uri!(simple_q(\"hi\"));\n\n    uri!(simple_q(id = \"hi\"));\n\n    uri!(other_q(100, S));\n\n    uri!(other_q(rest = S, id = 100));\n\n    uri!(other_q(rest = _, id = 100));\n\n    uri!(other_q(rest = S, id = _));\n\n    // These are all okay.\n    uri!(optionals_q(_, _));\n    uri!(optionals_q(id = Some(10), name = Some(\"Bob\".to_string())));\n    uri!(optionals_q(_, Some(\"Bob\".into())));\n    uri!(optionals_q(id = _, name = _));\n\n    // Invalid prefixes.\n    uri!(uri!(\"?foo#bar\"), simple(id = \"hi\"));\n    uri!(uri!(\"*\"), simple(id = \"hi\"));\n\n    // Invalid suffix.\n    uri!(_, simple(id = \"hi\"), uri!(\"*\"));\n    uri!(_, simple(id = \"hi\"), uri!(\"/foo/bar\"));\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/typed-uris-bad-params.rs",
    "content": "#![allow(unused_variables)]\n\n#[macro_use] extern crate rocket;\n\nuse rocket::http::CookieJar;\n\n#[post(\"/<id>\")]\nfn has_one(id: i32) {  }\n\n#[post(\"/<id>\")]\nfn has_one_guarded(cookies: &CookieJar<'_>, id: i32) {  }\n\n#[post(\"/<id>?<name>\")]\nfn has_two(cookies: &CookieJar<'_>, id: i32, name: String) {  }\n\n#[post(\"/<id>/<name>\")]\nfn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n\n#[post(\"/<_>\")]\nfn ignored() {  }\n\nfn main() {\n    uri!(has_one);\n    uri!(has_one());\n\n    uri!(has_one(1, 23));\n    uri!(has_one(\"Hello\", 23, ));\n    uri!(has_one_guarded(\"hi\", 100));\n\n    uri!(has_two(10, \"hi\", \"there\"));\n    uri!(has_two(10));\n\n    uri!(has_one(id = 100, name = \"hi\"));\n\n    uri!(has_one(name = 100, id = 100));\n\n    uri!(has_one(name = 100, age = 50, id = 100));\n\n    uri!(has_one(name = 100, age = 50, id = 100, id = 50));\n\n    uri!(has_one(id = 100, id = 100));\n\n    uri!(has_one(id = 100, id = 100, ));\n\n    uri!(has_one(name = \"hi\"));\n\n    uri!(has_one_guarded(cookies = \"hi\", id = 100));\n\n    uri!(has_one_guarded(id = 100, cookies = \"hi\"));\n\n    uri!(has_two(id = 100, id = 100, ));\n\n    uri!(has_two(name = \"hi\"));\n\n    uri!(has_two(cookies = \"hi\", id = 100, id = 10, id = 10));\n\n    uri!(has_two(id = 100, cookies = \"hi\"));\n\n    uri!(optionals(id = _, name = \"bob\".into()));\n\n    uri!(optionals(id = 10, name = _));\n\n    uri!(ignored(_));\n\n    uri!(ignored(_ = 10));\n\n    uri!(ignored(10, 20));\n\n    uri!(ignored(num = 10));\n\n    uri!(ignored(10, \"10\"));\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/typed-uris-invalid-syntax.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[get(\"/\")]\nfn index() {  }\n\n#[post(\"/<_id>/<_name>\")]\nfn simple(_id: i32, _name: String) -> &'static str { \"\" }\n\nfn main() {\n    uri!(simple: id = 100, \"Hello\");\n    uri!(simple(id = 100, \"Hello\"));\n    uri!(simple(\"Hello\", id = 100));\n    uri!(simple,);\n    uri!(simple:);\n    uri!(\"/mount\",);\n    uri!(\"mount\", simple);\n    uri!(\"mount\", simple, \"http://\");\n    uri!(\"/mount\", simple, \"http://\");\n    uri!(\"/mount\", simple, \"#foo\", \"?foo\");\n    uri!(\"mount\", simple(10, \"hi\"), \"http://\");\n    uri!(\"/mount\", simple(10, \"hi\"), \"http://\");\n    uri!(\"/mount?foo\", simple(10, \"hi\"), \"foo/bar?foo#bar\");\n    uri!(\"/mount\", simple(10, \"hi\"), \"a/b\");\n    uri!(\"/mount\", simple(10, \"hi\"), \"#foo\", \"?foo\");\n    uri!(\"/mount/<id>\", simple);\n    uri!();\n    uri!(simple: id = );\n    uri!(simple(id = ));\n    uri!(\"*\", simple(10), \"hi\");\n    uri!(\"some.host:8088\", simple(10), \"hi\");\n    uri!(\"?foo\");\n    uri!(\"\");\n    uri!(\"/foo\", \"bar\");\n    uri!(\"/foo\" (\"bar\"));\n    uri!(\"ftp:?\", index);\n    uri!(\"ftp:\", index, \"foo#bar\");\n    uri!(\"ftp:\", index, \"foo?bar\");\n}\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/uri_display.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[derive(UriDisplayQuery)]\nstruct Foo1;\n\n#[derive(UriDisplayQuery)]\nstruct Foo2();\n\n#[derive(UriDisplayQuery)]\nenum Foo3 { }\n\n#[derive(UriDisplayQuery)]\nenum Foo4 {\n    Variant,\n}\n\n#[derive(UriDisplayQuery)]\nstruct Foo5(String, String);\n\n#[derive(UriDisplayQuery)]\nstruct Foo6 {\n    #[field(name = 123)]\n    field: String,\n}\n\n#[derive(UriDisplayPath)]\nstruct Foo7(String, usize);\n\n#[derive(UriDisplayPath)]\nstruct Foo8;\n\n#[derive(UriDisplayPath)]\nenum Foo9 {  }\n\n#[derive(UriDisplayPath)]\nstruct Foo10 {\n    named: usize\n}\n\nfn main() { }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail/uri_display_type_errors.rs",
    "content": "#[macro_use] extern crate rocket;\n\nstruct BadType;\n\n#[derive(UriDisplayQuery)]\nstruct Bar1(BadType);\n\n#[derive(UriDisplayQuery)]\nstruct Bar2 {\n    field: BadType,\n}\n\n#[derive(UriDisplayQuery)]\nstruct Bar3 {\n    field: String,\n    bad: BadType,\n}\n\n#[derive(UriDisplayQuery)]\nenum Bar4 {\n    Inner(BadType),\n}\n\n#[derive(UriDisplayQuery)]\nenum Bar5 {\n    Inner {\n        field: BadType,\n    },\n}\n\n#[derive(UriDisplayQuery)]\nenum Bar6 {\n    Inner {\n        field: String,\n        other: BadType,\n    },\n}\n\n#[derive(UriDisplayPath)]\nstruct Baz(BadType);\n\nfn main() {  }\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/async-entry.stderr",
    "content": "error: attribute can only be applied to `async` functions\n --> tests/ui-fail-nightly/async-entry.rs:4:5\n  |\n4 |     #[rocket::main]\n  |     ^^^^^^^^^^^^^^^\n  |\nnote: this function must be `async`\n --> tests/ui-fail-nightly/async-entry.rs:5:5\n  |\n5 |     fn foo() { }\n  |     ^^^^^^^^\n  = note: this error originates in the attribute macro `rocket::main` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nwarning: attribute is typically applied to `main` function\n  --> tests/ui-fail-nightly/async-entry.rs:10:5\n   |\n10 |     #[rocket::main]\n   |     ^^^^^^^^^^^^^^^\n   |\nnote: this function is not `main`\n  --> tests/ui-fail-nightly/async-entry.rs:11:14\n   |\n11 |     async fn foo() { }\n   |              ^^^\n   = note: apply `#[suppress(arbitrary_main)]` before the item to suppress this lint\n   = note: this warning originates in the attribute macro `rocket::main` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: attribute can only be applied to `async` functions\n  --> tests/ui-fail-nightly/async-entry.rs:16:5\n   |\n16 |     #[rocket::main]\n   |     ^^^^^^^^^^^^^^^\n   |\nnote: this function must be `async`\n  --> tests/ui-fail-nightly/async-entry.rs:17:5\n   |\n17 |     fn main() {\n   |     ^^^^^^^^^\n   = note: this error originates in the attribute macro `rocket::main` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: attribute cannot be applied to `main` function\n  --> tests/ui-fail-nightly/async-entry.rs:49:5\n   |\n49 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this attribute generates a `main` function\nnote: this function cannot be `main`\n  --> tests/ui-fail-nightly/async-entry.rs:50:8\n   |\n50 |     fn main() -> rocket::Rocket<rocket::Build> {\n   |        ^^^^\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: attribute can only be applied to functions that return a value\n  --> tests/ui-fail-nightly/async-entry.rs:56:5\n   |\n56 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\nnote: this function must return a value\n  --> tests/ui-fail-nightly/async-entry.rs:57:5\n   |\n57 |     async fn rocket() {\n   |     ^^^^^^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: attribute can only be applied to functions that return a value\n  --> tests/ui-fail-nightly/async-entry.rs:64:5\n   |\n64 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\nnote: this function must return a value\n  --> tests/ui-fail-nightly/async-entry.rs:65:5\n   |\n65 |     fn rocket() {\n   |     ^^^^^^^^^^^\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: attribute cannot be applied to `main` function\n  --> tests/ui-fail-nightly/async-entry.rs:79:5\n   |\n79 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this attribute generates a `main` function\nnote: this function cannot be `main`\n  --> tests/ui-fail-nightly/async-entry.rs:80:8\n   |\n80 |     fn main() -> &'static str {\n   |        ^^^^\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: attribute cannot be applied to `main` function\n  --> tests/ui-fail-nightly/async-entry.rs:87:5\n   |\n87 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this attribute generates a `main` function\nnote: this function cannot be `main`\n  --> tests/ui-fail-nightly/async-entry.rs:88:14\n   |\n88 |     async fn main() -> _ {\n   |              ^^^^\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0728]: `await` is only allowed inside `async` functions and blocks\n  --> tests/ui-fail-nightly/async-entry.rs:73:42\n   |\n72 |     fn rocket() -> _ {\n   |     ---------------- this is not `async`\n73 |         let _ = rocket::build().launch().await;\n   |                                          ^^^^^ only allowed inside `async` functions and blocks\n\nerror[E0277]: `main` has invalid return type `Rocket<Build>`\n  --> tests/ui-fail-nightly/async-entry.rs:94:20\n   |\n94 | async fn main() -> rocket::Rocket<rocket::Build> {\n   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` can only return types that implement `Termination`\n   |\n   = help: consider using `()`, or a `Result`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-nightly/async-entry.rs:35:9\n   |\n33 |     async fn rocket() -> String {\n   |                          ------ expected `std::string::String` because of return type\n34 |         let _ = rocket::build().launch().await;\n35 |         rocket::build()\n   |         ^^^^^^^^^^^^^^^ expected `String`, found `Rocket<Build>`\n   |\n   = note: expected struct `std::string::String`\n              found struct `Rocket<Build>`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-nightly/async-entry.rs:44:9\n   |\n42 |     async fn rocket() -> _ {\n   |                          - expected `Rocket<Build>` because of return type\n43 |         let _ = rocket::build().launch().await;\n44 |         \"hi\".to_string()\n   |         ^^^^^^^^^^^^^^^^ expected `Rocket<Build>`, found `String`\n   |\n   = note: expected struct `Rocket<Build>`\n              found struct `std::string::String`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-nightly/async-entry.rs:24:21\n   |\n24 |       async fn main() {\n   |  ____________________-^\n   | |                    |\n   | |                    expected `()` because of default return type\n25 | |         rocket::build()\n26 | |     }\n   | |     ^- help: consider using a semicolon here: `;`\n   | |_____|\n   |       expected `()`, found `Rocket<Build>`\n   |\n   = note: expected unit type `()`\n                 found struct `Rocket<Build>`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-nightly/async-entry.rs:35:9\n   |\n35 |         rocket::build()\n   |         ^^^^^^^^^^^^^^^ expected `String`, found `Rocket<Build>`\n   |\n   = note: expected struct `std::string::String`\n              found struct `Rocket<Build>`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-nightly/async-entry.rs:44:9\n   |\n44 |         \"hi\".to_string()\n   |         ^^^^^^^^^^^^^^^^ expected `Rocket<Build>`, found `String`\n   |\n   = note: expected struct `Rocket<Build>`\n              found struct `std::string::String`\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/bad-ignored-segments.stderr",
    "content": "error: parameter must be named\n --> tests/ui-fail-nightly/bad-ignored-segments.rs:6:12\n  |\n6 | #[get(\"/c?<_>\")]\n  |            ^\n  |\n  = help: use a name such as `_guard` or `_param`\n\nerror: parameter must be named\n --> tests/ui-fail-nightly/bad-ignored-segments.rs:9:22\n  |\n9 | #[post(\"/d\", data = \"<_>\")]\n  |                      ^^^\n  |\n  = help: use a name such as `_guard` or `_param`\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/catch.stderr",
    "content": "error: expected `fn`\n --> tests/ui-fail-nightly/catch.rs:6:1\n  |\n6 | struct Catcher(String);\n  | ^^^^^^\n  |\n  = help: `#[catch]` can only be used on functions\n\nerror: expected `fn`\n --> tests/ui-fail-nightly/catch.rs:9:7\n  |\n9 | const CATCH: &str = \"Catcher\";\n  |       ^^^^^\n  |\n  = help: `#[catch]` can only be used on functions\n\nerror: expected integer or `default`, found string literal\n  --> tests/ui-fail-nightly/catch.rs:11:9\n   |\n11 | #[catch(\"404\")]\n   |         ^^^^^\n   |\n   = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n\nerror: unexpected keyed parameter: expected literal or identifier\n  --> tests/ui-fail-nightly/catch.rs:14:9\n   |\n14 | #[catch(code = \"404\")]\n   |         ^^^^^^^^^^^^\n   |\n   = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n\nerror: unexpected keyed parameter: expected literal or identifier\n  --> tests/ui-fail-nightly/catch.rs:17:9\n   |\n17 | #[catch(code = 404)]\n   |         ^^^^^^^^^^\n   |\n   = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n\nerror: status must be in range [100, 599]\n  --> tests/ui-fail-nightly/catch.rs:20:9\n   |\n20 | #[catch(99)]\n   |         ^^\n   |\n   = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n\nerror: status must be in range [100, 599]\n  --> tests/ui-fail-nightly/catch.rs:23:9\n   |\n23 | #[catch(600)]\n   |         ^^^\n   |\n   = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n\nerror: unexpected attribute parameter: `message`\n  --> tests/ui-fail-nightly/catch.rs:26:14\n   |\n26 | #[catch(400, message = \"foo\")]\n   |              ^^^^^^^^^^^^^^^\n   |\n   = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n\nerror[E0308]: arguments to this function are incorrect\n  --> tests/ui-fail-nightly/catch.rs:30:4\n   |\n30 | fn f3(_request: &Request, _other: bool) { }\n   |    ^^           --------          ---- argument #2 of type `bool` is missing\n   |                 |\n   |                 unexpected argument #1 of type `Status`\n   |\nnote: function defined here\n  --> tests/ui-fail-nightly/catch.rs:30:4\n   |\n30 | fn f3(_request: &Request, _other: bool) { }\n   |    ^^ ------------------  ------------\nhelp: provide the argument\n   |\n29 | f3(bool, /* bool */)\n   |\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/catch_type_errors.stderr",
    "content": "error[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n --> tests/ui-fail-nightly/catch_type_errors.rs:6:30\n  |\n5 | #[catch(404)]\n  | ------------- required by a bound introduced by this call\n6 | fn f1(_request: &Request) -> usize {\n  |                              ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n  |\n  = help: the following other types implement trait `Responder<'r, 'o>`:\n            `&'o [u8]` implements `Responder<'r, 'o>`\n            `&'o str` implements `Responder<'r, 'o>`\n            `()` implements `Responder<'r, 'static>`\n            `(ContentType, R)` implements `Responder<'r, 'o>`\n            `(Status, R)` implements `Responder<'r, 'o>`\n            `Accepted<R>` implements `Responder<'r, 'o>`\n            `Arc<[u8]>` implements `Responder<'r, 'static>`\n            `Arc<str>` implements `Responder<'r, 'static>`\n          and $N others\n\nerror[E0277]: the trait bound `bool: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-nightly/catch_type_errors.rs:11:30\n   |\n10 | #[catch(404)]\n   | ------------- required by a bound introduced by this call\n11 | fn f2(_request: &Request) -> bool {\n   |                              ^^^^ the trait `Responder<'_, '_>` is not implemented for `bool`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             `&'o [u8]` implements `Responder<'r, 'o>`\n             `&'o str` implements `Responder<'r, 'o>`\n             `()` implements `Responder<'r, 'static>`\n             `(ContentType, R)` implements `Responder<'r, 'o>`\n             `(Status, R)` implements `Responder<'r, 'o>`\n             `Accepted<R>` implements `Responder<'r, 'o>`\n             `Arc<[u8]>` implements `Responder<'r, 'static>`\n             `Arc<str>` implements `Responder<'r, 'static>`\n           and $N others\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-nightly/catch_type_errors.rs:16:17\n   |\n16 | fn f3(_request: bool) -> usize {\n   |    --           ^^^^ expected `bool`, found `&Request<'_>`\n   |    |\n   |    arguments to this function are incorrect\n   |\nnote: function defined here\n  --> tests/ui-fail-nightly/catch_type_errors.rs:16:4\n   |\n16 | fn f3(_request: bool) -> usize {\n   |    ^^ --------------\n\nerror[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-nightly/catch_type_errors.rs:16:26\n   |\n15 | #[catch(404)]\n   | ------------- required by a bound introduced by this call\n16 | fn f3(_request: bool) -> usize {\n   |                          ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             `&'o [u8]` implements `Responder<'r, 'o>`\n             `&'o str` implements `Responder<'r, 'o>`\n             `()` implements `Responder<'r, 'static>`\n             `(ContentType, R)` implements `Responder<'r, 'o>`\n             `(Status, R)` implements `Responder<'r, 'o>`\n             `Accepted<R>` implements `Responder<'r, 'o>`\n             `Arc<[u8]>` implements `Responder<'r, 'static>`\n             `Arc<str>` implements `Responder<'r, 'static>`\n           and $N others\n\nerror[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-nightly/catch_type_errors.rs:21:12\n   |\n20 | #[catch(404)]\n   | ------------- required by a bound introduced by this call\n21 | fn f4() -> usize {\n   |            ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             `&'o [u8]` implements `Responder<'r, 'o>`\n             `&'o str` implements `Responder<'r, 'o>`\n             `()` implements `Responder<'r, 'static>`\n             `(ContentType, R)` implements `Responder<'r, 'o>`\n             `(Status, R)` implements `Responder<'r, 'o>`\n             `Accepted<R>` implements `Responder<'r, 'o>`\n             `Arc<[u8]>` implements `Responder<'r, 'static>`\n             `Arc<str>` implements `Responder<'r, 'static>`\n           and $N others\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/catchers.stderr",
    "content": "error: expected `,`\n --> tests/ui-fail-nightly/catchers.rs:4:25\n  |\n4 |     let _ = catchers![a b];\n  |                         ^\n\nerror: expected identifier\n --> tests/ui-fail-nightly/catchers.rs:6:26\n  |\n6 |     let _ = catchers![a::, ];\n  |                          ^\n\nerror: unexpected end of input, expected identifier\n --> tests/ui-fail-nightly/catchers.rs:7:13\n  |\n7 |     let _ = catchers![a::];\n  |             ^^^^^^^^^^^^^^\n  |\n  = note: this error originates in the macro `catchers` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/from_form.stderr",
    "content": "error: enums are not supported\n --> tests/ui-fail-nightly/from_form.rs:4:1\n  |\n4 | enum Thing { }\n  | ^^^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `FromForm`\n --> tests/ui-fail-nightly/from_form.rs:3:10\n  |\n3 | #[derive(FromForm)]\n  |          ^^^^^^^^\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: at least one field is required\n --> tests/ui-fail-nightly/from_form.rs:7:1\n  |\n7 | struct Foo1;\n  | ^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `FromForm`\n --> tests/ui-fail-nightly/from_form.rs:6:10\n  |\n6 | #[derive(FromForm)]\n  |          ^^^^^^^^\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: at least one field is required\n  --> tests/ui-fail-nightly/from_form.rs:10:13\n   |\n10 | struct Foo2 {  }\n   |             ^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:9:10\n   |\n9  | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple struct must have exactly one field\n  --> tests/ui-fail-nightly/from_form.rs:16:12\n   |\n16 | struct Foo4(usize, usize, usize);\n   |            ^^^^^^^^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:15:10\n   |\n15 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: only one lifetime is supported\n  --> tests/ui-fail-nightly/from_form.rs:19:25\n   |\n19 | struct NextTodoTask<'f, 'a> {\n   |                         ^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:18:10\n   |\n18 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n  --> tests/ui-fail-nightly/from_form.rs:28:20\n   |\n28 |     #[field(name = \"isindex\")]\n   |                    ^^^^^^^^^\n   |\n   = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:26:10\n   |\n26 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-nightly/from_form.rs:36:5\n   |\n36 |     foo: usize,\n   |     ^^^\n   |\nhelp: declared in this field\n  --> tests/ui-fail-nightly/from_form.rs:36:5\n   |\n36 |     foo: usize,\n   |     ^^^^^^^^^^\nnote: previous field with conflicting name\n  --> tests/ui-fail-nightly/from_form.rs:34:5\n   |\n34 | /     #[field(name = \"foo\")]\n35 | |     field: String,\n   | |_________________^\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:32:10\n   |\n32 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-nightly/from_form.rs:43:20\n   |\n43 |     #[field(name = \"hello\")]\n   |                    ^^^^^^^\n   |\nhelp: declared in this field\n  --> tests/ui-fail-nightly/from_form.rs:43:5\n   |\n43 | /     #[field(name = \"hello\")]\n44 | |     other: String,\n   | |_________________^\nnote: previous field with conflicting name\n  --> tests/ui-fail-nightly/from_form.rs:41:5\n   |\n41 | /     #[field(name = \"hello\")]\n42 | |     first: String,\n   | |_________________^\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:39:10\n   |\n39 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-nightly/from_form.rs:50:20\n   |\n50 |     #[field(name = \"first\")]\n   |                    ^^^^^^^\n   |\nhelp: declared in this field\n  --> tests/ui-fail-nightly/from_form.rs:50:5\n   |\n50 | /     #[field(name = \"first\")]\n51 | |     other: String,\n   | |_________________^\nnote: previous field with conflicting name\n  --> tests/ui-fail-nightly/from_form.rs:49:5\n   |\n49 |     first: String,\n   |     ^^^^^^^^^^^^^\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:47:10\n   |\n47 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected attribute parameter: `field`\n  --> tests/ui-fail-nightly/from_form.rs:56:28\n   |\n56 |     #[field(name = \"blah\", field = \"bloo\")]\n   |                            ^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:54:10\n   |\n54 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[field(..)]`, found bare path \"field\"\n  --> tests/ui-fail-nightly/from_form.rs:62:7\n   |\n62 |     #[field]\n   |       ^^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:60:10\n   |\n60 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-nightly/from_form.rs:68:13\n   |\n68 |     #[field(\"blah\")]\n   |             ^^^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:66:10\n   |\n66 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-nightly/from_form.rs:74:13\n   |\n74 |     #[field(123)]\n   |             ^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:72:10\n   |\n72 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected attribute parameter: `beep`\n  --> tests/ui-fail-nightly/from_form.rs:80:13\n   |\n80 |     #[field(beep = \"bop\")]\n   |             ^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:78:10\n   |\n78 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field has conflicting names\n  --> tests/ui-fail-nightly/from_form.rs:86:5\n   |\n86 | /     #[field(name = \"blah\")]\n87 | |     #[field(name = \"blah\")]\n88 | |     my_field: String,\n   | |____________________^\n   |\nnote: this field name...\n  --> tests/ui-fail-nightly/from_form.rs:86:20\n   |\n86 |     #[field(name = \"blah\")]\n   |                    ^^^^^^\nnote: ...conflicts with this field name\n  --> tests/ui-fail-nightly/from_form.rs:87:20\n   |\n87 |     #[field(name = \"blah\")]\n   |                    ^^^^^^\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:84:10\n   |\n84 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[attr(..)]`, found bare boolean literal\n  --> tests/ui-fail-nightly/from_form.rs:93:20\n   |\n93 |     #[field(name = true)]\n   |                    ^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:91:10\n   |\n91 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected expression, found bare path \"name\"\n  --> tests/ui-fail-nightly/from_form.rs:99:13\n   |\n99 |     #[field(name)]\n   |             ^^^^\n   |\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form.rs:97:10\n   |\n97 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[attr(..)]`, found bare integer literal\n   --> tests/ui-fail-nightly/from_form.rs:105:20\n    |\n105 |     #[field(name = 123)]\n    |                    ^^^\n    |\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:103:10\n    |\n103 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n   --> tests/ui-fail-nightly/from_form.rs:111:20\n    |\n111 |     #[field(name = \"hello&world\")]\n    |                    ^^^^^^^^^^^^^\n    |\n    = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:109:10\n    |\n109 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n   --> tests/ui-fail-nightly/from_form.rs:117:20\n    |\n117 |     #[field(name = \"!@#$%^&*()_\")]\n    |                    ^^^^^^^^^^^^^\n    |\n    = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:115:10\n    |\n115 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n   --> tests/ui-fail-nightly/from_form.rs:123:20\n    |\n123 |     #[field(name = \"?\")]\n    |                    ^^^\n    |\n    = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:121:10\n    |\n121 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n   --> tests/ui-fail-nightly/from_form.rs:129:20\n    |\n129 |     #[field(name = \"\")]\n    |                    ^^\n    |\n    = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:127:10\n    |\n127 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n   --> tests/ui-fail-nightly/from_form.rs:135:20\n    |\n135 |     #[field(name = \"a&b\")]\n    |                    ^^^^^\n    |\n    = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:133:10\n    |\n133 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n   --> tests/ui-fail-nightly/from_form.rs:141:20\n    |\n141 |     #[field(name = \"a=\")]\n    |                    ^^^^\n    |\n    = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:139:10\n    |\n139 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate attribute parameter: default\n   --> tests/ui-fail-nightly/from_form.rs:177:26\n    |\n177 |     #[field(default = 1, default = 2)]\n    |                          ^^^^^^^^^^^\n    |\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:175:10\n    |\n175 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate default field expression\n   --> tests/ui-fail-nightly/from_form.rs:184:23\n    |\n181 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n...\n184 |     #[field(default = 2)]\n    |                       ^\n    |\n    = help: at most one `default` or `default_with` is allowed\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:181:10\n    |\n181 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate default expressions\n   --> tests/ui-fail-nightly/from_form.rs:190:23\n    |\n188 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n189 | struct Default3 {\n190 |     #[field(default = 1, default_with = None)]\n    |                       ^\n    |\n    = help: only one of `default` or `default_with` must be used\nnote: other default expression is here\n   --> tests/ui-fail-nightly/from_form.rs:190:41\n    |\n190 |     #[field(default = 1, default_with = None)]\n    |                                         ^^^^\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:188:10\n    |\n188 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate default expressions\n   --> tests/ui-fail-nightly/from_form.rs:197:23\n    |\n194 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n...\n197 |     #[field(default = 1)]\n    |                       ^\n    |\n    = help: only one of `default` or `default_with` must be used\nnote: other default expression is here\n   --> tests/ui-fail-nightly/from_form.rs:196:28\n    |\n196 |     #[field(default_with = None)]\n    |                            ^^^^\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form.rs:194:10\n    |\n194 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-nightly/from_form.rs:147:24\n    |\n147 |     #[field(validate = 123)]\n    |                        ^^^ expected `Result<(), Errors<'_>>`, found integer\n    |\n    = note: expected enum `Result<(), Errors<'_>>`\n               found type `{integer}`\n\nerror[E0425]: cannot find function `unknown` in this scope\n   --> tests/ui-fail-nightly/from_form.rs:153:24\n    |\n153 |     #[field(validate = unknown())]\n    |                        ^^^^^^^ not found in this scope\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-nightly/from_form.rs:160:12\n    |\n159 |     #[field(validate = ext(rocket::http::ContentType::HTML))]\n    |                        --- arguments to this function are incorrect\n160 |     first: String,\n    |            ^^^^^^ expected `&TempFile<'_>`, found `&String`\n    |\n    = note: expected reference `&TempFile<'_>`\n               found reference `&std::string::String`\nnote: function defined here\n   --> $WORKSPACE/core/lib/src/form/validate.rs\n    |\n    | pub fn ext<'v>(file: &TempFile<'_>, r#type: ContentType) -> Result<'v, ()> {\n    |        ^^^\n\nerror[E0308]: arguments to this function are incorrect\n   --> tests/ui-fail-nightly/from_form.rs:165:24\n    |\n165 |     #[field(validate = ext(\"hello\"))]\n    |                        ^^^ ------- expected `ContentType`, found `&str`\n166 |     first: String,\n    |            ------ expected `&TempFile<'_>`, found `&String`\n    |\n    = note: expected reference `&TempFile<'_>`\n               found reference `&std::string::String`\nnote: function defined here\n   --> $WORKSPACE/core/lib/src/form/validate.rs\n    |\n    | pub fn ext<'v>(file: &TempFile<'_>, r#type: ContentType) -> Result<'v, ()> {\n    |        ^^^\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-nightly/from_form.rs:171:23\n    |\n171 |     #[field(default = 123)]\n    |                       ^^^- help: try using a conversion method: `.to_string()`\n    |                       |\n    |                       expected `String`, found integer\n    |                       arguments to this enum variant are incorrect\n    |\nhelp: the type constructed contains `{integer}` due to the type of the argument passed\n   --> tests/ui-fail-nightly/from_form.rs:171:23\n    |\n169 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n170 | struct Default0 {\n171 |     #[field(default = 123)]\n    |                       ^^^ this argument influences the type of `Some`\nnote: tuple variant defined here\n   --> $RUST/core/src/option.rs\n    |\n    |     Some(#[stable(feature = \"rust1\", since = \"1.0.0\")] T),\n    |     ^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-nightly/from_form.rs:203:33\n    |\n203 |     #[field(default_with = Some(\"hi\"))]\n    |                            ---- ^^^^- help: try using a conversion method: `.to_string()`\n    |                            |    |\n    |                            |    expected `String`, found `&str`\n    |                            arguments to this enum variant are incorrect\n    |\nhelp: the type constructed contains `&'static str` due to the type of the argument passed\n   --> tests/ui-fail-nightly/from_form.rs:203:28\n    |\n203 |     #[field(default_with = Some(\"hi\"))]\n    |                            ^^^^^----^\n    |                                 |\n    |                                 this argument influences the type of `Some`\nnote: tuple variant defined here\n   --> $RUST/core/src/option.rs\n    |\n    |     Some(#[stable(feature = \"rust1\", since = \"1.0.0\")] T),\n    |     ^^^^\n\nerror[E0277]: the trait bound `bool: From<&str>` is not satisfied\n   --> tests/ui-fail-nightly/from_form.rs:209:23\n    |\n207 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n208 | struct Default6 {\n209 |     #[field(default = \"no conversion\")]\n    |                       ^^^^^^^^^^^^^^^\n    |                       |\n    |                       the trait `From<&str>` is not implemented for `bool`, which is required by `&str: Into<_>`\n    |                       this tail expression is of type `&str`\n    |\n    = help: the following other types implement trait `From<T>`:\n              `bool` implements `From<format_description::parse::format_item::HourBase>`\n              `bool` implements `From<format_description::parse::format_item::MonthCaseSensitive>`\n              `bool` implements `From<format_description::parse::format_item::PeriodCase>`\n              `bool` implements `From<format_description::parse::format_item::PeriodCaseSensitive>`\n              `bool` implements `From<format_description::parse::format_item::SignBehavior>`\n              `bool` implements `From<format_description::parse::format_item::WeekdayCaseSensitive>`\n              `bool` implements `From<format_description::parse::format_item::WeekdayOneIndexed>`\n              `bool` implements `From<format_description::parse::format_item::YearBase>`\n    = note: required for `&str` to implement `Into<bool>`\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/from_form_field.stderr",
    "content": "error: tuple structs are not supported\n --> tests/ui-fail-nightly/from_form_field.rs:4:1\n  |\n4 | struct Foo1;\n  | ^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `FromFormField`\n --> tests/ui-fail-nightly/from_form_field.rs:3:10\n  |\n3 | #[derive(FromFormField)]\n  |          ^^^^^^^^^^^^^\n  = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple structs are not supported\n --> tests/ui-fail-nightly/from_form_field.rs:7:1\n  |\n7 | struct Foo2(usize);\n  | ^^^^^^^^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `FromFormField`\n --> tests/ui-fail-nightly/from_form_field.rs:6:10\n  |\n6 | #[derive(FromFormField)]\n  |          ^^^^^^^^^^^^^\n  = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n  --> tests/ui-fail-nightly/from_form_field.rs:10:1\n   |\n10 | / struct Foo3 {\n11 | |     foo: usize,\n12 | | }\n   | |_^\n   |\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:9:10\n   |\n9  | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variants cannot have fields\n  --> tests/ui-fail-nightly/from_form_field.rs:16:6\n   |\n16 |     A(usize),\n   |      ^^^^^^^\n   |\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:14:10\n   |\n14 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: enum must have at least one variant\n  --> tests/ui-fail-nightly/from_form_field.rs:20:1\n   |\n20 | enum Foo5 { }\n   | ^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:19:10\n   |\n19 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: type generics are not supported\n  --> tests/ui-fail-nightly/from_form_field.rs:23:11\n   |\n23 | enum Foo6<T> {\n   |           ^\n   |\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:22:10\n   |\n22 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-nightly/from_form_field.rs:29:21\n   |\n29 |     #[field(value = 123)]\n   |                     ^^^\n   |\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:27:10\n   |\n27 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected literal, found bare path \"value\"\n  --> tests/ui-fail-nightly/from_form_field.rs:35:13\n   |\n35 |     #[field(value)]\n   |             ^^^^^\n   |\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:33:10\n   |\n33 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variant has conflicting values\n  --> tests/ui-fail-nightly/from_form_field.rs:41:5\n   |\n41 | /     #[field(value = \"bar\")]\n42 | |     #[field(value = \"bar\")]\n43 | |     A,\n   | |_____^\n   |\nnote: this value...\n  --> tests/ui-fail-nightly/from_form_field.rs:41:21\n   |\n41 |     #[field(value = \"bar\")]\n   |                     ^^^^^\nnote: ...conflicts with this value\n  --> tests/ui-fail-nightly/from_form_field.rs:42:21\n   |\n42 |     #[field(value = \"bar\")]\n   |                     ^^^^^\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:39:10\n   |\n39 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field value conflicts with previous value\n  --> tests/ui-fail-nightly/from_form_field.rs:50:21\n   |\n50 |     #[field(value = \"BAr\")]\n   |                     ^^^^^\n   |\nhelp: ...declared in this variant\n  --> tests/ui-fail-nightly/from_form_field.rs:50:5\n   |\n50 | /     #[field(value = \"BAr\")]\n51 | |     B,\n   | |_____^\nnote: previous field with conflicting name\n  --> tests/ui-fail-nightly/from_form_field.rs:48:5\n   |\n48 | /     #[field(value = \"bar\")]\n49 | |     A,\n   | |_____^\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:46:10\n   |\n46 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field value conflicts with previous value\n  --> tests/ui-fail-nightly/from_form_field.rs:57:21\n   |\n57 |     #[field(value = \"a\")]\n   |                     ^^^\n   |\nhelp: ...declared in this variant\n  --> tests/ui-fail-nightly/from_form_field.rs:57:5\n   |\n57 | /     #[field(value = \"a\")]\n58 | |     B,\n   | |_____^\nnote: previous field with conflicting name\n  --> tests/ui-fail-nightly/from_form_field.rs:56:5\n   |\n56 |     A,\n   |     ^\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:54:10\n   |\n54 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variant has conflicting values\n  --> tests/ui-fail-nightly/from_form_field.rs:80:5\n   |\n80 | /     #[field(value = \"FoO\")]\n81 | |     #[field(value = \"foo\")]\n82 | |     A,\n   | |_____^\n   |\nnote: this value...\n  --> tests/ui-fail-nightly/from_form_field.rs:80:21\n   |\n80 |     #[field(value = \"FoO\")]\n   |                     ^^^^^\nnote: ...conflicts with this value\n  --> tests/ui-fail-nightly/from_form_field.rs:81:21\n   |\n81 |     #[field(value = \"foo\")]\n   |                     ^^^^^\nnote: error occurred while deriving `FromFormField`\n  --> tests/ui-fail-nightly/from_form_field.rs:78:10\n   |\n78 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field has conflicting names\n  --> tests/ui-fail-nightly/from_form_field.rs:87:5\n   |\n87 | /     #[field(name = \"foo\")]\n88 | |     #[field(name = uncased(\"FOO\"))]\n89 | |     single: usize,\n   | |_________________^\n   |\nnote: this field name...\n  --> tests/ui-fail-nightly/from_form_field.rs:87:20\n   |\n87 |     #[field(name = \"foo\")]\n   |                    ^^^^^\nnote: ...conflicts with this field name\n  --> tests/ui-fail-nightly/from_form_field.rs:88:28\n   |\n88 |     #[field(name = uncased(\"FOO\"))]\n   |                            ^^^^^\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form_field.rs:85:10\n   |\n85 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-nightly/from_form_field.rs:96:20\n   |\n96 |     #[field(name = \"foo\")]\n   |                    ^^^^^\n   |\nhelp: declared in this field\n  --> tests/ui-fail-nightly/from_form_field.rs:96:5\n   |\n96 | /     #[field(name = \"foo\")]\n97 | |     other: usize,\n   | |________________^\nnote: previous field with conflicting name\n  --> tests/ui-fail-nightly/from_form_field.rs:94:5\n   |\n94 | /     #[field(name = \"foo\")]\n95 | |     single: usize,\n   | |_________________^\nnote: error occurred while deriving `FromForm`\n  --> tests/ui-fail-nightly/from_form_field.rs:92:10\n   |\n92 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n   --> tests/ui-fail-nightly/from_form_field.rs:104:5\n    |\n104 |     hello_there: usize,\n    |     ^^^^^^^^^^^\n    |\nhelp: declared in this field\n   --> tests/ui-fail-nightly/from_form_field.rs:104:5\n    |\n104 |     hello_there: usize,\n    |     ^^^^^^^^^^^^^^^^^^\nnote: previous field with conflicting name\n   --> tests/ui-fail-nightly/from_form_field.rs:102:5\n    |\n102 | /     #[field(name = uncased(\"HELLO_THERE\"))]\n103 | |     single: usize,\n    | |_________________^\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form_field.rs:100:10\n    |\n100 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n   --> tests/ui-fail-nightly/from_form_field.rs:111:5\n    |\n111 |     hello_there: usize,\n    |     ^^^^^^^^^^^\n    |\nhelp: declared in this field\n   --> tests/ui-fail-nightly/from_form_field.rs:111:5\n    |\n111 |     hello_there: usize,\n    |     ^^^^^^^^^^^^^^^^^^\nnote: previous field with conflicting name\n   --> tests/ui-fail-nightly/from_form_field.rs:109:5\n    |\n109 | /     #[field(name = \"hello_there\")]\n110 | |     single: usize,\n    | |_________________^\nnote: error occurred while deriving `FromForm`\n   --> tests/ui-fail-nightly/from_form_field.rs:107:10\n    |\n107 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/from_form_type_errors.stderr",
    "content": "error[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-nightly/from_form_type_errors.rs:7:12\n  |\n7 |     field: Unknown,\n  |            ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-nightly/from_form_type_errors.rs:5:10\n  |\n5 |   #[derive(FromForm)]\n  |            ^-------\n  |            |\n  |  __________in this derive macro expansion\n  | |\n6 | | struct BadType3 {\n  | |_______________^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `_::FromFormGeneratedContext<'r>: std::marker::Send`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\nnote: required because it appears within the type `_::FromFormGeneratedContext<'r>`\n --> tests/ui-fail-nightly/from_form_type_errors.rs:6:8\n  |\n5 | #[derive(FromForm)]\n  |          -------- in this derive macro expansion\n6 | struct BadType3 {\n  |        ^^^^^^^^\nnote: required by a bound in `rocket::form::FromForm::Context`\n --> $WORKSPACE/core/lib/src/form/from_form.rs\n  |\n  |     type Context: Send;\n  |                   ^^^^ required by this bound in `FromForm::Context`\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-nightly/from_form_type_errors.rs:14:12\n   |\n14 |     field: Foo<usize>,\n   |            ^^^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-nightly/from_form_type_errors.rs:12:10\n   |\n12 |   #[derive(FromForm)]\n   |            ^-------\n   |            |\n   |  __________in this derive macro expansion\n   | |\n13 | | struct Other {\n   | |____________^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `_::FromFormGeneratedContext<'r>: std::marker::Send`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\nnote: required because it appears within the type `_::FromFormGeneratedContext<'r>`\n  --> tests/ui-fail-nightly/from_form_type_errors.rs:13:8\n   |\n12 | #[derive(FromForm)]\n   |          -------- in this derive macro expansion\n13 | struct Other {\n   |        ^^^^^\nnote: required by a bound in `rocket::form::FromForm::Context`\n  --> $WORKSPACE/core/lib/src/form/from_form.rs\n   |\n   |     type Context: Send;\n   |                   ^^^^ required by this bound in `FromForm::Context`\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-nightly/from_form_type_errors.rs:5:10\n  |\n5 | #[derive(FromForm)]\n  |          ^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Unknown: FromForm<'r>` is not satisfied\n --> tests/ui-fail-nightly/from_form_type_errors.rs:7:12\n  |\n7 |     field: Unknown,\n  |            ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-nightly/from_form_type_errors.rs:7:12\n  |\n5 | #[derive(FromForm)]\n  |          -------- in this derive macro expansion\n6 | struct BadType3 {\n7 |     field: Unknown,\n  |            ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-nightly/from_form_type_errors.rs:12:10\n   |\n12 | #[derive(FromForm)]\n   |          ^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Foo<usize>: FromForm<'r>` is not satisfied\n  --> tests/ui-fail-nightly/from_form_type_errors.rs:14:12\n   |\n14 |     field: Foo<usize>,\n   |            ^^^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-nightly/from_form_type_errors.rs:14:12\n   |\n12 | #[derive(FromForm)]\n   |          -------- in this derive macro expansion\n13 | struct Other {\n14 |     field: Foo<usize>,\n   |            ^^^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/from_param.stderr",
    "content": "error: named structs are not supported\n --> tests/ui-fail-nightly/from_param.rs:4:1\n  |\n4 | / struct Foo1 {\n5 | |     a: String\n6 | | }\n  | |_^\n  |\nnote: error occurred while deriving `FromParam`\n --> tests/ui-fail-nightly/from_param.rs:3:10\n  |\n3 | #[derive(FromParam)]\n  |          ^^^^^^^^^\n  = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n --> tests/ui-fail-nightly/from_param.rs:9:1\n  |\n9 | struct Foo2 {}\n  | ^^^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `FromParam`\n --> tests/ui-fail-nightly/from_param.rs:8:10\n  |\n8 | #[derive(FromParam)]\n  |          ^^^^^^^^^\n  = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variants with data fields are not supported\n  --> tests/ui-fail-nightly/from_param.rs:13:6\n   |\n13 |     A(String),\n   |      ^^^^^^^^\n   |\nnote: error occurred while deriving `FromParam`\n  --> tests/ui-fail-nightly/from_param.rs:11:10\n   |\n11 | #[derive(FromParam)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple structs are not supported\n  --> tests/ui-fail-nightly/from_param.rs:18:1\n   |\n18 | struct Foo4(usize);\n   | ^^^^^^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `FromParam`\n  --> tests/ui-fail-nightly/from_param.rs:17:10\n   |\n17 | #[derive(FromParam)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/responder-types.stderr",
    "content": "error[E0277]: the trait bound `u8: Responder<'_, '_>` is not satisfied\n --> tests/ui-fail-nightly/responder-types.rs:5:12\n  |\n5 |     thing: u8,\n  |            ^^ the trait `Responder<'_, '_>` is not implemented for `u8`\n  |\n  = help: the following other types implement trait `Responder<'r, 'o>`:\n            `&'o [u8]` implements `Responder<'r, 'o>`\n            `&'o str` implements `Responder<'r, 'o>`\n            `()` implements `Responder<'r, 'static>`\n            `(ContentType, R)` implements `Responder<'r, 'o>`\n            `(Status, R)` implements `Responder<'r, 'o>`\n            `Accepted<R>` implements `Responder<'r, 'o>`\n            `Arc<[u8]>` implements `Responder<'r, 'static>`\n            `Arc<str>` implements `Responder<'r, 'static>`\n          and $N others\n\nerror[E0277]: the trait bound `Header<'_>: From<u8>` is not satisfied\n  --> tests/ui-fail-nightly/responder-types.rs:11:5\n   |\n11 |     other: u8,\n   |     ^^^^^^^^^ the trait `From<u8>` is not implemented for `Header<'_>`, which is required by `u8: Into<Header<'_>>`\n   |\n   = help: the following other types implement trait `From<T>`:\n             `Header<'static>` implements `From<&Cookie<'_>>`\n             `Header<'static>` implements `From<&ExpectCt>`\n             `Header<'static>` implements `From<&Frame>`\n             `Header<'static>` implements `From<&Hsts>`\n             `Header<'static>` implements `From<&NoSniff>`\n             `Header<'static>` implements `From<&Permission>`\n             `Header<'static>` implements `From<&Prefetch>`\n             `Header<'static>` implements `From<&Referrer>`\n           and $N others\n   = note: required for `u8` to implement `Into<Header<'_>>`\nnote: required by a bound in `Response::<'r>::set_header`\n  --> $WORKSPACE/core/lib/src/response/response.rs\n   |\n   |     pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {\n   |                                  ^^^^^^^^^^^^^^^^ required by this bound in `Response::<'r>::set_header`\n\nerror[E0277]: the trait bound `u8: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-nightly/responder-types.rs:16:12\n   |\n16 |     thing: u8,\n   |            ^^ the trait `Responder<'_, '_>` is not implemented for `u8`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             `&'o [u8]` implements `Responder<'r, 'o>`\n             `&'o str` implements `Responder<'r, 'o>`\n             `()` implements `Responder<'r, 'static>`\n             `(ContentType, R)` implements `Responder<'r, 'o>`\n             `(Status, R)` implements `Responder<'r, 'o>`\n             `Accepted<R>` implements `Responder<'r, 'o>`\n             `Arc<[u8]>` implements `Responder<'r, 'static>`\n             `Arc<str>` implements `Responder<'r, 'static>`\n           and $N others\n\nerror[E0277]: the trait bound `Header<'_>: From<u8>` is not satisfied\n  --> tests/ui-fail-nightly/responder-types.rs:17:5\n   |\n17 |     other: u8,\n   |     ^^^^^^^^^ the trait `From<u8>` is not implemented for `Header<'_>`, which is required by `u8: Into<Header<'_>>`\n   |\n   = help: the following other types implement trait `From<T>`:\n             `Header<'static>` implements `From<&Cookie<'_>>`\n             `Header<'static>` implements `From<&ExpectCt>`\n             `Header<'static>` implements `From<&Frame>`\n             `Header<'static>` implements `From<&Hsts>`\n             `Header<'static>` implements `From<&NoSniff>`\n             `Header<'static>` implements `From<&Permission>`\n             `Header<'static>` implements `From<&Prefetch>`\n             `Header<'static>` implements `From<&Referrer>`\n           and $N others\n   = note: required for `u8` to implement `Into<Header<'_>>`\nnote: required by a bound in `Response::<'r>::set_header`\n  --> $WORKSPACE/core/lib/src/response/response.rs\n   |\n   |     pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {\n   |                                  ^^^^^^^^^^^^^^^^ required by this bound in `Response::<'r>::set_header`\n\nerror[E0277]: the trait bound `Header<'_>: From<std::string::String>` is not satisfied\n  --> tests/ui-fail-nightly/responder-types.rs:24:5\n   |\n24 |     then: String,\n   |     ^^^^^^^^^^^^ the trait `From<std::string::String>` is not implemented for `Header<'_>`, which is required by `std::string::String: Into<Header<'_>>`\n   |\n   = help: the following other types implement trait `From<T>`:\n             `Header<'static>` implements `From<&Cookie<'_>>`\n             `Header<'static>` implements `From<&ExpectCt>`\n             `Header<'static>` implements `From<&Frame>`\n             `Header<'static>` implements `From<&Hsts>`\n             `Header<'static>` implements `From<&NoSniff>`\n             `Header<'static>` implements `From<&Permission>`\n             `Header<'static>` implements `From<&Prefetch>`\n             `Header<'static>` implements `From<&Referrer>`\n           and $N others\n   = note: required for `std::string::String` to implement `Into<Header<'_>>`\nnote: required by a bound in `Response::<'r>::set_header`\n  --> $WORKSPACE/core/lib/src/response/response.rs\n   |\n   |     pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {\n   |                                  ^^^^^^^^^^^^^^^^ required by this bound in `Response::<'r>::set_header`\n\nerror[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-nightly/responder-types.rs:28:13\n   |\n27 | #[get(\"/\")]\n   | ----------- in this procedural macro expansion\n28 | fn foo() -> usize { 0 }\n   |             ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             `&'o [u8]` implements `Responder<'r, 'o>`\n             `&'o str` implements `Responder<'r, 'o>`\n             `()` implements `Responder<'r, 'static>`\n             `(ContentType, R)` implements `Responder<'r, 'o>`\n             `(Status, R)` implements `Responder<'r, 'o>`\n             `Accepted<R>` implements `Responder<'r, 'o>`\n             `Arc<[u8]>` implements `Responder<'r, 'static>`\n             `Arc<str>` implements `Responder<'r, 'static>`\n           and $N others\nnote: required by a bound in `route::handler::<impl Outcome<Response<'o>, Status, (rocket::Data<'o>, Status)>>::from`\n  --> $WORKSPACE/core/lib/src/route/handler.rs\n   |\n   |     pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {\n   |                    ^^^^^^^^^^^^^^^^^ required by this bound in `route::handler::<impl Outcome<Response<'o>, Status, (Data<'o>, Status)>>::from`\n   = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/responder.stderr",
    "content": "error: need at least one field\n --> tests/ui-fail-nightly/responder.rs:4:1\n  |\n4 | struct Thing1;\n  | ^^^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `Responder`\n --> tests/ui-fail-nightly/responder.rs:3:10\n  |\n3 | #[derive(Responder)]\n  |          ^^^^^^^^^\n  = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: need at least one field\n --> tests/ui-fail-nightly/responder.rs:7:14\n  |\n7 | struct Thing2();\n  |              ^^\n  |\nnote: error occurred while deriving `Responder`\n --> tests/ui-fail-nightly/responder.rs:6:10\n  |\n6 | #[derive(Responder)]\n  |          ^^^^^^^^^\n  = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: need at least one field\n  --> tests/ui-fail-nightly/responder.rs:13:12\n   |\n13 | enum Foo { Bark, }\n   |            ^^^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:12:10\n   |\n12 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: only one lifetime is supported\n  --> tests/ui-fail-nightly/responder.rs:16:14\n   |\n16 | struct Thing4<'a, 'b>(&'a str, &'b str);\n   |              ^^^^^^^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:15:10\n   |\n15 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid or unknown content type\n  --> tests/ui-fail-nightly/responder.rs:25:27\n   |\n25 | #[response(content_type = \"\")]\n   |                           ^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:24:10\n   |\n24 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid or unknown content type\n  --> tests/ui-fail-nightly/responder.rs:29:27\n   |\n29 | #[response(content_type = \"idk\")]\n   |                           ^^^^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:28:10\n   |\n28 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-nightly/responder.rs:33:27\n   |\n33 | #[response(content_type = 100)]\n   |                           ^^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:32:10\n   |\n32 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: status must be in range [100, 599]\n  --> tests/ui-fail-nightly/responder.rs:37:21\n   |\n37 | #[response(status = 8)]\n   |                     ^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:36:10\n   |\n36 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected unsigned integer literal\n  --> tests/ui-fail-nightly/responder.rs:41:21\n   |\n41 | #[response(status = \"404\")]\n   |                     ^^^^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:40:10\n   |\n40 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected unsigned integer literal\n  --> tests/ui-fail-nightly/responder.rs:45:21\n   |\n45 | #[response(status = \"404\", content_type = \"html\")]\n   |                     ^^^^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:44:10\n   |\n44 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-nightly/responder.rs:49:41\n   |\n49 | #[response(status = 404, content_type = 120)]\n   |                                         ^^^\n   |\nnote: error occurred while deriving `Responder`\n  --> tests/ui-fail-nightly/responder.rs:48:10\n   |\n48 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/route-attribute-general-syntax.stderr",
    "content": "error: missing expected parameter: `uri`\n --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:4:1\n  |\n4 | #[get()]\n  | ^^^^^^^^\n  |\n  = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected `fn`\n --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:9:1\n  |\n9 | struct S;\n  | ^^^^^^\n  |\n  = help: #[get] can only be used on functions\n\nerror: expected `fn`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:12:1\n   |\n12 | enum A {  }\n   | ^^^^\n   |\n   = help: #[get] can only be used on functions\n\nerror: expected `fn`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:15:1\n   |\n15 | trait Foo {  }\n   | ^^^^^\n   |\n   = help: #[get] can only be used on functions\n\nerror: expected `fn`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:18:1\n   |\n18 | impl S {  }\n   | ^^^^\n   |\n   = help: #[get] can only be used on functions\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:21:12\n   |\n21 | #[get(\"/\", 123)]\n   |            ^^^\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:24:12\n   |\n24 | #[get(\"/\", \"/\")]\n   |            ^^^\n\nerror: unexpected keyed parameter: expected literal or identifier\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:27:7\n   |\n27 | #[get(data = \"<foo>\", \"/\")]\n   |       ^^^^^^^^^^^^^^\n\nerror: unexpected attribute parameter: `unknown`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:30:12\n   |\n30 | #[get(\"/\", unknown = \"foo\")]\n   |            ^^^^^^^^^^^^^^^\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:33:12\n   |\n33 | #[get(\"/\", ...)]\n   |            ^^^\n\nerror: handler arguments must be named\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:39:7\n   |\n39 | fn c1(_: usize) {}\n   |       ^^^^^^^^\n   |\n   = help: to name an ignored handler argument, use `_name`\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:43:7\n   |\n43 | #[get(100)]\n   |       ^^^\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:46:7\n   |\n46 | #[get('/')]\n   |       ^^^\n\nerror: invalid value: expected integer literal\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:49:19\n   |\n49 | #[get(\"/\", rank = \"1\")]\n   |                   ^^^\n\nerror: invalid value: expected integer literal\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:52:19\n   |\n52 | #[get(\"/\", rank = '1')]\n   |                   ^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:57:21\n   |\n57 | #[get(\"/\", format = \"applicationx-custom\")]\n   |                     ^^^^^^^^^^^^^^^^^^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:60:21\n   |\n60 | #[get(\"/\", format = \"\")]\n   |                     ^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:63:21\n   |\n63 | #[get(\"/\", format = \"//\")]\n   |                     ^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:66:21\n   |\n66 | #[get(\"/\", format = \"/\")]\n   |                     ^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:69:21\n   |\n69 | #[get(\"/\", format = \"a/\")]\n   |                     ^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:72:21\n   |\n72 | #[get(\"/\", format = \"/a\")]\n   |                     ^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:75:21\n   |\n75 | #[get(\"/\", format = \"/a/\")]\n   |                     ^^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:78:21\n   |\n78 | #[get(\"/\", format = \"a/b/\")]\n   |                     ^^^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:81:21\n   |\n81 | #[get(\"/\", format = \"unknown\")]\n   |                     ^^^^^^^^^\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:84:21\n   |\n84 | #[get(\"/\", format = 12)]\n   |                     ^^\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:87:21\n   |\n87 | #[get(\"/\", format = 'j')]\n   |                     ^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:90:21\n   |\n90 | #[get(\"/\", format = \"text//foo\")]\n   |                     ^^^^^^^^^^^\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:95:18\n   |\n95 | #[route(CONNECT, \"/\")]\n   |                  ^^^\n\nerror: invalid or unknown HTTP method\n  --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:98:9\n   |\n98 | #[route(FIX, \"/\")]\n   |         ^^^\n   |\n   = help: known methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH, ACL, BASELINE-CONTROL, BIND, CHECKIN, CHECKOUT, COPY, LABEL, LINK, LOCK, MERGE, MKACTIVITY, MKCALENDAR, MKCOL, MKREDIRECTREF, MKWORKSPACE, MOVE, ORDERPATCH, PROPFIND, PROPPATCH, REBIND, REPORT, SEARCH, UNBIND, UNCHECKOUT, UNLINK, UNLOCK, UPDATE, UPDATEREDIRECTREF, VERSION-CONTROL\n\nerror: invalid or unknown HTTP method\n   --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:101:9\n    |\n101 | #[route(\"hi\", \"/\")]\n    |         ^^^^\n    |\n    = help: known methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH, ACL, BASELINE-CONTROL, BIND, CHECKIN, CHECKOUT, COPY, LABEL, LINK, LOCK, MERGE, MKACTIVITY, MKCALENDAR, MKCOL, MKREDIRECTREF, MKWORKSPACE, MOVE, ORDERPATCH, PROPFIND, PROPPATCH, REBIND, REPORT, SEARCH, UNBIND, UNCHECKOUT, UNLINK, UNLOCK, UPDATE, UPDATEREDIRECTREF, VERSION-CONTROL\n\nerror: expected key/value `key = value`\n   --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:104:16\n    |\n104 | #[route(\"GET\", \"/\")]\n    |                ^^^\n\nerror: expected method ident or string, found integer literal\n   --> tests/ui-fail-nightly/route-attribute-general-syntax.rs:107:9\n    |\n107 | #[route(120, \"/\")]\n    |         ^^^\n    |\n    = help: known methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH, ACL, BASELINE-CONTROL, BIND, CHECKIN, CHECKOUT, COPY, LABEL, LINK, LOCK, MERGE, MKACTIVITY, MKCALENDAR, MKCOL, MKREDIRECTREF, MKWORKSPACE, MOVE, ORDERPATCH, PROPFIND, PROPPATCH, REBIND, REPORT, SEARCH, UNBIND, UNCHECKOUT, UNLINK, UNLOCK, UPDATE, UPDATEREDIRECTREF, VERSION-CONTROL\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/route-path-bad-syntax.stderr",
    "content": "error: invalid route URI: expected token '/' but found 'a' at index 0\n --> tests/ui-fail-nightly/route-path-bad-syntax.rs:5:8\n  |\n5 | #[get(\"a\")]\n  |        ^\n  |\n  = help: expected URI in origin form: \"/path/<param>\"\n\nerror: invalid route URI: unexpected EOF: expected token '/' at index 0\n --> tests/ui-fail-nightly/route-path-bad-syntax.rs:8:8\n  |\n8 | #[get(\"\")]\n  |        ^\n  |\n  = help: expected URI in origin form: \"/path/<param>\"\n\nerror: invalid route URI: expected token '/' but found 'a' at index 0\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:11:8\n   |\n11 | #[get(\"a/b/c\")]\n   |        ^\n   |\n   = help: expected URI in origin form: \"/path/<param>\"\n\nerror: route URIs cannot contain empty segments\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:14:10\n   |\n14 | #[get(\"/a///b\")]\n   |          ^^\n   |\n   = note: expected \"/a/b\", found \"/a///b\"\n\nerror: route URIs cannot contain empty segments\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:17:13\n   |\n17 | #[get(\"/?bat&&\")]\n   |             ^^\n   |\n   = note: expected \"/?bat\", found \"/?bat&&\"\n\nerror: route URIs cannot contain empty segments\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:20:13\n   |\n20 | #[get(\"/?bat&&\")]\n   |             ^^\n   |\n   = note: expected \"/?bat\", found \"/?bat&&\"\n\nerror: route URIs cannot contain empty segments\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:23:12\n   |\n23 | #[get(\"/a/b//\")]\n   |            ^^\n   |\n   = note: expected \"/a/b/\", found \"/a/b//\"\n\nerror: unused parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:42:10\n   |\n42 | #[get(\"/<name>\")]\n   |          ^^^^\n   |\nnote: expected argument named `name` here\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:43:6\n   |\n43 | fn h0(_name: usize) {}\n   |      ^^^^^^^^^^^^^^\n\nerror: unused parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:45:12\n   |\n45 | #[get(\"/a?<r>\")]\n   |            ^\n   |\nnote: expected argument named `r` here\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:46:6\n   |\n46 | fn h1() {}\n   |      ^^\n\nerror: unused parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:48:23\n   |\n48 | #[post(\"/a\", data = \"<test>\")]\n   |                       ^^^^\n   |\nnote: expected argument named `test` here\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:49:6\n   |\n49 | fn h2() {}\n   |      ^^\n\nerror: unused parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:51:10\n   |\n51 | #[get(\"/<_r>\")]\n   |          ^^\n   |\nnote: expected argument named `_r` here\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:52:6\n   |\n52 | fn h3() {}\n   |      ^^\n\nerror: unused parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:54:10\n   |\n54 | #[get(\"/<_r>/<b>\")]\n   |          ^^\n   |\nnote: expected argument named `_r` here\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:55:6\n   |\n55 | fn h4() {}\n   |      ^^\n\nerror: unused parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:54:15\n   |\n54 | #[get(\"/<_r>/<b>\")]\n   |               ^\n   |\nnote: expected argument named `b` here\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:55:6\n   |\n55 | fn h4() {}\n   |      ^^\n\nerror: invalid identifier: `foo_.`\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:60:10\n   |\n60 | #[get(\"/<foo_.>\")]\n   |          ^^^^^\n   |\n   = help: dynamic parameters must be valid identifiers\n   = help: did you mean `<foo_>`?\n\nerror: invalid identifier: `foo*`\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:63:10\n   |\n63 | #[get(\"/<foo*>\")]\n   |          ^^^^\n   |\n   = help: dynamic parameters must be valid identifiers\n   = help: did you mean `<foo>`?\n\nerror: invalid identifier: `!`\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:66:10\n   |\n66 | #[get(\"/<!>\")]\n   |          ^\n   |\n   = help: dynamic parameters must be valid identifiers\n   = help: did you mean `<param>`?\n\nerror: invalid identifier: `name>:<id`\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:69:10\n   |\n69 | #[get(\"/<name>:<id>\")]\n   |          ^^^^^^^^^\n   |\n   = help: dynamic parameters must be valid identifiers\n   = help: did you mean `<nameid>`?\n\nerror: unexpected static parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:74:20\n   |\n74 | #[get(\"/\", data = \"foo\")]\n   |                    ^^^\n   |\n   = help: parameter must be dynamic: `<foo>`\n\nerror: parameter cannot be trailing\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:77:20\n   |\n77 | #[get(\"/\", data = \"<foo..>\")]\n   |                    ^^^^^^^\n   |\n   = help: did you mean `<foo>`?\n\nwarning: `segment` starts with `<` but does not end with `>`\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:80:20\n   |\n80 | #[get(\"/\", data = \"<foo\")]\n   |                    ^^^^\n   |\n   = help: perhaps you meant the dynamic parameter `<foo>`?\n   = note: apply `#[suppress(segment_chars)]` before the item to suppress this lint\n\nerror: unexpected static parameter\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:80:20\n   |\n80 | #[get(\"/\", data = \"<foo\")]\n   |                    ^^^^\n   |\n   = help: parameter must be dynamic: `<foo>`\n\nerror: invalid identifier: `test `\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:83:21\n   |\n83 | #[get(\"/\", data = \"<test >\")]\n   |                     ^^^^^\n   |\n   = help: dynamic parameters must be valid identifiers\n   = help: did you mean `<test>`?\n\nerror: handler arguments must be named\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:89:7\n   |\n89 | fn k0(_: usize) {}\n   |       ^^^^^^^^\n   |\n   = help: to name an ignored handler argument, use `_name`\n\nerror: parameters cannot be empty\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:93:9\n   |\n93 | #[get(\"/<>\")]\n   |         ^^\n\nwarning: `segment` starts with `<` but does not end with `>`\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:96:9\n   |\n96 | #[get(\"/<id><\")]\n   |         ^^^^^\n   |\n   = help: perhaps you meant the dynamic parameter `<id>`?\n   = note: apply `#[suppress(segment_chars)]` before the item to suppress this lint\n\nwarning: `segment` starts with `<` but does not end with `>`\n  --> tests/ui-fail-nightly/route-path-bad-syntax.rs:99:9\n   |\n99 | #[get(\"/<<<<id><\")]\n   |         ^^^^^^^^\n   |\n   = help: perhaps you meant the dynamic parameter `<id>`?\n   = note: apply `#[suppress(segment_chars)]` before the item to suppress this lint\n\nwarning: `segment` starts with `<` but does not end with `>`\n   --> tests/ui-fail-nightly/route-path-bad-syntax.rs:102:9\n    |\n102 | #[get(\"/<>name><\")]\n    |         ^^^^^^^^\n    |\n    = help: perhaps you meant the dynamic parameter `<name>`?\n    = note: apply `#[suppress(segment_chars)]` before the item to suppress this lint\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/route-type-errors.stderr",
    "content": "error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n --> tests/ui-fail-nightly/route-type-errors.rs:6:13\n  |\n6 | fn f0(_foo: Q) {}\n  |             ^ the trait `FromParam<'_>` is not implemented for `Q`\n  |\n  = help: the following other types implement trait `FromParam<'a>`:\n            `&'a str` implements `FromParam<'a>`\n            `IpAddr` implements `FromParam<'a>`\n            `Ipv4Addr` implements `FromParam<'a>`\n            `Ipv6Addr` implements `FromParam<'a>`\n            `NonZero<i128>` implements `FromParam<'a>`\n            `NonZero<i16>` implements `FromParam<'a>`\n            `NonZero<i32>` implements `FromParam<'a>`\n            `NonZero<i64>` implements `FromParam<'a>`\n          and $N others\n\nerror[E0277]: the trait bound `Q: FromSegments<'_>` is not satisfied\n --> tests/ui-fail-nightly/route-type-errors.rs:9:13\n  |\n9 | fn f1(_foo: Q) {}\n  |             ^ the trait `FromSegments<'_>` is not implemented for `Q`\n  |\n  = help: the following other types implement trait `FromSegments<'r>`:\n            `PathBuf` implements `FromSegments<'_>`\n            `Result<T, <T as FromSegments<'r>>::Error>` implements `FromSegments<'r>`\n            `Segments<'r, rocket::http::uri::fmt::Path>` implements `FromSegments<'r>`\n            `std::option::Option<T>` implements `FromSegments<'r>`\n\nerror[E0277]: the trait bound `Q: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:12:13\n   |\n12 | fn f2(_foo: Q) {}\n   |             ^ the trait `FromFormField<'_>` is not implemented for `Q`, which is required by `Q: FromForm<'_>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Q` to implement `FromForm<'_>`\n\nerror[E0277]: the trait bound `Q: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:15:13\n   |\n15 | fn f3(_foo: Q) {}\n   |             ^ the trait `FromFormField<'_>` is not implemented for `Q`, which is required by `Q: FromForm<'_>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Q` to implement `FromForm<'_>`\n\nerror[E0277]: the trait bound `Q: FromData<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:18:13\n   |\n18 | fn f4(_foo: Q) {}\n   |             ^ the trait `FromData<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromData<'r>`:\n             &'r RawStr\n             &'r [u8]\n             &'r str\n             Capped<&'r RawStr>\n             Capped<&'r [u8]>\n             Capped<&'r str>\n             Capped<Cow<'_, str>>\n             Capped<TempFile<'_>>\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:21:11\n   |\n21 | fn f5(_a: Q, _foo: Q) {}\n   |           ^ the trait `FromRequest<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromRequest<'r>`:\n             &'r Accept\n             &'r ContentType\n             &'r CookieJar<'r>\n             &'r Endpoint\n             &'r Host<'r>\n             &'r Limits\n             &'r Route\n             &'r rocket::Config\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:21:20\n   |\n21 | fn f5(_a: Q, _foo: Q) {}\n   |                    ^ the trait `FromParam<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromParam<'a>`:\n             `&'a str` implements `FromParam<'a>`\n             `IpAddr` implements `FromParam<'a>`\n             `Ipv4Addr` implements `FromParam<'a>`\n             `Ipv6Addr` implements `FromParam<'a>`\n             `NonZero<i128>` implements `FromParam<'a>`\n             `NonZero<i16>` implements `FromParam<'a>`\n             `NonZero<i32>` implements `FromParam<'a>`\n             `NonZero<i64>` implements `FromParam<'a>`\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:24:11\n   |\n24 | fn f6(_a: Q, _foo: Q, _good: usize, _bar: Q) {}\n   |           ^ the trait `FromRequest<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromRequest<'r>`:\n             &'r Accept\n             &'r ContentType\n             &'r CookieJar<'r>\n             &'r Endpoint\n             &'r Host<'r>\n             &'r Limits\n             &'r Route\n             &'r rocket::Config\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:24:20\n   |\n24 | fn f6(_a: Q, _foo: Q, _good: usize, _bar: Q) {}\n   |                    ^ the trait `FromParam<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromParam<'a>`:\n             `&'a str` implements `FromParam<'a>`\n             `IpAddr` implements `FromParam<'a>`\n             `Ipv4Addr` implements `FromParam<'a>`\n             `Ipv6Addr` implements `FromParam<'a>`\n             `NonZero<i128>` implements `FromParam<'a>`\n             `NonZero<i16>` implements `FromParam<'a>`\n             `NonZero<i32>` implements `FromParam<'a>`\n             `NonZero<i64>` implements `FromParam<'a>`\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n  --> tests/ui-fail-nightly/route-type-errors.rs:24:43\n   |\n24 | fn f6(_a: Q, _foo: Q, _good: usize, _bar: Q) {}\n   |                                           ^ the trait `FromParam<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromParam<'a>`:\n             `&'a str` implements `FromParam<'a>`\n             `IpAddr` implements `FromParam<'a>`\n             `Ipv4Addr` implements `FromParam<'a>`\n             `Ipv6Addr` implements `FromParam<'a>`\n             `NonZero<i128>` implements `FromParam<'a>`\n             `NonZero<i16>` implements `FromParam<'a>`\n             `NonZero<i32>` implements `FromParam<'a>`\n             `NonZero<i64>` implements `FromParam<'a>`\n           and $N others\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/route-warnings.stderr",
    "content": "warning: 'application/x-custom' is not a known format or media type\n --> tests/ui-fail-nightly/route-warnings.rs:7:21\n  |\n7 | #[get(\"/\", format = \"application/x-custom\")]\n  |                     ^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = note: apply `#[suppress(unknown_format)]` before the item to suppress this lint\n\nwarning: 'x-custom/plain' is not a known format or media type\n  --> tests/ui-fail-nightly/route-warnings.rs:10:21\n   |\n10 | #[get(\"/\", format = \"x-custom/plain\")]\n   |                     ^^^^^^^^^^^^^^^^\n   |\n   = note: apply `#[suppress(unknown_format)]` before the item to suppress this lint\n\nwarning: 'x-custom/x-custom' is not a known format or media type\n  --> tests/ui-fail-nightly/route-warnings.rs:13:21\n   |\n13 | #[get(\"/\", format = \"x-custom/x-custom\")]\n   |                     ^^^^^^^^^^^^^^^^^^^\n   |\n   = note: apply `#[suppress(unknown_format)]` before the item to suppress this lint\n\nwarning: `data` used with non-payload-supporting method\n  --> tests/ui-fail-nightly/route-warnings.rs:22:12\n   |\n22 | #[get(\"/\", data = \"<_foo>\")]\n   |            ^^^^^^^^^^^^^^^\n   |\n   = note: 'GET' does not typically support payloads\n   = note: apply `#[suppress(dubious_payload)]` before the item to suppress this lint\n\nwarning: `data` used with non-payload-supporting method\n  --> tests/ui-fail-nightly/route-warnings.rs:25:13\n   |\n25 | #[head(\"/\", data = \"<_foo>\")]\n   |             ^^^^^^^^^^^^^^^\n   |\n   = note: 'HEAD' does not typically support payloads\n   = note: apply `#[suppress(dubious_payload)]` before the item to suppress this lint\n\nerror: checking for warnings!\n  --> tests/ui-fail-nightly/route-warnings.rs:33:5\n   |\n33 |     compile_error!(\"checking for warnings!\")\n   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/routes.stderr",
    "content": "error: expected `,`\n --> tests/ui-fail-nightly/routes.rs:4:23\n  |\n4 |     let _ = routes![a b];\n  |                       ^\n\nerror: expected identifier\n --> tests/ui-fail-nightly/routes.rs:6:24\n  |\n6 |     let _ = routes![a::, ];\n  |                        ^\n\nerror: unexpected end of input, expected identifier\n --> tests/ui-fail-nightly/routes.rs:7:13\n  |\n7 |     let _ = routes![a::];\n  |             ^^^^^^^^^^^^\n  |\n  = note: this error originates in the macro `routes` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/typed-uri-bad-type.stderr",
    "content": "error[E0271]: type mismatch resolving `<String as FromParam<'_>>::Error == &str`\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:24:37\n   |\n24 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                                     ^^^^^^^^^^^^^^^^^^^^ expected `Empty`, found `&str`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n47 |     uri!(simple(id = \"hi\"));\n   |     ----------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n49 |     uri!(simple(\"hello\"));\n   |     --------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, i64>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, i64>` is not implemented for `usize`\n...\n51 |     uri!(simple(id = 239239i64));\n   |     ---------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Path, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:18:35\n   |\n18 | fn not_uri_display(id: i32, name: S) {  }\n   |                                   ^ the trait `FromUriParam<rocket::http::uri::fmt::Path, _>` is not implemented for `S`\n...\n53 |     uri!(not_uri_display(10, S));\n   |     ---------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_not_uri_display` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Path, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:53:30\n   |\n53 |     uri!(not_uri_display(10, S));\n   |                              ^ the trait `FromUriParam<rocket::http::uri::fmt::Path, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `i32: FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:24:18\n   |\n24 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                  ^^^^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not implemented for `i32`, which is required by `std::option::Option<i32>: FromUriParam<rocket::http::uri::fmt::Path, _>`\n...\n58 |     uri!(optionals(id = Some(10), name = Ok(\"bob\".into())));\n   |     ------------------------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `i32` implements `FromUriParam<P, &'x i32>`\n             `i32` implements `FromUriParam<P, &'x mut i32>`\n             `i32` implements `FromUriParam<P, i32>`\n   = note: required for `std::option::Option<i32>` to implement `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>`\n   = note: this error originates in the macro `rocket_uri_macro_optionals` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `std::string::String: FromUriParam<rocket::http::uri::fmt::Path, Result<_, _>>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:24:37\n   |\n24 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                                     ^^^^^^^^^^^^^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, Result<_, _>>` is not implemented for `std::string::String`, which is required by `Result<std::string::String, &str>: FromUriParam<rocket::http::uri::fmt::Path, _>`\n...\n58 |     uri!(optionals(id = Some(10), name = Ok(\"bob\".into())));\n   |     ------------------------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `std::string::String` implements `FromUriParam<P, &'a str>`\n             `std::string::String` implements `FromUriParam<P, &'x &'a str>`\n             `std::string::String` implements `FromUriParam<P, &'x mut &'a str>`\n             `std::string::String` implements `FromUriParam<P, &'x mut std::string::String>`\n             `std::string::String` implements `FromUriParam<P, &'x std::string::String>`\n             `std::string::String` implements `FromUriParam<P, std::string::String>`\n   = note: required for `Result<std::string::String, &str>` to implement `FromUriParam<rocket::http::uri::fmt::Path, Result<_, _>>`\n   = note: this error originates in the macro `rocket_uri_macro_optionals` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:38:17\n   |\n38 | fn simple_q(id: isize) {  }\n   |                 ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n...\n60 |     uri!(simple_q(\"hi\"));\n   |     -------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `isize` implements `FromUriParam<P, &'x isize>`\n             `isize` implements `FromUriParam<P, &'x mut isize>`\n             `isize` implements `FromUriParam<P, isize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:38:17\n   |\n38 | fn simple_q(id: isize) {  }\n   |                 ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n...\n62 |     uri!(simple_q(id = \"hi\"));\n   |     ------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `isize` implements `FromUriParam<P, &'x isize>`\n             `isize` implements `FromUriParam<P, &'x mut isize>`\n             `isize` implements `FromUriParam<P, isize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:41:29\n   |\n41 | fn other_q(id: usize, rest: S) {  }\n   |                             ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n...\n64 |     uri!(other_q(100, S));\n   |     --------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_other_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:64:23\n   |\n64 |     uri!(other_q(100, S));\n   |                       ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:41:29\n   |\n41 | fn other_q(id: usize, rest: S) {  }\n   |                             ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n...\n66 |     uri!(other_q(rest = S, id = 100));\n   |     --------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_other_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:66:25\n   |\n66 |     uri!(other_q(rest = S, id = 100));\n   |                         ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: Ignorable<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:68:25\n   |\n68 |     uri!(other_q(rest = _, id = 100));\n   |                         ^ the trait `Ignorable<rocket::http::uri::fmt::Query>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `Ignorable<P>`:\n             Result<T, E>\n             std::option::Option<T>\nnote: required by a bound in `assert_ignorable`\n  --> $WORKSPACE/core/http/src/uri/fmt/uri_display.rs\n   |\n   | pub fn assert_ignorable<P: Part, T: Ignorable<P>>() {  }\n   |                                     ^^^^^^^^^^^^ required by this bound in `assert_ignorable`\n\nerror[E0277]: the trait bound `usize: Ignorable<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:70:33\n   |\n70 |     uri!(other_q(rest = S, id = _));\n   |                                 ^ the trait `Ignorable<rocket::http::uri::fmt::Query>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Ignorable<P>`:\n             Result<T, E>\n             std::option::Option<T>\nnote: required by a bound in `assert_ignorable`\n  --> $WORKSPACE/core/http/src/uri/fmt/uri_display.rs\n   |\n   | pub fn assert_ignorable<P: Part, T: Ignorable<P>>() {  }\n   |                                     ^^^^^^^^^^^^ required by this bound in `assert_ignorable`\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:41:29\n   |\n41 | fn other_q(id: usize, rest: S) {  }\n   |                             ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n...\n70 |     uri!(other_q(rest = S, id = _));\n   |     ------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_other_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:70:25\n   |\n70 |     uri!(other_q(rest = S, id = _));\n   |                         ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>`\n             `&'a [u8]` implements `FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>`\n             `&'a std::path::Path` implements `FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>`\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n79 |     uri!(uri!(\"?foo#bar\"), simple(id = \"hi\"));\n   |     ----------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Reference<'_>: ValidRoutePrefix` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:79:15\n   |\n79 |     uri!(uri!(\"?foo#bar\"), simple(id = \"hi\"));\n   |          -----^^^^^^^^^^-\n   |          |    |\n   |          |    the trait `ValidRoutePrefix` is not implemented for `rocket::http::uri::Reference<'_>`\n   |          required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRoutePrefix`:\n             rocket::http::uri::Absolute<'a>\n             rocket::http::uri::Origin<'a>\nnote: required by a bound in `RouteUriBuilder::with_prefix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_prefix<P: ValidRoutePrefix>(self, p: P) -> PrefixedRouteUri<P::Output> {\n   |                           ^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_prefix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n80 |     uri!(uri!(\"*\"), simple(id = \"hi\"));\n   |     ---------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Asterisk: ValidRoutePrefix` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:80:15\n   |\n80 |     uri!(uri!(\"*\"), simple(id = \"hi\"));\n   |          -----^^^-\n   |          |    |\n   |          |    the trait `ValidRoutePrefix` is not implemented for `rocket::http::uri::Asterisk`\n   |          required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRoutePrefix`:\n             rocket::http::uri::Absolute<'a>\n             rocket::http::uri::Origin<'a>\nnote: required by a bound in `RouteUriBuilder::with_prefix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_prefix<P: ValidRoutePrefix>(self, p: P) -> PrefixedRouteUri<P::Output> {\n   |                           ^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_prefix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n83 |     uri!(_, simple(id = \"hi\"), uri!(\"*\"));\n   |     ------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Asterisk: ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:83:37\n   |\n83 |     uri!(_, simple(id = \"hi\"), uri!(\"*\"));\n   |                                -----^^^-\n   |                                |    |\n   |                                |    the trait `ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not implemented for `rocket::http::uri::Asterisk`\n   |                                required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRouteSuffix<T>`:\n             `rocket::http::uri::Absolute<'a>` implements `ValidRouteSuffix<rocket::http::uri::Absolute<'a>>`\n             `rocket::http::uri::Absolute<'a>` implements `ValidRouteSuffix<rocket::http::uri::Origin<'a>>`\n             `rocket::http::uri::Reference<'a>` implements `ValidRouteSuffix<rocket::http::uri::Absolute<'a>>`\n             `rocket::http::uri::Reference<'a>` implements `ValidRouteSuffix<rocket::http::uri::Origin<'a>>`\nnote: required by a bound in `RouteUriBuilder::with_suffix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_suffix<S>(self, suffix: S) -> SuffixedRouteUri<S::Output>\n   |            ----------- required by a bound in this associated function\n   |         where S: ValidRouteSuffix<Origin<'static>>\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_suffix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n84 |     uri!(_, simple(id = \"hi\"), uri!(\"/foo/bar\"));\n   |     -------------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Origin<'_>: ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:84:37\n   |\n84 |     uri!(_, simple(id = \"hi\"), uri!(\"/foo/bar\"));\n   |                                -----^^^^^^^^^^-\n   |                                |    |\n   |                                |    the trait `ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not implemented for `rocket::http::uri::Origin<'_>`\n   |                                required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRouteSuffix<T>`:\n             `rocket::http::uri::Absolute<'a>` implements `ValidRouteSuffix<rocket::http::uri::Absolute<'a>>`\n             `rocket::http::uri::Absolute<'a>` implements `ValidRouteSuffix<rocket::http::uri::Origin<'a>>`\n             `rocket::http::uri::Reference<'a>` implements `ValidRouteSuffix<rocket::http::uri::Absolute<'a>>`\n             `rocket::http::uri::Reference<'a>` implements `ValidRouteSuffix<rocket::http::uri::Origin<'a>>`\nnote: required by a bound in `RouteUriBuilder::with_suffix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_suffix<S>(self, suffix: S) -> SuffixedRouteUri<S::Output>\n   |            ----------- required by a bound in this associated function\n   |         where S: ValidRouteSuffix<Origin<'static>>\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_suffix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:47:22\n   |\n47 |     uri!(simple(id = \"hi\"));\n   |                      ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:49:17\n   |\n49 |     uri!(simple(\"hello\"));\n   |                 ^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, i64>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:51:22\n   |\n51 |     uri!(simple(id = 239239i64));\n   |                      ^^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, i64>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `i32: FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:58:25\n   |\n58 |     uri!(optionals(id = Some(10), name = Ok(\"bob\".into())));\n   |                         ^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not implemented for `i32`, which is required by `std::option::Option<i32>: FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `i32` implements `FromUriParam<P, &'x i32>`\n             `i32` implements `FromUriParam<P, &'x mut i32>`\n             `i32` implements `FromUriParam<P, i32>`\n   = note: required for `std::option::Option<i32>` to implement `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:60:19\n   |\n60 |     uri!(simple_q(\"hi\"));\n   |                   ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `isize` implements `FromUriParam<P, &'x isize>`\n             `isize` implements `FromUriParam<P, &'x mut isize>`\n             `isize` implements `FromUriParam<P, isize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:62:24\n   |\n62 |     uri!(simple_q(id = \"hi\"));\n   |                        ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `isize` implements `FromUriParam<P, &'x isize>`\n             `isize` implements `FromUriParam<P, &'x mut isize>`\n             `isize` implements `FromUriParam<P, isize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:79:40\n   |\n79 |     uri!(uri!(\"?foo#bar\"), simple(id = \"hi\"));\n   |                                        ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:80:33\n   |\n80 |     uri!(uri!(\"*\"), simple(id = \"hi\"));\n   |                                 ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:83:25\n   |\n83 |     uri!(_, simple(id = \"hi\"), uri!(\"*\"));\n   |                         ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-nightly/typed-uri-bad-type.rs:84:25\n   |\n84 |     uri!(_, simple(id = \"hi\"), uri!(\"/foo/bar\"));\n   |                         ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             `usize` implements `FromUriParam<P, &'x mut usize>`\n             `usize` implements `FromUriParam<P, &'x usize>`\n             `usize` implements `FromUriParam<P, usize>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/typed-uris-bad-params.stderr",
    "content": "error: expected identifier, found keyword `_`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:65:18\n   |\n65 |     uri!(ignored(_ = 10));\n   |                  ^\n\nerror: route expects 1 parameter but 2 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:71:18\n   |\n71 |     uri!(ignored(10, \"10\"));\n   |                  ^^^^^^^^\n   |\n   = note: route `ignored` has uri \"/<_>\"\n\nerror: expected unnamed arguments due to ignored parameters\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:69:18\n   |\n69 |     uri!(ignored(num = 10));\n   |                  ^^^^^^^^\n   |\n   = note: uri for route `ignored` ignores 1 path parameters: \"/<_>\"\n\nerror: route expects 1 parameter but 2 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:67:18\n   |\n67 |     uri!(ignored(10, 20));\n   |                  ^^^^^^\n   |\n   = note: route `ignored` has uri \"/<_>\"\n\nerror: path parameters cannot be ignored\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:63:18\n   |\n63 |     uri!(ignored(_));\n   |                  ^\n\nerror: path parameters cannot be ignored\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:61:36\n   |\n61 |     uri!(optionals(id = 10, name = _));\n   |                                    ^\n\nerror: path parameters cannot be ignored\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:59:25\n   |\n59 |     uri!(optionals(id = _, name = \"bob\".into()));\n   |                         ^\n\nerror: invalid parameters for `has_two` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:57:18\n   |\n57 |     uri!(has_two(id = 100, cookies = \"hi\"));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32, name: String\n   = help: missing parameter: `name`\nhelp: unknown parameter: `cookies`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:57:28\n   |\n57 |     uri!(has_two(id = 100, cookies = \"hi\"));\n   |                            ^^^^^^^\n\nerror: invalid parameters for `has_two` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:55:18\n   |\n55 |     uri!(has_two(cookies = \"hi\", id = 100, id = 10, id = 10));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32, name: String\n   = help: missing parameter: `name`\nhelp: unknown parameter: `cookies`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:55:18\n   |\n55 |     uri!(has_two(cookies = \"hi\", id = 100, id = 10, id = 10));\n   |                  ^^^^^^^\nhelp: duplicate parameter: `id`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:55:44\n   |\n55 |     uri!(has_two(cookies = \"hi\", id = 100, id = 10, id = 10));\n   |                                            ^^       ^^\n\nerror: invalid parameters for `has_two` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:53:18\n   |\n53 |     uri!(has_two(name = \"hi\"));\n   |                  ^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32, name: String\n   = help: missing parameter: `id`\n\nerror: invalid parameters for `has_two` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:51:18\n   |\n51 |     uri!(has_two(id = 100, id = 100, ));\n   |                  ^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32, name: String\n   = help: missing parameter: `name`\nhelp: duplicate parameter: `id`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:51:28\n   |\n51 |     uri!(has_two(id = 100, id = 100, ));\n   |                            ^^\n\nerror: invalid parameters for `has_one_guarded` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:49:26\n   |\n49 |     uri!(has_one_guarded(id = 100, cookies = \"hi\"));\n   |                          ^^^^^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: unknown parameter: `cookies`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:49:36\n   |\n49 |     uri!(has_one_guarded(id = 100, cookies = \"hi\"));\n   |                                    ^^^^^^^\n\nerror: invalid parameters for `has_one_guarded` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:47:26\n   |\n47 |     uri!(has_one_guarded(cookies = \"hi\", id = 100));\n   |                          ^^^^^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: unknown parameter: `cookies`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:47:26\n   |\n47 |     uri!(has_one_guarded(cookies = \"hi\", id = 100));\n   |                          ^^^^^^^\n\nerror: invalid parameters for `has_one` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:45:18\n   |\n45 |     uri!(has_one(name = \"hi\"));\n   |                  ^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\n   = help: missing parameter: `id`\nhelp: unknown parameter: `name`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:45:18\n   |\n45 |     uri!(has_one(name = \"hi\"));\n   |                  ^^^^\n\nerror: invalid parameters for `has_one` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:43:18\n   |\n43 |     uri!(has_one(id = 100, id = 100, ));\n   |                  ^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: duplicate parameter: `id`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:43:28\n   |\n43 |     uri!(has_one(id = 100, id = 100, ));\n   |                            ^^\n\nerror: invalid parameters for `has_one` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:41:18\n   |\n41 |     uri!(has_one(id = 100, id = 100));\n   |                  ^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: duplicate parameter: `id`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:41:28\n   |\n41 |     uri!(has_one(id = 100, id = 100));\n   |                            ^^\n\nerror: invalid parameters for `has_one` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:39:18\n   |\n39 |     uri!(has_one(name = 100, age = 50, id = 100, id = 50));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: unknown parameters: `name`, `age`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:39:18\n   |\n39 |     uri!(has_one(name = 100, age = 50, id = 100, id = 50));\n   |                  ^^^^        ^^^\nhelp: duplicate parameter: `id`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:39:50\n   |\n39 |     uri!(has_one(name = 100, age = 50, id = 100, id = 50));\n   |                                                  ^^\n\nerror: invalid parameters for `has_one` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:37:18\n   |\n37 |     uri!(has_one(name = 100, age = 50, id = 100));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: unknown parameters: `name`, `age`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:37:18\n   |\n37 |     uri!(has_one(name = 100, age = 50, id = 100));\n   |                  ^^^^        ^^^\n\nerror: invalid parameters for `has_one` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:35:18\n   |\n35 |     uri!(has_one(name = 100, id = 100));\n   |                  ^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: unknown parameter: `name`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:35:18\n   |\n35 |     uri!(has_one(name = 100, id = 100));\n   |                  ^^^^\n\nerror: invalid parameters for `has_one` route uri\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:33:18\n   |\n33 |     uri!(has_one(id = 100, name = \"hi\"));\n   |                  ^^^^^^^^^^^^^^^^^^^^^\n   |\n   = note: uri parameters are: id: i32\nhelp: unknown parameter: `name`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:33:28\n   |\n33 |     uri!(has_one(id = 100, name = \"hi\"));\n   |                            ^^^^\n\nerror: route expects 2 parameters but 1 was supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:31:18\n   |\n31 |     uri!(has_two(10));\n   |                  ^^\n   |\n   = note: route `has_two` has uri \"/<id>?<name>\"\n\nerror: route expects 2 parameters but 3 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:30:18\n   |\n30 |     uri!(has_two(10, \"hi\", \"there\"));\n   |                  ^^^^^^^^^^^^^^^^^\n   |\n   = note: route `has_two` has uri \"/<id>?<name>\"\n\nerror: route expects 1 parameter but 2 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:28:26\n   |\n28 |     uri!(has_one_guarded(\"hi\", 100));\n   |                          ^^^^^^^^^\n   |\n   = note: route `has_one_guarded` has uri \"/<id>\"\n\nerror: route expects 1 parameter but 2 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:27:18\n   |\n27 |     uri!(has_one(\"Hello\", 23, ));\n   |                  ^^^^^^^^^^^^\n   |\n   = note: route `has_one` has uri \"/<id>\"\n\nerror: route expects 1 parameter but 2 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:26:18\n   |\n26 |     uri!(has_one(1, 23));\n   |                  ^^^^^\n   |\n   = note: route `has_one` has uri \"/<id>\"\n\nerror: route expects 1 parameter but 0 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:24:10\n   |\n24 |     uri!(has_one());\n   |          ^^^^^^^\n   |\n   = note: route `has_one` has uri \"/<id>\"\n\nerror: route expects 1 parameter but 0 were supplied\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:23:10\n   |\n23 |     uri!(has_one);\n   |          ^^^^^^^\n   |\n   = note: route `has_one` has uri \"/<id>\"\n\nerror[E0271]: type mismatch resolving `<String as FromParam<'_>>::Error == &str`\n  --> tests/ui-fail-nightly/typed-uris-bad-params.rs:17:37\n   |\n17 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                                     ^^^^^^^^^^^^^^^^^^^^ expected `Empty`, found `&str`\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/typed-uris-invalid-syntax.stderr",
    "content": "error: unexpected token\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:10:16\n   |\n10 |     uri!(simple: id = 100, \"Hello\");\n   |                ^\n\nerror: named and unnamed parameters cannot be mixed\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:11:17\n   |\n11 |     uri!(simple(id = 100, \"Hello\"));\n   |                 ^^^^^^^^^^^^^^^^^\n\nerror: named and unnamed parameters cannot be mixed\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:12:17\n   |\n12 |     uri!(simple(\"Hello\", id = 100));\n   |                 ^^^^^^^^^^^^^^^^^\n\nerror: unexpected token\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:14:16\n   |\n14 |     uri!(simple:);\n   |                ^\n\nerror: invalid URI: unexpected EOF: expected token ':' at index 5\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:16:16\n   |\n16 |     uri!(\"mount\", simple);\n   |                ^\n\nerror: invalid URI: unexpected EOF: expected token ':' at index 5\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:17:16\n   |\n17 |     uri!(\"mount\", simple, \"http://\");\n   |                ^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:18:28\n   |\n18 |     uri!(\"/mount\", simple, \"http://\");\n   |                            ^^^^^^^^^\n\nerror: expected 1, 2, or 3 arguments, found 4\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:19:36\n   |\n19 |     uri!(\"/mount\", simple, \"#foo\", \"?foo\");\n   |                                    ^^^^^^\n\nerror: invalid URI: unexpected EOF: expected token ':' at index 5\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:20:16\n   |\n20 |     uri!(\"mount\", simple(10, \"hi\"), \"http://\");\n   |                ^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:21:38\n   |\n21 |     uri!(\"/mount\", simple(10, \"hi\"), \"http://\");\n   |                                      ^^^^^^^^^\n\nerror: URI prefix cannot contain query part\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:22:10\n   |\n22 |     uri!(\"/mount?foo\", simple(10, \"hi\"), \"foo/bar?foo#bar\");\n   |          ^^^^^^^^^^^^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:23:38\n   |\n23 |     uri!(\"/mount\", simple(10, \"hi\"), \"a/b\");\n   |                                      ^^^^^\n\nerror: expected 1, 2, or 3 arguments, found 4\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:24:46\n   |\n24 |     uri!(\"/mount\", simple(10, \"hi\"), \"#foo\", \"?foo\");\n   |                                              ^^^^^^\n\nerror: invalid URI: unexpected token '<' at index 7\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:25:18\n   |\n25 |     uri!(\"/mount/<id>\", simple);\n   |                  ^\n\nerror: expected at least 1 argument, found none\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:26:5\n   |\n26 |     uri!();\n   |     ^^^^^^\n   |\n   = note: this error originates in the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected token\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:27:16\n   |\n27 |     uri!(simple: id = );\n   |                ^\n\nerror: unexpected end of input, expected an expression\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:28:22\n   |\n28 |     uri!(simple(id = ));\n   |                      ^\n\nerror: invalid URI: unexpected EOF: expected some token at index 0\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:29:11\n   |\n29 |     uri!(\"*\", simple(10), \"hi\");\n   |           ^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:30:40\n   |\n30 |     uri!(\"some.host:8088\", simple(10), \"hi\");\n   |                                        ^^^^\n\nerror: expected identifier\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:33:18\n   |\n33 |     uri!(\"/foo\", \"bar\");\n   |                  ^^^^^\n\nerror: unexpected token\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:34:17\n   |\n34 |     uri!(\"/foo\" (\"bar\"));\n   |                 ^^^^^^^\n\nerror: URI prefix cannot contain query part\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:35:10\n   |\n35 |     uri!(\"ftp:?\", index);\n   |          ^^^^^^^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:36:25\n   |\n36 |     uri!(\"ftp:\", index, \"foo#bar\");\n   |                         ^^^^^^^^^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:37:25\n   |\n37 |     uri!(\"ftp:\", index, \"foo?bar\");\n   |                         ^^^^^^^^^\n\nerror: route expects 2 parameters but 0 were supplied\n  --> tests/ui-fail-nightly/typed-uris-invalid-syntax.rs:13:10\n   |\n13 |     uri!(simple,);\n   |          ^^^^^^\n   |\n   = note: route `simple` has uri \"/<_id>/<_name>\"\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/uri_display.stderr",
    "content": "error: fieldless structs are not supported\n --> tests/ui-fail-nightly/uri_display.rs:4:1\n  |\n4 | struct Foo1;\n  | ^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `UriDisplay`\n --> tests/ui-fail-nightly/uri_display.rs:3:10\n  |\n3 | #[derive(UriDisplayQuery)]\n  |          ^^^^^^^^^^^^^^^\n  = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: fieldless structs are not supported\n --> tests/ui-fail-nightly/uri_display.rs:7:1\n  |\n7 | struct Foo2();\n  | ^^^^^^^^^^^^^^\n  |\nnote: error occurred while deriving `UriDisplay`\n --> tests/ui-fail-nightly/uri_display.rs:6:10\n  |\n6 | #[derive(UriDisplayQuery)]\n  |          ^^^^^^^^^^^^^^^\n  = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: empty enums are not supported\n  --> tests/ui-fail-nightly/uri_display.rs:10:11\n   |\n10 | enum Foo3 { }\n   |           ^^^\n   |\nnote: error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-nightly/uri_display.rs:9:10\n   |\n9  | #[derive(UriDisplayQuery)]\n   |          ^^^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple structs or variants must have exactly one field\n  --> tests/ui-fail-nightly/uri_display.rs:18:12\n   |\n18 | struct Foo5(String, String);\n   |            ^^^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-nightly/uri_display.rs:17:10\n   |\n17 | #[derive(UriDisplayQuery)]\n   |          ^^^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[attr(..)]`, found bare integer literal\n  --> tests/ui-fail-nightly/uri_display.rs:22:20\n   |\n22 |     #[field(name = 123)]\n   |                    ^^^\n   |\nnote: error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-nightly/uri_display.rs:20:10\n   |\n20 | #[derive(UriDisplayQuery)]\n   |          ^^^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one field\n  --> tests/ui-fail-nightly/uri_display.rs:27:12\n   |\n27 | struct Foo7(String, usize);\n   |            ^^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-nightly/uri_display.rs:26:10\n   |\n26 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one field\n  --> tests/ui-fail-nightly/uri_display.rs:30:1\n   |\n30 | struct Foo8;\n   | ^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-nightly/uri_display.rs:29:10\n   |\n29 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: enums are not supported\n  --> tests/ui-fail-nightly/uri_display.rs:33:1\n   |\n33 | enum Foo9 {  }\n   | ^^^^^^^^^^^^^^\n   |\nnote: error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-nightly/uri_display.rs:32:10\n   |\n32 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n  --> tests/ui-fail-nightly/uri_display.rs:36:1\n   |\n36 | / struct Foo10 {\n37 | |     named: usize\n38 | | }\n   | |_^\n   |\nnote: error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-nightly/uri_display.rs:35:10\n   |\n35 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-nightly/uri_display_type_errors.stderr",
    "content": "error[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n --> tests/ui-fail-nightly/uri_display_type_errors.rs:6:13\n  |\n6 | struct Bar1(BadType);\n  |             ^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n  |\n  = help: the following other types implement trait `UriDisplay<P>`:\n            `&T` implements `UriDisplay<P>`\n            `&mut T` implements `UriDisplay<P>`\n            `BTreeMap<K, V>` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n            `Bar1` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n            `Bar2` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n            `Bar3` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n            `Bar4` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n            `Bar5` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n          and $N others\n  = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'i, P>::write_value`\n --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n  |\n  |     pub fn write_value<T: UriDisplay<P>>(&mut self, value: T) -> fmt::Result {\n  |                           ^^^^^^^^^^^^^ required by this bound in `Formatter::<'i, P>::write_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-nightly/uri_display_type_errors.rs:10:5\n   |\n10 |     field: BadType,\n   |     ^^^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             `&T` implements `UriDisplay<P>`\n             `&mut T` implements `UriDisplay<P>`\n             `BTreeMap<K, V>` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar1` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar2` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar3` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar4` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar5` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-nightly/uri_display_type_errors.rs:16:5\n   |\n16 |     bad: BadType,\n   |     ^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             `&T` implements `UriDisplay<P>`\n             `&mut T` implements `UriDisplay<P>`\n             `BTreeMap<K, V>` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar1` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar2` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar3` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar4` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar5` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-nightly/uri_display_type_errors.rs:21:11\n   |\n21 |     Inner(BadType),\n   |           ^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             `&T` implements `UriDisplay<P>`\n             `&mut T` implements `UriDisplay<P>`\n             `BTreeMap<K, V>` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar1` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar2` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar3` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar4` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar5` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\n   = note: 1 redundant requirement hidden\n   = note: required for `&&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'i, P>::write_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_value<T: UriDisplay<P>>(&mut self, value: T) -> fmt::Result {\n   |                           ^^^^^^^^^^^^^ required by this bound in `Formatter::<'i, P>::write_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-nightly/uri_display_type_errors.rs:27:9\n   |\n27 |         field: BadType,\n   |         ^^^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             `&T` implements `UriDisplay<P>`\n             `&mut T` implements `UriDisplay<P>`\n             `BTreeMap<K, V>` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar1` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar2` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar3` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar4` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar5` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\n   = note: 1 redundant requirement hidden\n   = note: required for `&&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-nightly/uri_display_type_errors.rs:35:9\n   |\n35 |         other: BadType,\n   |         ^^^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             `&T` implements `UriDisplay<P>`\n             `&mut T` implements `UriDisplay<P>`\n             `BTreeMap<K, V>` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar1` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar2` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar3` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar4` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar5` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\n   = note: 1 redundant requirement hidden\n   = note: required for `&&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Path>` is not satisfied\n  --> tests/ui-fail-nightly/uri_display_type_errors.rs:40:12\n   |\n40 | struct Baz(BadType);\n   |            ^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Path>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Path>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             `&T` implements `UriDisplay<P>`\n             `&mut T` implements `UriDisplay<P>`\n             `BTreeMap<K, V>` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar1` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar2` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar3` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar4` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n             `Bar5` implements `UriDisplay<rocket::http::uri::fmt::Query>`\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Path>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'i, P>::write_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_value<T: UriDisplay<P>>(&mut self, value: T) -> fmt::Result {\n   |                           ^^^^^^^^^^^^^ required by this bound in `Formatter::<'i, P>::write_value`\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/async-entry.stderr",
    "content": "error: attribute can only be applied to `async` functions\n --> tests/ui-fail-stable/async-entry.rs:4:5\n  |\n4 |     #[rocket::main]\n  |     ^^^^^^^^^^^^^^^\n  |\n  = note: this error originates in the attribute macro `rocket::main` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] this function must be `async`\n --> tests/ui-fail-stable/async-entry.rs:5:5\n  |\n5 |     fn foo() { }\n  |     ^^^^^^^^\n\nerror: attribute can only be applied to `async` functions\n  --> tests/ui-fail-stable/async-entry.rs:16:5\n   |\n16 |     #[rocket::main]\n   |     ^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `rocket::main` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] this function must be `async`\n  --> tests/ui-fail-stable/async-entry.rs:17:5\n   |\n17 |     fn main() {\n   |     ^^^^^^^^^\n\nerror: attribute cannot be applied to `main` function\n       = note: this attribute generates a `main` function\n  --> tests/ui-fail-stable/async-entry.rs:49:5\n   |\n49 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] this function cannot be `main`\n  --> tests/ui-fail-stable/async-entry.rs:50:8\n   |\n50 |     fn main() -> rocket::Rocket<rocket::Build> {\n   |        ^^^^\n\nerror: attribute can only be applied to functions that return a value\n  --> tests/ui-fail-stable/async-entry.rs:56:5\n   |\n56 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] this function must return a value\n  --> tests/ui-fail-stable/async-entry.rs:57:5\n   |\n57 |     async fn rocket() {\n   |     ^^^^^^^^^^^^^^^^^\n\nerror: attribute can only be applied to functions that return a value\n  --> tests/ui-fail-stable/async-entry.rs:64:5\n   |\n64 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] this function must return a value\n  --> tests/ui-fail-stable/async-entry.rs:65:5\n   |\n65 |     fn rocket() {\n   |     ^^^^^^^^^^^\n\nerror: attribute cannot be applied to `main` function\n       = note: this attribute generates a `main` function\n  --> tests/ui-fail-stable/async-entry.rs:79:5\n   |\n79 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] this function cannot be `main`\n  --> tests/ui-fail-stable/async-entry.rs:80:8\n   |\n80 |     fn main() -> &'static str {\n   |        ^^^^\n\nerror: attribute cannot be applied to `main` function\n       = note: this attribute generates a `main` function\n  --> tests/ui-fail-stable/async-entry.rs:87:5\n   |\n87 |     #[rocket::launch]\n   |     ^^^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the attribute macro `rocket::launch` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] this function cannot be `main`\n  --> tests/ui-fail-stable/async-entry.rs:88:14\n   |\n88 |     async fn main() -> _ {\n   |              ^^^^\n\nerror[E0728]: `await` is only allowed inside `async` functions and blocks\n  --> tests/ui-fail-stable/async-entry.rs:73:42\n   |\n72 |     fn rocket() -> _ {\n   |     ---------------- this is not `async`\n73 |         let _ = rocket::build().launch().await;\n   |                                          ^^^^^ only allowed inside `async` functions and blocks\n\nerror[E0277]: `main` has invalid return type `Rocket<Build>`\n  --> tests/ui-fail-stable/async-entry.rs:94:20\n   |\n94 | async fn main() -> rocket::Rocket<rocket::Build> {\n   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` can only return types that implement `Termination`\n   |\n   = help: consider using `()`, or a `Result`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-stable/async-entry.rs:35:9\n   |\n33 |     async fn rocket() -> String {\n   |                          ------ expected `std::string::String` because of return type\n34 |         let _ = rocket::build().launch().await;\n35 |         rocket::build()\n   |         ^^^^^^^^^^^^^^^ expected `String`, found `Rocket<Build>`\n   |\n   = note: expected struct `std::string::String`\n              found struct `Rocket<Build>`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-stable/async-entry.rs:44:9\n   |\n42 |     async fn rocket() -> _ {\n   |                          - expected `Rocket<Build>` because of return type\n43 |         let _ = rocket::build().launch().await;\n44 |         \"hi\".to_string()\n   |         ^^^^^^^^^^^^^^^^ expected `Rocket<Build>`, found `String`\n   |\n   = note: expected struct `Rocket<Build>`\n              found struct `std::string::String`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-stable/async-entry.rs:24:21\n   |\n24 |       async fn main() {\n   |  ____________________-^\n   | |                    |\n   | |                    expected `()` because of default return type\n25 | |         rocket::build()\n26 | |     }\n   | |     ^- help: consider using a semicolon here: `;`\n   | |_____|\n   |       expected `()`, found `Rocket<Build>`\n   |\n   = note: expected unit type `()`\n                 found struct `Rocket<Build>`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-stable/async-entry.rs:35:9\n   |\n35 |         rocket::build()\n   |         ^^^^^^^^^^^^^^^ expected `String`, found `Rocket<Build>`\n   |\n   = note: expected struct `std::string::String`\n              found struct `Rocket<Build>`\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-stable/async-entry.rs:44:9\n   |\n44 |         \"hi\".to_string()\n   |         ^^^^^^^^^^^^^^^^ expected `Rocket<Build>`, found `String`\n   |\n   = note: expected struct `Rocket<Build>`\n              found struct `std::string::String`\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/bad-ignored-segments.stderr",
    "content": "error: parameter must be named\n       = help: use a name such as `_guard` or `_param`\n --> tests/ui-fail-stable/bad-ignored-segments.rs:6:12\n  |\n6 | #[get(\"/c?<_>\")]\n  |            ^\n\nerror: parameter must be named\n       = help: use a name such as `_guard` or `_param`\n --> tests/ui-fail-stable/bad-ignored-segments.rs:9:22\n  |\n9 | #[post(\"/d\", data = \"<_>\")]\n  |                      ^^^\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/catch.stderr",
    "content": "error: expected `fn`\n       = help: `#[catch]` can only be used on functions\n --> tests/ui-fail-stable/catch.rs:6:1\n  |\n6 | struct Catcher(String);\n  | ^^^^^^\n\nerror: expected `fn`\n       = help: `#[catch]` can only be used on functions\n --> tests/ui-fail-stable/catch.rs:9:7\n  |\n9 | const CATCH: &str = \"Catcher\";\n  |       ^^^^^\n\nerror: expected integer or `default`, found string literal\n       = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n  --> tests/ui-fail-stable/catch.rs:11:9\n   |\n11 | #[catch(\"404\")]\n   |         ^^^^^\n\nerror: unexpected keyed parameter: expected literal or identifier\n       = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n  --> tests/ui-fail-stable/catch.rs:14:9\n   |\n14 | #[catch(code = \"404\")]\n   |         ^^^^^^^^^^^^\n\nerror: unexpected keyed parameter: expected literal or identifier\n       = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n  --> tests/ui-fail-stable/catch.rs:17:9\n   |\n17 | #[catch(code = 404)]\n   |         ^^^^^^^^^^\n\nerror: status must be in range [100, 599]\n       = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n  --> tests/ui-fail-stable/catch.rs:20:9\n   |\n20 | #[catch(99)]\n   |         ^^\n\nerror: status must be in range [100, 599]\n       = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n  --> tests/ui-fail-stable/catch.rs:23:9\n   |\n23 | #[catch(600)]\n   |         ^^^\n\nerror: unexpected attribute parameter: `message`\n       = help: `#[catch]` expects a status code int or `default`: `#[catch(404)]` or `#[catch(default)]`\n  --> tests/ui-fail-stable/catch.rs:26:14\n   |\n26 | #[catch(400, message = \"foo\")]\n   |              ^^^^^^^^^^^^^^^\n\nerror[E0308]: arguments to this function are incorrect\n  --> tests/ui-fail-stable/catch.rs:30:4\n   |\n30 | fn f3(_request: &Request, _other: bool) { }\n   |    ^^           --------          ---- an argument of type `bool` is missing\n   |                 |\n   |                 unexpected argument of type `Status`\n   |\nnote: function defined here\n  --> tests/ui-fail-stable/catch.rs:30:4\n   |\n30 | fn f3(_request: &Request, _other: bool) { }\n   |    ^^ ------------------  ------------\nhelp: provide the argument\n   |\n29 | f3(bool, /* bool */)\n   |\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/catch_type_errors.stderr",
    "content": "error[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n --> tests/ui-fail-stable/catch_type_errors.rs:6:30\n  |\n5 | #[catch(404)]\n  | ------------- required by a bound introduced by this call\n6 | fn f1(_request: &Request) -> usize {\n  |                              ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n  |\n  = help: the following other types implement trait `Responder<'r, 'o>`:\n            <&'o [u8] as Responder<'r, 'o>>\n            <&'o str as Responder<'r, 'o>>\n            <() as Responder<'r, 'static>>\n            <(ContentType, R) as Responder<'r, 'o>>\n            <(Status, R) as Responder<'r, 'o>>\n            <Accepted<R> as Responder<'r, 'o>>\n            <Arc<[u8]> as Responder<'r, 'static>>\n            <Arc<str> as Responder<'r, 'static>>\n          and $N others\n\nerror[E0277]: the trait bound `bool: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-stable/catch_type_errors.rs:11:30\n   |\n10 | #[catch(404)]\n   | ------------- required by a bound introduced by this call\n11 | fn f2(_request: &Request) -> bool {\n   |                              ^^^^ the trait `Responder<'_, '_>` is not implemented for `bool`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             <&'o [u8] as Responder<'r, 'o>>\n             <&'o str as Responder<'r, 'o>>\n             <() as Responder<'r, 'static>>\n             <(ContentType, R) as Responder<'r, 'o>>\n             <(Status, R) as Responder<'r, 'o>>\n             <Accepted<R> as Responder<'r, 'o>>\n             <Arc<[u8]> as Responder<'r, 'static>>\n             <Arc<str> as Responder<'r, 'static>>\n           and $N others\n\nerror[E0308]: mismatched types\n  --> tests/ui-fail-stable/catch_type_errors.rs:16:17\n   |\n16 | fn f3(_request: bool) -> usize {\n   |    --           ^^^^ expected `bool`, found `&Request<'_>`\n   |    |\n   |    arguments to this function are incorrect\n   |\nnote: function defined here\n  --> tests/ui-fail-stable/catch_type_errors.rs:16:4\n   |\n16 | fn f3(_request: bool) -> usize {\n   |    ^^ --------------\n\nerror[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-stable/catch_type_errors.rs:16:26\n   |\n15 | #[catch(404)]\n   | ------------- required by a bound introduced by this call\n16 | fn f3(_request: bool) -> usize {\n   |                          ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             <&'o [u8] as Responder<'r, 'o>>\n             <&'o str as Responder<'r, 'o>>\n             <() as Responder<'r, 'static>>\n             <(ContentType, R) as Responder<'r, 'o>>\n             <(Status, R) as Responder<'r, 'o>>\n             <Accepted<R> as Responder<'r, 'o>>\n             <Arc<[u8]> as Responder<'r, 'static>>\n             <Arc<str> as Responder<'r, 'static>>\n           and $N others\n\nerror[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-stable/catch_type_errors.rs:21:12\n   |\n20 | #[catch(404)]\n   | ------------- required by a bound introduced by this call\n21 | fn f4() -> usize {\n   |            ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             <&'o [u8] as Responder<'r, 'o>>\n             <&'o str as Responder<'r, 'o>>\n             <() as Responder<'r, 'static>>\n             <(ContentType, R) as Responder<'r, 'o>>\n             <(Status, R) as Responder<'r, 'o>>\n             <Accepted<R> as Responder<'r, 'o>>\n             <Arc<[u8]> as Responder<'r, 'static>>\n             <Arc<str> as Responder<'r, 'static>>\n           and $N others\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/catchers.stderr",
    "content": "error: expected `,`\n --> $DIR/catchers.rs:4:25\n  |\n4 |     let _ = catchers![a b];\n  |                         ^\n\nerror: expected identifier\n --> $DIR/catchers.rs:6:26\n  |\n6 |     let _ = catchers![a::, ];\n  |                          ^\n\nerror: unexpected end of input, expected identifier\n --> $DIR/catchers.rs:7:13\n  |\n7 |     let _ = catchers![a::];\n  |             ^^^^^^^^^^^^^^\n  |\n  = note: this error originates in the macro `catchers` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/from_form.stderr",
    "content": "error: enums are not supported\n --> tests/ui-fail-stable/from_form.rs:4:1\n  |\n4 | enum Thing { }\n  | ^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n --> tests/ui-fail-stable/from_form.rs:3:10\n  |\n3 | #[derive(FromForm)]\n  |          ^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: at least one field is required\n --> tests/ui-fail-stable/from_form.rs:7:1\n  |\n7 | struct Foo1;\n  | ^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n --> tests/ui-fail-stable/from_form.rs:6:10\n  |\n6 | #[derive(FromForm)]\n  |          ^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: at least one field is required\n  --> tests/ui-fail-stable/from_form.rs:10:13\n   |\n10 | struct Foo2 {  }\n   |             ^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n --> tests/ui-fail-stable/from_form.rs:9:10\n  |\n9 | #[derive(FromForm)]\n  |          ^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple struct must have exactly one field\n  --> tests/ui-fail-stable/from_form.rs:16:12\n   |\n16 | struct Foo4(usize, usize, usize);\n   |            ^^^^^^^^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:15:10\n   |\n15 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: only one lifetime is supported\n  --> tests/ui-fail-stable/from_form.rs:19:25\n   |\n19 | struct NextTodoTask<'f, 'a> {\n   |                         ^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:18:10\n   |\n18 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n       = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\n  --> tests/ui-fail-stable/from_form.rs:28:20\n   |\n28 |     #[field(name = \"isindex\")]\n   |                    ^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:26:10\n   |\n26 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-stable/from_form.rs:36:5\n   |\n36 |     foo: usize,\n   |     ^^^\n\nerror: [help] declared in this field\n  --> tests/ui-fail-stable/from_form.rs:36:5\n   |\n36 |     foo: usize,\n   |     ^^^^^^^^^^\n\nerror: [note] previous field with conflicting name\n  --> tests/ui-fail-stable/from_form.rs:34:5\n   |\n34 | /     #[field(name = \"foo\")]\n35 | |     field: String,\n   | |_________________^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:32:10\n   |\n32 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-stable/from_form.rs:43:20\n   |\n43 |     #[field(name = \"hello\")]\n   |                    ^^^^^^^\n\nerror: [help] declared in this field\n  --> tests/ui-fail-stable/from_form.rs:43:5\n   |\n43 | /     #[field(name = \"hello\")]\n44 | |     other: String,\n   | |_________________^\n\nerror: [note] previous field with conflicting name\n  --> tests/ui-fail-stable/from_form.rs:41:5\n   |\n41 | /     #[field(name = \"hello\")]\n42 | |     first: String,\n   | |_________________^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:39:10\n   |\n39 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-stable/from_form.rs:50:20\n   |\n50 |     #[field(name = \"first\")]\n   |                    ^^^^^^^\n\nerror: [help] declared in this field\n  --> tests/ui-fail-stable/from_form.rs:50:5\n   |\n50 | /     #[field(name = \"first\")]\n51 | |     other: String,\n   | |_________________^\n\nerror: [note] previous field with conflicting name\n  --> tests/ui-fail-stable/from_form.rs:49:5\n   |\n49 |     first: String,\n   |     ^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:47:10\n   |\n47 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected attribute parameter: `field`\n  --> tests/ui-fail-stable/from_form.rs:56:28\n   |\n56 |     #[field(name = \"blah\", field = \"bloo\")]\n   |                            ^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:54:10\n   |\n54 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[field(..)]`, found bare path \"field\"\n  --> tests/ui-fail-stable/from_form.rs:62:7\n   |\n62 |     #[field]\n   |       ^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:60:10\n   |\n60 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-stable/from_form.rs:68:13\n   |\n68 |     #[field(\"blah\")]\n   |             ^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:66:10\n   |\n66 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-stable/from_form.rs:74:13\n   |\n74 |     #[field(123)]\n   |             ^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:72:10\n   |\n72 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected attribute parameter: `beep`\n  --> tests/ui-fail-stable/from_form.rs:80:13\n   |\n80 |     #[field(beep = \"bop\")]\n   |             ^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:78:10\n   |\n78 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field has conflicting names\n  --> tests/ui-fail-stable/from_form.rs:86:5\n   |\n86 | /     #[field(name = \"blah\")]\n87 | |     #[field(name = \"blah\")]\n88 | |     my_field: String,\n   | |____________________^\n\nerror: [note] this field name...\n  --> tests/ui-fail-stable/from_form.rs:86:20\n   |\n86 |     #[field(name = \"blah\")]\n   |                    ^^^^^^\n\nerror: [note] ...conflicts with this field name\n  --> tests/ui-fail-stable/from_form.rs:87:20\n   |\n87 |     #[field(name = \"blah\")]\n   |                    ^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:84:10\n   |\n84 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[attr(..)]`, found bare boolean literal\n  --> tests/ui-fail-stable/from_form.rs:93:20\n   |\n93 |     #[field(name = true)]\n   |                    ^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:91:10\n   |\n91 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected expression, found bare path \"name\"\n  --> tests/ui-fail-stable/from_form.rs:99:13\n   |\n99 |     #[field(name)]\n   |             ^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form.rs:97:10\n   |\n97 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[attr(..)]`, found bare integer literal\n   --> tests/ui-fail-stable/from_form.rs:105:20\n    |\n105 |     #[field(name = 123)]\n    |                    ^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:103:10\n    |\n103 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n       = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\n   --> tests/ui-fail-stable/from_form.rs:111:20\n    |\n111 |     #[field(name = \"hello&world\")]\n    |                    ^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:109:10\n    |\n109 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n       = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\n   --> tests/ui-fail-stable/from_form.rs:117:20\n    |\n117 |     #[field(name = \"!@#$%^&*()_\")]\n    |                    ^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:115:10\n    |\n115 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n       = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\n   --> tests/ui-fail-stable/from_form.rs:123:20\n    |\n123 |     #[field(name = \"?\")]\n    |                    ^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:121:10\n    |\n121 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n       = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\n   --> tests/ui-fail-stable/from_form.rs:129:20\n    |\n129 |     #[field(name = \"\")]\n    |                    ^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:127:10\n    |\n127 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n       = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\n   --> tests/ui-fail-stable/from_form.rs:135:20\n    |\n135 |     #[field(name = \"a&b\")]\n    |                    ^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:133:10\n    |\n133 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid form field name\n       = help: field name cannot be `isindex` or contain '&', '=', '?', '.', '[', ']'\n   --> tests/ui-fail-stable/from_form.rs:141:20\n    |\n141 |     #[field(name = \"a=\")]\n    |                    ^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:139:10\n    |\n139 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate attribute parameter: default\n   --> tests/ui-fail-stable/from_form.rs:177:26\n    |\n177 |     #[field(default = 1, default = 2)]\n    |                          ^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:175:10\n    |\n175 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate default field expression\n       = help: at most one `default` or `default_with` is allowed\n   --> tests/ui-fail-stable/from_form.rs:184:23\n    |\n181 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n...\n184 |     #[field(default = 2)]\n    |                       ^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:181:10\n    |\n181 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate default expressions\n       = help: only one of `default` or `default_with` must be used\n   --> tests/ui-fail-stable/from_form.rs:190:23\n    |\n188 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n189 | struct Default3 {\n190 |     #[field(default = 1, default_with = None)]\n    |                       ^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] other default expression is here\n   --> tests/ui-fail-stable/from_form.rs:190:41\n    |\n190 |     #[field(default = 1, default_with = None)]\n    |                                         ^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:188:10\n    |\n188 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: duplicate default expressions\n       = help: only one of `default` or `default_with` must be used\n   --> tests/ui-fail-stable/from_form.rs:197:23\n    |\n194 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n...\n197 |     #[field(default = 1)]\n    |                       ^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: [note] other default expression is here\n   --> tests/ui-fail-stable/from_form.rs:196:28\n    |\n196 |     #[field(default_with = None)]\n    |                            ^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form.rs:194:10\n    |\n194 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-stable/from_form.rs:147:24\n    |\n147 |     #[field(validate = 123)]\n    |                        ^^^ expected `Result<(), Errors<'_>>`, found integer\n    |\n    = note: expected enum `Result<(), Errors<'_>>`\n               found type `{integer}`\n\nerror[E0425]: cannot find function `unknown` in this scope\n   --> tests/ui-fail-stable/from_form.rs:153:24\n    |\n153 |     #[field(validate = unknown())]\n    |                        ^^^^^^^ not found in this scope\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-stable/from_form.rs:160:12\n    |\n159 |     #[field(validate = ext(rocket::http::ContentType::HTML))]\n    |                        --- arguments to this function are incorrect\n160 |     first: String,\n    |            ^^^^^^ expected `&TempFile<'_>`, found `&String`\n    |\n    = note: expected reference `&TempFile<'_>`\n               found reference `&std::string::String`\nnote: function defined here\n   --> $WORKSPACE/core/lib/src/form/validate.rs\n    |\n    | pub fn ext<'v>(file: &TempFile<'_>, r#type: ContentType) -> Result<'v, ()> {\n    |        ^^^\n\nerror[E0308]: arguments to this function are incorrect\n   --> tests/ui-fail-stable/from_form.rs:165:24\n    |\n165 |     #[field(validate = ext(\"hello\"))]\n    |                        ^^^ ------- expected `ContentType`, found `&str`\n166 |     first: String,\n    |            ------ expected `&TempFile<'_>`, found `&String`\n    |\n    = note: expected reference `&TempFile<'_>`\n               found reference `&std::string::String`\nnote: function defined here\n   --> $WORKSPACE/core/lib/src/form/validate.rs\n    |\n    | pub fn ext<'v>(file: &TempFile<'_>, r#type: ContentType) -> Result<'v, ()> {\n    |        ^^^\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-stable/from_form.rs:171:23\n    |\n171 |     #[field(default = 123)]\n    |                       ^^^- help: try using a conversion method: `.to_string()`\n    |                       |\n    |                       expected `String`, found integer\n    |                       arguments to this enum variant are incorrect\n    |\nhelp: the type constructed contains `{integer}` due to the type of the argument passed\n   --> tests/ui-fail-stable/from_form.rs:171:23\n    |\n169 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n170 | struct Default0 {\n171 |     #[field(default = 123)]\n    |                       ^^^ this argument influences the type of `Some`\nnote: tuple variant defined here\n   --> $RUST/core/src/option.rs\n    |\n    |     Some(#[stable(feature = \"rust1\", since = \"1.0.0\")] T),\n    |     ^^^^\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0308]: mismatched types\n   --> tests/ui-fail-stable/from_form.rs:203:33\n    |\n203 |     #[field(default_with = Some(\"hi\"))]\n    |                            ---- ^^^^- help: try using a conversion method: `.to_string()`\n    |                            |    |\n    |                            |    expected `String`, found `&str`\n    |                            arguments to this enum variant are incorrect\n    |\nhelp: the type constructed contains `&'static str` due to the type of the argument passed\n   --> tests/ui-fail-stable/from_form.rs:203:28\n    |\n203 |     #[field(default_with = Some(\"hi\"))]\n    |                            ^^^^^----^\n    |                                 |\n    |                                 this argument influences the type of `Some`\nnote: tuple variant defined here\n   --> $RUST/core/src/option.rs\n    |\n    |     Some(#[stable(feature = \"rust1\", since = \"1.0.0\")] T),\n    |     ^^^^\n\nerror[E0277]: the trait bound `bool: From<&str>` is not satisfied\n   --> tests/ui-fail-stable/from_form.rs:209:23\n    |\n207 | #[derive(FromForm)]\n    |          -------- in this derive macro expansion\n208 | struct Default6 {\n209 |     #[field(default = \"no conversion\")]\n    |                       ^^^^^^^^^^^^^^^\n    |                       |\n    |                       the trait `From<&str>` is not implemented for `bool`, which is required by `&str: Into<_>`\n    |                       this tail expression is of type `&str`\n    |\n    = help: the following other types implement trait `From<T>`:\n              <bool as From<format_description::parse::format_item::HourBase>>\n              <bool as From<format_description::parse::format_item::MonthCaseSensitive>>\n              <bool as From<format_description::parse::format_item::PeriodCase>>\n              <bool as From<format_description::parse::format_item::PeriodCaseSensitive>>\n              <bool as From<format_description::parse::format_item::SignBehavior>>\n              <bool as From<format_description::parse::format_item::WeekdayCaseSensitive>>\n              <bool as From<format_description::parse::format_item::WeekdayOneIndexed>>\n              <bool as From<format_description::parse::format_item::YearBase>>\n    = note: required for `&str` to implement `Into<bool>`\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/from_form_field.stderr",
    "content": "error: tuple structs are not supported\n --> tests/ui-fail-stable/from_form_field.rs:4:1\n  |\n4 | struct Foo1;\n  | ^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n --> tests/ui-fail-stable/from_form_field.rs:3:10\n  |\n3 | #[derive(FromFormField)]\n  |          ^^^^^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple structs are not supported\n --> tests/ui-fail-stable/from_form_field.rs:7:1\n  |\n7 | struct Foo2(usize);\n  | ^^^^^^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n --> tests/ui-fail-stable/from_form_field.rs:6:10\n  |\n6 | #[derive(FromFormField)]\n  |          ^^^^^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n  --> tests/ui-fail-stable/from_form_field.rs:10:1\n   |\n10 | / struct Foo3 {\n11 | |     foo: usize,\n12 | | }\n   | |_^\n\nerror: [note] error occurred while deriving `FromFormField`\n --> tests/ui-fail-stable/from_form_field.rs:9:10\n  |\n9 | #[derive(FromFormField)]\n  |          ^^^^^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variants cannot have fields\n  --> tests/ui-fail-stable/from_form_field.rs:16:6\n   |\n16 |     A(usize),\n   |      ^^^^^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:14:10\n   |\n14 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: enum must have at least one variant\n  --> tests/ui-fail-stable/from_form_field.rs:20:1\n   |\n20 | enum Foo5 { }\n   | ^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:19:10\n   |\n19 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: type generics are not supported\n  --> tests/ui-fail-stable/from_form_field.rs:23:11\n   |\n23 | enum Foo6<T> {\n   |           ^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:22:10\n   |\n22 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-stable/from_form_field.rs:29:21\n   |\n29 |     #[field(value = 123)]\n   |                     ^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:27:10\n   |\n27 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected literal, found bare path \"value\"\n  --> tests/ui-fail-stable/from_form_field.rs:35:13\n   |\n35 |     #[field(value)]\n   |             ^^^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:33:10\n   |\n33 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variant has conflicting values\n  --> tests/ui-fail-stable/from_form_field.rs:41:5\n   |\n41 | /     #[field(value = \"bar\")]\n42 | |     #[field(value = \"bar\")]\n43 | |     A,\n   | |_____^\n\nerror: [note] this value...\n  --> tests/ui-fail-stable/from_form_field.rs:41:21\n   |\n41 |     #[field(value = \"bar\")]\n   |                     ^^^^^\n\nerror: [note] ...conflicts with this value\n  --> tests/ui-fail-stable/from_form_field.rs:42:21\n   |\n42 |     #[field(value = \"bar\")]\n   |                     ^^^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:39:10\n   |\n39 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field value conflicts with previous value\n  --> tests/ui-fail-stable/from_form_field.rs:50:21\n   |\n50 |     #[field(value = \"BAr\")]\n   |                     ^^^^^\n\nerror: [help] ...declared in this variant\n  --> tests/ui-fail-stable/from_form_field.rs:50:5\n   |\n50 | /     #[field(value = \"BAr\")]\n51 | |     B,\n   | |_____^\n\nerror: [note] previous field with conflicting name\n  --> tests/ui-fail-stable/from_form_field.rs:48:5\n   |\n48 | /     #[field(value = \"bar\")]\n49 | |     A,\n   | |_____^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:46:10\n   |\n46 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field value conflicts with previous value\n  --> tests/ui-fail-stable/from_form_field.rs:57:21\n   |\n57 |     #[field(value = \"a\")]\n   |                     ^^^\n\nerror: [help] ...declared in this variant\n  --> tests/ui-fail-stable/from_form_field.rs:57:5\n   |\n57 | /     #[field(value = \"a\")]\n58 | |     B,\n   | |_____^\n\nerror: [note] previous field with conflicting name\n  --> tests/ui-fail-stable/from_form_field.rs:56:5\n   |\n56 |     A,\n   |     ^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:54:10\n   |\n54 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variant has conflicting values\n  --> tests/ui-fail-stable/from_form_field.rs:80:5\n   |\n80 | /     #[field(value = \"FoO\")]\n81 | |     #[field(value = \"foo\")]\n82 | |     A,\n   | |_____^\n\nerror: [note] this value...\n  --> tests/ui-fail-stable/from_form_field.rs:80:21\n   |\n80 |     #[field(value = \"FoO\")]\n   |                     ^^^^^\n\nerror: [note] ...conflicts with this value\n  --> tests/ui-fail-stable/from_form_field.rs:81:21\n   |\n81 |     #[field(value = \"foo\")]\n   |                     ^^^^^\n\nerror: [note] error occurred while deriving `FromFormField`\n  --> tests/ui-fail-stable/from_form_field.rs:78:10\n   |\n78 | #[derive(FromFormField)]\n   |          ^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromFormField` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field has conflicting names\n  --> tests/ui-fail-stable/from_form_field.rs:87:5\n   |\n87 | /     #[field(name = \"foo\")]\n88 | |     #[field(name = uncased(\"FOO\"))]\n89 | |     single: usize,\n   | |_________________^\n\nerror: [note] this field name...\n  --> tests/ui-fail-stable/from_form_field.rs:87:20\n   |\n87 |     #[field(name = \"foo\")]\n   |                    ^^^^^\n\nerror: [note] ...conflicts with this field name\n  --> tests/ui-fail-stable/from_form_field.rs:88:28\n   |\n88 |     #[field(name = uncased(\"FOO\"))]\n   |                            ^^^^^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form_field.rs:85:10\n   |\n85 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n  --> tests/ui-fail-stable/from_form_field.rs:96:20\n   |\n96 |     #[field(name = \"foo\")]\n   |                    ^^^^^\n\nerror: [help] declared in this field\n  --> tests/ui-fail-stable/from_form_field.rs:96:5\n   |\n96 | /     #[field(name = \"foo\")]\n97 | |     other: usize,\n   | |________________^\n\nerror: [note] previous field with conflicting name\n  --> tests/ui-fail-stable/from_form_field.rs:94:5\n   |\n94 | /     #[field(name = \"foo\")]\n95 | |     single: usize,\n   | |_________________^\n\nerror: [note] error occurred while deriving `FromForm`\n  --> tests/ui-fail-stable/from_form_field.rs:92:10\n   |\n92 | #[derive(FromForm)]\n   |          ^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n   --> tests/ui-fail-stable/from_form_field.rs:104:5\n    |\n104 |     hello_there: usize,\n    |     ^^^^^^^^^^^\n\nerror: [help] declared in this field\n   --> tests/ui-fail-stable/from_form_field.rs:104:5\n    |\n104 |     hello_there: usize,\n    |     ^^^^^^^^^^^^^^^^^^\n\nerror: [note] previous field with conflicting name\n   --> tests/ui-fail-stable/from_form_field.rs:102:5\n    |\n102 | /     #[field(name = uncased(\"HELLO_THERE\"))]\n103 | |     single: usize,\n    | |_________________^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form_field.rs:100:10\n    |\n100 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: field name conflicts with previous name\n   --> tests/ui-fail-stable/from_form_field.rs:111:5\n    |\n111 |     hello_there: usize,\n    |     ^^^^^^^^^^^\n\nerror: [help] declared in this field\n   --> tests/ui-fail-stable/from_form_field.rs:111:5\n    |\n111 |     hello_there: usize,\n    |     ^^^^^^^^^^^^^^^^^^\n\nerror: [note] previous field with conflicting name\n   --> tests/ui-fail-stable/from_form_field.rs:109:5\n    |\n109 | /     #[field(name = \"hello_there\")]\n110 | |     single: usize,\n    | |_________________^\n\nerror: [note] error occurred while deriving `FromForm`\n   --> tests/ui-fail-stable/from_form_field.rs:107:10\n    |\n107 | #[derive(FromForm)]\n    |          ^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/from_form_type_errors.stderr",
    "content": "error[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-stable/from_form_type_errors.rs:7:12\n  |\n7 |     field: Unknown,\n  |            ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-stable/from_form_type_errors.rs:5:10\n  |\n5 |   #[derive(FromForm)]\n  |            ^-------\n  |            |\n  |  __________in this derive macro expansion\n  | |\n6 | | struct BadType3 {\n  | |_______________^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `_::FromFormGeneratedContext<'r>: std::marker::Send`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\nnote: required because it appears within the type `_::FromFormGeneratedContext<'r>`\n --> tests/ui-fail-stable/from_form_type_errors.rs:6:8\n  |\n5 | #[derive(FromForm)]\n  |          -------- in this derive macro expansion\n6 | struct BadType3 {\n  |        ^^^^^^^^\nnote: required by a bound in `rocket::form::FromForm::Context`\n --> $WORKSPACE/core/lib/src/form/from_form.rs\n  |\n  |     type Context: Send;\n  |                   ^^^^ required by this bound in `FromForm::Context`\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-stable/from_form_type_errors.rs:14:12\n   |\n14 |     field: Foo<usize>,\n   |            ^^^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-stable/from_form_type_errors.rs:12:10\n   |\n12 |   #[derive(FromForm)]\n   |            ^-------\n   |            |\n   |  __________in this derive macro expansion\n   | |\n13 | | struct Other {\n   | |____________^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `_::FromFormGeneratedContext<'r>: std::marker::Send`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\nnote: required because it appears within the type `_::FromFormGeneratedContext<'r>`\n  --> tests/ui-fail-stable/from_form_type_errors.rs:13:8\n   |\n12 | #[derive(FromForm)]\n   |          -------- in this derive macro expansion\n13 | struct Other {\n   |        ^^^^^\nnote: required by a bound in `rocket::form::FromForm::Context`\n  --> $WORKSPACE/core/lib/src/form/from_form.rs\n   |\n   |     type Context: Send;\n   |                   ^^^^ required by this bound in `FromForm::Context`\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-stable/from_form_type_errors.rs:5:10\n  |\n5 | #[derive(FromForm)]\n  |          ^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Unknown: FromForm<'r>` is not satisfied\n --> tests/ui-fail-stable/from_form_type_errors.rs:7:12\n  |\n7 |     field: Unknown,\n  |            ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromForm<'r>`:\n            <(A, B) as FromForm<'v>>\n            <Arc<T> as FromForm<'v>>\n            <BTreeMap<K, V> as FromForm<'v>>\n            <BadType3 as FromForm<'r>>\n            <Contextual<'v, T> as FromForm<'v>>\n            <HashMap<K, V> as FromForm<'v>>\n            <Lenient<T> as FromForm<'v>>\n            <Other as FromForm<'r>>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied\n --> tests/ui-fail-stable/from_form_type_errors.rs:7:12\n  |\n5 | #[derive(FromForm)]\n  |          -------- in this derive macro expansion\n6 | struct BadType3 {\n7 |     field: Unknown,\n  |            ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown`, which is required by `Unknown: FromForm<'r>`\n  |\n  = help: the following other types implement trait `FromFormField<'v>`:\n            &'v [u8]\n            &'v str\n            Capped<&'v [u8]>\n            Capped<&'v str>\n            Capped<Cow<'v, str>>\n            Capped<TempFile<'v>>\n            Capped<std::string::String>\n            Cow<'v, str>\n          and $N others\n  = note: required for `Unknown` to implement `FromForm<'r>`\n  = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-stable/from_form_type_errors.rs:12:10\n   |\n12 | #[derive(FromForm)]\n   |          ^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `Foo<usize>: FromForm<'r>` is not satisfied\n  --> tests/ui-fail-stable/from_form_type_errors.rs:14:12\n   |\n14 |     field: Foo<usize>,\n   |            ^^^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromForm<'r>`:\n             <(A, B) as FromForm<'v>>\n             <Arc<T> as FromForm<'v>>\n             <BTreeMap<K, V> as FromForm<'v>>\n             <BadType3 as FromForm<'r>>\n             <Contextual<'v, T> as FromForm<'v>>\n             <HashMap<K, V> as FromForm<'v>>\n             <Lenient<T> as FromForm<'v>>\n             <Other as FromForm<'r>>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n\nerror[E0277]: the trait bound `Foo<usize>: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-stable/from_form_type_errors.rs:14:12\n   |\n12 | #[derive(FromForm)]\n   |          -------- in this derive macro expansion\n13 | struct Other {\n14 |     field: Foo<usize>,\n   |            ^^^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo<usize>`, which is required by `Foo<usize>: FromForm<'r>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Foo<usize>` to implement `FromForm<'r>`\n   = note: this error originates in the derive macro `FromForm` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/from_param.stderr",
    "content": "error: named structs are not supported\n --> tests/ui-fail-stable/from_param.rs:4:1\n  |\n4 | / struct Foo1 {\n5 | |     a: String\n6 | | }\n  | |_^\n\nerror: [note] error occurred while deriving `FromParam`\n --> tests/ui-fail-stable/from_param.rs:3:10\n  |\n3 | #[derive(FromParam)]\n  |          ^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n --> tests/ui-fail-stable/from_param.rs:9:1\n  |\n9 | struct Foo2 {}\n  | ^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromParam`\n --> tests/ui-fail-stable/from_param.rs:8:10\n  |\n8 | #[derive(FromParam)]\n  |          ^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: variants with data fields are not supported\n  --> tests/ui-fail-stable/from_param.rs:13:6\n   |\n13 |     A(String),\n   |      ^^^^^^^^\n\nerror: [note] error occurred while deriving `FromParam`\n  --> tests/ui-fail-stable/from_param.rs:11:10\n   |\n11 | #[derive(FromParam)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple structs are not supported\n  --> tests/ui-fail-stable/from_param.rs:18:1\n   |\n18 | struct Foo4(usize);\n   | ^^^^^^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `FromParam`\n  --> tests/ui-fail-stable/from_param.rs:17:10\n   |\n17 | #[derive(FromParam)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `FromParam` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/responder-types.stderr",
    "content": "error[E0277]: the trait bound `u8: Responder<'_, '_>` is not satisfied\n --> tests/ui-fail-stable/responder-types.rs:5:12\n  |\n5 |     thing: u8,\n  |            ^^ the trait `Responder<'_, '_>` is not implemented for `u8`\n  |\n  = help: the following other types implement trait `Responder<'r, 'o>`:\n            <&'o [u8] as Responder<'r, 'o>>\n            <&'o str as Responder<'r, 'o>>\n            <() as Responder<'r, 'static>>\n            <(ContentType, R) as Responder<'r, 'o>>\n            <(Status, R) as Responder<'r, 'o>>\n            <Accepted<R> as Responder<'r, 'o>>\n            <Arc<[u8]> as Responder<'r, 'static>>\n            <Arc<str> as Responder<'r, 'static>>\n          and $N others\n\nerror[E0277]: the trait bound `Header<'_>: From<u8>` is not satisfied\n  --> tests/ui-fail-stable/responder-types.rs:11:5\n   |\n11 |     other: u8,\n   |     ^^^^^^^^^ the trait `From<u8>` is not implemented for `Header<'_>`, which is required by `u8: Into<Header<'_>>`\n   |\n   = help: the following other types implement trait `From<T>`:\n             <Header<'static> as From<&Cookie<'_>>>\n             <Header<'static> as From<&ExpectCt>>\n             <Header<'static> as From<&Frame>>\n             <Header<'static> as From<&Hsts>>\n             <Header<'static> as From<&NoSniff>>\n             <Header<'static> as From<&Permission>>\n             <Header<'static> as From<&Prefetch>>\n             <Header<'static> as From<&Referrer>>\n           and $N others\n   = note: required for `u8` to implement `Into<Header<'_>>`\nnote: required by a bound in `Response::<'r>::set_header`\n  --> $WORKSPACE/core/lib/src/response/response.rs\n   |\n   |     pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {\n   |                                  ^^^^^^^^^^^^^^^^ required by this bound in `Response::<'r>::set_header`\n\nerror[E0277]: the trait bound `u8: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-stable/responder-types.rs:16:12\n   |\n16 |     thing: u8,\n   |            ^^ the trait `Responder<'_, '_>` is not implemented for `u8`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             <&'o [u8] as Responder<'r, 'o>>\n             <&'o str as Responder<'r, 'o>>\n             <() as Responder<'r, 'static>>\n             <(ContentType, R) as Responder<'r, 'o>>\n             <(Status, R) as Responder<'r, 'o>>\n             <Accepted<R> as Responder<'r, 'o>>\n             <Arc<[u8]> as Responder<'r, 'static>>\n             <Arc<str> as Responder<'r, 'static>>\n           and $N others\n\nerror[E0277]: the trait bound `Header<'_>: From<u8>` is not satisfied\n  --> tests/ui-fail-stable/responder-types.rs:17:5\n   |\n17 |     other: u8,\n   |     ^^^^^^^^^ the trait `From<u8>` is not implemented for `Header<'_>`, which is required by `u8: Into<Header<'_>>`\n   |\n   = help: the following other types implement trait `From<T>`:\n             <Header<'static> as From<&Cookie<'_>>>\n             <Header<'static> as From<&ExpectCt>>\n             <Header<'static> as From<&Frame>>\n             <Header<'static> as From<&Hsts>>\n             <Header<'static> as From<&NoSniff>>\n             <Header<'static> as From<&Permission>>\n             <Header<'static> as From<&Prefetch>>\n             <Header<'static> as From<&Referrer>>\n           and $N others\n   = note: required for `u8` to implement `Into<Header<'_>>`\nnote: required by a bound in `Response::<'r>::set_header`\n  --> $WORKSPACE/core/lib/src/response/response.rs\n   |\n   |     pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {\n   |                                  ^^^^^^^^^^^^^^^^ required by this bound in `Response::<'r>::set_header`\n\nerror[E0277]: the trait bound `Header<'_>: From<std::string::String>` is not satisfied\n  --> tests/ui-fail-stable/responder-types.rs:24:5\n   |\n24 |     then: String,\n   |     ^^^^^^^^^^^^ the trait `From<std::string::String>` is not implemented for `Header<'_>`, which is required by `std::string::String: Into<Header<'_>>`\n   |\n   = help: the following other types implement trait `From<T>`:\n             <Header<'static> as From<&Cookie<'_>>>\n             <Header<'static> as From<&ExpectCt>>\n             <Header<'static> as From<&Frame>>\n             <Header<'static> as From<&Hsts>>\n             <Header<'static> as From<&NoSniff>>\n             <Header<'static> as From<&Permission>>\n             <Header<'static> as From<&Prefetch>>\n             <Header<'static> as From<&Referrer>>\n           and $N others\n   = note: required for `std::string::String` to implement `Into<Header<'_>>`\nnote: required by a bound in `Response::<'r>::set_header`\n  --> $WORKSPACE/core/lib/src/response/response.rs\n   |\n   |     pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {\n   |                                  ^^^^^^^^^^^^^^^^ required by this bound in `Response::<'r>::set_header`\n\nerror[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied\n  --> tests/ui-fail-stable/responder-types.rs:28:13\n   |\n27 | #[get(\"/\")]\n   | ----------- in this procedural macro expansion\n28 | fn foo() -> usize { 0 }\n   |             ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Responder<'r, 'o>`:\n             <&'o [u8] as Responder<'r, 'o>>\n             <&'o str as Responder<'r, 'o>>\n             <() as Responder<'r, 'static>>\n             <(ContentType, R) as Responder<'r, 'o>>\n             <(Status, R) as Responder<'r, 'o>>\n             <Accepted<R> as Responder<'r, 'o>>\n             <Arc<[u8]> as Responder<'r, 'static>>\n             <Arc<str> as Responder<'r, 'static>>\n           and $N others\nnote: required by a bound in `route::handler::<impl Outcome<Response<'o>, Status, (rocket::Data<'o>, Status)>>::from`\n  --> $WORKSPACE/core/lib/src/route/handler.rs\n   |\n   |     pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {\n   |                    ^^^^^^^^^^^^^^^^^ required by this bound in `route::handler::<impl Outcome<Response<'o>, Status, (Data<'o>, Status)>>::from`\n   = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/responder.stderr",
    "content": "error: need at least one field\n --> tests/ui-fail-stable/responder.rs:4:1\n  |\n4 | struct Thing1;\n  | ^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `Responder`\n --> tests/ui-fail-stable/responder.rs:3:10\n  |\n3 | #[derive(Responder)]\n  |          ^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: need at least one field\n --> tests/ui-fail-stable/responder.rs:7:14\n  |\n7 | struct Thing2();\n  |              ^^\n\nerror: [note] error occurred while deriving `Responder`\n --> tests/ui-fail-stable/responder.rs:6:10\n  |\n6 | #[derive(Responder)]\n  |          ^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: need at least one field\n  --> tests/ui-fail-stable/responder.rs:13:12\n   |\n13 | enum Foo { Bark, }\n   |            ^^^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:12:10\n   |\n12 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: only one lifetime is supported\n  --> tests/ui-fail-stable/responder.rs:16:14\n   |\n16 | struct Thing4<'a, 'b>(&'a str, &'b str);\n   |              ^^^^^^^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:15:10\n   |\n15 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid or unknown content type\n  --> tests/ui-fail-stable/responder.rs:25:27\n   |\n25 | #[response(content_type = \"\")]\n   |                           ^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:24:10\n   |\n24 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid or unknown content type\n  --> tests/ui-fail-stable/responder.rs:29:27\n   |\n29 | #[response(content_type = \"idk\")]\n   |                           ^^^^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:28:10\n   |\n28 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-stable/responder.rs:33:27\n   |\n33 | #[response(content_type = 100)]\n   |                           ^^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:32:10\n   |\n32 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: status must be in range [100, 599]\n  --> tests/ui-fail-stable/responder.rs:37:21\n   |\n37 | #[response(status = 8)]\n   |                     ^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:36:10\n   |\n36 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected unsigned integer literal\n  --> tests/ui-fail-stable/responder.rs:41:21\n   |\n41 | #[response(status = \"404\")]\n   |                     ^^^^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:40:10\n   |\n40 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected unsigned integer literal\n  --> tests/ui-fail-stable/responder.rs:45:21\n   |\n45 | #[response(status = \"404\", content_type = \"html\")]\n   |                     ^^^^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:44:10\n   |\n44 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-stable/responder.rs:49:41\n   |\n49 | #[response(status = 404, content_type = 120)]\n   |                                         ^^^\n\nerror: [note] error occurred while deriving `Responder`\n  --> tests/ui-fail-stable/responder.rs:48:10\n   |\n48 | #[derive(Responder)]\n   |          ^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `Responder` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/route-attribute-general-syntax.stderr",
    "content": "error: missing expected parameter: `uri`\n --> tests/ui-fail-stable/route-attribute-general-syntax.rs:4:1\n  |\n4 | #[get()]\n  | ^^^^^^^^\n  |\n  = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected `fn`\n       = help: #[get] can only be used on functions\n --> tests/ui-fail-stable/route-attribute-general-syntax.rs:9:1\n  |\n9 | struct S;\n  | ^^^^^^\n\nerror: expected `fn`\n       = help: #[get] can only be used on functions\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:12:1\n   |\n12 | enum A {  }\n   | ^^^^\n\nerror: expected `fn`\n       = help: #[get] can only be used on functions\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:15:1\n   |\n15 | trait Foo {  }\n   | ^^^^^\n\nerror: expected `fn`\n       = help: #[get] can only be used on functions\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:18:1\n   |\n18 | impl S {  }\n   | ^^^^\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:21:12\n   |\n21 | #[get(\"/\", 123)]\n   |            ^^^\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:24:12\n   |\n24 | #[get(\"/\", \"/\")]\n   |            ^^^\n\nerror: unexpected keyed parameter: expected literal or identifier\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:27:7\n   |\n27 | #[get(data = \"<foo>\", \"/\")]\n   |       ^^^^^^^^^^^^^^\n\nerror: unexpected attribute parameter: `unknown`\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:30:12\n   |\n30 | #[get(\"/\", unknown = \"foo\")]\n   |            ^^^^^^^^^^^^^^^\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:33:12\n   |\n33 | #[get(\"/\", ...)]\n   |            ^^^\n\nerror: handler arguments must be named\n       = help: to name an ignored handler argument, use `_name`\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:39:7\n   |\n39 | fn c1(_: usize) {}\n   |       ^^^^^^^^\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:43:7\n   |\n43 | #[get(100)]\n   |       ^^^\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:46:7\n   |\n46 | #[get('/')]\n   |       ^^^\n\nerror: invalid value: expected integer literal\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:49:19\n   |\n49 | #[get(\"/\", rank = \"1\")]\n   |                   ^^^\n\nerror: invalid value: expected integer literal\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:52:19\n   |\n52 | #[get(\"/\", rank = '1')]\n   |                   ^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:57:21\n   |\n57 | #[get(\"/\", format = \"applicationx-custom\")]\n   |                     ^^^^^^^^^^^^^^^^^^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:60:21\n   |\n60 | #[get(\"/\", format = \"\")]\n   |                     ^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:63:21\n   |\n63 | #[get(\"/\", format = \"//\")]\n   |                     ^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:66:21\n   |\n66 | #[get(\"/\", format = \"/\")]\n   |                     ^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:69:21\n   |\n69 | #[get(\"/\", format = \"a/\")]\n   |                     ^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:72:21\n   |\n72 | #[get(\"/\", format = \"/a\")]\n   |                     ^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:75:21\n   |\n75 | #[get(\"/\", format = \"/a/\")]\n   |                     ^^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:78:21\n   |\n78 | #[get(\"/\", format = \"a/b/\")]\n   |                     ^^^^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:81:21\n   |\n81 | #[get(\"/\", format = \"unknown\")]\n   |                     ^^^^^^^^^\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:84:21\n   |\n84 | #[get(\"/\", format = 12)]\n   |                     ^^\n\nerror: invalid value: expected string literal\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:87:21\n   |\n87 | #[get(\"/\", format = 'j')]\n   |                     ^^^\n\nerror: invalid or unknown media type\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:90:21\n   |\n90 | #[get(\"/\", format = \"text//foo\")]\n   |                     ^^^^^^^^^^^\n\nerror: expected key/value `key = value`\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:95:18\n   |\n95 | #[route(CONNECT, \"/\")]\n   |                  ^^^\n\nerror: invalid or unknown HTTP method\n       = help: known methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH, ACL, BASELINE-CONTROL, BIND, CHECKIN, CHECKOUT, COPY, LABEL, LINK, LOCK, MERGE, MKACTIVITY, MKCALENDAR, MKCOL, MKREDIRECTREF, MKWORKSPACE, MOVE, ORDERPATCH, PROPFIND, PROPPATCH, REBIND, REPORT, SEARCH, UNBIND, UNCHECKOUT, UNLINK, UNLOCK, UPDATE, UPDATEREDIRECTREF, VERSION-CONTROL\n  --> tests/ui-fail-stable/route-attribute-general-syntax.rs:98:9\n   |\n98 | #[route(FIX, \"/\")]\n   |         ^^^\n\nerror: invalid or unknown HTTP method\n       = help: known methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH, ACL, BASELINE-CONTROL, BIND, CHECKIN, CHECKOUT, COPY, LABEL, LINK, LOCK, MERGE, MKACTIVITY, MKCALENDAR, MKCOL, MKREDIRECTREF, MKWORKSPACE, MOVE, ORDERPATCH, PROPFIND, PROPPATCH, REBIND, REPORT, SEARCH, UNBIND, UNCHECKOUT, UNLINK, UNLOCK, UPDATE, UPDATEREDIRECTREF, VERSION-CONTROL\n   --> tests/ui-fail-stable/route-attribute-general-syntax.rs:101:9\n    |\n101 | #[route(\"hi\", \"/\")]\n    |         ^^^^\n\nerror: expected key/value `key = value`\n   --> tests/ui-fail-stable/route-attribute-general-syntax.rs:104:16\n    |\n104 | #[route(\"GET\", \"/\")]\n    |                ^^^\n\nerror: expected method ident or string, found integer literal\n       = help: known methods: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH, ACL, BASELINE-CONTROL, BIND, CHECKIN, CHECKOUT, COPY, LABEL, LINK, LOCK, MERGE, MKACTIVITY, MKCALENDAR, MKCOL, MKREDIRECTREF, MKWORKSPACE, MOVE, ORDERPATCH, PROPFIND, PROPPATCH, REBIND, REPORT, SEARCH, UNBIND, UNCHECKOUT, UNLINK, UNLOCK, UPDATE, UPDATEREDIRECTREF, VERSION-CONTROL\n   --> tests/ui-fail-stable/route-attribute-general-syntax.rs:107:9\n    |\n107 | #[route(120, \"/\")]\n    |         ^^^\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/route-path-bad-syntax.stderr",
    "content": "error: invalid route URI: expected token '/' but found 'a' at index 0\n       = help: expected URI in origin form: \"/path/<param>\"\n --> tests/ui-fail-stable/route-path-bad-syntax.rs:5:8\n  |\n5 | #[get(\"a\")]\n  |        ^\n\nerror: invalid route URI: unexpected EOF: expected token '/' at index 0\n       = help: expected URI in origin form: \"/path/<param>\"\n --> tests/ui-fail-stable/route-path-bad-syntax.rs:8:8\n  |\n8 | #[get(\"\")]\n  |        ^\n\nerror: invalid route URI: expected token '/' but found 'a' at index 0\n       = help: expected URI in origin form: \"/path/<param>\"\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:11:8\n   |\n11 | #[get(\"a/b/c\")]\n   |        ^\n\nerror: route URIs cannot contain empty segments\n       = note: expected \"/a/b\", found \"/a///b\"\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:14:10\n   |\n14 | #[get(\"/a///b\")]\n   |          ^^\n\nerror: route URIs cannot contain empty segments\n       = note: expected \"/?bat\", found \"/?bat&&\"\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:17:13\n   |\n17 | #[get(\"/?bat&&\")]\n   |             ^^\n\nerror: route URIs cannot contain empty segments\n       = note: expected \"/?bat\", found \"/?bat&&\"\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:20:13\n   |\n20 | #[get(\"/?bat&&\")]\n   |             ^^\n\nerror: route URIs cannot contain empty segments\n       = note: expected \"/a/b/\", found \"/a/b//\"\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:23:12\n   |\n23 | #[get(\"/a/b//\")]\n   |            ^^\n\nerror: unused parameter\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:42:10\n   |\n42 | #[get(\"/<name>\")]\n   |          ^^^^\n\nerror: [note] expected argument named `name` here\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:43:6\n   |\n43 | fn h0(_name: usize) {}\n   |      ^^^^^^^^^^^^^^\n\nerror: unused parameter\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:45:12\n   |\n45 | #[get(\"/a?<r>\")]\n   |            ^\n\nerror: [note] expected argument named `r` here\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:46:6\n   |\n46 | fn h1() {}\n   |      ^^\n\nerror: unused parameter\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:48:23\n   |\n48 | #[post(\"/a\", data = \"<test>\")]\n   |                       ^^^^\n\nerror: [note] expected argument named `test` here\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:49:6\n   |\n49 | fn h2() {}\n   |      ^^\n\nerror: unused parameter\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:51:10\n   |\n51 | #[get(\"/<_r>\")]\n   |          ^^\n\nerror: [note] expected argument named `_r` here\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:52:6\n   |\n52 | fn h3() {}\n   |      ^^\n\nerror: unused parameter\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:54:15\n   |\n54 | #[get(\"/<_r>/<b>\")]\n   |               ^\n\nerror: [note] expected argument named `b` here\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:55:6\n   |\n55 | fn h4() {}\n   |      ^^\n\nerror: invalid identifier: `foo_.`\n       = help: dynamic parameters must be valid identifiers\n       = help: did you mean `<foo_>`?\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:60:10\n   |\n60 | #[get(\"/<foo_.>\")]\n   |          ^^^^^\n\nerror: invalid identifier: `foo*`\n       = help: dynamic parameters must be valid identifiers\n       = help: did you mean `<foo>`?\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:63:10\n   |\n63 | #[get(\"/<foo*>\")]\n   |          ^^^^\n\nerror: invalid identifier: `!`\n       = help: dynamic parameters must be valid identifiers\n       = help: did you mean `<param>`?\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:66:10\n   |\n66 | #[get(\"/<!>\")]\n   |          ^\n\nerror: invalid identifier: `name>:<id`\n       = help: dynamic parameters must be valid identifiers\n       = help: did you mean `<nameid>`?\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:69:10\n   |\n69 | #[get(\"/<name>:<id>\")]\n   |          ^^^^^^^^^\n\nerror: unexpected static parameter\n       = help: parameter must be dynamic: `<foo>`\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:74:20\n   |\n74 | #[get(\"/\", data = \"foo\")]\n   |                    ^^^\n\nerror: parameter cannot be trailing\n       = help: did you mean `<foo>`?\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:77:20\n   |\n77 | #[get(\"/\", data = \"<foo..>\")]\n   |                    ^^^^^^^\n\nerror: unexpected static parameter\n       = help: parameter must be dynamic: `<foo>`\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:80:20\n   |\n80 | #[get(\"/\", data = \"<foo\")]\n   |                    ^^^^\n\nerror: invalid identifier: `test `\n       = help: dynamic parameters must be valid identifiers\n       = help: did you mean `<test>`?\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:83:21\n   |\n83 | #[get(\"/\", data = \"<test >\")]\n   |                     ^^^^^\n\nerror: handler arguments must be named\n       = help: to name an ignored handler argument, use `_name`\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:89:7\n   |\n89 | fn k0(_: usize) {}\n   |       ^^^^^^^^\n\nerror: parameters cannot be empty\n  --> tests/ui-fail-stable/route-path-bad-syntax.rs:93:9\n   |\n93 | #[get(\"/<>\")]\n   |         ^^\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/route-type-errors.stderr",
    "content": "error[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n --> tests/ui-fail-stable/route-type-errors.rs:6:13\n  |\n6 | fn f0(_foo: Q) {}\n  |             ^ the trait `FromParam<'_>` is not implemented for `Q`\n  |\n  = help: the following other types implement trait `FromParam<'a>`:\n            <&'a str as FromParam<'a>>\n            <IpAddr as FromParam<'a>>\n            <Ipv4Addr as FromParam<'a>>\n            <Ipv6Addr as FromParam<'a>>\n            <NonZero<i128> as FromParam<'a>>\n            <NonZero<i16> as FromParam<'a>>\n            <NonZero<i32> as FromParam<'a>>\n            <NonZero<i64> as FromParam<'a>>\n          and $N others\n\nerror[E0277]: the trait bound `Q: FromSegments<'_>` is not satisfied\n --> tests/ui-fail-stable/route-type-errors.rs:9:13\n  |\n9 | fn f1(_foo: Q) {}\n  |             ^ the trait `FromSegments<'_>` is not implemented for `Q`\n  |\n  = help: the following other types implement trait `FromSegments<'r>`:\n            <PathBuf as FromSegments<'_>>\n            <Result<T, <T as FromSegments<'r>>::Error> as FromSegments<'r>>\n            <Segments<'r, rocket::http::uri::fmt::Path> as FromSegments<'r>>\n            <std::option::Option<T> as FromSegments<'r>>\n\nerror[E0277]: the trait bound `Q: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:12:13\n   |\n12 | fn f2(_foo: Q) {}\n   |             ^ the trait `FromFormField<'_>` is not implemented for `Q`, which is required by `Q: FromForm<'_>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Q` to implement `FromForm<'_>`\n\nerror[E0277]: the trait bound `Q: FromFormField<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:15:13\n   |\n15 | fn f3(_foo: Q) {}\n   |             ^ the trait `FromFormField<'_>` is not implemented for `Q`, which is required by `Q: FromForm<'_>`\n   |\n   = help: the following other types implement trait `FromFormField<'v>`:\n             &'v [u8]\n             &'v str\n             Capped<&'v [u8]>\n             Capped<&'v str>\n             Capped<Cow<'v, str>>\n             Capped<TempFile<'v>>\n             Capped<std::string::String>\n             Cow<'v, str>\n           and $N others\n   = note: required for `Q` to implement `FromForm<'_>`\n\nerror[E0277]: the trait bound `Q: FromData<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:18:13\n   |\n18 | fn f4(_foo: Q) {}\n   |             ^ the trait `FromData<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromData<'r>`:\n             &'r RawStr\n             &'r [u8]\n             &'r str\n             Capped<&'r RawStr>\n             Capped<&'r [u8]>\n             Capped<&'r str>\n             Capped<Cow<'_, str>>\n             Capped<TempFile<'_>>\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:21:11\n   |\n21 | fn f5(_a: Q, _foo: Q) {}\n   |           ^ the trait `FromRequest<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromRequest<'r>`:\n             &'r Accept\n             &'r ContentType\n             &'r CookieJar<'r>\n             &'r Endpoint\n             &'r Host<'r>\n             &'r Limits\n             &'r Route\n             &'r rocket::Config\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:21:20\n   |\n21 | fn f5(_a: Q, _foo: Q) {}\n   |                    ^ the trait `FromParam<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromParam<'a>`:\n             <&'a str as FromParam<'a>>\n             <IpAddr as FromParam<'a>>\n             <Ipv4Addr as FromParam<'a>>\n             <Ipv6Addr as FromParam<'a>>\n             <NonZero<i128> as FromParam<'a>>\n             <NonZero<i16> as FromParam<'a>>\n             <NonZero<i32> as FromParam<'a>>\n             <NonZero<i64> as FromParam<'a>>\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromRequest<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:24:11\n   |\n24 | fn f6(_a: Q, _foo: Q, _good: usize, _bar: Q) {}\n   |           ^ the trait `FromRequest<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromRequest<'r>`:\n             &'r Accept\n             &'r ContentType\n             &'r CookieJar<'r>\n             &'r Endpoint\n             &'r Host<'r>\n             &'r Limits\n             &'r Route\n             &'r rocket::Config\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:24:20\n   |\n24 | fn f6(_a: Q, _foo: Q, _good: usize, _bar: Q) {}\n   |                    ^ the trait `FromParam<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromParam<'a>`:\n             <&'a str as FromParam<'a>>\n             <IpAddr as FromParam<'a>>\n             <Ipv4Addr as FromParam<'a>>\n             <Ipv6Addr as FromParam<'a>>\n             <NonZero<i128> as FromParam<'a>>\n             <NonZero<i16> as FromParam<'a>>\n             <NonZero<i32> as FromParam<'a>>\n             <NonZero<i64> as FromParam<'a>>\n           and $N others\n\nerror[E0277]: the trait bound `Q: FromParam<'_>` is not satisfied\n  --> tests/ui-fail-stable/route-type-errors.rs:24:43\n   |\n24 | fn f6(_a: Q, _foo: Q, _good: usize, _bar: Q) {}\n   |                                           ^ the trait `FromParam<'_>` is not implemented for `Q`\n   |\n   = help: the following other types implement trait `FromParam<'a>`:\n             <&'a str as FromParam<'a>>\n             <IpAddr as FromParam<'a>>\n             <Ipv4Addr as FromParam<'a>>\n             <Ipv6Addr as FromParam<'a>>\n             <NonZero<i128> as FromParam<'a>>\n             <NonZero<i16> as FromParam<'a>>\n             <NonZero<i32> as FromParam<'a>>\n             <NonZero<i64> as FromParam<'a>>\n           and $N others\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/route-warnings.stderr",
    "content": "error: checking for warnings!\n  --> tests/ui-fail-stable/route-warnings.rs:33:5\n   |\n33 |     compile_error!(\"checking for warnings!\")\n   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/routes.stderr",
    "content": "error: expected `,`\n --> $DIR/routes.rs:4:23\n  |\n4 |     let _ = routes![a b];\n  |                       ^\n\nerror: expected identifier\n --> $DIR/routes.rs:6:24\n  |\n6 |     let _ = routes![a::, ];\n  |                        ^\n\nerror: unexpected end of input, expected identifier\n --> $DIR/routes.rs:7:13\n  |\n7 |     let _ = routes![a::];\n  |             ^^^^^^^^^^^^\n  |\n  = note: this error originates in the macro `routes` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/typed-uri-bad-type.stderr",
    "content": "error[E0271]: type mismatch resolving `<String as FromParam<'_>>::Error == &str`\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:24:37\n   |\n24 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                                     ^^^^^^^^^^^^^^^^^^^^ expected `Empty`, found `&str`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n47 |     uri!(simple(id = \"hi\"));\n   |     ----------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n49 |     uri!(simple(\"hello\"));\n   |     --------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, i64>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, i64>` is not implemented for `usize`\n...\n51 |     uri!(simple(id = 239239i64));\n   |     ---------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Path, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:18:35\n   |\n18 | fn not_uri_display(id: i32, name: S) {  }\n   |                                   ^ the trait `FromUriParam<rocket::http::uri::fmt::Path, _>` is not implemented for `S`\n...\n53 |     uri!(not_uri_display(10, S));\n   |     ---------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_not_uri_display` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Path, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:53:30\n   |\n53 |     uri!(not_uri_display(10, S));\n   |                              ^ the trait `FromUriParam<rocket::http::uri::fmt::Path, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `i32: FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:24:18\n   |\n24 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                  ^^^^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not implemented for `i32`, which is required by `std::option::Option<i32>: FromUriParam<rocket::http::uri::fmt::Path, _>`\n...\n58 |     uri!(optionals(id = Some(10), name = Ok(\"bob\".into())));\n   |     ------------------------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <i32 as FromUriParam<P, &'x i32>>\n             <i32 as FromUriParam<P, &'x mut i32>>\n             <i32 as FromUriParam<P, i32>>\n   = note: required for `std::option::Option<i32>` to implement `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>`\n   = note: this error originates in the macro `rocket_uri_macro_optionals` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `std::string::String: FromUriParam<rocket::http::uri::fmt::Path, Result<_, _>>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:24:37\n   |\n24 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                                     ^^^^^^^^^^^^^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, Result<_, _>>` is not implemented for `std::string::String`, which is required by `Result<std::string::String, &str>: FromUriParam<rocket::http::uri::fmt::Path, _>`\n...\n58 |     uri!(optionals(id = Some(10), name = Ok(\"bob\".into())));\n   |     ------------------------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <std::string::String as FromUriParam<P, &'a str>>\n             <std::string::String as FromUriParam<P, &'x &'a str>>\n             <std::string::String as FromUriParam<P, &'x mut &'a str>>\n             <std::string::String as FromUriParam<P, &'x mut std::string::String>>\n             <std::string::String as FromUriParam<P, &'x std::string::String>>\n             <std::string::String as FromUriParam<P, std::string::String>>\n   = note: required for `Result<std::string::String, &str>` to implement `FromUriParam<rocket::http::uri::fmt::Path, Result<_, _>>`\n   = note: this error originates in the macro `rocket_uri_macro_optionals` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:38:17\n   |\n38 | fn simple_q(id: isize) {  }\n   |                 ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n...\n60 |     uri!(simple_q(\"hi\"));\n   |     -------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <isize as FromUriParam<P, &'x isize>>\n             <isize as FromUriParam<P, &'x mut isize>>\n             <isize as FromUriParam<P, isize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:38:17\n   |\n38 | fn simple_q(id: isize) {  }\n   |                 ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n...\n62 |     uri!(simple_q(id = \"hi\"));\n   |     ------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <isize as FromUriParam<P, &'x isize>>\n             <isize as FromUriParam<P, &'x mut isize>>\n             <isize as FromUriParam<P, isize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:41:29\n   |\n41 | fn other_q(id: usize, rest: S) {  }\n   |                             ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n...\n64 |     uri!(other_q(100, S));\n   |     --------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_other_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:64:23\n   |\n64 |     uri!(other_q(100, S));\n   |                       ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:41:29\n   |\n41 | fn other_q(id: usize, rest: S) {  }\n   |                             ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n...\n66 |     uri!(other_q(rest = S, id = 100));\n   |     --------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_other_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:66:25\n   |\n66 |     uri!(other_q(rest = S, id = 100));\n   |                         ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: Ignorable<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:68:25\n   |\n68 |     uri!(other_q(rest = _, id = 100));\n   |                         ^ the trait `Ignorable<rocket::http::uri::fmt::Query>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `Ignorable<P>`:\n             Result<T, E>\n             std::option::Option<T>\nnote: required by a bound in `assert_ignorable`\n  --> $WORKSPACE/core/http/src/uri/fmt/uri_display.rs\n   |\n   | pub fn assert_ignorable<P: Part, T: Ignorable<P>>() {  }\n   |                                     ^^^^^^^^^^^^ required by this bound in `assert_ignorable`\n\nerror[E0277]: the trait bound `usize: Ignorable<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:70:33\n   |\n70 |     uri!(other_q(rest = S, id = _));\n   |                                 ^ the trait `Ignorable<rocket::http::uri::fmt::Query>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `Ignorable<P>`:\n             Result<T, E>\n             std::option::Option<T>\nnote: required by a bound in `assert_ignorable`\n  --> $WORKSPACE/core/http/src/uri/fmt/uri_display.rs\n   |\n   | pub fn assert_ignorable<P: Part, T: Ignorable<P>>() {  }\n   |                                     ^^^^^^^^^^^^ required by this bound in `assert_ignorable`\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:41:29\n   |\n41 | fn other_q(id: usize, rest: S) {  }\n   |                             ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n...\n70 |     uri!(other_q(rest = S, id = _));\n   |     ------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `rocket_uri_macro_other_q` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `S: FromUriParam<rocket::http::uri::fmt::Query, _>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:70:25\n   |\n70 |     uri!(other_q(rest = S, id = _));\n   |                         ^ the trait `FromUriParam<rocket::http::uri::fmt::Query, _>` is not implemented for `S`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x &'a [u8]>>\n             <&'a [u8] as FromUriParam<rocket::http::uri::fmt::Query, &'x mut &'a [u8]>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x PathBuf>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut &'a std::path::Path>>\n             <&'a std::path::Path as FromUriParam<rocket::http::uri::fmt::Path, &'x mut PathBuf>>\n           and $N others\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n79 |     uri!(uri!(\"?foo#bar\"), simple(id = \"hi\"));\n   |     ----------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Reference<'_>: ValidRoutePrefix` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:79:15\n   |\n79 |     uri!(uri!(\"?foo#bar\"), simple(id = \"hi\"));\n   |          -----^^^^^^^^^^-\n   |          |    |\n   |          |    the trait `ValidRoutePrefix` is not implemented for `rocket::http::uri::Reference<'_>`\n   |          required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRoutePrefix`:\n             rocket::http::uri::Absolute<'a>\n             rocket::http::uri::Origin<'a>\nnote: required by a bound in `RouteUriBuilder::with_prefix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_prefix<P: ValidRoutePrefix>(self, p: P) -> PrefixedRouteUri<P::Output> {\n   |                           ^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_prefix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n80 |     uri!(uri!(\"*\"), simple(id = \"hi\"));\n   |     ---------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Asterisk: ValidRoutePrefix` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:80:15\n   |\n80 |     uri!(uri!(\"*\"), simple(id = \"hi\"));\n   |          -----^^^-\n   |          |    |\n   |          |    the trait `ValidRoutePrefix` is not implemented for `rocket::http::uri::Asterisk`\n   |          required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRoutePrefix`:\n             rocket::http::uri::Absolute<'a>\n             rocket::http::uri::Origin<'a>\nnote: required by a bound in `RouteUriBuilder::with_prefix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_prefix<P: ValidRoutePrefix>(self, p: P) -> PrefixedRouteUri<P::Output> {\n   |                           ^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_prefix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n83 |     uri!(_, simple(id = \"hi\"), uri!(\"*\"));\n   |     ------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Asterisk: ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:83:37\n   |\n83 |     uri!(_, simple(id = \"hi\"), uri!(\"*\"));\n   |                                -----^^^-\n   |                                |    |\n   |                                |    the trait `ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not implemented for `rocket::http::uri::Asterisk`\n   |                                required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRouteSuffix<T>`:\n             <rocket::http::uri::Absolute<'a> as ValidRouteSuffix<rocket::http::uri::Absolute<'a>>>\n             <rocket::http::uri::Absolute<'a> as ValidRouteSuffix<rocket::http::uri::Origin<'a>>>\n             <rocket::http::uri::Reference<'a> as ValidRouteSuffix<rocket::http::uri::Absolute<'a>>>\n             <rocket::http::uri::Reference<'a> as ValidRouteSuffix<rocket::http::uri::Origin<'a>>>\nnote: required by a bound in `RouteUriBuilder::with_suffix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_suffix<S>(self, suffix: S) -> SuffixedRouteUri<S::Output>\n   |            ----------- required by a bound in this associated function\n   |         where S: ValidRouteSuffix<Origin<'static>>\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_suffix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:15:15\n   |\n15 | fn simple(id: usize) {  }\n   |               ^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n...\n84 |     uri!(_, simple(id = \"hi\"), uri!(\"/foo/bar\"));\n   |     -------------------------------------------- in this macro invocation\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `rocket_uri_macro_simple` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `rocket::http::uri::Origin<'_>: ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:84:37\n   |\n84 |     uri!(_, simple(id = \"hi\"), uri!(\"/foo/bar\"));\n   |                                -----^^^^^^^^^^-\n   |                                |    |\n   |                                |    the trait `ValidRouteSuffix<rocket::http::uri::Origin<'static>>` is not implemented for `rocket::http::uri::Origin<'_>`\n   |                                required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `ValidRouteSuffix<T>`:\n             <rocket::http::uri::Absolute<'a> as ValidRouteSuffix<rocket::http::uri::Absolute<'a>>>\n             <rocket::http::uri::Absolute<'a> as ValidRouteSuffix<rocket::http::uri::Origin<'a>>>\n             <rocket::http::uri::Reference<'a> as ValidRouteSuffix<rocket::http::uri::Absolute<'a>>>\n             <rocket::http::uri::Reference<'a> as ValidRouteSuffix<rocket::http::uri::Origin<'a>>>\nnote: required by a bound in `RouteUriBuilder::with_suffix`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn with_suffix<S>(self, suffix: S) -> SuffixedRouteUri<S::Output>\n   |            ----------- required by a bound in this associated function\n   |         where S: ValidRouteSuffix<Origin<'static>>\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RouteUriBuilder::with_suffix`\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:47:22\n   |\n47 |     uri!(simple(id = \"hi\"));\n   |                      ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:49:17\n   |\n49 |     uri!(simple(\"hello\"));\n   |                 ^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, i64>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:51:22\n   |\n51 |     uri!(simple(id = 239239i64));\n   |                      ^^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, i64>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `i32: FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:58:25\n   |\n58 |     uri!(optionals(id = Some(10), name = Ok(\"bob\".into())));\n   |                         ^^^^^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>` is not implemented for `i32`, which is required by `std::option::Option<i32>: FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <i32 as FromUriParam<P, &'x i32>>\n             <i32 as FromUriParam<P, &'x mut i32>>\n             <i32 as FromUriParam<P, i32>>\n   = note: required for `std::option::Option<i32>` to implement `FromUriParam<rocket::http::uri::fmt::Path, std::option::Option<{integer}>>`\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:60:19\n   |\n60 |     uri!(simple_q(\"hi\"));\n   |                   ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <isize as FromUriParam<P, &'x isize>>\n             <isize as FromUriParam<P, &'x mut isize>>\n             <isize as FromUriParam<P, isize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `isize: FromUriParam<rocket::http::uri::fmt::Query, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:62:24\n   |\n62 |     uri!(simple_q(id = \"hi\"));\n   |                        ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Query, &str>` is not implemented for `isize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <isize as FromUriParam<P, &'x isize>>\n             <isize as FromUriParam<P, &'x mut isize>>\n             <isize as FromUriParam<P, isize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:79:40\n   |\n79 |     uri!(uri!(\"?foo#bar\"), simple(id = \"hi\"));\n   |                                        ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:80:33\n   |\n80 |     uri!(uri!(\"*\"), simple(id = \"hi\"));\n   |                                 ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:83:25\n   |\n83 |     uri!(_, simple(id = \"hi\"), uri!(\"*\"));\n   |                         ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `usize: FromUriParam<rocket::http::uri::fmt::Path, &str>` is not satisfied\n  --> tests/ui-fail-stable/typed-uri-bad-type.rs:84:25\n   |\n84 |     uri!(_, simple(id = \"hi\"), uri!(\"/foo/bar\"));\n   |                         ^^^^ the trait `FromUriParam<rocket::http::uri::fmt::Path, &str>` is not implemented for `usize`\n   |\n   = help: the following other types implement trait `FromUriParam<P, T>`:\n             <usize as FromUriParam<P, &'x mut usize>>\n             <usize as FromUriParam<P, &'x usize>>\n             <usize as FromUriParam<P, usize>>\n   = note: this error originates in the macro `::rocket::rocket_internal_uri` which comes from the expansion of the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/typed-uris-bad-params.stderr",
    "content": "error: expected identifier, found keyword `_`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:65:18\n   |\n65 |     uri!(ignored(_ = 10));\n   |                  ^\n\nerror: route expects 1 parameter but 2 were supplied\n       = note: route `ignored` has uri \"/<_>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:71:18\n   |\n71 |     uri!(ignored(10, \"10\"));\n   |                  ^^^^^^^^\n\nerror: expected unnamed arguments due to ignored parameters\n       = note: uri for route `ignored` ignores 1 path parameters: \"/<_>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:69:18\n   |\n69 |     uri!(ignored(num = 10));\n   |                  ^^^^^^^^\n\nerror: route expects 1 parameter but 2 were supplied\n       = note: route `ignored` has uri \"/<_>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:67:18\n   |\n67 |     uri!(ignored(10, 20));\n   |                  ^^^^^^\n\nerror: path parameters cannot be ignored\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:63:18\n   |\n63 |     uri!(ignored(_));\n   |                  ^\n\nerror: path parameters cannot be ignored\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:61:36\n   |\n61 |     uri!(optionals(id = 10, name = _));\n   |                                    ^\n\nerror: path parameters cannot be ignored\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:59:25\n   |\n59 |     uri!(optionals(id = _, name = \"bob\".into()));\n   |                         ^\n\nerror: invalid parameters for `has_two` route uri\n       = note: uri parameters are: id: i32, name: String\n       = help: missing parameter: `name`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:57:18\n   |\n57 |     uri!(has_two(id = 100, cookies = \"hi\"));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameter: `cookies`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:57:28\n   |\n57 |     uri!(has_two(id = 100, cookies = \"hi\"));\n   |                            ^^^^^^^\n\nerror: invalid parameters for `has_two` route uri\n       = note: uri parameters are: id: i32, name: String\n       = help: missing parameter: `name`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:55:18\n   |\n55 |     uri!(has_two(cookies = \"hi\", id = 100, id = 10, id = 10));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameter: `cookies`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:55:18\n   |\n55 |     uri!(has_two(cookies = \"hi\", id = 100, id = 10, id = 10));\n   |                  ^^^^^^^\n\nerror: [help] duplicate parameter: `id`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:55:44\n   |\n55 |     uri!(has_two(cookies = \"hi\", id = 100, id = 10, id = 10));\n   |                                            ^^\n\nerror: invalid parameters for `has_two` route uri\n       = note: uri parameters are: id: i32, name: String\n       = help: missing parameter: `id`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:53:18\n   |\n53 |     uri!(has_two(name = \"hi\"));\n   |                  ^^^^^^^^^^^\n\nerror: invalid parameters for `has_two` route uri\n       = note: uri parameters are: id: i32, name: String\n       = help: missing parameter: `name`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:51:18\n   |\n51 |     uri!(has_two(id = 100, id = 100, ));\n   |                  ^^^^^^^^^^^^^^^^^^^\n\nerror: [help] duplicate parameter: `id`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:51:28\n   |\n51 |     uri!(has_two(id = 100, id = 100, ));\n   |                            ^^\n\nerror: invalid parameters for `has_one_guarded` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:49:26\n   |\n49 |     uri!(has_one_guarded(id = 100, cookies = \"hi\"));\n   |                          ^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameter: `cookies`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:49:36\n   |\n49 |     uri!(has_one_guarded(id = 100, cookies = \"hi\"));\n   |                                    ^^^^^^^\n\nerror: invalid parameters for `has_one_guarded` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:47:26\n   |\n47 |     uri!(has_one_guarded(cookies = \"hi\", id = 100));\n   |                          ^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameter: `cookies`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:47:26\n   |\n47 |     uri!(has_one_guarded(cookies = \"hi\", id = 100));\n   |                          ^^^^^^^\n\nerror: invalid parameters for `has_one` route uri\n       = note: uri parameters are: id: i32\n       = help: missing parameter: `id`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:45:18\n   |\n45 |     uri!(has_one(name = \"hi\"));\n   |                  ^^^^^^^^^^^\n\nerror: [help] unknown parameter: `name`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:45:18\n   |\n45 |     uri!(has_one(name = \"hi\"));\n   |                  ^^^^\n\nerror: invalid parameters for `has_one` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:43:18\n   |\n43 |     uri!(has_one(id = 100, id = 100, ));\n   |                  ^^^^^^^^^^^^^^^^^^^\n\nerror: [help] duplicate parameter: `id`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:43:28\n   |\n43 |     uri!(has_one(id = 100, id = 100, ));\n   |                            ^^\n\nerror: invalid parameters for `has_one` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:41:18\n   |\n41 |     uri!(has_one(id = 100, id = 100));\n   |                  ^^^^^^^^^^^^^^^^^^\n\nerror: [help] duplicate parameter: `id`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:41:28\n   |\n41 |     uri!(has_one(id = 100, id = 100));\n   |                            ^^\n\nerror: invalid parameters for `has_one` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:39:18\n   |\n39 |     uri!(has_one(name = 100, age = 50, id = 100, id = 50));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameters: `name`, `age`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:39:18\n   |\n39 |     uri!(has_one(name = 100, age = 50, id = 100, id = 50));\n   |                  ^^^^\n\nerror: [help] duplicate parameter: `id`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:39:50\n   |\n39 |     uri!(has_one(name = 100, age = 50, id = 100, id = 50));\n   |                                                  ^^\n\nerror: invalid parameters for `has_one` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:37:18\n   |\n37 |     uri!(has_one(name = 100, age = 50, id = 100));\n   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameters: `name`, `age`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:37:18\n   |\n37 |     uri!(has_one(name = 100, age = 50, id = 100));\n   |                  ^^^^\n\nerror: invalid parameters for `has_one` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:35:18\n   |\n35 |     uri!(has_one(name = 100, id = 100));\n   |                  ^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameter: `name`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:35:18\n   |\n35 |     uri!(has_one(name = 100, id = 100));\n   |                  ^^^^\n\nerror: invalid parameters for `has_one` route uri\n       = note: uri parameters are: id: i32\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:33:18\n   |\n33 |     uri!(has_one(id = 100, name = \"hi\"));\n   |                  ^^^^^^^^^^^^^^^^^^^^^\n\nerror: [help] unknown parameter: `name`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:33:28\n   |\n33 |     uri!(has_one(id = 100, name = \"hi\"));\n   |                            ^^^^\n\nerror: route expects 2 parameters but 1 was supplied\n       = note: route `has_two` has uri \"/<id>?<name>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:31:18\n   |\n31 |     uri!(has_two(10));\n   |                  ^^\n\nerror: route expects 2 parameters but 3 were supplied\n       = note: route `has_two` has uri \"/<id>?<name>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:30:18\n   |\n30 |     uri!(has_two(10, \"hi\", \"there\"));\n   |                  ^^^^^^^^^^^^^^^^^\n\nerror: route expects 1 parameter but 2 were supplied\n       = note: route `has_one_guarded` has uri \"/<id>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:28:26\n   |\n28 |     uri!(has_one_guarded(\"hi\", 100));\n   |                          ^^^^^^^^^\n\nerror: route expects 1 parameter but 2 were supplied\n       = note: route `has_one` has uri \"/<id>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:27:18\n   |\n27 |     uri!(has_one(\"Hello\", 23, ));\n   |                  ^^^^^^^^^^^^\n\nerror: route expects 1 parameter but 2 were supplied\n       = note: route `has_one` has uri \"/<id>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:26:18\n   |\n26 |     uri!(has_one(1, 23));\n   |                  ^^^^^\n\nerror: route expects 1 parameter but 0 were supplied\n       = note: route `has_one` has uri \"/<id>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:24:10\n   |\n24 |     uri!(has_one());\n   |          ^^^^^^^\n\nerror: route expects 1 parameter but 0 were supplied\n       = note: route `has_one` has uri \"/<id>\"\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:23:10\n   |\n23 |     uri!(has_one);\n   |          ^^^^^^^\n\nerror[E0271]: type mismatch resolving `<String as FromParam<'_>>::Error == &str`\n  --> tests/ui-fail-stable/typed-uris-bad-params.rs:17:37\n   |\n17 | fn optionals(id: Option<i32>, name: Result<String, &str>) {  }\n   |                                     ^^^^^^^^^^^^^^^^^^^^ expected `Empty`, found `&str`\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/typed-uris-invalid-syntax.stderr",
    "content": "error: unexpected token\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:10:16\n   |\n10 |     uri!(simple: id = 100, \"Hello\");\n   |                ^\n\nerror: named and unnamed parameters cannot be mixed\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:11:17\n   |\n11 |     uri!(simple(id = 100, \"Hello\"));\n   |                 ^^^^^^^^^^^^^^^^^\n\nerror: named and unnamed parameters cannot be mixed\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:12:17\n   |\n12 |     uri!(simple(\"Hello\", id = 100));\n   |                 ^^^^^^^^^^^^^^^^^\n\nerror: unexpected token\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:14:16\n   |\n14 |     uri!(simple:);\n   |                ^\n\nerror: invalid URI: unexpected EOF: expected token ':' at index 5\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:16:16\n   |\n16 |     uri!(\"mount\", simple);\n   |                ^\n\nerror: invalid URI: unexpected EOF: expected token ':' at index 5\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:17:16\n   |\n17 |     uri!(\"mount\", simple, \"http://\");\n   |                ^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:18:28\n   |\n18 |     uri!(\"/mount\", simple, \"http://\");\n   |                            ^^^^^^^^^\n\nerror: expected 1, 2, or 3 arguments, found 4\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:19:36\n   |\n19 |     uri!(\"/mount\", simple, \"#foo\", \"?foo\");\n   |                                    ^^^^^^\n\nerror: invalid URI: unexpected EOF: expected token ':' at index 5\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:20:16\n   |\n20 |     uri!(\"mount\", simple(10, \"hi\"), \"http://\");\n   |                ^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:21:38\n   |\n21 |     uri!(\"/mount\", simple(10, \"hi\"), \"http://\");\n   |                                      ^^^^^^^^^\n\nerror: URI prefix cannot contain query part\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:22:10\n   |\n22 |     uri!(\"/mount?foo\", simple(10, \"hi\"), \"foo/bar?foo#bar\");\n   |          ^^^^^^^^^^^^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:23:38\n   |\n23 |     uri!(\"/mount\", simple(10, \"hi\"), \"a/b\");\n   |                                      ^^^^^\n\nerror: expected 1, 2, or 3 arguments, found 4\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:24:46\n   |\n24 |     uri!(\"/mount\", simple(10, \"hi\"), \"#foo\", \"?foo\");\n   |                                              ^^^^^^\n\nerror: invalid URI: unexpected token '<' at index 7\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:25:18\n   |\n25 |     uri!(\"/mount/<id>\", simple);\n   |                  ^\n\nerror: expected at least 1 argument, found none\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:26:5\n   |\n26 |     uri!();\n   |     ^^^^^^\n   |\n   = note: this error originates in the macro `uri` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: unexpected token\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:27:16\n   |\n27 |     uri!(simple: id = );\n   |                ^\n\nerror: unexpected end of input, expected an expression\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:28:22\n   |\n28 |     uri!(simple(id = ));\n   |                      ^\n\nerror: invalid URI: unexpected EOF: expected some token at index 0\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:29:11\n   |\n29 |     uri!(\"*\", simple(10), \"hi\");\n   |           ^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:30:40\n   |\n30 |     uri!(\"some.host:8088\", simple(10), \"hi\");\n   |                                        ^^^^\n\nerror: expected identifier\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:33:18\n   |\n33 |     uri!(\"/foo\", \"bar\");\n   |                  ^^^^^\n\nerror: unexpected token\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:34:17\n   |\n34 |     uri!(\"/foo\" (\"bar\"));\n   |                 ^^^^^^^\n\nerror: URI prefix cannot contain query part\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:35:10\n   |\n35 |     uri!(\"ftp:?\", index);\n   |          ^^^^^^^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:36:25\n   |\n36 |     uri!(\"ftp:\", index, \"foo#bar\");\n   |                         ^^^^^^^^^\n\nerror: URI suffix must contain only query and/or fragment\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:37:25\n   |\n37 |     uri!(\"ftp:\", index, \"foo?bar\");\n   |                         ^^^^^^^^^\n\nerror: route expects 2 parameters but 0 were supplied\n       = note: route `simple` has uri \"/<_id>/<_name>\"\n  --> tests/ui-fail-stable/typed-uris-invalid-syntax.rs:13:10\n   |\n13 |     uri!(simple,);\n   |          ^^^^^^\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/uri_display.stderr",
    "content": "error: fieldless structs are not supported\n --> tests/ui-fail-stable/uri_display.rs:4:1\n  |\n4 | struct Foo1;\n  | ^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n --> tests/ui-fail-stable/uri_display.rs:3:10\n  |\n3 | #[derive(UriDisplayQuery)]\n  |          ^^^^^^^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: fieldless structs are not supported\n --> tests/ui-fail-stable/uri_display.rs:7:1\n  |\n7 | struct Foo2();\n  | ^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n --> tests/ui-fail-stable/uri_display.rs:6:10\n  |\n6 | #[derive(UriDisplayQuery)]\n  |          ^^^^^^^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: empty enums are not supported\n  --> tests/ui-fail-stable/uri_display.rs:10:11\n   |\n10 | enum Foo3 { }\n   |           ^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n --> tests/ui-fail-stable/uri_display.rs:9:10\n  |\n9 | #[derive(UriDisplayQuery)]\n  |          ^^^^^^^^^^^^^^^\n  |\n  = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: tuple structs or variants must have exactly one field\n  --> tests/ui-fail-stable/uri_display.rs:18:12\n   |\n18 | struct Foo5(String, String);\n   |            ^^^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-stable/uri_display.rs:17:10\n   |\n17 | #[derive(UriDisplayQuery)]\n   |          ^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected list `#[attr(..)]`, found bare integer literal\n  --> tests/ui-fail-stable/uri_display.rs:22:20\n   |\n22 |     #[field(name = 123)]\n   |                    ^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-stable/uri_display.rs:20:10\n   |\n20 | #[derive(UriDisplayQuery)]\n   |          ^^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `UriDisplayQuery` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one field\n  --> tests/ui-fail-stable/uri_display.rs:27:12\n   |\n27 | struct Foo7(String, usize);\n   |            ^^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-stable/uri_display.rs:26:10\n   |\n26 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: struct must have exactly one field\n  --> tests/ui-fail-stable/uri_display.rs:30:1\n   |\n30 | struct Foo8;\n   | ^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-stable/uri_display.rs:29:10\n   |\n29 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: enums are not supported\n  --> tests/ui-fail-stable/uri_display.rs:33:1\n   |\n33 | enum Foo9 {  }\n   | ^^^^^^^^^^^^^^\n\nerror: [note] error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-stable/uri_display.rs:32:10\n   |\n32 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: named structs are not supported\n  --> tests/ui-fail-stable/uri_display.rs:36:1\n   |\n36 | / struct Foo10 {\n37 | |     named: usize\n38 | | }\n   | |_^\n\nerror: [note] error occurred while deriving `UriDisplay`\n  --> tests/ui-fail-stable/uri_display.rs:35:10\n   |\n35 | #[derive(UriDisplayPath)]\n   |          ^^^^^^^^^^^^^^\n   |\n   = note: this error originates in the derive macro `UriDisplayPath` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "core/codegen/tests/ui-fail-stable/uri_display_type_errors.stderr",
    "content": "error[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n --> tests/ui-fail-stable/uri_display_type_errors.rs:6:13\n  |\n6 | struct Bar1(BadType);\n  |             ^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n  |\n  = help: the following other types implement trait `UriDisplay<P>`:\n            <&T as UriDisplay<P>>\n            <&mut T as UriDisplay<P>>\n            <BTreeMap<K, V> as UriDisplay<rocket::http::uri::fmt::Query>>\n            <Bar1 as UriDisplay<rocket::http::uri::fmt::Query>>\n            <Bar2 as UriDisplay<rocket::http::uri::fmt::Query>>\n            <Bar3 as UriDisplay<rocket::http::uri::fmt::Query>>\n            <Bar4 as UriDisplay<rocket::http::uri::fmt::Query>>\n            <Bar5 as UriDisplay<rocket::http::uri::fmt::Query>>\n          and $N others\n  = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'i, P>::write_value`\n --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n  |\n  |     pub fn write_value<T: UriDisplay<P>>(&mut self, value: T) -> fmt::Result {\n  |                           ^^^^^^^^^^^^^ required by this bound in `Formatter::<'i, P>::write_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-stable/uri_display_type_errors.rs:10:5\n   |\n10 |     field: BadType,\n   |     ^^^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             <&T as UriDisplay<P>>\n             <&mut T as UriDisplay<P>>\n             <BTreeMap<K, V> as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar1 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar2 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar3 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar4 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar5 as UriDisplay<rocket::http::uri::fmt::Query>>\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-stable/uri_display_type_errors.rs:16:5\n   |\n16 |     bad: BadType,\n   |     ^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             <&T as UriDisplay<P>>\n             <&mut T as UriDisplay<P>>\n             <BTreeMap<K, V> as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar1 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar2 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar3 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar4 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar5 as UriDisplay<rocket::http::uri::fmt::Query>>\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-stable/uri_display_type_errors.rs:21:11\n   |\n21 |     Inner(BadType),\n   |           ^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             <&T as UriDisplay<P>>\n             <&mut T as UriDisplay<P>>\n             <BTreeMap<K, V> as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar1 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar2 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar3 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar4 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar5 as UriDisplay<rocket::http::uri::fmt::Query>>\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\n   = note: 1 redundant requirement hidden\n   = note: required for `&&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'i, P>::write_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_value<T: UriDisplay<P>>(&mut self, value: T) -> fmt::Result {\n   |                           ^^^^^^^^^^^^^ required by this bound in `Formatter::<'i, P>::write_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-stable/uri_display_type_errors.rs:27:9\n   |\n27 |         field: BadType,\n   |         ^^^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             <&T as UriDisplay<P>>\n             <&mut T as UriDisplay<P>>\n             <BTreeMap<K, V> as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar1 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar2 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar3 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar4 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar5 as UriDisplay<rocket::http::uri::fmt::Query>>\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\n   = note: 1 redundant requirement hidden\n   = note: required for `&&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Query>` is not satisfied\n  --> tests/ui-fail-stable/uri_display_type_errors.rs:35:9\n   |\n35 |         other: BadType,\n   |         ^^^^^^^^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Query>` is not implemented for `BadType`, which is required by `&&BadType: UriDisplay<rocket::http::uri::fmt::Query>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             <&T as UriDisplay<P>>\n             <&mut T as UriDisplay<P>>\n             <BTreeMap<K, V> as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar1 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar2 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar3 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar4 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar5 as UriDisplay<rocket::http::uri::fmt::Query>>\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\n   = note: 1 redundant requirement hidden\n   = note: required for `&&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Query>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'_, rocket::http::uri::fmt::Query>::write_named_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n   |                                 ^^^^^^^^^^^^^^^^^ required by this bound in `Formatter::<'_, Query>::write_named_value`\n\nerror[E0277]: the trait bound `BadType: UriDisplay<rocket::http::uri::fmt::Path>` is not satisfied\n  --> tests/ui-fail-stable/uri_display_type_errors.rs:40:12\n   |\n40 | struct Baz(BadType);\n   |            ^^^^^^^ the trait `UriDisplay<rocket::http::uri::fmt::Path>` is not implemented for `BadType`, which is required by `&BadType: UriDisplay<rocket::http::uri::fmt::Path>`\n   |\n   = help: the following other types implement trait `UriDisplay<P>`:\n             <&T as UriDisplay<P>>\n             <&mut T as UriDisplay<P>>\n             <BTreeMap<K, V> as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar1 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar2 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar3 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar4 as UriDisplay<rocket::http::uri::fmt::Query>>\n             <Bar5 as UriDisplay<rocket::http::uri::fmt::Query>>\n           and $N others\n   = note: required for `&BadType` to implement `UriDisplay<rocket::http::uri::fmt::Path>`\nnote: required by a bound in `rocket::http::uri::fmt::Formatter::<'i, P>::write_value`\n  --> $WORKSPACE/core/http/src/uri/fmt/formatter.rs\n   |\n   |     pub fn write_value<T: UriDisplay<P>>(&mut self, value: T) -> fmt::Result {\n   |                           ^^^^^^^^^^^^^ required by this bound in `Formatter::<'i, P>::write_value`\n"
  },
  {
    "path": "core/codegen/tests/ui-fail.rs",
    "content": "#[test]\n#[ignore]\nfn ui() {\n    let path = match version_check::is_feature_flaggable() {\n        Some(true) => \"ui-fail-nightly\",\n        _ => \"ui-fail-stable\"\n    };\n\n    let t = trybuild::TestCases::new();\n    t.compile_fail(format!(\"tests/{}/*.rs\", path));\n}\n"
  },
  {
    "path": "core/codegen/tests/uri_display.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::http::uri::fmt::{UriDisplay, Query, Path};\nuse rocket::serde::{Serialize, Deserialize};\n\nmacro_rules! assert_uri_display_query {\n    ($v:expr, $expected:expr) => (\n        let uri_string = format!(\"{}\", &$v as &dyn UriDisplay<Query>);\n        assert_eq!(uri_string, $expected);\n    )\n}\n\nmacro_rules! assert_query_form_roundtrip {\n    ($T:ty, $v:expr) => ({\n        use rocket::form::{Form, Strict};\n        use rocket::http::RawStr;\n\n        let v = $v;\n        let string = format!(\"{}\", &v as &dyn UriDisplay<Query>);\n        let raw = RawStr::new(&string);\n        let value = Form::<Strict<$T>>::parse_encoded(raw).map(|s| s.into_inner());\n        assert_eq!(value.expect(\"form parse\"), v);\n    })\n}\n\nmacro_rules! assert_query_value_roundtrip {\n    ($T:ty, $v:expr) => ({\n        use rocket::form::{Form, Strict};\n        use rocket::http::RawStr;\n\n        let v = $v;\n        let string = format!(\"={}\", &v as &dyn UriDisplay<Query>);\n        let raw = RawStr::new(&string);\n        let value = Form::<Strict<$T>>::parse_encoded(raw).map(|s| s.into_inner());\n        assert_eq!(value.expect(\"form parse\"), v);\n    })\n}\n\n#[derive(UriDisplayQuery, Clone)]\nenum Foo<'r> {\n    First(&'r str),\n    Second {\n        inner: &'r str,\n        other: usize,\n    },\n    Third {\n        #[field(name = \"type\")]\n        kind: String,\n    },\n}\n\n#[test]\nfn uri_display_foo() {\n    let foo = Foo::First(\"hello\".into());\n    assert_uri_display_query!(foo, \"hello\");\n\n    let foo = Foo::First(\"hello there\".into());\n    assert_uri_display_query!(foo, \"hello%20there\");\n\n    let foo = Foo::Second { inner: \"hi\".into(), other: 123 };\n    assert_uri_display_query!(foo, \"inner=hi&other=123\");\n\n    let foo = Foo::Second { inner: \"hi bo\".into(), other: 321 };\n    assert_uri_display_query!(foo, \"inner=hi%20bo&other=321\");\n\n    let foo = Foo::Third { kind: \"hello\".into() };\n    assert_uri_display_query!(foo, \"type=hello\");\n\n    let foo = Foo::Third { kind: \"hello there\".into() };\n    assert_uri_display_query!(foo, \"type=hello%20there\");\n}\n\n#[derive(UriDisplayQuery)]\nstruct Bar<'a> {\n    foo: Foo<'a>,\n    baz: String,\n}\n\n#[test]\nfn uri_display_bar() {\n    let foo = Foo::First(\"hello\".into());\n    let bar = Bar { foo, baz: \"well, hi!\".into() };\n    assert_uri_display_query!(bar, \"foo=hello&baz=well,%20hi!\");\n\n    let foo = Foo::Second { inner: \"hi\".into(), other: 123 };\n    let bar = Bar { foo, baz: \"done\".into() };\n    assert_uri_display_query!(bar, \"foo.inner=hi&foo.other=123&baz=done\");\n\n    let foo = Foo::Third { kind: \"hello\".into() };\n    let bar = Bar { foo, baz: \"turkey day\".into() };\n    assert_uri_display_query!(bar, \"foo.type=hello&baz=turkey%20day\");\n}\n\n#[derive(UriDisplayQuery)]\nstruct Baz<'a> {\n    foo: Foo<'a>,\n    bar: Bar<'a>,\n    last: String\n}\n\n#[test]\nfn uri_display_baz() {\n    let foo1 = Foo::Second { inner: \"hi\".into(), other: 123 };\n    let foo2 = Foo::Second { inner: \"bye\".into(), other: 321 };\n    let bar = Bar { foo: foo2, baz: \"done\".into() };\n    let baz = Baz { foo: foo1, bar, last: \"ok\".into() };\n    assert_uri_display_query!(baz, \"foo.inner=hi&foo.other=123&\\\n                              bar.foo.inner=bye&bar.foo.other=321&bar.baz=done&\\\n                              last=ok\");\n\n    let foo1 = Foo::Third { kind: \"hello\".into() };\n    let foo2 = Foo::First(\"bye\".into());\n    let bar = Bar { foo: foo1, baz: \"end\".into() };\n    let baz = Baz { foo: foo2, bar, last: \"done\".into() };\n    assert_uri_display_query!(baz, \"foo=bye&\\\n                              bar.foo.type=hello&bar.baz=end&\\\n                              last=done\");\n}\n\n#[derive(UriDisplayQuery)]\nstruct Bam<'a> {\n    foo: &'a str,\n    bar: Option<usize>,\n    baz: Result<&'a str, usize>,\n}\n\n#[test]\nfn uri_display_bam() {\n    let bam = Bam { foo: \"hi hi\", bar: Some(1), baz: Err(2) };\n    assert_uri_display_query!(bam, \"foo=hi%20hi&bar=1\");\n\n    let bam = Bam { foo: \"hi hi\", bar: None, baz: Err(2) };\n    assert_uri_display_query!(bam, \"foo=hi%20hi\");\n\n    let bam = Bam { foo: \"hi hi\", bar: Some(1), baz: Ok(\"tony\".into()) };\n    assert_uri_display_query!(bam, \"foo=hi%20hi&bar=1&baz=tony\");\n\n    let bam = Bam { foo: \"hi hi\", bar: None, baz: Ok(\"tony\".into()) };\n    assert_uri_display_query!(bam, \"foo=hi%20hi&baz=tony\");\n}\n\n#[test]\nfn uri_display_c_like() {\n    #[derive(UriDisplayQuery)]\n    enum CLike { A, B, C }\n\n    assert_uri_display_query!(CLike::A, \"A\");\n    assert_uri_display_query!(CLike::B, \"B\");\n    assert_uri_display_query!(CLike::C, \"C\");\n\n    #[derive(UriDisplayQuery)]\n    enum CLikeV {\n        #[field(value = \"a\")]\n        A,\n        #[field(value = \"tomato\")]\n        #[field(value = \"juice\")]\n        B,\n        #[field(value = \"carrot\")]\n        C\n    }\n\n    assert_uri_display_query!(CLikeV::A, \"a\");\n    assert_uri_display_query!(CLikeV::B, \"tomato\");\n    assert_uri_display_query!(CLikeV::C, \"carrot\");\n\n    #[derive(UriDisplayQuery)]\n    #[allow(non_camel_case_types)]\n    enum CLikeR { r#for, r#type, r#async, #[field(value = \"stop\")] r#yield }\n\n    assert_uri_display_query!(CLikeR::r#for, \"for\");\n    assert_uri_display_query!(CLikeR::r#type, \"type\");\n    assert_uri_display_query!(CLikeR::r#async, \"async\");\n    assert_uri_display_query!(CLikeR::r#yield, \"stop\");\n\n    #[derive(UriDisplayQuery)]\n    struct Nested {\n        foo: CLike,\n        bar: CLikeV,\n        last: CLikeR\n    }\n\n    let nested = Nested {\n        foo: CLike::B,\n        bar: CLikeV::B,\n        last: CLikeR::r#type,\n    };\n\n    assert_uri_display_query!(nested, \"foo=B&bar=tomato&last=type\");\n}\n\nmacro_rules! assert_uri_display_path {\n    ($v:expr, $s:expr) => (\n        let uri_string = format!(\"{}\", &$v as &dyn UriDisplay<Path>);\n        assert_eq!(uri_string, $s);\n    )\n}\n\n#[derive(UriDisplayPath)]\nstruct FooP(&'static str);\n\n#[derive(UriDisplayPath)]\nstruct BarP<'a>(&'a str);\n\n#[derive(UriDisplayPath)]\nstruct BazP<'a, T>(&'a T);\n\n#[derive(UriDisplayPath)]\nstruct BamP<T>(T);\n\n#[derive(UriDisplayPath)]\nstruct BopP(FooP);\n\n#[test]\nfn uri_display_path() {\n    assert_uri_display_path!(FooP(\"hi\"), \"hi\");\n    assert_uri_display_path!(FooP(\"hi there\"), \"hi%20there\");\n    assert_uri_display_path!(BarP(\"hi there\"), \"hi%20there\");\n    assert_uri_display_path!(BazP(&FooP(\"hi\")), \"hi\");\n    assert_uri_display_path!(BazP(&BarP(\"hi there\")), \"hi%20there\");\n    assert_uri_display_path!(BamP(12), \"12\");\n    assert_uri_display_path!(BamP(BazP(&100)), \"100\");\n    assert_uri_display_path!(BopP(FooP(\"bop foo\")), \"bop%20foo\");\n}\n\n#[test]\nfn uri_display_serde() {\n    use rocket::serde::json::Json;\n\n    #[derive(Debug, PartialEq, Clone, FromForm, UriDisplayQuery, Deserialize, Serialize)]\n    #[serde(crate = \"rocket::serde\")]\n    struct Bam {\n        foo: String,\n        bar: Option<usize>,\n        baz: bool,\n    }\n\n    #[derive(Debug, PartialEq, FromForm, UriDisplayQuery)]\n    struct JsonFoo(Json<Bam>);\n\n    let bam = Bam {\n        foo: \"hi[]=there.baz !?\".into(),\n        bar: None,\n        baz: true,\n    };\n\n    assert_query_form_roundtrip!(Bam, bam.clone());\n\n    assert_query_value_roundtrip!(JsonFoo, JsonFoo(Json(bam.clone())));\n\n    #[allow(renamed_and_removed_lints)]\n    #[allow(private_in_public)]\n    #[derive(Debug, PartialEq, Clone, FromForm, UriDisplayQuery)]\n    struct Q<T>(Json<T>);\n\n    #[derive(Debug, PartialEq, Clone, FromForm, UriDisplayQuery)]\n    pub struct Generic<A, B> {\n        a: Q<A>,\n        b: Q<B>,\n        c: Q<A>,\n    }\n\n    assert_query_form_roundtrip!(Generic<usize, String>, Generic {\n        a: Q(Json(133)),\n        b: Q(Json(\"hello, world#rocket!\".into())),\n        c: Q(Json(40486)),\n    });\n\n    #[derive(Debug, PartialEq, Clone, FromForm, UriDisplayQuery)]\n    // This is here to ensure we don't warn, which we can't test with trybuild.\n    pub struct GenericBorrow<'a, A: ?Sized, B: 'a> {\n        a: Q<&'a A>,\n        b: Q<B>,\n        c: Q<&'a A>,\n    }\n\n    // TODO: This requires `MsgPack` to parse from value form fields.\n    //\n    // use rocket::serde::msgpack::MsgPack;\n    //\n    // #[derive(Debug, PartialEq, FromForm, UriDisplayQuery)]\n    // struct MsgPackFoo(MsgPack<Bam>);\n    //\n    // assert_query_value_roundtrip!(MsgPackFoo, MsgPackFoo(MsgPack(bam)));\n}\n"
  },
  {
    "path": "core/http/Cargo.toml",
    "content": "[package]\nname = \"rocket_http\"\nversion = \"0.6.0-dev\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\"]\ndescription = \"\"\"\nTypes, traits, and parsers for HTTP requests, responses, and headers.\n\"\"\"\ndocumentation = \"https://api.rocket.rs/master/rocket_http/\"\nhomepage = \"https://rocket.rs\"\nrepository = \"https://github.com/rwf2/Rocket\"\nreadme = \"../../README.md\"\nkeywords = [\"rocket\", \"web\", \"framework\", \"http\"]\nlicense = \"MIT OR Apache-2.0\"\ncategories = [\"web-programming\"]\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[lints]\nworkspace = true\n\n[features]\ndefault = []\nserde = [\"dep:serde\", \"uncased/with-serde-alloc\"]\nuuid = [\"dep:uuid\"]\n\n[dependencies]\ntinyvec = { version = \"1.6\", features = [\"std\", \"rustc_1_57\"] }\npercent-encoding = \"2\"\ntime = { version = \"0.3\", features = [\"formatting\", \"macros\"] }\nindexmap = \"2\"\nref-cast = \"1.0\"\nuncased = \"0.9.10\"\neither = \"1\"\npear = \"0.2.9\"\nmemchr = \"2\"\nstable-pattern = \"0.1\"\ncookie = { version = \"0.18\", features = [\"percent-encode\"] }\nstate = \"0.6\"\n\n[dependencies.serde]\nversion = \"1.0\"\noptional = true\ndefault-features = false\nfeatures = [\"std\"]\n\n[dependencies.uuid]\nversion = \"1\"\noptional = true\ndefault-features = false\n\n[dev-dependencies]\nrocket = { path = \"../lib\", features = [\"mtls\"] }\n"
  },
  {
    "path": "core/http/src/ext.rs",
    "content": "//! Extension traits implemented by several HTTP types.\n\nuse std::borrow::Cow;\n\nuse state::InitCell;\n\n/// Trait implemented by types that can be converted into owned versions of\n/// themselves.\npub trait IntoOwned {\n    /// The owned version of the type.\n    type Owned: 'static;\n\n    /// Converts `self` into an owned version of itself.\n    fn into_owned(self) -> Self::Owned;\n}\n\nimpl<T: IntoOwned> IntoOwned for Option<T> {\n    type Owned = Option<T::Owned>;\n\n    #[inline(always)]\n    fn into_owned(self) -> Self::Owned {\n        self.map(|inner| inner.into_owned())\n    }\n}\n\nimpl<T: IntoOwned> IntoOwned for Vec<T> {\n    type Owned = Vec<T::Owned>;\n\n    #[inline(always)]\n    fn into_owned(self) -> Self::Owned {\n        self.into_iter()\n            .map(|inner| inner.into_owned())\n            .collect()\n    }\n}\n\nimpl<T: IntoOwned + Send + Sync> IntoOwned for InitCell<T>\n    where T::Owned: Send + Sync\n{\n    type Owned = InitCell<T::Owned>;\n\n    #[inline(always)]\n    fn into_owned(self) -> Self::Owned {\n        self.map(|inner| inner.into_owned())\n    }\n}\n\nimpl<A: IntoOwned, B: IntoOwned> IntoOwned for (A, B) {\n    type Owned = (A::Owned, B::Owned);\n\n    #[inline(always)]\n    fn into_owned(self) -> Self::Owned {\n        (self.0.into_owned(), self.1.into_owned())\n    }\n}\n\nimpl<B: 'static + ToOwned + ?Sized> IntoOwned for Cow<'_, B> {\n    type Owned = Cow<'static, B>;\n\n    #[inline(always)]\n    fn into_owned(self) -> <Self as IntoOwned>::Owned {\n        Cow::Owned(self.into_owned())\n    }\n}\n\nmacro_rules! impl_into_owned_self {\n    ($($T:ty),*) => ($(\n        impl IntoOwned for $T {\n            type Owned = Self;\n\n            #[inline(always)]\n            fn into_owned(self) -> <Self as IntoOwned>::Owned {\n                self\n            }\n        }\n    )*)\n}\n\nimpl_into_owned_self!(bool);\nimpl_into_owned_self!(u8, u16, u32, u64, usize);\nimpl_into_owned_self!(i8, i16, i32, i64, isize);\n\nuse std::path::Path;\n\n// Outside of http, this is used by a test.\n#[doc(hidden)]\npub trait Normalize {\n    fn normalized_str(&self) -> Cow<'_, str>;\n}\n\nimpl<T: AsRef<Path>> Normalize for T {\n    #[cfg(windows)]\n    fn normalized_str(&self) -> Cow<'_, str> {\n        self.as_ref().to_string_lossy().replace('\\\\', \"/\").into()\n    }\n\n    #[cfg(not(windows))]\n    fn normalized_str(&self) -> Cow<'_, str> {\n        self.as_ref().to_string_lossy()\n    }\n}\n"
  },
  {
    "path": "core/http/src/header/accept.rs",
    "content": "use std::borrow::Cow;\nuse std::ops::Deref;\nuse std::str::FromStr;\nuse std::fmt;\n\nuse crate::{Header, MediaType};\nuse crate::parse::parse_accept;\n\n/// The HTTP Accept header.\n///\n/// An `Accept` header is composed of zero or more media types, each of which\n/// may have an optional quality value (a [`QMediaType`]). The header is sent by\n/// an HTTP client to describe the formats it accepts as well as the order in\n/// which it prefers different formats.\n///\n/// # Usage\n///\n/// The Accept header of an incoming request can be retrieved via the\n/// [`Request::accept()`] method. The [`preferred()`] method can be used to\n/// retrieve the client's preferred media type.\n///\n/// [`Request::accept()`]: rocket::Request::accept()\n/// [`preferred()`]: Accept::preferred()\n///\n/// An `Accept` type with a single, common media type can be easily constructed\n/// via provided associated constants.\n///\n/// ## Example\n///\n/// Construct an `Accept` header with a single `application/json` media type:\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::Accept;\n///\n/// # #[allow(unused_variables)]\n/// let accept_json = Accept::JSON;\n/// ```\n///\n/// # Header\n///\n/// `Accept` implements `Into<Header>`. As such, it can be used in any context\n/// where an `Into<Header>` is expected:\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::Accept;\n/// use rocket::response::Response;\n///\n/// let response = Response::build().header(Accept::JSON).finalize();\n/// ```\n#[derive(Debug, Clone)]\npub struct Accept(pub(crate) Cow<'static, [QMediaType]>);\n\n/// A `MediaType` with an associated quality value.\n#[derive(Debug, Clone, PartialEq)]\npub struct QMediaType(pub MediaType, pub Option<f32>);\n\nmacro_rules! accept_constructor {\n    ($($name:ident ($check:ident): $str:expr, $t:expr,\n        $s:expr $(; $k:expr => $v:expr)*,)+) => {\n        $(\n            #[doc=\"An `Accept` header with the single media type for\"]\n            #[doc=concat!(\"**\", $str, \"**: \", \"_\", $t, \"/\", $s, \"_\")]\n            #[allow(non_upper_case_globals)]\n            pub const $name: Accept = Accept({\n                const INNER: &[QMediaType] = &[QMediaType(MediaType::$name, None)];\n                Cow::Borrowed(INNER)\n            });\n         )+\n    };\n}\n\nimpl Accept {\n    /// Constructs a new `Accept` header from one or more media types.\n    ///\n    /// The `items` parameter may be of type `QMediaType`, `[QMediaType]`,\n    /// `&[QMediaType]` or `Vec<QMediaType>`. To prevent additional allocations,\n    /// prefer to provide inputs of type `QMediaType`, `[QMediaType]`, or\n    /// `Vec<QMediaType>`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{QMediaType, MediaType, Accept};\n    ///\n    /// // Construct an `Accept` via a `Vec<MediaType>`.\n    /// let json_then_html = vec![MediaType::JSON, MediaType::HTML];\n    /// let accept = Accept::new(json_then_html);\n    /// assert_eq!(accept.preferred().media_type(), &MediaType::JSON);\n    ///\n    /// // Construct an `Accept` via an `[MediaType]`.\n    /// let accept = Accept::new([MediaType::JSON, MediaType::HTML]);\n    /// assert_eq!(accept.preferred().media_type(), &MediaType::JSON);\n    ///\n    /// // Construct an `Accept` via a single `QMediaType`.\n    /// let accept = Accept::new(QMediaType(MediaType::JSON, Some(0.4)));\n    /// assert_eq!(accept.preferred().media_type(), &MediaType::JSON);\n    /// ```\n    #[inline(always)]\n    pub fn new<T: IntoIterator<Item = M>, M: Into<QMediaType>>(items: T) -> Accept {\n        Accept(items.into_iter().map(|v| v.into()).collect())\n    }\n\n    /// Adds `media_type` to `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{QMediaType, MediaType, Accept};\n    ///\n    /// let mut accept = Accept::new(QMediaType(MediaType::JSON, Some(0.1)));\n    /// assert_eq!(accept.preferred().media_type(), &MediaType::JSON);\n    /// assert_eq!(accept.iter().count(), 1);\n    ///\n    /// accept.add(QMediaType(MediaType::HTML, Some(0.7)));\n    /// assert_eq!(accept.preferred().media_type(), &MediaType::HTML);\n    /// assert_eq!(accept.iter().count(), 2);\n    ///\n    /// accept.add(QMediaType(MediaType::XML, Some(0.6)));\n    /// assert_eq!(accept.preferred().media_type(), &MediaType::HTML);\n    /// assert_eq!(accept.iter().count(), 3);\n    /// ```\n    #[inline(always)]\n    pub fn add<M: Into<QMediaType>>(&mut self, media_type: M) {\n        self.0.to_mut().push(media_type.into());\n    }\n\n    /// Retrieve the client's preferred media type. This method follows [RFC\n    /// 7231 5.3.2]. If the list of media types is empty, this method returns a\n    /// media type of any with no quality value: (`*/*`).\n    ///\n    /// [RFC 7231 5.3.2]: https://tools.ietf.org/html/rfc7231#section-5.3.2\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{QMediaType, MediaType, Accept};\n    ///\n    /// let media_types = vec![\n    ///     QMediaType(MediaType::JSON, Some(0.3)),\n    ///     QMediaType(MediaType::HTML, Some(0.9))\n    /// ];\n    ///\n    /// let accept = Accept::new(media_types);\n    /// assert_eq!(accept.preferred().media_type(), &MediaType::HTML);\n    /// ```\n    pub fn preferred(&self) -> &QMediaType {\n        static ANY: QMediaType = QMediaType(MediaType::Any, None);\n\n        // See https://tools.ietf.org/html/rfc7231#section-5.3.2.\n        let mut all = self.iter();\n        let mut preferred = all.next().unwrap_or(&ANY);\n        for media_type in all {\n            if media_type.weight().is_none() && preferred.weight().is_some() {\n                // Media types without a `q` parameter are preferred.\n                preferred = media_type;\n            } else if media_type.weight_or(0.0) > preferred.weight_or(1.0) {\n                // Prefer media types with a greater weight, but if one doesn't\n                // have a weight, prefer the one we already have.\n                preferred = media_type;\n            } else if media_type.specificity() > preferred.specificity() {\n                // Prefer more specific media types over less specific ones. IE:\n                // text/html over application/*.\n                preferred = media_type;\n            } else if media_type == preferred {\n                // Finally, all other things being equal, prefer a media type\n                // with more parameters over one with fewer. IE: text/html; a=b\n                // over text/html.\n                if media_type.params().count() > preferred.params().count() {\n                    preferred = media_type;\n                }\n            }\n        }\n\n        preferred\n    }\n\n    /// Retrieve the first media type in `self`, if any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{QMediaType, MediaType, Accept};\n    ///\n    /// let accept = Accept::new(QMediaType(MediaType::XML, None));\n    /// assert_eq!(accept.first(), Some(&MediaType::XML.into()));\n    /// ```\n    #[inline(always)]\n    pub fn first(&self) -> Option<&QMediaType> {\n        self.iter().next()\n    }\n\n    /// Returns an iterator over all of the (quality) media types in `self`.\n    /// Media types are returned in the order in which they appear in the\n    /// header.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{QMediaType, MediaType, Accept};\n    ///\n    /// let qmedia_types = vec![\n    ///     QMediaType(MediaType::JSON, Some(0.3)),\n    ///     QMediaType(MediaType::HTML, Some(0.9))\n    /// ];\n    ///\n    /// let accept = Accept::new(qmedia_types.clone());\n    ///\n    /// let mut iter = accept.iter();\n    /// assert_eq!(iter.next(), Some(&qmedia_types[0]));\n    /// assert_eq!(iter.next(), Some(&qmedia_types[1]));\n    /// assert_eq!(iter.next(), None);\n    /// ```\n    #[inline(always)]\n    pub fn iter(&self) -> impl Iterator<Item=&'_ QMediaType> + '_ {\n        self.0.iter()\n    }\n\n    /// Returns an iterator over all of the (bare) media types in `self`. Media\n    /// types are returned in the order in which they appear in the header.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{QMediaType, MediaType, Accept};\n    ///\n    /// let qmedia_types = vec![\n    ///     QMediaType(MediaType::JSON, Some(0.3)),\n    ///     QMediaType(MediaType::HTML, Some(0.9))\n    /// ];\n    ///\n    /// let accept = Accept::new(qmedia_types.clone());\n    ///\n    /// let mut iter = accept.media_types();\n    /// assert_eq!(iter.next(), Some(qmedia_types[0].media_type()));\n    /// assert_eq!(iter.next(), Some(qmedia_types[1].media_type()));\n    /// assert_eq!(iter.next(), None);\n    /// ```\n    #[inline(always)]\n    pub fn media_types(&self) -> impl Iterator<Item=&'_ MediaType> + '_ {\n        self.iter().map(|weighted_mt| weighted_mt.media_type())\n    }\n\n    known_media_types!(accept_constructor);\n}\n\nimpl<T: IntoIterator<Item = MediaType>> From<T> for Accept {\n    #[inline(always)]\n    fn from(items: T) -> Accept {\n        Accept::new(items.into_iter().map(QMediaType::from))\n    }\n}\n\nimpl PartialEq for Accept {\n    fn eq(&self, other: &Accept) -> bool {\n        self.iter().eq(other.iter())\n    }\n}\n\nimpl fmt::Display for Accept {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        for (i, media_type) in self.iter().enumerate() {\n            if i >= 1 {\n                write!(f, \", {}\", media_type.0)?;\n            } else {\n                write!(f, \"{}\", media_type.0)?;\n            }\n        }\n\n        Ok(())\n    }\n}\n\nimpl FromStr for Accept {\n    // Ideally we'd return a `ParseError`, but that requires a lifetime.\n    type Err = String;\n\n    #[inline]\n    fn from_str(raw: &str) -> Result<Accept, String> {\n        parse_accept(raw).map_err(|e| e.to_string())\n    }\n}\n\n/// Creates a new `Header` with name `Accept` and the value set to the HTTP\n/// rendering of this `Accept` header.\nimpl From<Accept> for Header<'static> {\n    #[inline(always)]\n    fn from(val: Accept) -> Self {\n        Header::new(\"Accept\", val.to_string())\n    }\n}\n\nimpl QMediaType {\n    /// Retrieve the weight of the media type, if there is any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{MediaType, QMediaType};\n    ///\n    /// let q_type = QMediaType(MediaType::HTML, Some(0.3));\n    /// assert_eq!(q_type.weight(), Some(0.3));\n    /// ```\n    #[inline(always)]\n    pub fn weight(&self) -> Option<f32> {\n        self.1\n    }\n\n    /// Retrieve the weight of the media type or a given default value.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{MediaType, QMediaType};\n    ///\n    /// let q_type = QMediaType(MediaType::HTML, Some(0.3));\n    /// assert_eq!(q_type.weight_or(0.9), 0.3);\n    ///\n    /// let q_type = QMediaType(MediaType::HTML, None);\n    /// assert_eq!(q_type.weight_or(0.9), 0.9);\n    /// ```\n    #[inline(always)]\n    pub fn weight_or(&self, default: f32) -> f32 {\n        self.1.unwrap_or(default)\n    }\n\n    /// Borrow the internal `MediaType`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{MediaType, QMediaType};\n    ///\n    /// let q_type = QMediaType(MediaType::HTML, Some(0.3));\n    /// assert_eq!(q_type.media_type(), &MediaType::HTML);\n    /// ```\n    #[inline(always)]\n    pub fn media_type(&self) -> &MediaType {\n        &self.0\n    }\n}\n\nimpl IntoIterator for QMediaType {\n    type Item = Self;\n\n    type IntoIter = std::iter::Once<Self>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        std::iter::once(self)\n    }\n}\n\nimpl From<MediaType> for QMediaType {\n    #[inline(always)]\n    fn from(media_type: MediaType) -> QMediaType {\n        QMediaType(media_type, None)\n    }\n}\n\nimpl Deref for QMediaType {\n    type Target = MediaType;\n\n    #[inline(always)]\n    fn deref(&self) -> &MediaType {\n        &self.0\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use crate::{Accept, MediaType};\n\n    #[track_caller]\n    fn assert_preference(string: &str, expect: &str) {\n        let accept: Accept = string.parse().expect(\"accept string parse\");\n        let expected: MediaType = expect.parse().expect(\"media type parse\");\n        let preferred = accept.preferred();\n        let actual = preferred.media_type();\n        if *actual != expected {\n            panic!(\"mismatch for {}: expected {}, got {}\", string, expected, actual)\n        }\n    }\n\n    #[test]\n    fn test_preferred() {\n        assert_preference(\"text/*\", \"text/*\");\n        assert_preference(\"text/*, text/html\", \"text/html\");\n        assert_preference(\"text/*; q=0.1, text/html\", \"text/html\");\n        assert_preference(\"text/*; q=1, text/html\", \"text/html\");\n        assert_preference(\"text/html, text/*\", \"text/html\");\n        assert_preference(\"text/*, text/html\", \"text/html\");\n        assert_preference(\"text/html, text/*; q=1\", \"text/html\");\n        assert_preference(\"text/html; q=1, text/html\", \"text/html\");\n        assert_preference(\"text/html, text/*; q=0.1\", \"text/html\");\n\n        assert_preference(\"text/html, application/json\", \"text/html\");\n        assert_preference(\"text/html, application/json; q=1\", \"text/html\");\n        assert_preference(\"application/json; q=1, text/html\", \"text/html\");\n\n        assert_preference(\"text/*, application/json\", \"application/json\");\n        assert_preference(\"*/*, text/*\", \"text/*\");\n        assert_preference(\"*/*, text/*, text/plain\", \"text/plain\");\n\n        assert_preference(\"a/b; q=0.1, a/b; q=0.2\", \"a/b; q=0.2\");\n        assert_preference(\"a/b; q=0.1, b/c; q=0.2\", \"b/c; q=0.2\");\n        assert_preference(\"a/b; q=0.5, b/c; q=0.2\", \"a/b; q=0.5\");\n\n        assert_preference(\"a/b; q=0.5, b/c; q=0.2, c/d\", \"c/d\");\n        assert_preference(\"a/b; q=0.5; v=1, a/b\", \"a/b\");\n\n        assert_preference(\"a/b; v=1, a/b; v=1; c=2\", \"a/b; v=1; c=2\");\n        assert_preference(\"a/b; v=1; c=2, a/b; v=1\", \"a/b; v=1; c=2\");\n        assert_preference(\"a/b; q=0.5; v=1, a/b; q=0.5; v=1; c=2\", \"a/b; q=0.5; v=1; c=2\");\n        assert_preference(\"a/b; q=0.6; v=1, a/b; q=0.5; v=1; c=2\", \"a/b; q=0.6; v=1\");\n    }\n}\n"
  },
  {
    "path": "core/http/src/header/content_type.rs",
    "content": "use std::borrow::Cow;\nuse std::ops::Deref;\nuse std::str::FromStr;\nuse std::fmt;\n\nuse crate::header::{Header, MediaType};\nuse crate::uncased::UncasedStr;\n\n/// Representation of HTTP Content-Types.\n///\n/// # Usage\n///\n/// `ContentType`s should rarely be created directly. Instead, an associated\n/// constant should be used; one is declared for most commonly used content\n/// types.\n///\n/// ## Example\n///\n/// A Content-Type of `text/html; charset=utf-8` can be instantiated via the\n/// `HTML` constant:\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::ContentType;\n///\n/// # #[allow(unused_variables)]\n/// let html = ContentType::HTML;\n/// ```\n///\n/// # Header\n///\n/// `ContentType` implements `Into<Header>`. As such, it can be used in any\n/// context where an `Into<Header>` is expected:\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::ContentType;\n/// use rocket::response::Response;\n///\n/// let response = Response::build().header(ContentType::HTML).finalize();\n/// ```\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\npub struct ContentType(pub MediaType);\n\nmacro_rules! content_types {\n    (\n        $(\n            $name:ident ($check:ident): $str:expr,\n            $t:expr, $s:expr $(; $k:expr => $v:expr)*,\n        )+\n    ) => {\n    $(\n\n        /// Content Type for\n        #[doc = concat!(\"**\", $str, \"**: \")]\n        #[doc = concat!(\"`\", $t, \"/\", $s, $(\"; \", $k, \"=\", $v,)* \"`\")]\n\n        #[allow(non_upper_case_globals)]\n        pub const $name: ContentType = ContentType(MediaType::$name);\n    )+\n}}\n\nmacro_rules! from_extension {\n    ($($ext:expr => $name:ident,)*) => (\n        /// Returns the Content-Type associated with the extension `ext`.\n        ///\n        /// Extensions are matched case-insensitively. Not all extensions are\n        /// recognized. If an extensions is not recognized, `None` is returned.\n        /// The currently recognized extensions are:\n        ///\n        $(\n            #[doc = concat!(\"* \", $ext, \" - [`ContentType::\", stringify!($name), \"`]\")]\n        )*\n        ///\n        /// This list is likely to grow.\n        ///\n        /// # Example\n        ///\n        /// Recognized content types:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::ContentType;\n        ///\n        /// let xml = ContentType::from_extension(\"xml\");\n        /// assert_eq!(xml, Some(ContentType::XML));\n        ///\n        /// let xml = ContentType::from_extension(\"XML\");\n        /// assert_eq!(xml, Some(ContentType::XML));\n        /// ```\n        ///\n        /// An unrecognized content type:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::ContentType;\n        ///\n        /// let foo = ContentType::from_extension(\"foo\");\n        /// assert!(foo.is_none());\n        /// ```\n        #[inline]\n        pub fn from_extension(ext: &str) -> Option<ContentType> {\n            MediaType::from_extension(ext).map(ContentType)\n        }\n    )\n}\n\nmacro_rules! extension {\n    ($($ext:expr => $name:ident,)*) => (\n        /// Returns the most common file extension associated with the\n        /// Content-Type `self` if it is known. Otherwise, returns `None`.\n        ///\n        /// The currently recognized extensions are identical to those in\n        /// [`ContentType::from_extension()`] with the most common extension\n        /// being the first extension appearing in the list for a given\n        /// Content-Type.\n        ///\n        /// # Example\n        ///\n        /// Known extension:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::ContentType;\n        ///\n        /// assert_eq!(ContentType::JSON.extension().unwrap(), \"json\");\n        /// assert_eq!(ContentType::JPEG.extension().unwrap(), \"jpeg\");\n        /// assert_eq!(ContentType::JPEG.extension().unwrap(), \"JPEG\");\n        /// assert_eq!(ContentType::PDF.extension().unwrap(), \"pdf\");\n        /// ```\n        ///\n        /// An unknown extension:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::ContentType;\n        ///\n        /// let foo = ContentType::new(\"foo\", \"bar\");\n        /// assert!(foo.extension().is_none());\n        /// ```\n        #[inline]\n        pub fn extension(&self) -> Option<&UncasedStr> {\n            $(if self == &ContentType::$name { return Some($ext.into()) })*\n            None\n        }\n    )\n}\n\nmacro_rules! parse_flexible {\n    ($($short:expr => $name:ident,)*) => (\n        /// Flexibly parses `name` into a [`ContentType`]. The parse is\n        /// _flexible_ because, in addition to strictly correct content types,\n        /// it recognizes the following shorthands:\n        ///\n        $(\n            #[doc = concat!(\"* \", $short, \" - [`ContentType::\", stringify!($name), \"`]\")]\n        )*\n        ///\n        /// For regular parsing, use [`ContentType::from_str()`].\n        ///\n        /// # Example\n        ///\n        /// Using a shorthand:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::ContentType;\n        ///\n        /// let html = ContentType::parse_flexible(\"html\");\n        /// assert_eq!(html, Some(ContentType::HTML));\n        ///\n        /// let json = ContentType::parse_flexible(\"json\");\n        /// assert_eq!(json, Some(ContentType::JSON));\n        /// ```\n        ///\n        /// Using the full content-type:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::ContentType;\n        ///\n        /// let html = ContentType::parse_flexible(\"text/html; charset=utf-8\");\n        /// assert_eq!(html, Some(ContentType::HTML));\n        ///\n        /// let json = ContentType::parse_flexible(\"application/json\");\n        /// assert_eq!(json, Some(ContentType::JSON));\n        ///\n        /// let custom = ContentType::parse_flexible(\"application/x+custom\");\n        /// assert_eq!(custom, Some(ContentType::new(\"application\", \"x+custom\")));\n        /// ```\n        ///\n        /// An unrecognized content-type:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::ContentType;\n        ///\n        /// let foo = ContentType::parse_flexible(\"foo\");\n        /// assert_eq!(foo, None);\n        ///\n        /// let bar = ContentType::parse_flexible(\"foo/bar/baz\");\n        /// assert_eq!(bar, None);\n        /// ```\n        #[inline]\n        pub fn parse_flexible(name: &str) -> Option<ContentType> {\n            MediaType::parse_flexible(name).map(ContentType)\n        }\n    )\n}\n\nimpl ContentType {\n    /// Creates a new `ContentType` with top-level type `top` and subtype `sub`.\n    /// This should _only_ be used to construct uncommon or custom content\n    /// types. Use an associated constant for everything else.\n    ///\n    /// # Example\n    ///\n    /// Create a custom `application/x-person` content type:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::ContentType;\n    ///\n    /// let custom = ContentType::new(\"application\", \"x-person\");\n    /// assert_eq!(custom.top(), \"application\");\n    /// assert_eq!(custom.sub(), \"x-person\");\n    /// ```\n    #[inline(always)]\n    pub fn new<T, S>(top: T, sub: S) -> ContentType\n        where T: Into<Cow<'static, str>>, S: Into<Cow<'static, str>>\n    {\n        ContentType(MediaType::new(top, sub))\n    }\n\n    known_shorthands!(parse_flexible);\n\n    known_extensions!(from_extension);\n\n    /// Sets the parameters `parameters` on `self`.\n    ///\n    /// # Example\n    ///\n    /// Create a custom `application/x-id; id=1` media type:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::ContentType;\n    ///\n    /// let id = ContentType::new(\"application\", \"x-id\").with_params([(\"id\", \"1\")]);\n    /// assert_eq!(id.to_string(), \"application/x-id; id=1\".to_string());\n    /// ```\n    ///\n    /// Create a custom `text/person; name=bob; weight=175` media type:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::ContentType;\n    ///\n    /// let mt = ContentType::new(\"text\", \"person\")\n    ///     .with_params([(\"name\", \"bob\"), (\"ref\", \"2382\")]);\n    ///\n    /// assert_eq!(mt.to_string(), \"text/person; name=bob; ref=2382\".to_string());\n    /// ```\n    pub fn with_params<K, V, P>(self, parameters: P) -> ContentType\n        where K: Into<Cow<'static, str>>,\n              V: Into<Cow<'static, str>>,\n              P: IntoIterator<Item = (K, V)>\n    {\n        ContentType(self.0.with_params(parameters))\n    }\n\n    /// Borrows the inner `MediaType` of `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{ContentType, MediaType};\n    ///\n    /// let http = ContentType::HTML;\n    /// let media_type = http.media_type();\n    /// ```\n    #[inline(always)]\n    pub fn media_type(&self) -> &MediaType {\n        &self.0\n    }\n\n    known_extensions!(extension);\n\n    known_media_types!(content_types);\n}\n\nimpl Default for ContentType {\n    /// Returns a ContentType of `Any`, or `*/*`.\n    #[inline(always)]\n    fn default() -> ContentType {\n        ContentType::Any\n    }\n}\n\nimpl Deref for ContentType {\n    type Target = MediaType;\n\n    #[inline(always)]\n    fn deref(&self) -> &MediaType {\n        &self.0\n    }\n}\n\nimpl FromStr for ContentType {\n    type Err = String;\n\n    /// Parses a `ContentType` from a given Content-Type header value.\n    ///\n    /// # Examples\n    ///\n    /// Parsing an `application/json`:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::str::FromStr;\n    /// use rocket::http::ContentType;\n    ///\n    /// let json = ContentType::from_str(\"application/json\").unwrap();\n    /// assert!(json.is_known());\n    /// assert_eq!(json, ContentType::JSON);\n    /// ```\n    ///\n    /// Parsing a content type extension:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::str::FromStr;\n    /// use rocket::http::ContentType;\n    ///\n    /// let custom = ContentType::from_str(\"application/x-custom\").unwrap();\n    /// assert!(!custom.is_known());\n    /// assert_eq!(custom.top(), \"application\");\n    /// assert_eq!(custom.sub(), \"x-custom\");\n    /// ```\n    ///\n    /// Parsing an invalid Content-Type value:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::str::FromStr;\n    /// use rocket::http::ContentType;\n    ///\n    /// let custom = ContentType::from_str(\"application//x-custom\");\n    /// assert!(custom.is_err());\n    /// ```\n    #[inline(always)]\n    fn from_str(raw: &str) -> Result<ContentType, String> {\n        MediaType::from_str(raw).map(ContentType)\n    }\n}\n\nimpl From<MediaType> for ContentType {\n    fn from(media_type: MediaType) -> Self {\n        ContentType(media_type)\n    }\n}\n\nimpl fmt::Display for ContentType {\n    /// Formats the ContentType as an HTTP Content-Type value.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::ContentType;\n    ///\n    /// let ct = format!(\"{}\", ContentType::JSON);\n    /// assert_eq!(ct, \"application/json\");\n    /// ```\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.0)\n    }\n}\n\n/// Creates a new `Header` with name `Content-Type` and the value set to the\n/// HTTP rendering of this Content-Type.\nimpl From<ContentType> for Header<'static> {\n    #[inline(always)]\n    fn from(content_type: ContentType) -> Self {\n        if let Some(src) = content_type.known_source() {\n            Header::new(\"Content-Type\", src)\n        } else {\n            Header::new(\"Content-Type\", content_type.to_string())\n        }\n    }\n}\n"
  },
  {
    "path": "core/http/src/header/header.rs",
    "content": "use std::borrow::{Borrow, Cow};\nuse std::fmt;\n\nuse indexmap::IndexMap;\n\nuse crate::uncased::{Uncased, UncasedStr};\n\n/// Simple representation of an HTTP header.\n#[derive(Debug, Clone, Hash, PartialEq, Eq)]\npub struct Header<'h> {\n    /// The name of the header.\n    pub name: Uncased<'h>,\n    /// The value of the header.\n    pub value: Cow<'h, str>,\n}\n\nimpl<'h> Header<'h> {\n    /// Constructs a new header. This method should be used rarely and only for\n    /// non-standard headers. Instead, prefer to use the `Into<Header>`\n    /// implementations of many types, including\n    /// [`ContentType`](crate::ContentType) and all of the headers in\n    /// [`http::hyper::header`](hyper::header).\n    ///\n    /// # Examples\n    ///\n    /// Create a custom header with name `X-Custom-Header` and value `custom\n    /// value`.\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    ///\n    /// let header = Header::new(\"X-Custom-Header\", \"custom value\");\n    /// assert_eq!(header.to_string(), \"X-Custom-Header: custom value\");\n    /// ```\n    ///\n    /// Use a `String` as a value to do the same.\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    ///\n    /// let value = format!(\"{} value\", \"custom\");\n    /// let header = Header::new(\"X-Custom-Header\", value);\n    /// assert_eq!(header.to_string(), \"X-Custom-Header: custom value\");\n    /// ```\n    #[inline(always)]\n    pub fn new<'a: 'h, 'b: 'h, N, V>(name: N, value: V) -> Header<'h>\n        where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>\n    {\n        Header {\n            name: Uncased::new(name),\n            value: value.into()\n        }\n    }\n\n    /// Returns `true` if `name` is a valid header name.\n    ///\n    /// This implements a simple (i.e, correct but not particularly performant)\n    /// header \"field-name\" checker as defined in RFC 7230.\n    ///\n    /// ```text\n    ///     header-field   = field-name \":\" OWS field-value OWS\n    ///     field-name     = token\n    ///     token          = 1*tchar\n    ///     tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n    ///                    / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n    ///                    / DIGIT / ALPHA\n    ///                    ; any VCHAR, except delimiters\n    /// ```\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    ///\n    /// assert!(!Header::is_valid_name(\"\"));\n    /// assert!(!Header::is_valid_name(\"some header\"));\n    /// assert!(!Header::is_valid_name(\"some()\"));\n    /// assert!(!Header::is_valid_name(\"[SomeHeader]\"));\n    /// assert!(!Header::is_valid_name(\"<\"));\n    /// assert!(!Header::is_valid_name(\"\"));\n    /// assert!(!Header::is_valid_name(\"header,here\"));\n    ///\n    /// assert!(Header::is_valid_name(\"Some#Header\"));\n    /// assert!(Header::is_valid_name(\"Some-Header\"));\n    /// assert!(Header::is_valid_name(\"This-Is_A~Header\"));\n    /// ```\n    #[doc(hidden)]\n    pub const fn is_valid_name(name: &str) -> bool {\n        const fn is_tchar(b: &u8) -> bool {\n            b.is_ascii_alphanumeric() || matches!(*b,\n                b'!' | b'#' | b'$' | b'%' | b'&' | b'\\'' | b'*' | b'+' | b'-' |\n                b'.' | b'^' | b'_' | b'`' | b'|' | b'~')\n        }\n\n        let mut i = 0;\n        let bytes = name.as_bytes();\n        while i < bytes.len() {\n            if !is_tchar(&bytes[i]) {\n                return false\n            }\n\n            i += 1;\n        }\n\n        i > 0\n    }\n\n    /// Returns `true` if `val` is a valid header value.\n    ///\n    /// If `allow_empty` is `true`, this function returns `true` for empty\n    /// values. Otherwise, this function returns `false` for empty values.\n    ///\n    /// This implements a simple (i.e, correct but not particularly performant)\n    /// header \"field-content\" checker as defined in RFC 7230 without support\n    /// for obsolete (`obs-`) syntax:\n    ///\n    ///   field-value    = *(field-content)\n    ///   field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n    ///   field-vchar    = VCHAR\n    ///   VCHAR          = %x21-7E ; visible (printing) characters\n    ///\n    /// Note that this is a generic checker. Specific headers may have stricter\n    /// requirements. For example, the `Server` header does not allow delimiters\n    /// in its values.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    ///\n    /// assert!(!Header::is_valid_value(\"\", false));\n    /// assert!(!Header::is_valid_value(\" \" , false));\n    /// assert!(!Header::is_valid_value(\" hi\", false));\n    /// assert!(!Header::is_valid_value(\"a\\nbc\", false));\n    /// assert!(!Header::is_valid_value(\"\\nbc\", false));\n    /// assert!(!Header::is_valid_value(\"\\n\", false));\n    /// assert!(!Header::is_valid_value(\"\\t\", false));\n    /// assert!(!Header::is_valid_value(\"\\r\", false));\n    /// assert!(!Header::is_valid_value(\"a\\nb\\nc\", false));\n    /// assert!(!Header::is_valid_value(\"a\\rb\\rc\", false));\n    ///\n    /// assert!(Header::is_valid_value(\"\", true));\n    /// assert!(Header::is_valid_value(\"a\", false));\n    /// assert!(Header::is_valid_value(\"a\", true));\n    /// assert!(Header::is_valid_value(\"abc\", false));\n    /// assert!(Header::is_valid_value(\"abc\", true));\n    /// assert!(Header::is_valid_value(\"a b c\", false));\n    /// assert!(Header::is_valid_value(\"a b c\", true));\n    /// ```\n    #[doc(hidden)]\n    pub const fn is_valid_value(val: &str, allow_empty: bool) -> bool {\n        const fn is_valid_start(b: &u8) -> bool {\n            b.is_ascii_graphic()\n        }\n\n        const fn is_valid_continue(b: &u8) -> bool {\n            is_valid_start(b) || *b == b' ' || *b == b'\\t'\n        }\n\n        let mut i = 0;\n        let bytes = val.as_bytes();\n        while i < bytes.len() {\n            match i {\n                0 if !is_valid_start(&bytes[i]) => return false,\n                _ if i > 0 && !is_valid_continue(&bytes[i]) => return false,\n                _ => { /* ok */ }\n            };\n\n            i += 1;\n        }\n\n        allow_empty || i > 0\n    }\n\n    /// Returns the name of this header.\n    ///\n    /// # Example\n    ///\n    /// A case-sensitive equality check:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    ///\n    /// let value = format!(\"{} value\", \"custom\");\n    /// let header = Header::new(\"X-Custom-Header\", value);\n    /// assert_eq!(header.name().as_str(), \"X-Custom-Header\");\n    /// assert_ne!(header.name().as_str(), \"X-CUSTOM-HEADER\");\n    /// ```\n    ///\n    /// A case-insensitive equality check:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    ///\n    /// let header = Header::new(\"X-Custom-Header\", \"custom value\");\n    /// assert_eq!(header.name(), \"X-Custom-Header\");\n    /// assert_eq!(header.name(), \"X-CUSTOM-HEADER\");\n    /// ```\n    #[inline(always)]\n    pub fn name(&self) -> &UncasedStr {\n        &self.name\n    }\n\n    /// Returns the value of this header.\n    ///\n    /// # Example\n    ///\n    /// A case-sensitive equality check:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    ///\n    /// let header = Header::new(\"X-Custom-Header\", \"custom value\");\n    /// assert_eq!(header.value(), \"custom value\");\n    /// ```\n    #[inline(always)]\n    pub fn value(&self) -> &str {\n        &self.value\n    }\n}\n\nimpl fmt::Display for Header<'_> {\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}: {}\", self.name, self.value)\n    }\n}\n\n/// A collection of headers, mapping a header name to its many ordered values.\n///\n/// # Case-Insensitivity\n///\n/// All header names, including those passed in to `HeaderMap` methods and those\n/// stored in an existing `HeaderMap`, are treated case-insensitively. This\n/// means that, for instance, a look for a header by the name of \"aBC\" will\n/// returns values for headers of names \"AbC\", \"ABC\", \"abc\", and so on.\n#[derive(Clone, Debug, PartialEq, Default)]\npub struct HeaderMap<'h> {\n    headers: IndexMap<Uncased<'h>, Vec<Cow<'h, str>>>\n}\n\nimpl<'h> HeaderMap<'h> {\n    /// Returns an empty header collection.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let map = HeaderMap::new();\n    /// ```\n    #[inline(always)]\n    pub fn new() -> HeaderMap<'h> {\n        HeaderMap { headers: IndexMap::new() }\n    }\n\n    /// Returns true if `self` contains a header with the name `name`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{HeaderMap, ContentType};\n    ///\n    /// let mut map = HeaderMap::new();\n    /// map.add(ContentType::HTML);\n    ///\n    /// assert!(map.contains(\"Content-Type\"));\n    /// assert!(!map.contains(\"Accepts\"));\n    /// ```\n    #[inline]\n    pub fn contains<N: AsRef<str>>(&self, name: N) -> bool {\n        self.headers.get(UncasedStr::new(name.as_ref())).is_some()\n    }\n\n    /// Returns the number of _values_ stored in the map.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    /// assert_eq!(map.len(), 0);\n    ///\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    /// assert_eq!(map.len(), 1);\n    ///\n    /// map.replace_raw(\"X-Custom\", \"value_2\");\n    /// assert_eq!(map.len(), 1);\n    ///\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    /// assert_eq!(map.len(), 2);\n    /// ```\n    #[inline]\n    pub fn len(&self) -> usize {\n        self.headers.iter().flat_map(|(_, values)| values.iter()).count()\n    }\n\n    /// Returns `true` if there are no headers stored in the map. Otherwise\n    /// returns `false`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let map = HeaderMap::new();\n    /// assert!(map.is_empty());\n    /// ```\n    #[inline]\n    pub fn is_empty(&self) -> bool {\n        self.headers.is_empty()\n    }\n\n    /// Returns an iterator over all of the values stored in `self` for the\n    /// header with name `name`. The headers are returned in FIFO order.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    /// map.add_raw(\"X-Custom\", \"value_2\");\n    ///\n    /// assert_eq!(map.len(), 2);\n    ///\n    /// let mut values = map.get(\"X-Custom\");\n    /// assert_eq!(values.next(), Some(\"value_1\"));\n    /// assert_eq!(values.next(), Some(\"value_2\"));\n    /// assert_eq!(values.next(), None);\n    /// ```\n    #[inline]\n    pub fn get(&self, name: &str) -> impl Iterator<Item=&str> {\n        self.headers\n            .get(UncasedStr::new(name))\n            .into_iter()\n            .flat_map(|values| values.iter().map(|val| val.borrow()))\n    }\n\n    /// Returns the _first_ value stored for the header with name `name` if\n    /// there is one.\n    ///\n    /// # Examples\n    ///\n    /// Retrieve the first value when one exists:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    /// map.add_raw(\"X-Custom\", \"value_2\");\n    ///\n    /// assert_eq!(map.len(), 2);\n    ///\n    /// let first_value = map.get_one(\"X-Custom\");\n    /// assert_eq!(first_value, Some(\"value_1\"));\n    /// ```\n    ///\n    /// Attempt to retrieve a value that doesn't exist:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    ///\n    /// let first_value = map.get_one(\"X-Other\");\n    /// assert_eq!(first_value, None);\n    /// ```\n    #[inline]\n    pub fn get_one<'a>(&'a self, name: &str) -> Option<&'a str> {\n        self.headers.get(UncasedStr::new(name))\n            .and_then(|values| {\n                if !values.is_empty() { Some(values[0].borrow()) }\n                else { None }\n            })\n    }\n\n    /// Replace any header that matches the name of `header.name` with `header`.\n    /// If there is no such header in `self`, add `header`. If the matching\n    /// header had multiple values, all of the values are removed, and only the\n    /// value in `header` will remain.\n    ///\n    /// # Example\n    ///\n    /// Replace a header that doesn't yet exist:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{HeaderMap, ContentType};\n    ///\n    /// let mut map = HeaderMap::new();\n    /// map.replace(ContentType::JSON);\n    ///\n    /// assert!(map.get_one(\"Content-Type\").is_some());\n    /// ```\n    ///\n    /// Replace a header that already exists:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{HeaderMap, ContentType};\n    ///\n    /// let mut map = HeaderMap::new();\n    ///\n    /// map.replace(ContentType::JSON);\n    /// assert_eq!(map.get_one(\"Content-Type\"), Some(\"application/json\"));\n    ///\n    /// map.replace(ContentType::GIF);\n    /// assert_eq!(map.get_one(\"Content-Type\"), Some(\"image/gif\"));\n    /// assert_eq!(map.len(), 1);\n    /// ```\n    ///\n    /// An example of case-insensitivity.\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{HeaderMap, Header, ContentType};\n    ///\n    /// let mut map = HeaderMap::new();\n    ///\n    /// map.replace(ContentType::JSON);\n    /// assert_eq!(map.get_one(\"Content-Type\"), Some(\"application/json\"));\n    ///\n    /// map.replace(Header::new(\"CONTENT-type\", \"image/gif\"));\n    /// assert_eq!(map.get_one(\"Content-Type\"), Some(\"image/gif\"));\n    /// assert_eq!(map.len(), 1);\n    /// ```\n    #[inline(always)]\n    pub fn replace<'p: 'h, H: Into<Header<'p>>>(&mut self, header: H) -> bool {\n        let header = header.into();\n        self.headers.insert(header.name, vec![header.value]).is_some()\n    }\n\n    /// A convenience method to replace a header using a raw name and value.\n    /// Aliases `replace(Header::new(name, value))`. Should be used rarely.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    ///\n    /// map.replace_raw(\"X-Custom\", \"value_1\");\n    /// assert_eq!(map.get_one(\"X-Custom\"), Some(\"value_1\"));\n    ///\n    /// map.replace_raw(\"X-Custom\", \"value_2\");\n    /// assert_eq!(map.get_one(\"X-Custom\"), Some(\"value_2\"));\n    /// assert_eq!(map.len(), 1);\n    /// ```\n    #[inline(always)]\n    pub fn replace_raw<'a: 'h, 'b: 'h, N, V>(&mut self, name: N, value: V) -> bool\n        where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>\n    {\n        self.replace(Header::new(name, value))\n    }\n\n    /// Replaces all of the values for a header with name `name` with `values`.\n    /// This a low-level method and should rarely be used.\n    ///\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    /// map.add_raw(\"X-Custom\", \"value_2\");\n    ///\n    /// let vals: Vec<_> = map.get(\"X-Custom\").map(|s| s.to_string()).collect();\n    /// assert_eq!(vals, vec![\"value_1\", \"value_2\"]);\n    ///\n    /// map.replace_all(\"X-Custom\", vec![\"value_3\".into(), \"value_4\".into()]);\n    /// let vals: Vec<_> = map.get(\"X-Custom\").collect();\n    /// assert_eq!(vals, vec![\"value_3\", \"value_4\"]);\n    /// ```\n    #[inline(always)]\n    pub fn replace_all<'n, 'v: 'h, H>(&mut self, name: H, values: Vec<Cow<'v, str>>)\n        where 'n: 'h, H: Into<Cow<'n, str>>\n    {\n        self.headers.insert(Uncased::new(name), values);\n    }\n\n    /// Adds `header` into the map. If a header with `header.name` was\n    /// previously added, that header will have one more value.\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{Cookie, HeaderMap};\n    ///\n    /// let mut map = HeaderMap::new();\n    ///\n    /// map.add(&Cookie::new(\"a\", \"b\"));\n    /// assert_eq!(map.get(\"Set-Cookie\").count(), 1);\n    ///\n    /// map.add(&Cookie::new(\"c\", \"d\"));\n    /// assert_eq!(map.get(\"Set-Cookie\").count(), 2);\n    /// ```\n    #[inline(always)]\n    pub fn add<'p: 'h, H: Into<Header<'p>>>(&mut self, header: H) {\n        let header = header.into();\n        self.headers.entry(header.name).or_default().push(header.value);\n    }\n\n    /// A convenience method to add a header using a raw name and value.\n    /// Aliases `add(Header::new(name, value))`. Should be used rarely.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    ///\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    /// assert_eq!(map.get(\"X-Custom\").count(), 1);\n    ///\n    /// map.add_raw(\"X-Custom\", \"value_2\");\n    /// let values: Vec<_> = map.get(\"X-Custom\").collect();\n    /// assert_eq!(values, vec![\"value_1\", \"value_2\"]);\n    /// ```\n    #[inline(always)]\n    pub fn add_raw<'a: 'h, 'b: 'h, N, V>(&mut self, name: N, value: V)\n        where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>\n    {\n        self.add(Header::new(name, value))\n    }\n\n    /// Adds all of the values to a header with name `name`. This a low-level\n    /// method and should rarely be used. `values` will be empty when this\n    /// method returns.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    ///\n    /// let mut values = vec![\"value_1\".into(), \"value_2\".into()];\n    /// map.add_all(\"X-Custom\", &mut values);\n    /// assert_eq!(map.get(\"X-Custom\").count(), 2);\n    /// assert_eq!(values.len(), 0);\n    ///\n    /// let mut values = vec![\"value_3\".into(), \"value_4\".into()];\n    /// map.add_all(\"X-Custom\", &mut values);\n    /// assert_eq!(map.get(\"X-Custom\").count(), 4);\n    /// assert_eq!(values.len(), 0);\n    ///\n    /// let values: Vec<_> = map.get(\"X-Custom\").collect();\n    /// assert_eq!(values, vec![\"value_1\", \"value_2\", \"value_3\", \"value_4\"]);\n    /// ```\n    #[inline(always)]\n    pub fn add_all<'n, H>(&mut self, name: H, values: &mut Vec<Cow<'h, str>>)\n        where 'n:'h, H: Into<Cow<'n, str>>\n    {\n        self.headers.entry(Uncased::new(name))\n            .or_default()\n            .append(values)\n    }\n\n    /// Remove all of the values for header with name `name`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::HeaderMap;\n    ///\n    /// let mut map = HeaderMap::new();\n    /// map.add_raw(\"X-Custom\", \"value_1\");\n    /// map.add_raw(\"X-Custom\", \"value_2\");\n    /// map.add_raw(\"X-Other\", \"other\");\n    ///\n    /// assert_eq!(map.len(), 3);\n    ///\n    /// map.remove(\"X-Custom\");\n    /// assert_eq!(map.len(), 1);\n    #[inline(always)]\n    pub fn remove(&mut self, name: &str) {\n        self.headers.swap_remove(UncasedStr::new(name));\n    }\n\n    /// Removes all of the headers stored in this map and returns a vector\n    /// containing them. Header names are returned in no specific order, but all\n    /// values for a given header name are grouped together, and values are in\n    /// FIFO order.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{HeaderMap, Header};\n    /// use std::collections::HashSet;\n    ///\n    /// // The headers we'll be storing.\n    /// let all_headers = vec![\n    ///     Header::new(\"X-Custom\", \"value_1\"),\n    ///     Header::new(\"X-Custom\", \"value_2\"),\n    ///     Header::new(\"X-Other\", \"other\")\n    /// ];\n    ///\n    /// // Create a map, store all of the headers.\n    /// let mut map = HeaderMap::new();\n    /// for header in all_headers.clone() {\n    ///     map.add(header)\n    /// }\n    ///\n    /// assert_eq!(map.len(), 3);\n    ///\n    /// // Now remove them all, ensure the map is empty.\n    /// let removed_headers = map.remove_all();\n    /// assert!(map.is_empty());\n    ///\n    /// // Create two sets: what we expect and got. Ensure they're equal.\n    /// let expected_set: HashSet<_> = all_headers.into_iter().collect();\n    /// let actual_set: HashSet<_> = removed_headers.into_iter().collect();\n    /// assert_eq!(expected_set, actual_set);\n    /// ```\n    #[inline(always)]\n    pub fn remove_all(&mut self) -> Vec<Header<'h>> {\n        let old_map = std::mem::replace(self, HeaderMap::new());\n        old_map.into_iter().collect()\n    }\n\n    /// Returns an iterator over all of the `Header`s stored in the map. Header\n    /// names are returned in no specific order, but all values for a given\n    /// header name are grouped together, and values are in FIFO order.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::{HeaderMap, Header};\n    ///\n    /// // The headers we'll be storing.\n    /// let all_headers = vec![\n    ///     Header::new(\"X-Custom\", \"value_0\"),\n    ///     Header::new(\"X-Custom\", \"value_1\"),\n    ///     Header::new(\"X-Other\", \"other\"),\n    ///     Header::new(\"X-Third\", \"third\"),\n    /// ];\n    ///\n    /// // Create a map, store all of the headers.\n    /// let mut map = HeaderMap::new();\n    /// for header in all_headers {\n    ///     map.add(header)\n    /// }\n    ///\n    /// // Ensure there are three headers via the iterator.\n    /// assert_eq!(map.iter().count(), 4);\n    ///\n    /// // Actually iterate through them.\n    /// let mut custom = 0;\n    /// for header in map.iter() {\n    ///     match header.name().as_str() {\n    ///         \"X-Other\" => assert_eq!(header.value(), \"other\"),\n    ///         \"X-Third\" => assert_eq!(header.value(), \"third\"),\n    ///         \"X-Custom\" => {\n    ///             assert_eq!(header.value(), format!(\"value_{custom}\"));\n    ///             custom += 1;\n    ///         },\n    ///         _ => unreachable!(\"there are only three uniquely named headers\")\n    ///     }\n    /// }\n    /// ```\n    pub fn iter(&self) -> impl Iterator<Item=Header<'_>> {\n        self.headers.iter().flat_map(|(key, values)| {\n            values.iter().map(move |val| {\n                Header::new(key.as_str(), &**val)\n            })\n        })\n    }\n\n    /// Consumes `self` and returns an iterator over all of the headers stored\n    /// in the map in the way they are stored. This is a low-level mechanism and\n    /// should likely not be used.\n    /// WARNING: This is unstable! Do not use this method outside of Rocket!\n    #[doc(hidden)]\n    #[inline]\n    pub fn into_iter_raw(self) -> impl Iterator<Item=(Uncased<'h>, Vec<Cow<'h, str>>)> {\n        self.headers.into_iter()\n    }\n}\n\n/// Consumes `self` and returns an iterator over all of the `Header`s stored\n/// in the map. Header names are returned in no specific order, but all\n/// values for a given header name are grouped together, and values are in\n/// FIFO order.\n///\n/// # Example\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::{HeaderMap, Header};\n///\n/// // The headers we'll be storing.\n/// let all_headers = vec![\n///     Header::new(\"X-Custom\", \"value_0\"),\n///     Header::new(\"X-Custom\", \"value_1\"),\n///     Header::new(\"X-Other\", \"other\"),\n///     Header::new(\"X-Third\", \"third\"),\n/// ];\n///\n/// // Create a map, store all of the headers.\n/// let mut map = HeaderMap::new();\n/// for header in all_headers {\n///     map.add(header)\n/// }\n///\n/// // Ensure there are three headers via the iterator.\n/// assert_eq!(map.iter().count(), 4);\n///\n/// // Actually iterate through them.\n/// let mut custom = 0;\n/// for header in map.into_iter() {\n///     match header.name().as_str() {\n///         \"X-Other\" => assert_eq!(header.value(), \"other\"),\n///         \"X-Third\" => assert_eq!(header.value(), \"third\"),\n///         \"X-Custom\" => {\n///             assert_eq!(header.value(), format!(\"value_{custom}\"));\n///             custom += 1;\n///         },\n///         _ => unreachable!(\"there are only three uniquely named headers\")\n///     }\n/// }\n/// ```\nimpl<'h> IntoIterator for HeaderMap<'h> {\n    type Item = Header<'h>;\n\n    type IntoIter = IntoIter<'h>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        IntoIter {\n            headers: self.headers.into_iter(),\n            current: None,\n        }\n    }\n}\n\n/// Owned iterator over [`Header`]s in a [`HeaderMap`].\n///\n/// See [`HeaderMap::into_iter()`] for details.\npub struct IntoIter<'h> {\n    headers: indexmap::map::IntoIter<Uncased<'h>, Vec<Cow<'h, str>>>,\n    current: Option<(Uncased<'h>, std::vec::IntoIter<Cow<'h, str>>)>,\n}\n\nimpl<'h> Iterator for IntoIter<'h> {\n    type Item = Header<'h>;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        loop {\n            if let Some((name, values)) = &mut self.current {\n                if let Some(value) = values.next() {\n                    return Some(Header { name: name.clone(), value });\n                }\n            }\n\n            let (name, values) = self.headers.next()?;\n            self.current = Some((name, values.into_iter()));\n        }\n    }\n}\n\nimpl From<cookie::Cookie<'_>> for Header<'static> {\n    fn from(cookie: cookie::Cookie<'_>) -> Header<'static> {\n        Header::new(\"Set-Cookie\", cookie.encoded().to_string())\n    }\n}\n\nimpl From<&cookie::Cookie<'_>> for Header<'static> {\n    fn from(cookie: &cookie::Cookie<'_>) -> Header<'static> {\n        Header::new(\"Set-Cookie\", cookie.encoded().to_string())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::HeaderMap;\n\n    #[test]\n    fn case_insensitive_add_get() {\n        let mut map = HeaderMap::new();\n        map.add_raw(\"content-type\", \"application/json\");\n\n        let ct = map.get_one(\"Content-Type\");\n        assert_eq!(ct, Some(\"application/json\"));\n\n        let ct2 = map.get_one(\"CONTENT-TYPE\");\n        assert_eq!(ct2, Some(\"application/json\"))\n    }\n\n    #[test]\n    fn case_insensitive_multiadd() {\n        let mut map = HeaderMap::new();\n        map.add_raw(\"x-custom\", \"a\");\n        map.add_raw(\"X-Custom\", \"b\");\n        map.add_raw(\"x-CUSTOM\", \"c\");\n\n        let vals: Vec<_> = map.get(\"x-CuStOm\").collect();\n        assert_eq!(vals, vec![\"a\", \"b\", \"c\"]);\n    }\n}\n"
  },
  {
    "path": "core/http/src/header/known_media_types.rs",
    "content": "macro_rules! known_media_types {\n    ($cont:ident) => ($cont! {\n        Any (is_any): \"any media type\", \"*\", \"*\",\n        Binary (is_binary): \"binary data\", \"application\", \"octet-stream\",\n        Bytes (is_bytes): \"binary data\", \"application\", \"octet-stream\",\n        HTML (is_html): \"HTML\", \"text\", \"html\" ; \"charset\" => \"utf-8\",\n        Plain (is_plain): \"plain text\", \"text\", \"plain\" ; \"charset\" => \"utf-8\",\n        Text (is_text): \"plain text\", \"text\", \"plain\" ; \"charset\" => \"utf-8\",\n        JSON (is_json): \"JSON\", \"application\", \"json\",\n        MsgPack (is_msgpack): \"MsgPack\", \"application\", \"msgpack\",\n        Form (is_form): \"forms\", \"application\", \"x-www-form-urlencoded\",\n        JavaScript (is_javascript): \"JavaScript\", \"text\", \"javascript\",\n        CSS (is_css): \"CSS\", \"text\", \"css\" ; \"charset\" => \"utf-8\",\n        FormData (is_form_data): \"multipart form data\", \"multipart\", \"form-data\",\n        XML (is_xml): \"XML\", \"text\", \"xml\" ; \"charset\" => \"utf-8\",\n        OPF (is_opf): \"OPF\", \"application\", \"oebps-package+xml\",\n        XHTML (is_xhtml): \"XHTML\", \"application\", \"xhtml+xml\",\n        CSV (is_csv): \"CSV\", \"text\", \"csv\" ; \"charset\" => \"utf-8\",\n        PNG (is_png): \"PNG\", \"image\", \"png\",\n        GIF (is_gif): \"GIF\", \"image\", \"gif\",\n        BMP (is_bmp): \"BMP\", \"image\", \"bmp\",\n        JPEG (is_jpeg): \"JPEG\", \"image\", \"jpeg\",\n        WEBP (is_webp): \"WEBP\", \"image\", \"webp\",\n        AVIF (is_avif): \"AVIF\", \"image\", \"avif\",\n        SVG (is_svg): \"SVG\", \"image\", \"svg+xml\",\n        Icon (is_icon): \"Icon\", \"image\", \"x-icon\",\n        WEBM (is_webm): \"WEBM\", \"video\", \"webm\",\n        WEBA (is_weba): \"WEBM Audio\", \"audio\", \"webm\",\n        OGG (is_ogg): \"OGG Video\", \"video\", \"ogg\",\n        FLAC (is_flac): \"FLAC\", \"audio\", \"flac\",\n        WAV (is_wav): \"WAV\", \"audio\", \"wav\",\n        PDF (is_pdf): \"PDF\", \"application\", \"pdf\",\n        TTF (is_ttf): \"TTF\", \"application\", \"font-sfnt\",\n        OTF (is_otf): \"OTF\", \"application\", \"font-sfnt\",\n        WOFF (is_woff): \"WOFF\", \"application\", \"font-woff\",\n        WOFF2 (is_woff2): \"WOFF2\", \"font\", \"woff2\",\n        JsonApi (is_json_api): \"JSON API\", \"application\", \"vnd.api+json\",\n        WASM (is_wasm): \"WASM\", \"application\", \"wasm\",\n        TIFF (is_tiff): \"TIFF\", \"image\", \"tiff\",\n        AAC (is_aac): \"AAC Audio\", \"audio\", \"aac\",\n        Calendar (is_ical): \"iCalendar\", \"text\", \"calendar\",\n        MPEG (is_mpeg): \"MPEG Video\", \"video\", \"mpeg\",\n        TAR (is_tar): \"tape archive\", \"application\", \"x-tar\",\n        GZIP (is_gzip): \"gzipped binary\", \"application\", \"gzip\",\n        MOV (is_mov): \"quicktime video\", \"video\", \"quicktime\",\n        MP3 (is_mp3): \"MPEG Audio\", \"audio\", \"mpeg\",\n        MP4 (is_mp4): \"MPEG4 Video\", \"video\", \"mp4\",\n        ZIP (is_zip): \"ZIP archive\", \"application\", \"zip\",\n        CBZ (is_cbz): \"Comic ZIP archive\", \"application\", \"vnd.comicbook+zip\",\n        CBR (is_cbr): \"Comic RAR compressed archive\", \"application\", \"vnd.comicbook-rar\",\n        RAR (is_rar): \"RAR compressed archive\", \"application\", \"vnd.rar\",\n        EPUB (is_epub): \"EPUB\", \"application\", \"epub+zip\",\n        EventStream (is_event_stream): \"SSE stream\", \"text\", \"event-stream\",\n        Markdown (is_markdown): \"markdown text\", \"text\", \"markdown\" ; \"charset\" => \"utf-8\",\n        EXE (is_exe): \"executable\", \"application\", \"vnd.microsoft.portable-executable\",\n    })\n}\n\nmacro_rules! known_extensions {\n    ($cont:ident) => ($cont! {\n        \"txt\" => Plain,\n        \"html\" => HTML,\n        \"htm\" => HTML,\n        \"xml\" => XML,\n        \"opf\" => OPF,\n        \"xhtml\" => XHTML,\n        \"csv\" => CSV,\n        \"js\" => JavaScript,\n        \"mjs\" => JavaScript,\n        \"css\" => CSS,\n        \"json\" => JSON,\n        \"png\" => PNG,\n        \"gif\" => GIF,\n        \"bmp\" => BMP,\n        \"jpeg\" => JPEG,\n        \"jpg\" => JPEG,\n        \"webp\" => WEBP,\n        \"avif\" => AVIF,\n        \"svg\" => SVG,\n        \"ico\" => Icon,\n        \"flac\" => FLAC,\n        \"wav\" => WAV,\n        \"webm\" => WEBM,\n        \"weba\" => WEBA,\n        \"ogg\" => OGG,\n        \"ogv\" => OGG,\n        \"pdf\" => PDF,\n        \"ttf\" => TTF,\n        \"otf\" => OTF,\n        \"woff\" => WOFF,\n        \"woff2\" => WOFF2,\n        \"mp3\" => MP3,\n        \"mp4\" => MP4,\n        \"mpeg4\" => MP4,\n        \"wasm\" => WASM,\n        \"aac\" => AAC,\n        \"ics\" => Calendar,\n        \"bin\" => Binary,\n        \"iso\" => Binary,\n        \"dmg\" => Binary,\n        \"mpg\" => MPEG,\n        \"mpeg\" => MPEG,\n        \"tar\" => TAR,\n        \"gz\" => GZIP,\n        \"tif\" => TIFF,\n        \"tiff\" => TIFF,\n        \"mov\" => MOV,\n        \"zip\" => ZIP,\n        \"cbz\" => CBZ,\n        \"cbr\" => CBR,\n        \"rar\" => RAR,\n        \"epub\" => EPUB,\n        \"md\" => Markdown,\n        \"markdown\" => Markdown,\n        \"exe\" => EXE,\n    })\n}\n\nmacro_rules! known_shorthands {\n    ($cont:ident) => ($cont! {\n        \"any\" => Any,\n        \"binary\" => Binary,\n        \"bytes\" => Bytes,\n        \"html\" => HTML,\n        \"plain\" => Plain,\n        \"text\" => Text,\n        \"json\" => JSON,\n        \"msgpack\" => MsgPack,\n        \"form\" => Form,\n        \"js\" => JavaScript,\n        \"css\" => CSS,\n        \"multipart\" => FormData,\n        \"xml\" => XML,\n        \"pdf\" => PDF,\n        \"markdown\" => Markdown,\n        \"md\" => Markdown,\n    })\n}\n"
  },
  {
    "path": "core/http/src/header/media_type.rs",
    "content": "use std::borrow::{Cow, Borrow};\nuse std::str::FromStr;\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\n\nuse either::Either;\n\nuse crate::uncased::UncasedStr;\nuse crate::parse::{Indexed, IndexedStr, parse_media_type};\n\n/// An HTTP media type.\n///\n/// # Usage\n///\n/// A `MediaType` should rarely be used directly. Instead, one is typically used\n/// indirectly via types like [`Accept`](crate::Accept) and\n/// [`ContentType`](crate::ContentType), which internally contain `MediaType`s.\n/// Nonetheless, a `MediaType` can be created via the [`MediaType::new()`],\n/// [`MediaType::with_params()`], and [`MediaType::from_extension`()] methods.\n/// The preferred method, however, is to create a `MediaType` via an associated\n/// constant.\n///\n/// ## Example\n///\n/// A media type of `application/json` can be instantiated via the\n/// [`MediaType::JSON`] constant:\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::MediaType;\n///\n/// let json = MediaType::JSON;\n/// assert_eq!(json.top(), \"application\");\n/// assert_eq!(json.sub(), \"json\");\n///\n/// let json = MediaType::new(\"application\", \"json\");\n/// assert_eq!(MediaType::JSON, json);\n/// ```\n///\n/// # Comparison and Hashing\n///\n/// The `PartialEq` and `Hash` implementations for `MediaType` _do not_ take\n/// into account parameters. This means that a media type of `text/html` is\n/// equal to a media type of `text/html; charset=utf-8`, for instance. This is\n/// typically the comparison that is desired.\n///\n/// If an exact comparison is desired that takes into account parameters, the\n/// [`exact_eq()`](MediaType::exact_eq()) method can be used.\n#[derive(Debug, Clone)]\npub struct MediaType {\n    /// InitCell for the entire media type string.\n    pub(crate) source: Source,\n    /// The top-level type.\n    pub(crate) top: IndexedStr<'static>,\n    /// The subtype.\n    pub(crate) sub: IndexedStr<'static>,\n    /// The parameters, if any.\n    pub(crate) params: MediaParams,\n}\n\n// TODO: `Static` variant is needed for `const`.\n#[derive(Debug, Clone)]\npub(crate) enum MediaParams {\n    Static(&'static [(&'static str, &'static str)]),\n    Dynamic(Vec<(IndexedStr<'static>, IndexedStr<'static>)>)\n}\n\n#[derive(Debug, Clone, PartialEq, Eq)]\npub(crate) enum Source {\n    Known(&'static str),\n    Custom(Cow<'static, str>),\n    None\n}\n\nimpl From<Cow<'static, str>> for Source {\n    fn from(custom: Cow<'static, str>) -> Source {\n        Source::Custom(custom)\n    }\n}\n\nmacro_rules! media_types {\n    ($($name:ident ($check:ident): $str:expr, $t:expr,\n        $s:expr $(; $k:expr => $v:expr)*,)+) => {\n    $(\n        /// Media Type for\n        #[doc = concat!(\"**\", $str, \"**: \")]\n        #[doc = concat!(\"`\", $t, \"/\", $s, $(\"; \", $k, \"=\", $v,)* \"`\")]\n        #[allow(non_upper_case_globals)]\n        pub const $name: MediaType = MediaType::new_known(\n            concat!($t, \"/\", $s, $(\"; \", $k, \"=\", $v),*),\n            $t, $s, &[$(($k, $v)),*]\n        );\n    )+\n\n    /// Returns `true` if this MediaType is known to Rocket. In other words,\n    /// returns `true` if there is an associated constant for `self`.\n    pub fn is_known(&self) -> bool {\n        if let Source::Known(_) = self.source {\n            return true;\n        }\n\n        $(if self.$check() { return true })+\n        false\n    }\n\n    $(\n        /// Returns `true` if the top-level and sublevel types of\n        /// `self` are the same as those of\n        #[doc = concat!(\"`MediaType::\", stringify!($name), \"`, \")]\n        /// i.e\n        #[doc = concat!(\"`\", $t, \"/\", $s, \"`.\")]\n        #[inline(always)]\n        pub fn $check(&self) -> bool {\n            *self == MediaType::$name\n        }\n    )+\n}}\n\nmacro_rules! from_extension {\n    ($($ext:expr => $name:ident,)*) => (\n        /// Returns the Media Type associated with the extension `ext`.\n        ///\n        /// Extensions are matched case-insensitively. Not all extensions are\n        /// recognized. If an extensions is not recognized, `None` is returned.\n        /// The currently recognized extensions are:\n        ///\n        $(\n            #[doc = concat!(\"* \", $ext, \" - [`MediaType::\", stringify!($name), \"`]\")]\n        )*\n        ///\n        /// This list is likely to grow.\n        ///\n        /// # Example\n        ///\n        /// Recognized media types:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::MediaType;\n        ///\n        /// let xml = MediaType::from_extension(\"xml\");\n        /// assert_eq!(xml, Some(MediaType::XML));\n        ///\n        /// let xml = MediaType::from_extension(\"XML\");\n        /// assert_eq!(xml, Some(MediaType::XML));\n        /// ```\n        ///\n        /// An unrecognized media type:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::MediaType;\n        ///\n        /// let foo = MediaType::from_extension(\"foo\");\n        /// assert!(foo.is_none());\n        /// ```\n        pub fn from_extension(ext: &str) -> Option<MediaType> {\n            match ext {\n                $(x if uncased::eq(x, $ext) => Some(MediaType::$name)),*,\n                _ => None\n            }\n        }\n    )\n}\n\nmacro_rules! extension {\n    ($($ext:expr => $name:ident,)*) => (\n        /// Returns the most common file extension associated with the\n        /// Media-Type `self` if it is known. Otherwise, returns `None`.\n        ///\n        /// The currently recognized extensions are identical to those in\n        /// [`MediaType::from_extension()`] with the most common extension being\n        /// the first extension appearing in the list for a given Content-Type.\n        ///\n        /// # Example\n        ///\n        /// Known extension:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::MediaType;\n        ///\n        /// assert_eq!(MediaType::JSON.extension().unwrap(), \"json\");\n        /// assert_eq!(MediaType::JPEG.extension().unwrap(), \"jpeg\");\n        /// assert_eq!(MediaType::JPEG.extension().unwrap(), \"JPEG\");\n        /// assert_eq!(MediaType::PDF.extension().unwrap(), \"pdf\");\n        /// ```\n        ///\n        /// An unknown extension:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::MediaType;\n        ///\n        /// let foo = MediaType::new(\"foo\", \"bar\");\n        /// assert!(foo.extension().is_none());\n        /// ```\n        #[inline]\n        pub fn extension(&self) -> Option<&UncasedStr> {\n            $(if self == &MediaType::$name { return Some($ext.into()) })*\n            None\n        }\n    )\n}\n\nmacro_rules! parse_flexible {\n    ($($short:expr => $name:ident,)*) => (\n        /// Flexibly parses `name` into a [`MediaType`]. The parse is\n        /// _flexible_ because, in addition to strictly correct content types,\n        /// it recognizes the following shorthands:\n        ///\n        $(\n            #[doc = concat!(\"* \", $short, \" - [`MediaType::\", stringify!($name), \"`]\")]\n        )*\n        ///\n        /// For regular parsing, use [`MediaType::from_str()`].\n        ///\n        /// # Example\n        ///\n        /// Using a shorthand:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::MediaType;\n        ///\n        /// let html = MediaType::parse_flexible(\"html\");\n        /// assert_eq!(html, Some(MediaType::HTML));\n        ///\n        /// let json = MediaType::parse_flexible(\"json\");\n        /// assert_eq!(json, Some(MediaType::JSON));\n        /// ```\n        ///\n        /// Using the full media type:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::MediaType;\n        ///\n        /// let html = MediaType::parse_flexible(\"text/html; charset=utf-8\");\n        /// assert_eq!(html, Some(MediaType::HTML));\n        ///\n        /// let json = MediaType::parse_flexible(\"application/json\");\n        /// assert_eq!(json, Some(MediaType::JSON));\n        ///\n        /// let custom = MediaType::parse_flexible(\"application/x+custom\");\n        /// assert_eq!(custom, Some(MediaType::new(\"application\", \"x+custom\")));\n        /// ```\n        ///\n        /// An unrecognized media type:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::MediaType;\n        ///\n        /// let foo = MediaType::parse_flexible(\"foo\");\n        /// assert_eq!(foo, None);\n        ///\n        /// let bar = MediaType::parse_flexible(\"foo/bar/baz\");\n        /// assert_eq!(bar, None);\n        /// ```\n        pub fn parse_flexible(name: &str) -> Option<MediaType> {\n            match name {\n                $(x if uncased::eq(x, $short) => Some(MediaType::$name)),*,\n                _ => MediaType::from_str(name).ok(),\n            }\n        }\n    )\n}\n\nimpl MediaType {\n    /// Creates a new `MediaType` with top-level type `top` and subtype `sub`.\n    /// This should _only_ be used to construct uncommon or custom media types.\n    /// Use an associated constant for everything else.\n    ///\n    /// # Example\n    ///\n    /// Create a custom `application/x-person` media type:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let custom = MediaType::new(\"application\", \"x-person\");\n    /// assert_eq!(custom.top(), \"application\");\n    /// assert_eq!(custom.sub(), \"x-person\");\n    /// ```\n    #[inline]\n    pub fn new<T, S>(top: T, sub: S) -> MediaType\n        where T: Into<Cow<'static, str>>, S: Into<Cow<'static, str>>\n    {\n        MediaType {\n            source: Source::None,\n            top: Indexed::Concrete(top.into()),\n            sub: Indexed::Concrete(sub.into()),\n            params: MediaParams::Static(&[]),\n        }\n    }\n\n    /// Sets the parameters `parameters` on `self`.\n    ///\n    /// # Example\n    ///\n    /// Create a custom `application/x-id; id=1` media type:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let id = MediaType::new(\"application\", \"x-id\").with_params([(\"id\", \"1\")]);\n    /// assert_eq!(id.to_string(), \"application/x-id; id=1\".to_string());\n    /// ```\n    ///\n    /// Create a custom `text/person; name=bob; weight=175` media type:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let mt = MediaType::new(\"text\", \"person\")\n    ///     .with_params([(\"name\", \"bob\"), (\"ref\", \"2382\")]);\n    ///\n    /// assert_eq!(mt.to_string(), \"text/person; name=bob; ref=2382\".to_string());\n    /// ```\n    pub fn with_params<K, V, P>(mut self, ps: P) -> MediaType\n        where K: Into<Cow<'static, str>>,\n              V: Into<Cow<'static, str>>,\n              P: IntoIterator<Item = (K, V)>\n    {\n        let params = ps.into_iter()\n            .map(|(k, v)| (Indexed::Concrete(k.into()), Indexed::Concrete(v.into())))\n            .collect();\n\n        self.params = MediaParams::Dynamic(params);\n        self\n    }\n\n    /// A `const` variant of [`MediaType::with_params()`]. Creates a new\n    /// `MediaType` with top-level type `top`, subtype `sub`, and parameters\n    /// `params`, which may be empty.\n    ///\n    /// # Example\n    ///\n    /// Create a custom `application/x-person` media type:\n    ///\n    /// ```rust\n    /// use rocket::http::MediaType;\n    ///\n    /// let custom = MediaType::const_new(\"application\", \"x-person\", &[]);\n    /// assert_eq!(custom.top(), \"application\");\n    /// assert_eq!(custom.sub(), \"x-person\");\n    /// ```\n    #[inline]\n    pub const fn const_new(\n        top: &'static str,\n        sub: &'static str,\n        params: &'static [(&'static str, &'static str)]\n    ) -> MediaType {\n        MediaType {\n            source: Source::None,\n            top: Indexed::Concrete(Cow::Borrowed(top)),\n            sub: Indexed::Concrete(Cow::Borrowed(sub)),\n            params: MediaParams::Static(params),\n        }\n    }\n\n    #[inline]\n    pub(crate) const fn new_known(\n        source: &'static str,\n        top: &'static str,\n        sub: &'static str,\n        params: &'static [(&'static str, &'static str)]\n    ) -> MediaType {\n        MediaType {\n            source: Source::Known(source),\n            top: Indexed::Concrete(Cow::Borrowed(top)),\n            sub: Indexed::Concrete(Cow::Borrowed(sub)),\n            params: MediaParams::Static(params),\n        }\n    }\n\n    pub(crate) fn known_source(&self) -> Option<&'static str> {\n        match self.source {\n            Source::Known(string) => Some(string),\n            Source::Custom(Cow::Borrowed(string)) => Some(string),\n            _ => None\n        }\n    }\n\n    known_shorthands!(parse_flexible);\n\n    known_extensions!(from_extension);\n\n    /// Returns the top-level type for this media type. The return type,\n    /// `UncasedStr`, has caseless equality comparison and hashing.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let plain = MediaType::Plain;\n    /// assert_eq!(plain.top(), \"text\");\n    /// assert_eq!(plain.top(), \"TEXT\");\n    /// assert_eq!(plain.top(), \"Text\");\n    /// ```\n    #[inline]\n    pub fn top(&self) -> &UncasedStr {\n        self.top.from_source(self.source.as_str()).into()\n    }\n\n    /// Returns the subtype for this media type. The return type,\n    /// `UncasedStr`, has caseless equality comparison and hashing.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let plain = MediaType::Plain;\n    /// assert_eq!(plain.sub(), \"plain\");\n    /// assert_eq!(plain.sub(), \"PlaIN\");\n    /// assert_eq!(plain.sub(), \"pLaIn\");\n    /// ```\n    #[inline]\n    pub fn sub(&self) -> &UncasedStr {\n        self.sub.from_source(self.source.as_str()).into()\n    }\n\n    /// Returns a `u8` representing how specific the top-level type and subtype\n    /// of this media type are.\n    ///\n    /// The return value is either `0`, `1`, or `2`, where `2` is the most\n    /// specific. A `0` is returned when both the top and sublevel types are\n    /// `*`. A `1` is returned when only one of the top or sublevel types is\n    /// `*`, and a `2` is returned when neither the top or sublevel types are\n    /// `*`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let mt = MediaType::Plain;\n    /// assert_eq!(mt.specificity(), 2);\n    ///\n    /// let mt = MediaType::new(\"text\", \"*\");\n    /// assert_eq!(mt.specificity(), 1);\n    ///\n    /// let mt = MediaType::Any;\n    /// assert_eq!(mt.specificity(), 0);\n    /// ```\n    #[inline]\n    pub fn specificity(&self) -> u8 {\n        (self.top() != \"*\") as u8 + (self.sub() != \"*\") as u8\n    }\n\n    /// Compares `self` with `other` and returns `true` if `self` and `other`\n    /// are exactly equal to each other, including with respect to their\n    /// parameters and their order.\n    ///\n    /// This is different from the `PartialEq` implementation in that it\n    /// considers parameters. In particular, `Eq` implies `PartialEq` but\n    /// `PartialEq` does not imply `Eq`. That is, if `PartialEq` returns false,\n    /// this function is guaranteed to return false. Similarly, if `exact_eq`\n    /// returns `true`, `PartialEq` is guaranteed to return true. However, if\n    /// `PartialEq` returns `true`, `exact_eq` function may or may not return\n    /// `true`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let plain = MediaType::Plain;\n    /// let plain2 = MediaType::new(\"text\", \"plain\").with_params([(\"charset\", \"utf-8\")]);\n    /// let just_plain = MediaType::new(\"text\", \"plain\");\n    ///\n    /// // The `PartialEq` implementation doesn't consider parameters.\n    /// assert!(plain == just_plain);\n    /// assert!(just_plain == plain2);\n    /// assert!(plain == plain2);\n    ///\n    /// // While `exact_eq` does.\n    /// assert!(!plain.exact_eq(&just_plain));\n    /// assert!(!plain2.exact_eq(&just_plain));\n    /// assert!(plain.exact_eq(&plain2));\n    /// ```\n    pub fn exact_eq(&self, other: &MediaType) -> bool {\n        self == other && self.params().eq(other.params())\n    }\n\n    /// Returns an iterator over the (key, value) pairs of the media type's\n    /// parameter list. The iterator will be empty if the media type has no\n    /// parameters.\n    ///\n    /// # Example\n    ///\n    /// The `MediaType::Plain` type has one parameter: `charset=utf-8`:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let plain = MediaType::Plain;\n    /// let (key, val) = plain.params().next().unwrap();\n    /// assert_eq!(key, \"charset\");\n    /// assert_eq!(val, \"utf-8\");\n    /// ```\n    ///\n    /// The `MediaType::PNG` type has no parameters:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::MediaType;\n    ///\n    /// let png = MediaType::PNG;\n    /// assert_eq!(png.params().count(), 0);\n    /// ```\n    #[inline]\n    pub fn params(&self) -> impl Iterator<Item=(&'_ UncasedStr, &'_ str)> + '_ {\n        let raw = match self.params {\n            MediaParams::Static(slice) => Either::Left(slice.iter().cloned()),\n            MediaParams::Dynamic(ref vec) => {\n                Either::Right(vec.iter().map(move |(key, val)| {\n                    let source_str = self.source.as_str();\n                    (key.from_source(source_str), val.from_source(source_str))\n                }))\n            }\n        };\n\n        raw.map(|(k, v)| (k.into(), v))\n    }\n\n    /// Returns the first parameter with name `name`, if there is any.\n    #[inline]\n    pub fn param<'a>(&'a self, name: &str) -> Option<&'a str> {\n        self.params()\n            .filter(|(k, _)| *k == name)\n            .map(|(_, v)| v)\n            .next()\n    }\n\n    known_extensions!(extension);\n\n    known_media_types!(media_types);\n}\n\nimpl FromStr for MediaType {\n    // Ideally we'd return a `ParseError`, but that requires a lifetime.\n    type Err = String;\n\n    #[inline]\n    fn from_str(raw: &str) -> Result<MediaType, String> {\n        parse_media_type(raw).map_err(|e| e.to_string())\n    }\n}\n\nimpl PartialEq for MediaType {\n    #[inline(always)]\n    fn eq(&self, other: &MediaType) -> bool {\n        self.top() == other.top() && self.sub() == other.sub()\n    }\n}\n\nimpl Eq for MediaType {  }\n\nimpl Hash for MediaType {\n    #[inline]\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.top().hash(state);\n        self.sub().hash(state);\n    }\n}\n\nimpl fmt::Display for MediaType {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(src) = self.known_source() {\n            src.fmt(f)\n        } else {\n            write!(f, \"{}/{}\", self.top(), self.sub())?;\n            for (key, val) in self.params() {\n                write!(f, \"; {}={}\", key, val)?;\n            }\n\n            Ok(())\n        }\n    }\n}\n\nimpl IntoIterator for MediaType {\n    type Item = Self;\n\n    type IntoIter = std::iter::Once<Self>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        std::iter::once(self)\n    }\n}\n\nimpl Default for MediaParams {\n    fn default() -> Self {\n        MediaParams::Dynamic(Vec::new())\n    }\n}\n\nimpl Extend<(IndexedStr<'static>, IndexedStr<'static>)> for MediaParams {\n    fn extend<T>(&mut self, iter: T)\n        where T: IntoIterator<Item = (IndexedStr<'static>, IndexedStr<'static>)>\n    {\n        match self {\n            MediaParams::Static(..) => panic!(\"can't add to static collection!\"),\n            MediaParams::Dynamic(ref mut v) => v.extend(iter)\n        }\n    }\n}\n\nimpl Source {\n    #[inline]\n    fn as_str(&self) -> Option<&str> {\n        match *self {\n            Source::Known(s) => Some(s),\n            Source::Custom(ref s) => Some(s.borrow()),\n            Source::None => None\n        }\n    }\n}\n"
  },
  {
    "path": "core/http/src/header/mod.rs",
    "content": "#[macro_use]\nmod known_media_types;\nmod media_type;\nmod content_type;\nmod accept;\nmod header;\nmod proxy_proto;\n\npub use self::content_type::ContentType;\npub use self::accept::{Accept, QMediaType};\npub use self::media_type::MediaType;\npub use self::header::{Header, HeaderMap};\npub use self::proxy_proto::ProxyProto;\n\npub(crate) use self::media_type::Source;\n"
  },
  {
    "path": "core/http/src/header/proxy_proto.rs",
    "content": "use std::fmt;\n\nuse uncased::{UncasedStr, AsUncased};\n\n/// Parsed [`Config::proxy_proto_header`] value: identifies a forwarded HTTP\n/// protocol (aka [X-Forwarded-Proto]).\n///\n/// The value of the header with name [`Config::proxy_proto_header`] is parsed\n/// case-insensitively into this `enum`. For a given request, the parsed value,\n/// if the header was present, can be retrieved via [`Request::proxy_proto()`]\n/// or directly as a [request guard]. That value is used to determine whether a\n/// request's context is likely secure ([`Request::context_is_likely_secure()`])\n/// which in-turn is used to determine whether the `Secure` cookie flag is set\n/// by default when [cookies are added] to a `CookieJar`.\n///\n/// [X-Forwarded-Proto]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto\n/// [`Config::proxy_proto_header`]: ../../rocket/struct.Config.html#structfield.proxy_proto_header\n/// [`Request::proxy_proto()`]: ../../rocket/request/struct.Request.html#method.proxy_proto\n/// [`Request::context_is_likely_secure()`]: ../../rocket/request/struct.Request.html#method.context_is_likely_secure\n/// [cookies are added]: ../..//rocket/http/struct.CookieJar.html#method.add\n/// [request guard]: ../../rocket/request/trait.FromRequest.html#provided-implementations\n#[derive(Clone, Debug, Eq, PartialEq)]\npub enum ProxyProto<'a> {\n    /// `\"http\"`: Hypertext Transfer Protocol.\n    Http,\n    /// `\"https\"`: Hypertext Transfer Protocol Secure.\n    Https,\n    /// Any protocol name other than `\"http\"` or `\"https\"`.\n    Unknown(&'a UncasedStr),\n}\n\nimpl ProxyProto<'_> {\n    /// Returns `true` if `self` is `ProxyProto::Https` and `false` otherwise.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::ProxyProto;\n    ///\n    /// assert!(ProxyProto::Https.is_https());\n    /// assert!(!ProxyProto::Http.is_https());\n    /// ```\n    pub fn is_https(&self) -> bool {\n        self == &ProxyProto::Https\n    }\n}\n\nimpl<'a> From<&'a str> for ProxyProto<'a> {\n    fn from(value: &'a str) -> ProxyProto<'a> {\n        match value.as_uncased() {\n            v if v == \"http\" => ProxyProto::Http,\n            v if v == \"https\" => ProxyProto::Https,\n            v => ProxyProto::Unknown(v)\n        }\n    }\n}\n\nimpl fmt::Display for ProxyProto<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(match *self {\n            ProxyProto::Http => \"http\",\n            ProxyProto::Https => \"https\",\n            ProxyProto::Unknown(s) => s.as_str(),\n        })\n    }\n}\n"
  },
  {
    "path": "core/http/src/lib.rs",
    "content": "#![warn(rust_2018_idioms)]\n#![warn(missing_docs)]\n\n//! Types that map to concepts in HTTP.\n//!\n//! This module exports types that map to HTTP concepts or to the underlying\n//! HTTP library when needed.\n\n#[macro_use]\nextern crate pear;\n\npub mod uri;\npub mod ext;\n\n#[macro_use]\nmod header;\nmod method;\nmod status;\nmod raw_str;\nmod parse;\n\n/// Case-preserving, ASCII case-insensitive string types.\n///\n/// An _uncased_ string is case-preserving. That is, the string itself contains\n/// cased characters, but comparison (including ordering, equality, and hashing)\n/// is ASCII case-insensitive. **Note:** the `alloc` feature _is_ enabled.\npub mod uncased {\n    #[doc(inline)] pub use uncased::*;\n}\n\n// Types that we expose for use _only_ by core. Please don't use this.\n#[doc(hidden)]\n#[path = \".\"]\npub mod private {\n    pub use crate::parse::Indexed;\n}\n\npub use crate::method::Method;\npub use crate::status::{Status, StatusClass};\npub use crate::raw_str::{RawStr, RawStrBuf};\npub use crate::header::*;\n\n/// HTTP Protocol version\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n#[non_exhaustive]\npub enum HttpVersion {\n    /// `HTTP/0.9`\n    Http09,\n    /// `HTTP/1.0`\n    Http10,\n    /// `HTTP/1.1`\n    Http11,\n    /// `HTTP/2`\n    Http2,\n    /// `HTTP/3`\n    Http3,\n}\n"
  },
  {
    "path": "core/http/src/method.rs",
    "content": "use std::fmt;\nuse std::str::FromStr;\n\nself::define_methods! {\n    // enum variant   method name         body   safe idempotent [RFC,section]\n    Get               \"GET\"               maybe  yes  yes        [9110,9.3.1]\n    Head              \"HEAD\"              maybe  yes  yes        [9110,9.3.2]\n    Post              \"POST\"              yes    no   no         [9110,9.3.3]\n    Put               \"PUT\"               yes    no   yes        [9110,9.3.4]\n    Delete            \"DELETE\"            maybe  no   yes        [9110,9.3.5]\n    Connect           \"CONNECT\"           maybe  no   no         [9110,9.3.6]\n    Options           \"OPTIONS\"           maybe  yes  yes        [9110,9.3.7]\n    Trace             \"TRACE\"             no     yes  yes        [9110,9.3.8]\n    Patch             \"PATCH\"             yes    no   no         [5789,2]\n\n    Acl               \"ACL\"               yes    no   yes        [3744,8.1]\n    BaselineControl   \"BASELINE-CONTROL\"  yes    no   yes        [3253,12.6]\n    Bind              \"BIND\"              yes    no   yes        [5842,4]\n    CheckIn           \"CHECKIN\"           yes    no   yes        [3253,4.4]\n    CheckOut          \"CHECKOUT\"          maybe  no   yes        [3253,4.3]\n    Copy              \"COPY\"              maybe  no   yes        [4918,9.8]\n    Label             \"LABEL\"             yes    no   yes        [3253,8.2]\n    Link              \"LINK\"              maybe  no   yes        [2068,19.6.1.2]\n    Lock              \"LOCK\"              yes    no   no         [4918,9.10]\n    Merge             \"MERGE\"             yes    no   yes        [3253,11.2]\n    MkActivity        \"MKACTIVITY\"        yes    no   yes        [3253,13.5]\n    MkCalendar        \"MKCALENDAR\"        yes    no   yes        [4791,5.3.1][8144,2.3]\n    MkCol             \"MKCOL\"             yes    no   yes        [4918,9.3][5689,3][8144,2.3]\n    MkRedirectRef     \"MKREDIRECTREF\"     yes    no   yes        [4437,6]\n    MkWorkspace       \"MKWORKSPACE\"       yes    no   yes        [3253,6.3]\n    Move              \"MOVE\"              maybe  no   yes        [4918,9.9]\n    OrderPatch        \"ORDERPATCH\"        yes    no   yes        [3648,7]\n    PropFind          \"PROPFIND\"          yes    yes  yes        [4918,9.1][8144,2.1]\n    PropPatch         \"PROPPATCH\"         yes    no   yes        [4918,9.2][8144,2.2]\n    Rebind            \"REBIND\"            yes    no   yes        [5842,6]\n    Report            \"REPORT\"            yes    yes  yes        [3253,3.6][8144,2.1]\n    Search            \"SEARCH\"            yes    yes  yes        [5323,2]\n    Unbind            \"UNBIND\"            yes    no   yes        [5842,5]\n    Uncheckout        \"UNCHECKOUT\"        maybe  no   yes        [3253,4.5]\n    Unlink            \"UNLINK\"            maybe  no   yes        [2068,19.6.1.3]\n    Unlock            \"UNLOCK\"            maybe  no   yes        [4918,9.11]\n    Update            \"UPDATE\"            yes    no   yes        [3253,7.1]\n    UpdateRedirectRef \"UPDATEREDIRECTREF\" yes    no   yes        [4437,7]\n    VersionControl    \"VERSION-CONTROL\"   yes    no   yes        [3253,3.5]\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! define_methods {\n    ($($V:ident $name:tt $body:ident $safe:ident $idem:ident $([$n:expr,$s:expr])+)*) => {\n        /// An HTTP method.\n        ///\n        /// Each variant corresponds to a method in the [HTTP Method Registry].\n        /// The string form of the method can be obtained via\n        /// [`Method::as_str()`] and parsed via the `FromStr` or\n        /// `TryFrom<&[u8]>` implementations. The parse implementations parse\n        /// both the case-sensitive string form as well as a lowercase version\n        /// of the string, but _not_ mixed-case versions.\n        ///\n        /// [HTTP Method Registry]: https://www.iana.org/assignments/http-methods/http-methods.xhtml\n        ///\n        /// # (De)Serialization\n        ///\n        /// `Method` is both `Serialize` and `Deserialize`.\n        ///\n        ///   - `Method` _serializes_ as the specification-defined string form\n        ///   of the method, equivalent to the value returned from\n        ///   [`Method::as_str()`].\n        ///   - `Method` _deserializes_ from method's string form _or_ from a\n        ///   lowercased string, equivalent to the `FromStr` implementation.\n        ///\n        /// For example, [`Method::Get`] serializes to `\"GET\"` and deserializes\n        /// from either `\"GET\"` or `\"get\"` but not `\"GeT\"`.\n        ///\n        /// ```rust\n        /// # #[cfg(feature = \"serde\")] mod serde_impl {\n        /// use rocket::http::Method;\n        /// use rocket::serde::{Serialize, Deserialize};\n        ///\n        /// #[derive(Deserialize, Serialize)]\n        /// #[serde(crate = \"rocket::serde\")]\n        /// struct Foo {\n        ///     method: Method,\n        /// }\n        /// # }\n        /// ```\n        #[non_exhaustive]\n        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n        pub enum Method {$(\n            #[doc = concat!(\"The `\", $name, \"` method.\")]\n            #[doc = concat!(\"Defined in\" $(,\n                \" [RFC\", stringify!($n), \" §\", stringify!($s), \"]\",\n                \"(https://www.rfc-editor.org/rfc/rfc\", stringify!($n), \".html\",\n                \"#section-\", stringify!($s), \")\",\n            )\",\"+ \".\")]\n            ///\n            #[doc = concat!(\"* safe: `\", stringify!($safe), \"`\")]\n            #[doc = concat!(\"* idempotent: `\", stringify!($idem), \"`\")]\n            #[doc = concat!(\"* request body: `\", stringify!($body), \"`\")]\n            $V\n        ),*}\n\n        macro_rules! lowercase {\n            ($str:literal) => {{\n                const BYTES: [u8; $str.len()] = {\n                    let mut i = 0;\n                    let _: &str = $str;\n                    let mut result = [0; $str.len()];\n                    while i < $str.len() {\n                        result[i] = $str.as_bytes()[i].to_ascii_lowercase();\n                        i += 1;\n                    }\n\n                    result\n                };\n\n                unsafe { std::str::from_utf8_unchecked(&BYTES) }\n            }};\n        }\n\n        #[allow(non_upper_case_globals)]\n        impl Method {\n            /// A slice containing every defined method string.\n            #[doc(hidden)]\n            pub const ALL: &'static [&'static str] = &[$($name),*];\n\n            /// A slice containing every defined method variant.\n            #[doc(hidden)]\n            pub const ALL_VARIANTS: &'static [Method] = &[$(Self::$V),*];\n\n            /// Whether the method is considered \"safe\".\n            ///\n            /// From [RFC9110 §9.2.1](https://www.rfc-editor.org/rfc/rfc9110#section-9.2.1):\n            ///\n            /// > Request methods are considered \"safe\" if their defined\n            /// semantics are essentially read-only; i.e., the client does not\n            /// request, and does not expect, any state change on the origin server\n            /// as a result of applying a safe method to a target resource.\n            /// Likewise, reasonable use of a safe method is not expected to cause\n            /// any harm, loss of property, or unusual burden on the origin server.\n            /// Of the request methods defined by this specification, the GET,\n            /// HEAD, OPTIONS, and TRACE methods are defined to be safe.\n            ///\n            /// # Example\n            ///\n            /// ```rust\n            /// use rocket::http::Method;\n            ///\n            /// assert!(Method::Get.is_safe());\n            /// assert!(Method::Head.is_safe());\n            ///\n            /// assert!(!Method::Put.is_safe());\n            /// assert!(!Method::Post.is_safe());\n            /// ```\n            pub const fn is_safe(&self) -> bool {\n                const yes: bool = true;\n                const no: bool = false;\n\n                match self {\n                    $(Self::$V => $safe),*\n                }\n            }\n\n            /// Whether the method is considered \"idempotent\".\n            ///\n            /// From [RFC9110 §9.2.2](https://www.rfc-editor.org/rfc/rfc9110#section-9.2.2):\n            ///\n            /// > A request method is considered \"idempotent\" if the intended\n            /// effect on the server of multiple identical requests with that method\n            /// is the same as the effect for a single such request. Of the request\n            /// methods defined by this specification, PUT, DELETE, and safe request\n            /// methods are idempotent.\n            ///\n            /// # Example\n            ///\n            /// ```rust\n            /// use rocket::http::Method;\n            ///\n            /// assert!(Method::Get.is_idempotent());\n            /// assert!(Method::Head.is_idempotent());\n            /// assert!(Method::Put.is_idempotent());\n            ///\n            /// assert!(!Method::Post.is_idempotent());\n            /// assert!(!Method::Patch.is_idempotent());\n            /// ```\n            pub const fn is_idempotent(&self) -> bool {\n                const yes: bool = true;\n                const no: bool = false;\n\n                match self {\n                    $(Self::$V => $idem),*\n                }\n            }\n\n            /// Whether requests with this method are allowed to have a body.\n            ///\n            /// Returns:\n            ///   * `Some(true)` if a request body is _always_ allowed.\n            ///   * `Some(false)` if a request body is **never** allowed.\n            ///   * `None` if a request body is discouraged or has no defined semantics.\n            ///\n            /// # Example\n            ///\n            /// ```rust\n            /// use rocket::http::Method;\n            ///\n            /// assert_eq!(Method::Post.allows_request_body(), Some(true));\n            /// assert_eq!(Method::Put.allows_request_body(), Some(true));\n            ///\n            /// assert_eq!(Method::Trace.allows_request_body(), Some(false));\n            ///\n            /// assert_eq!(Method::Get.allows_request_body(), None);\n            /// assert_eq!(Method::Head.allows_request_body(), None);\n            /// ```\n            pub const fn allows_request_body(self) -> Option<bool> {\n                const yes: Option<bool> = Some(true);\n                const no: Option<bool> = Some(false);\n                const maybe: Option<bool> = None;\n\n                match self {\n                    $(Self::$V => $body),*\n                }\n            }\n\n            /// Returns the method's string representation.\n            ///\n            /// # Example\n            ///\n            /// ```rust\n            /// use rocket::http::Method;\n            ///\n            /// assert_eq!(Method::Get.as_str(), \"GET\");\n            /// assert_eq!(Method::Put.as_str(), \"PUT\");\n            /// assert_eq!(Method::BaselineControl.as_str(), \"BASELINE-CONTROL\");\n            /// ```\n            pub const fn as_str(self) -> &'static str {\n                match self {\n                    $(Self::$V => $name),*\n                }\n            }\n\n            /// Returns a static reference to the method.\n            ///\n            /// # Example\n            ///\n            /// ```rust\n            /// use rocket::http::Method;\n            ///\n            /// assert_eq!(Method::Get.as_ref(), &Method::Get);\n            /// ```\n            pub const fn as_ref(self) -> &'static Method {\n                match self {\n                    $(Self::$V => &Self::$V),*\n                }\n            }\n\n            #[doc(hidden)]\n            pub const fn variant_str(self) -> &'static str {\n                match self {\n                    $(Self::$V => stringify!($V)),*\n                }\n            }\n        }\n\n        #[cfg(test)]\n        mod tests {\n            use super::*;\n\n            #[test]\n            #[allow(non_upper_case_globals)]\n            fn test_properties_and_parsing() {\n                const yes: bool = true;\n                const no: bool = false;\n\n                $(\n                    assert_eq!(Method::$V.is_idempotent(), $idem);\n                    assert_eq!(Method::$V.is_safe(), $safe);\n                    assert_eq!(Method::from_str($name).unwrap(), Method::$V);\n                    assert_eq!(Method::from_str(lowercase!($name)).unwrap(), Method::$V);\n                    assert_eq!(Method::$V.as_ref(), Method::$V);\n                )*\n            }\n        }\n\n        impl TryFrom<&[u8]> for Method {\n            type Error = ParseMethodError;\n\n            #[inline]\n            #[allow(non_upper_case_globals)]\n            fn try_from(value: &[u8]) -> Result<Self, Self::Error> {\n                mod upper { $(pub const $V: &[u8] = $name.as_bytes();)* }\n                mod lower { $(pub const $V: &[u8] = lowercase!($name).as_bytes();)* }\n\n                match value {\n                    $(upper::$V | lower::$V => Ok(Self::$V),)*\n                    _ => Err(ParseMethodError)\n                }\n            }\n        }\n    };\n}\n\nimpl Method {\n    /// Deprecated. Returns `self.allows_request_body() == Some(true)`.\n    ///\n    /// Use [`Method::allows_request_body()`] instead.\n    #[deprecated(since = \"0.6.0\", note = \"use Self::allows_request_body()\")]\n    pub const fn supports_payload(self) -> bool {\n        match self.allows_request_body() {\n            Some(v) => v,\n            None => false,\n        }\n    }\n}\n\nuse define_methods as define_methods;\n\n#[derive(Debug, PartialEq, Eq)]\npub struct ParseMethodError;\n\nimpl std::error::Error for ParseMethodError { }\n\nimpl From<std::convert::Infallible> for ParseMethodError {\n    fn from(infallible: std::convert::Infallible) -> Self {\n        match infallible {}\n    }\n}\n\nimpl fmt::Display for ParseMethodError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(\"invalid HTTP method\")\n    }\n}\n\nimpl FromStr for Method {\n    type Err = ParseMethodError;\n\n    #[inline(always)]\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        Self::try_from(s.as_bytes())\n    }\n}\n\nimpl TryFrom<&str> for Method {\n    type Error = ParseMethodError;\n\n    fn try_from(s: &str) -> Result<Self, Self::Error> {\n        Self::try_from(s.as_bytes())\n    }\n}\n\nimpl AsRef<str> for Method {\n    fn as_ref(&self) -> &str {\n        self.as_str()\n    }\n}\n\nimpl fmt::Display for Method {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.as_str().fmt(f)\n    }\n}\n\nimpl PartialEq<&Method> for Method {\n    fn eq(&self, other: &&Method) -> bool {\n        self == *other\n    }\n}\n\nimpl PartialEq<Method> for &Method {\n    fn eq(&self, other: &Method) -> bool {\n        *self == other\n    }\n}\n\n#[cfg(feature = \"serde\")]\nmod serde_impl {\n    use super::*;\n\n    use serde::ser::{Serialize, Serializer};\n    use serde::de::{Deserialize, Deserializer, Error, Visitor, Unexpected};\n\n    impl Serialize for Method {\n        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {\n            serializer.serialize_str(self.as_str())\n        }\n    }\n\n    struct DeVisitor;\n\n    impl<'de> Visitor<'de> for DeVisitor {\n        type Value = Method;\n\n        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n            write!(formatter, \"valid HTTP method string\")\n        }\n\n        fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {\n            Method::from_str(v).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))\n        }\n    }\n\n    impl<'de> Deserialize<'de> for Method {\n        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {\n            deserializer.deserialize_str(DeVisitor)\n        }\n    }\n}\n"
  },
  {
    "path": "core/http/src/parse/accept.rs",
    "content": "use pear::macros::{parser, parse_error};\nuse pear::combinators::{series, surrounded};\n\nuse crate::{Accept, QMediaType};\nuse crate::parse::checkers::is_whitespace;\nuse crate::parse::media_type::media_type;\n\ntype Input<'a> = pear::input::Pear<pear::input::Cursor<&'a str>>;\ntype Result<'a, T> = pear::input::Result<T, Input<'a>>;\n\n#[parser]\nfn weighted_media_type<'a>(input: &mut Input<'a>) -> Result<'a, QMediaType> {\n    let media_type = media_type()?;\n    let q = match media_type.params().next() {\n        Some((name, value)) if name  == \"q\" => Some(value),\n        _ => None\n    };\n\n    let weight = match q {\n        Some(value) if value.len() <= 5 => match value.parse::<f32>().ok() {\n            Some(q) if q > 1. => parse_error!(\"q value must be <= 1\")?,\n            Some(q) if q < 0. => parse_error!(\"q value must be > 0\")?,\n            Some(q) => Some(q),\n            None => parse_error!(\"invalid media-type weight\")?\n        },\n        _ => None\n    };\n\n    QMediaType(media_type, weight)\n}\n\n#[parser]\nfn accept<'a>(input: &mut Input<'a>) -> Result<'a, Accept> {\n    let vec = series(|i| surrounded(i, weighted_media_type, is_whitespace), ',')?;\n    Accept(std::borrow::Cow::Owned(vec))\n}\n\npub fn parse_accept(input: &str) -> Result<'_, Accept> {\n    parse!(accept: Input::new(input))\n}\n\n#[cfg(test)]\nmod test {\n    use crate::MediaType;\n    use super::parse_accept;\n\n    macro_rules! assert_parse {\n        ($string:expr) => ({\n            match parse_accept($string) {\n                Ok(accept) => accept,\n                Err(e) => panic!(\"{:?} failed to parse: {}\", $string, e)\n            }\n        });\n    }\n\n    macro_rules! assert_parse_eq {\n        ($string:expr, [$($mt:expr),*]) => ({\n            let expected = vec![$($mt),*];\n            let result = assert_parse!($string);\n            for (i, wmt) in result.iter().enumerate() {\n                assert_eq!(wmt.media_type(), &expected[i]);\n            }\n        });\n    }\n\n    #[test]\n    fn check_does_parse() {\n        assert_parse!(\"text/html\");\n        assert_parse!(\"*/*, a/b; q=1.0; v=1, application/something, a/b\");\n        assert_parse!(\"a/b, b/c\");\n        assert_parse!(\"text/*\");\n        assert_parse!(\"text/*; q=1\");\n        assert_parse!(\"text/*; q=1; level=2\");\n        assert_parse!(\"audio/*; q=0.2, audio/basic\");\n        assert_parse!(\"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c\");\n        assert_parse!(\"text/*, text/html, text/html;level=1, */*\");\n        assert_parse!(\"text/*;q=0.3, text/html;q=0.7, text/html;level=1, \\\n               text/html;level=2;q=0.4, */*;q=0.5\");\n    }\n\n    #[test]\n    fn check_parse_eq() {\n        assert_parse_eq!(\"text/html\", [MediaType::HTML]);\n        assert_parse_eq!(\"text/html, application/json\",\n                         [MediaType::HTML, MediaType::JSON]);\n        assert_parse_eq!(\"text/html; charset=utf-8; v=1, application/json\",\n                         [MediaType::HTML, MediaType::JSON]);\n        assert_parse_eq!(\"text/html, text/html; q=0.1, text/html; q=0.2\",\n                         [MediaType::HTML, MediaType::HTML, MediaType::HTML]);\n    }\n}\n"
  },
  {
    "path": "core/http/src/parse/checkers.rs",
    "content": "#[inline(always)]\npub fn is_whitespace(&byte: &char) -> bool {\n    byte == ' ' || byte == '\\t'\n}\n\n#[inline]\npub fn is_valid_token(&c: &char) -> bool {\n     matches!(c, '0'..='9' | 'A'..='Z' | '^'..='~' | '#'..='\\''\n            | '!' | '*' | '+' | '-' | '.')\n    }\n"
  },
  {
    "path": "core/http/src/parse/indexed.rs",
    "content": "#![allow(dead_code)]\n\nuse std::borrow::Cow;\nuse std::ops::{Index, Range};\nuse std::fmt::{self, Debug};\n\nuse pear::input::Length;\n\nuse crate::ext::IntoOwned;\n\npub use pear::input::Extent;\n\npub type IndexedStr<'a> = Indexed<'a, str>;\npub type IndexedBytes<'a> = Indexed<'a, [u8]>;\n\npub trait AsPtr {\n    fn as_ptr(&self) -> *const u8;\n}\n\nimpl AsPtr for str {\n    #[inline(always)]\n    fn as_ptr(&self) -> *const u8 {\n        str::as_ptr(self)\n    }\n}\n\nimpl AsPtr for [u8] {\n    #[inline(always)]\n    fn as_ptr(&self) -> *const u8 {\n        <[u8]>::as_ptr(self)\n    }\n}\n\n/// Either a concrete string or indices to the start and end of a string.\n#[derive(PartialEq)]\npub enum Indexed<'a, T: ?Sized + ToOwned> {\n    /// The start and end index of a string.\n    Indexed(usize, usize),\n    /// A concrete string.\n    Concrete(Cow<'a, T>)\n}\n\nimpl<A, T: ?Sized + ToOwned> From<Extent<A>> for Indexed<'_, T> {\n    fn from(e: Extent<A>) -> Self {\n        Indexed::Indexed(e.start, e.end)\n    }\n}\n\nimpl<'a, T: ?Sized + ToOwned + 'a> From<Cow<'a, T>> for Indexed<'a, T> {\n    #[inline(always)]\n    fn from(value: Cow<'a, T>) -> Indexed<'a, T> {\n        Indexed::Concrete(value)\n    }\n}\n\nimpl<'a, T: ?Sized + ToOwned + 'a> Indexed<'a, T> {\n    /// Panics if `self` is not an `Indexed`.\n    #[inline(always)]\n    pub fn indices(self) -> (usize, usize) {\n        match self {\n            Indexed::Indexed(a, b) => (a, b),\n            _ => panic!(\"cannot convert indexed T to U unless indexed\")\n        }\n    }\n\n    /// Panics if `self` is not an `Indexed`.\n    #[inline(always)]\n    pub fn coerce<U: ?Sized + ToOwned>(self) -> Indexed<'a, U> {\n        match self {\n            Indexed::Indexed(a, b) => Indexed::Indexed(a, b),\n            _ => panic!(\"cannot convert indexed T to U unless indexed\")\n        }\n    }\n\n    /// Panics if `self` is not an `Indexed`.\n    #[inline(always)]\n    pub fn coerce_lifetime<'b>(self) -> Indexed<'b, T> {\n        match self {\n            Indexed::Indexed(a, b) => Indexed::Indexed(a, b),\n            _ => panic!(\"cannot coerce lifetime unless indexed\")\n        }\n    }\n}\n\nimpl<T: 'static + ?Sized + ToOwned> IntoOwned for Indexed<'_, T> {\n    type Owned = Indexed<'static, T>;\n\n    fn into_owned(self) -> Indexed<'static, T> {\n        match self {\n            Indexed::Indexed(a, b) => Indexed::Indexed(a, b),\n            Indexed::Concrete(cow) => Indexed::Concrete(IntoOwned::into_owned(cow))\n        }\n    }\n}\n\nuse std::ops::Add;\n\nimpl<'a, T: ?Sized + ToOwned + 'a> Add for Indexed<'a, T> {\n    type Output = Indexed<'a, T>;\n\n    #[inline]\n    fn add(self, other: Indexed<'a, T>) -> Indexed<'a, T> {\n        match self {\n            Indexed::Indexed(a, b) => match other {\n                Indexed::Indexed(c, d) if b == c && a < d => Indexed::Indexed(a, d),\n                _ => panic!(\"+ requires indexed\")\n            }\n            _ => panic!(\"+ requires indexed\")\n        }\n    }\n}\n\nimpl<'a, T: ?Sized + ToOwned + 'a> Indexed<'a, T>\n    where T: Length + AsPtr + Index<Range<usize>, Output = T>\n{\n    /// Returns `None` if `needle` is not a substring of `haystack`. Otherwise\n    /// returns an `Indexed` with the indices of `needle` in `haystack`.\n    pub fn checked_from(needle: &T, haystack: &T) -> Option<Indexed<'a, T>> {\n        let needle_start = needle.as_ptr() as usize;\n        let haystack_start = haystack.as_ptr() as usize;\n        if needle_start < haystack_start {\n            return None;\n        }\n\n        let needle_end = needle_start + needle.len();\n        let haystack_end = haystack_start + haystack.len();\n        if needle_end > haystack_end {\n            return None;\n        }\n\n        let start = needle_start - haystack_start;\n        let end = start + needle.len();\n        Some(Indexed::Indexed(start, end))\n    }\n\n    /// Like `checked_from` but without checking if `needle` is indeed a\n    /// substring of `haystack`.\n    ///\n    /// # Safety\n    ///\n    /// The caller must ensure that `needle` is indeed a substring of\n    /// `haystack`.\n    pub unsafe fn unchecked_from(needle: &T, haystack: &T) -> Indexed<'a, T> {\n        let haystack_start = haystack.as_ptr() as usize;\n        let needle_start = needle.as_ptr() as usize;\n\n        let start = needle_start - haystack_start;\n        let end = start + needle.len();\n        Indexed::Indexed(start, end)\n    }\n\n    /// Whether this string is derived from indexes or not.\n    #[inline]\n    pub fn is_indexed(&self) -> bool {\n        match *self {\n            Indexed::Indexed(..) => true,\n            Indexed::Concrete(..) => false,\n        }\n    }\n\n    /// Whether this string is empty.\n    #[inline]\n    pub fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    /// Make `self` concrete by allocating if indexed.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `self` is an indexed string and `source` is None.\n    pub fn into_concrete(self, source: &Option<Cow<'_, T>>) -> Cow<'a, T> {\n        if self.is_indexed() && source.is_none() {\n            panic!(\"cannot concretize indexed str to str without base string!\")\n        }\n\n        match self {\n            Indexed::Indexed(i, j) => Cow::Owned(source.as_ref().unwrap()[i..j].to_owned()),\n            Indexed::Concrete(string) => string,\n        }\n    }\n\n    /// Retrieves the string `self` corresponds to. If `self` is derived from\n    /// indexes, the corresponding subslice of `source` is returned. Otherwise,\n    /// the concrete string is returned.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `self` is an indexed string and `source` is None.\n    pub fn from_cow_source<'s>(&'s self, source: &'s Option<Cow<'_, T>>) -> &'s T {\n        if self.is_indexed() && source.is_none() {\n            panic!(\"cannot convert indexed str to str without base string!\")\n        }\n\n        match *self {\n            Indexed::Indexed(i, j) => &source.as_ref().unwrap()[i..j],\n            Indexed::Concrete(ref mstr) => mstr.as_ref(),\n        }\n    }\n\n    /// Retrieves the string `self` corresponds to. If `self` is derived from\n    /// indexes, the corresponding subslice of `string` is returned. Otherwise,\n    /// the concrete string is returned.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `self` is an indexed string and `string` is None.\n    pub fn from_source<'s>(&'s self, source: Option<&'s T>) -> &'s T {\n        if self.is_indexed() && source.is_none() {\n            panic!(\"Cannot convert indexed str to str without base string!\")\n        }\n\n        match *self {\n            Indexed::Indexed(i, j) => &source.unwrap()[i..j],\n            Indexed::Concrete(ref mstr) => mstr,\n        }\n    }\n}\n\nimpl<'a, T: ToOwned + ?Sized + 'a> Clone for Indexed<'a, T> {\n    fn clone(&self) -> Self {\n        match *self {\n            Indexed::Indexed(a, b) => Indexed::Indexed(a, b),\n            Indexed::Concrete(ref cow) => Indexed::Concrete(cow.clone())\n        }\n    }\n}\n\nimpl<'a, T: ?Sized + 'a> Debug for Indexed<'a, T>\n    where T: ToOwned + Debug, T::Owned: Debug\n{\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            Indexed::Indexed(a, b) => fmt::Debug::fmt(&(a, b), f),\n            Indexed::Concrete(ref cow) => fmt::Debug::fmt(cow, f),\n        }\n    }\n}\n\nimpl<'a, T: ?Sized + Length + ToOwned + 'a> Length for Indexed<'a, T> {\n    #[inline(always)]\n    fn len(&self) -> usize {\n        match *self {\n            Indexed::Indexed(a, b) => b.saturating_sub(a),\n            Indexed::Concrete(ref cow) => cow.len()\n        }\n    }\n}\n"
  },
  {
    "path": "core/http/src/parse/media_type.rs",
    "content": "use std::borrow::Cow;\n\nuse pear::input::Extent;\nuse pear::combinators::{prefixed_series, surrounded};\nuse pear::macros::{parser, switch, parse};\nuse pear::parsers::*;\n\nuse crate::header::{MediaType, Source};\nuse crate::parse::checkers::{is_whitespace, is_valid_token};\n\ntype Input<'a> = pear::input::Pear<pear::input::Cursor<&'a str>>;\ntype Result<'a, T> = pear::input::Result<T, Input<'a>>;\n\n#[parser]\nfn quoted_string<'a>(input: &mut Input<'a>) -> Result<'a, Extent<&'a str>> {\n    eat('\"')?;\n\n    let mut is_escaped = false;\n    let inner = take_while(|&c| {\n        if is_escaped { is_escaped = false; return true; }\n        if c == '\\\\' { is_escaped = true; return true; }\n        c != '\"'\n    })?;\n\n    eat('\"')?;\n    inner\n}\n\n#[parser]\nfn media_param<'a>(input: &mut Input<'a>) -> Result<'a, (Extent<&'a str>, Extent<&'a str>)> {\n    let key = (take_some_while_until(is_valid_token, '=')?, eat('=')?).0;\n    let value = switch! {\n        peek('\"') => quoted_string()?,\n        _ => take_some_while_until(is_valid_token, ';')?\n    };\n\n    (key, value)\n}\n\n#[parser]\npub fn media_type<'a>(input: &mut Input<'a>) -> Result<'a, MediaType> {\n    let (top, sub, params) = {\n        let top = (take_some_while_until(is_valid_token, '/')?, eat('/')?).0;\n        let sub = take_some_while_until(is_valid_token, ';')?;\n        let params = prefixed_series(';', |i| {\n            let param = surrounded(i, media_param, is_whitespace)?;\n            Ok((param.0.into(), param.1.into()))\n        }, ';')?;\n\n        (top, sub, params)\n    };\n\n    MediaType {\n        params,\n        source: Source::Custom(Cow::Owned(input.start.to_string())),\n        top: top.into(),\n        sub: sub.into(),\n    }\n}\n\npub fn parse_media_type(input: &str) -> Result<'_, MediaType> {\n    parse!(media_type: Input::new(input))\n}\n\n#[cfg(test)]\nmod test {\n    use crate::MediaType;\n    use super::parse_media_type;\n\n    macro_rules! assert_no_parse {\n        ($string:expr) => ({\n            let result: Result<_, _> = parse_media_type($string).into();\n            if result.is_ok() {\n                panic!(\"{:?} parsed unexpectedly.\", $string)\n            }\n        });\n    }\n\n    macro_rules! assert_parse {\n        ($string:expr) => ({\n            match parse_media_type($string) {\n                Ok(media_type) => media_type,\n                Err(e) => panic!(\"{:?} failed to parse: {}\", $string, e)\n            }\n        });\n    }\n\n    macro_rules! assert_parse_eq {\n        (@full $string:expr, $result:expr, $(($k:expr, $v:expr)),*) => ({\n            let result = assert_parse!($string);\n            assert_eq!(result, $result);\n\n            let expected_params: Vec<(&str, &str)> = vec![$(($k, $v)),*];\n            if expected_params.len() > 0 {\n                assert_eq!(result.params().count(), expected_params.len());\n                let all_params = result.params().zip(expected_params.iter());\n                for ((key, val), &(ekey, eval)) in all_params {\n                    assert_eq!(key, ekey);\n                    assert_eq!(val, eval);\n                }\n            }\n        });\n\n        (from: $string:expr, into: $result:expr)\n            => (assert_parse_eq!(@full $string, $result, ));\n        (from: $string:expr, into: $result:expr, params: $(($key:expr, $val:expr)),*)\n            => (assert_parse_eq!(@full $string, $result, $(($key, $val)),*));\n    }\n\n    #[test]\n    fn check_does_parse() {\n        assert_parse!(\"text/html\");\n        assert_parse!(\"a/b\");\n        assert_parse!(\"*/*\");\n    }\n\n    #[test]\n    fn check_parse_eq() {\n        assert_parse_eq!(from: \"text/html\", into: MediaType::HTML);\n        assert_parse_eq!(from: \"text/html; charset=utf-8\", into: MediaType::HTML);\n        assert_parse_eq!(from: \"text/html\", into: MediaType::HTML);\n\n        assert_parse_eq!(from: \"a/b\", into: MediaType::new(\"a\", \"b\"));\n        assert_parse_eq!(from: \"*/*\", into: MediaType::Any);\n        assert_parse_eq!(from: \"application/pdf\", into: MediaType::PDF);\n        assert_parse_eq!(from: \"application/json\", into: MediaType::JSON);\n        assert_parse_eq!(from: \"image/svg+xml\", into: MediaType::SVG);\n\n        assert_parse_eq!(from: \"*/json\", into: MediaType::new(\"*\", \"json\"));\n        assert_parse_eq! {\n            from: \"application/*; param=1\",\n            into: MediaType::new(\"application\", \"*\")\n        };\n    }\n\n    #[test]\n    fn check_param_eq() {\n        assert_parse_eq! {\n            from: \"text/html; a=b; b=c; c=d\",\n            into: MediaType::new(\"text\", \"html\"),\n            params: (\"a\", \"b\"), (\"b\", \"c\"), (\"c\", \"d\")\n        };\n\n        assert_parse_eq! {\n            from: \"text/html;a=b;b=c;     c=d; d=e\",\n            into: MediaType::new(\"text\", \"html\"),\n            params: (\"a\", \"b\"), (\"b\", \"c\"), (\"c\", \"d\"), (\"d\", \"e\")\n        };\n\n        assert_parse_eq! {\n            from: \"text/html; charset=utf-8\",\n            into: MediaType::new(\"text\", \"html\"),\n            params: (\"charset\", \"utf-8\")\n        };\n\n        assert_parse_eq! {\n            from: \"application/*; param=1\",\n            into: MediaType::new(\"application\", \"*\"),\n            params: (\"param\", \"1\")\n        };\n\n        assert_parse_eq! {\n            from: \"*/*;q=0.5;b=c;c=d\",\n            into: MediaType::Any,\n            params: (\"q\", \"0.5\"), (\"b\", \"c\"), (\"c\", \"d\")\n        };\n\n        assert_parse_eq! {\n            from: \"multipart/form-data; boundary=----WebKitFormBoundarypRshfItmvaC3aEuq\",\n            into: MediaType::FormData,\n            params: (\"boundary\", \"----WebKitFormBoundarypRshfItmvaC3aEuq\")\n        };\n\n        assert_parse_eq! {\n            from: r#\"*/*; a=\"hello, world!@#$%^&*();;hi\"\"#,\n            into: MediaType::Any,\n            params: (\"a\", \"hello, world!@#$%^&*();;hi\")\n        };\n\n        assert_parse_eq! {\n            from: r#\"application/json; a=\";,;\"\"#,\n            into: MediaType::JSON,\n            params: (\"a\", \";,;\")\n        };\n\n        assert_parse_eq! {\n            from: r#\"application/json; a=\";,;\"; b=c\"#,\n            into: MediaType::JSON,\n            params: (\"a\", \";,;\"), (\"b\", \"c\")\n        };\n\n        assert_parse_eq! {\n            from: r#\"application/json; b=c; a=\";.,.;\"\"#,\n            into: MediaType::JSON,\n            params: (\"b\", \"c\"), (\"a\", \";.,.;\")\n        };\n\n        assert_parse_eq! {\n            from: r#\"*/*; a=\"a\"; b=\"b\"; a=a; b=b; c=c\"#,\n            into: MediaType::Any,\n            params: (\"a\", \"a\"), (\"b\", \"b\"), (\"a\", \"a\"), (\"b\", \"b\"), (\"c\", \"c\")\n        };\n    }\n\n    #[test]\n    fn check_params_do_parse() {\n        assert_parse!(\"*/*; q=1; q=2\");\n        assert_parse!(\"*/*; q=1;q=2;q=3;a=v;c=1;da=1;sdlkldsadasd=uhisdcb89\");\n        assert_parse!(\"*/*; q=1; q=2\");\n        assert_parse!(\"*/*; q=1; q=2; a=b;c=d;    e=f; a=s;a=e\");\n        assert_parse!(\"*/*; q=1; q=2 ; a=b\");\n        assert_parse!(\"*/*; q=1; q=2; hello=\\\"world !\\\"\");\n    }\n\n    #[test]\n    fn test_bad_parses() {\n        assert_no_parse!(\"*&_/*)()\");\n        assert_no_parse!(\"/json\");\n        assert_no_parse!(\"text/\");\n        assert_no_parse!(\"text//\");\n        assert_no_parse!(\"/\");\n        assert_no_parse!(\"*/\");\n        assert_no_parse!(\"/*\");\n        assert_no_parse!(\"///\");\n        assert_no_parse!(\"application//json\");\n        assert_no_parse!(\"application///json\");\n        assert_no_parse!(\"a/b;\");\n        assert_no_parse!(\"*/*; a=b;;\");\n        assert_no_parse!(\"*/*; a=b;a\");\n        assert_no_parse!(\"*/*; a=b; \");\n        assert_no_parse!(\"*/*; a=b;\");\n        assert_no_parse!(\"*/*; a = b\");\n        assert_no_parse!(\"*/*; a= b\");\n        assert_no_parse!(\"*/*; a =b\");\n        assert_no_parse!(r#\"*/*; a=\"b\"#);\n        assert_no_parse!(r#\"*/*; a=\"b; c=d\"#);\n        assert_no_parse!(r#\"*/*; a=\"b; c=d\"#);\n        assert_no_parse!(\"*/*;a=@#$%^&*()\");\n        assert_no_parse!(\"*/*;;\");\n        assert_no_parse!(\"*/*;=;\");\n        assert_no_parse!(\"*/*=;\");\n        assert_no_parse!(\"*/*=;=\");\n    }\n}\n"
  },
  {
    "path": "core/http/src/parse/mod.rs",
    "content": "mod media_type;\nmod accept;\nmod checkers;\nmod indexed;\n\npub use self::media_type::*;\npub use self::accept::*;\n\npub mod uri;\n\npub use self::indexed::*;\n"
  },
  {
    "path": "core/http/src/parse/uri/error.rs",
    "content": "use std::{fmt, convert};\nuse std::borrow::Cow;\n\nuse pear::error::Expected;\nuse pear::input::ParseError;\nuse crate::parse::uri::RawInput;\nuse crate::ext::IntoOwned;\n\n/// Error emitted on URI parse failure.\n///\n/// Internally, the type includes information about where the parse error\n/// occurred (the error's context) and information about what went wrong.\n/// Externally, this information can be retrieved (in textual form) through its\n/// `Display` implementation. In other words, by printing a value of this type.\n#[derive(Debug)]\npub struct Error<'a> {\n    pub(crate) expected: Expected<u8, Cow<'a, [u8]>>,\n    pub(crate) index: usize,\n}\n\n#[doc(hidden)]\nimpl<'a> From<ParseError<RawInput<'a>>> for Error<'a> {\n    fn from(inner: ParseError<RawInput<'a>>) -> Self {\n        let expected = inner.error.map(convert::identity, |v| v.values.into());\n        Error { expected, index: inner.info.context.start }\n    }\n}\n\nimpl Error<'_> {\n    /// Returns the byte index into the text where the error occurred if it is\n    /// known.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let err = Origin::parse(\"/foo bar\").unwrap_err();\n    /// assert_eq!(err.index(), 4);\n    /// ```\n    pub fn index(&self) -> usize {\n        self.index\n    }\n}\n\nimpl fmt::Display for Error<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{} at index {}\", self.expected, self.index)\n    }\n}\n\nimpl IntoOwned for Error<'_> {\n    type Owned = Error<'static>;\n\n    fn into_owned(self) -> Error<'static> {\n        Error {\n            expected: self.expected.map(|t| t, |s| s.into_owned().into()),\n            index: self.index\n        }\n    }\n}\n\nimpl std::error::Error for Error<'_> { }\n\n#[cfg(test)]\nmod tests {\n    use crate::parse::uri::origin_from_str;\n\n    macro_rules! check_err {\n        ($url:expr => $error:expr) => {{\n            let e = origin_from_str($url).unwrap_err();\n            assert_eq!(e.to_string(), $error.to_string())\n        }}\n    }\n\n    #[test]\n    fn check_display() {\n        check_err!(\"a\" => \"expected token '/' but found 'a' at index 0\");\n        check_err!(\"?\" => \"expected token '/' but found '?' at index 0\");\n        check_err!(\"这\" => \"expected token '/' but found byte 232 at index 0\");\n    }\n}\n"
  },
  {
    "path": "core/http/src/parse/uri/mod.rs",
    "content": "mod parser;\nmod error;\npub(crate) mod tables;\n\n#[cfg(test)] mod tests;\n\nuse crate::uri::{Uri, Origin, Absolute, Authority, Reference, Asterisk};\n\nuse self::parser::*;\n\npub use self::error::Error;\n\ntype RawInput<'a> = pear::input::Pear<pear::input::Cursor<&'a [u8]>>;\n\n#[inline]\npub fn from_str(s: &str) -> Result<Uri<'_>, Error<'_>> {\n    Ok(parse!(uri: RawInput::new(s.as_bytes()))?)\n}\n\n#[inline]\npub fn origin_from_str(s: &str) -> Result<Origin<'_>, Error<'_>> {\n    Ok(parse!(origin: RawInput::new(s.as_bytes()))?)\n}\n\n#[inline]\npub fn authority_from_str(s: &str) -> Result<Authority<'_>, Error<'_>> {\n    Ok(parse!(authority: RawInput::new(s.as_bytes()))?)\n}\n\n#[inline]\npub fn authority_from_bytes(s: &[u8]) -> Result<Authority<'_>, Error<'_>> {\n    Ok(parse!(authority: RawInput::new(s))?)\n}\n\n#[inline]\npub fn scheme_from_str(s: &str) -> Result<&str, Error<'_>> {\n    let _validated = parse!(scheme: RawInput::new(s.as_bytes()))?;\n    Ok(s)\n}\n\n#[inline]\npub fn absolute_from_str(s: &str) -> Result<Absolute<'_>, Error<'_>> {\n    Ok(parse!(absolute: RawInput::new(s.as_bytes()))?)\n}\n\n#[inline]\npub fn asterisk_from_str(s: &str) -> Result<Asterisk, Error<'_>> {\n    Ok(parse!(asterisk: RawInput::new(s.as_bytes()))?)\n}\n\n#[inline]\npub fn reference_from_str(s: &str) -> Result<Reference<'_>, Error<'_>> {\n    Ok(parse!(reference: RawInput::new(s.as_bytes()))?)\n}\n"
  },
  {
    "path": "core/http/src/parse/uri/parser.rs",
    "content": "use pear::parsers::*;\nuse pear::combinators::*;\nuse pear::input::{self, Pear, Extent, Rewind, Input};\nuse pear::macros::{parser, switch, parse_error, parse_try};\n\nuse crate::uri::{Uri, Origin, Authority, Absolute, Reference, Asterisk};\nuse crate::parse::uri::tables::*;\nuse crate::parse::uri::RawInput;\n\ntype Result<'a, T> = pear::input::Result<T, RawInput<'a>>;\n\n// SAFETY: Every `unsafe` here comes from bytes -> &str conversions. Since all\n// bytes are checked against tables in `tables.rs`, all of which allow only\n// ASCII characters, these are all safe.\n\n// TODO: We should cap the source we pass into `raw` to the bytes we've actually\n// checked. Otherwise, we could have good bytes followed by unchecked bad bytes\n// since eof() may not called. However, note that we only actually expose these\n// parsers via `parse!()`, which _does_ call `eof()`, so we're externally okay.\n\n#[parser(rewind)]\npub fn complete<I, P, O>(input: &mut Pear<I>, p: P) -> input::Result<O, I>\n    where I: Input + Rewind, P: FnOnce(&mut Pear<I>) -> input::Result<O, I>\n{\n    (p()?, eof()?).0\n}\n\n/// TODO: Have a way to ask for for preference in ambiguity resolution.\n///   * An ordered [Preference] is probably best.\n///   * Need to filter/uniqueify. See `uri-pref`.\n/// Once we have this, we should probably set the default so that `authority` is\n/// preferred over `absolute`, otherwise something like `foo:3122` is absolute.\n#[parser]\npub fn uri<'a>(input: &mut RawInput<'a>) -> Result<'a, Uri<'a>> {\n    // To resolve all ambiguities with preference, we might need to look at the\n    // complete string twice: origin/ref, asterisk/ref, authority/absolute.\n    switch! {\n        asterisk@complete(asterisk) => Uri::Asterisk(asterisk),\n        origin@complete(origin) => Uri::Origin(origin),\n        authority@complete(authority) => Uri::Authority(authority),\n        absolute@complete(absolute) => Uri::Absolute(absolute),\n        _ => Uri::Reference(reference()?)\n    }\n}\n\n#[parser]\npub fn asterisk<'a>(input: &mut RawInput<'a>) -> Result<'a, Asterisk> {\n    eat(b'*')?;\n    Asterisk\n}\n\n#[parser]\npub fn origin<'a>(input: &mut RawInput<'a>) -> Result<'a, Origin<'a>> {\n    let (_, path, query) = (peek(b'/')?, path()?, query()?);\n    unsafe { Origin::raw(input.start.into(), path, query) }\n}\n\n#[parser]\npub fn authority<'a>(input: &mut RawInput<'a>) -> Result<'a, Authority<'a>> {\n    let prefix = take_while(is_reg_name_char)?;\n    let (user_info, host, port) = switch! {\n        peek(b'[') if prefix.is_empty() => (None, host()?, port()?),\n        eat(b':') => {\n            let suffix = take_while(is_reg_name_char)?;\n            switch! {\n                peek(b':') => {\n                    let end = (take_while(is_user_info_char)?, eat(b'@')?).0;\n                    (input.span(prefix, end), host()?, port()?)\n                },\n                eat(b'@') => (input.span(prefix, suffix), host()?, port()?),\n                // FIXME: Rewind to just after prefix to get the right context\n                // to be able to call `port()`. Then remove `maybe_port()`.\n                _ => (None, prefix, maybe_port(&suffix)?)\n            }\n        },\n        eat(b'@') => (Some(prefix), host()?, port()?),\n        _ => (None, prefix, None),\n    };\n\n    unsafe { Authority::raw(input.start.into(), user_info, host, port) }\n}\n\n#[parser]\npub fn scheme<'a>(input: &mut RawInput<'a>) -> Result<'a, Extent<&'a [u8]>> {\n    let scheme = take_some_while(is_scheme_char)?;\n    if !scheme.get(0).map_or(false, |b| b.is_ascii_alphabetic()) {\n        parse_error!(\"invalid scheme\")?;\n    }\n\n    scheme\n}\n\n#[parser]\npub fn absolute<'a>(input: &mut RawInput<'a>) -> Result<'a, Absolute<'a>> {\n    let scheme = scheme()?;\n    let (_, (authority, path), query) = (eat(b':')?, hier_part()?, query()?);\n    unsafe { Absolute::raw(input.start.into(), scheme, authority, path, query) }\n}\n\n#[parser]\npub fn reference<'a>(\n    input: &mut RawInput<'a>,\n) -> Result<'a, Reference<'a>> {\n    let prefix = take_while(is_scheme_char)?;\n    let (scheme, authority, path) = switch! {\n        peek(b':') if prefix.is_empty() => parse_error!(\"missing scheme\")?,\n        eat(b':') => {\n            if !prefix.get(0).map_or(false, |b| b.is_ascii_alphabetic()) {\n                parse_error!(\"invalid scheme\")?;\n            }\n\n            let (authority, path) = hier_part()?;\n            (Some(prefix), authority, path)\n        },\n        peek_slice(b\"//\") if prefix.is_empty() => {\n            let (authority, path) = hier_part()?;\n            (None, authority, path)\n        },\n        _ => {\n            let path = path()?;\n            let full_path = input.span(prefix, path).unwrap_or(none()?);\n            (None, None, full_path)\n        },\n    };\n\n    let (source, query, fragment) = (input.start.into(), query()?, fragment()?);\n    unsafe { Reference::raw(source, scheme, authority, path, query, fragment) }\n}\n\n#[parser]\npub fn hier_part<'a>(\n    input: &mut RawInput<'a>\n) -> Result<'a, (Option<Authority<'a>>, Extent<&'a [u8]>)> {\n    switch! {\n        eat_slice(b\"//\") => {\n            let authority = authority()?;\n            let path = parse_try!(peek(b'/') => path()? => || none()?);\n            (Some(authority), path)\n        },\n        _ => (None, path()?)\n    }\n}\n\n#[parser]\nfn host<'a>(\n    input: &mut RawInput<'a>,\n) -> Result<'a, Extent<&'a [u8]>> {\n    switch! {\n        peek(b'[') => enclosed(b'[', is_host_char, b']')?,\n        _ => take_while(is_reg_name_char)?\n    }\n}\n\n#[parser]\nfn port<'a>(\n    input: &mut RawInput<'a>,\n) -> Result<'a, Option<u16>> {\n    if !succeeds(input, |i| eat(i, b':')) {\n        return Ok(None);\n    }\n\n    let bytes = take_n_while(5, |c| c.is_ascii_digit())?;\n    maybe_port(&bytes)?\n}\n\n// FIXME: The context here is wrong since it's empty. We should reset to\n// current - bytes.len(). Or something like that.\n#[parser]\nfn maybe_port<'a>(input: &mut RawInput<'a>, bytes: &[u8]) -> Result<'a, Option<u16>> {\n    if bytes.is_empty() {\n        return Ok(None);\n    } else if bytes.len() > 5 {\n        parse_error!(\"port len is out of range\")?;\n    } else if !bytes.iter().all(|b| b.is_ascii_digit()) {\n        parse_error!(\"invalid port bytes\")?;\n    }\n\n    let mut port_num: u32 = 0;\n    for (b, i) in bytes.iter().rev().zip(&[1, 10, 100, 1000, 10000]) {\n        port_num += (b - b'0') as u32 * i;\n    }\n\n    if port_num > u16::max_value() as u32 {\n        parse_error!(\"port out of range: {}\", port_num)?;\n    }\n\n    Some(port_num as u16)\n}\n\n#[parser]\nfn path<'a>(input: &mut RawInput<'a>) -> Result<'a, Extent<&'a [u8]>> {\n    take_while(is_pchar)?\n}\n\n#[parser]\nfn query<'a>(input: &mut RawInput<'a>) -> Result<'a, Option<Extent<&'a [u8]>>> {\n    parse_try!(eat(b'?') => take_while(is_qchar)?)\n}\n\n#[parser]\nfn fragment<'a>(input: &mut RawInput<'a>) -> Result<'a, Option<Extent<&'a [u8]>>> {\n    parse_try!(eat(b'#') => take_while(is_qchar)?)\n}\n"
  },
  {
    "path": "core/http/src/parse/uri/spec.txt",
    "content": "RFC 7230 Uri-Reference Grammar\n\nURI-reference = URI / relative-ref\n\nURI           = absolute-URI [ \"#\" fragment ]\n\nrelative-ref  = relative-part [ \"?\" query ] [ \"#\" fragment ]\n\n; like hier-part - rootless + noscheme\nrelative-part = \"//\" authority path-abempty\n              / path-absolute\n              / path-noscheme ; like rootless but first seg can't have ':'\n              / path-empty\n\nfragment      = *( pchar / \"/\" / \"?\" ) ;; = query\n\n# unrolled form of `URI-reference` above, for comparison\nURI-reference = scheme \":\" hier-part [ \"?\" query ] [ \"#\" fragment ]\n                         / relative-part [ \"?\" query ] [ \"#\" fragment ]\n\n--------------------------------------------------------------------------------\n\nRFC 7230 Target Grammar\n\nrequest-target = origin-form / absolute-form / authority-form / asterisk-form\n\n-------------------------------------------------------------------------------\n\nasterisk-form = \"*\"\n\n-------------------------------------------------------------------------------\n\norigin-form = absolute-path [ \"?\" query ]\n\nabsolute-path = 1*( \"/\" segment )\n\n-------------------------------------------------------------------------------\n\nauthority-form = authority\n\n-------------------------------------------------------------------------------\n\nabsolute-form = absolute-URI\n\nabsolute-URI  = scheme \":\" hier-part [ \"?\" query ]\n\nscheme        = ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n\nhier-part     = \"//\" authority path-abempty\n             / path-absolute\n             / path-rootless\n             / path-empty\n\nquery         = *( pchar / \"/\" / \"?\" )\n\nauthority     = [ userinfo \"@\" ] host [ \":\" port ]\nuserinfo      = *( unreserved / pct-encoded / sub-delims / \":\" )\nhost          = IP-literal / IPv4address / reg-name\nport          = *DIGIT\n\nreg-name      = *( unreserved / pct-encoded / sub-delims )\n\npath-abempty  = *( \"/\" segment )\n\npath-absolute = \"/\" [ segment-nz *( \"/\" segment ) ]\npath-noscheme = segment-nz-nc *( \"/\" segment )\npath-rootless = segment-nz *( \"/\" segment )\npath-empty    = 0<pchar>\n\nsegment       = *pchar\nsegment-nz    = 1*pchar\nsegment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / \"@\" )\n            ; non-zero-length segment without any colon \":\"\n\npchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n\nunreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\npct-encoded   = \"%\" HEXDIG HEXDIG\nsub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n             / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n\nIP-literal    = \"[\" ( IPv6address / IPvFuture  ) \"]\"\n\nIPvFuture     = \"v\" 1*HEXDIG \".\" 1*( unreserved / sub-delims / \":\" )\n\nIPv6address   =                            6( h16 \":\" ) ls32\n             /                       \"::\" 5( h16 \":\" ) ls32\n             / [               h16 ] \"::\" 4( h16 \":\" ) ls32\n             / [ *1( h16 \":\" ) h16 ] \"::\" 3( h16 \":\" ) ls32\n             / [ *2( h16 \":\" ) h16 ] \"::\" 2( h16 \":\" ) ls32\n             / [ *3( h16 \":\" ) h16 ] \"::\"    h16 \":\"   ls32\n             / [ *4( h16 \":\" ) h16 ] \"::\"              ls32\n             / [ *5( h16 \":\" ) h16 ] \"::\"              h16\n             / [ *6( h16 \":\" ) h16 ] \"::\"\n\nIPv4address   = dec-octet \".\" dec-octet \".\" dec-octet \".\" dec-octet\n\ndec-octet     = DIGIT                 ; 0-9\n             / %x31-39 DIGIT         ; 10-99\n             / \"1\" 2DIGIT            ; 100-199\n             / \"2\" %x30-34 DIGIT     ; 200-249\n             / \"25\" %x30-35          ; 250-255\n\nALPHA          =  %x41-5A / %x61-7A   ; A-Z / a-z\nHEXDIG         =  DIGIT / \"A\" / \"B\" / \"C\" / \"D\" / \"E\" / \"F\"\nDIGIT          =  %x30-39 ; 0-9\n"
  },
  {
    "path": "core/http/src/parse/uri/tables.rs",
    "content": "/// Takes a set of sets of byte characters, return a 2^8 array with non-zero\n/// values at the indices corresponding to the character byte values.\nconst fn char_table(sets: &[&[u8]]) -> [u8; 256] {\n    let mut table = [0u8; 256];\n\n    let mut i = 0;\n    while i < sets.len() {\n        let set: &[u8] = sets[i];\n\n        let mut j = 0;\n        while j < set.len() {\n            let c: u8 = set[j];\n            table[c as usize] = c;\n            j += 1;\n        }\n\n        i += 1;\n    }\n\n    table\n}\n\nconst ALPHA: &[u8] = &[\n    b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L',\n    b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X',\n    b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j',\n    b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v',\n    b'w', b'x', b'y', b'z'\n];\n\nconst DIGIT: &[u8] = &[\n    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9'\n];\n\nconst PCT_ENCODED: &[u8] = &[\n    b'%', b'A', b'B', b'C', b'D', b'E', b'F', b'a', b'b', b'c', b'd', b'e',\n    b'f', b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9'\n];\n\nconst SUB_DELIMS: &[u8] = &[\n    b'!', b'$', b'&', b'\\'', b'(', b')', b'*', b'+', b',', b';', b'='\n];\n\nconst SCHEME_CHAR: [u8; 256] = char_table(&[\n    ALPHA, DIGIT, &[b'+', b'-', b'.']\n]);\n\nconst UNRESERVED: [u8; 256] = char_table(&[\n    ALPHA, DIGIT, &[b'-', b'.', b'_', b'~']\n]);\n\nconst REG_NAME_CHARS: [u8; 256] = char_table(&[\n    &UNRESERVED, PCT_ENCODED, SUB_DELIMS\n]);\n\nconst USER_INFO_CHARS: [u8; 256] = char_table(&[\n    &REG_NAME_CHARS, &[b':']\n]);\n\npub const PATH_CHARS: [u8; 256] = char_table(&[\n    &REG_NAME_CHARS, &[b':', b'@', b'/'],\n\n    // NOTE: these are _not_ accepted in RFC 7230/3986. However, browsers\n    // routinely send these unencoded, so allow them to support the real-world.\n    &[b'[',  b']'],\n]);\n\nconst QUERY_CHARS: [u8; 256] = char_table(&[\n    &PATH_CHARS, &[b'/', b'?'],\n\n    // NOTE: these are _not_ accepted in RFC 7230/3986. However, browsers\n    // routinely send these unencoded, so allow them to support the real-world.\n    &[b'{', b'}', b'[',  b']', b'\\\\',  b'^',  b'`', b'|'],\n]);\n\n#[inline(always)]\npub const fn is_pchar(&c: &u8) -> bool { PATH_CHARS[c as usize] != 0 }\n\n#[inline(always)]\npub const fn is_host_char(c: &u8) -> bool { is_pchar(c) && *c != b'[' && *c != b']' }\n\n#[inline(always)]\npub const fn is_scheme_char(&c: &u8) -> bool { SCHEME_CHAR[c as usize] != 0 }\n\n#[inline(always)]\npub const fn is_user_info_char(&c: &u8) -> bool { USER_INFO_CHARS[c as usize] != 0 }\n\n#[inline(always)]\npub const fn is_qchar(&c: &u8) -> bool { QUERY_CHARS[c as usize] != 0 }\n\n#[inline(always)]\npub const fn is_reg_name_char(&c: &u8) -> bool { REG_NAME_CHARS[c as usize] != 0 }\n\n#[cfg(test)]\nmod tests {\n    fn test_char_table(table: &[u8]) {\n        for (i, &v) in table.iter().enumerate() {\n            if v != 0 {\n                assert_eq!(i, v as usize);\n            }\n        }\n    }\n\n    #[test]\n    fn check_tables() {\n        test_char_table(&super::PATH_CHARS[..]);\n        test_char_table(&super::QUERY_CHARS[..]);\n        test_char_table(&super::REG_NAME_CHARS[..]);\n    }\n}\n"
  },
  {
    "path": "core/http/src/parse/uri/tests.rs",
    "content": "use crate::parse::uri::*;\n\nmacro_rules! assert_parse_eq {\n    ($($from:expr => $to:expr),+ $(,)?) => (\n        $(\n            let expected = $to;\n            match from_str($from) {\n                Ok(output) => {\n                    if output != expected {\n                        println!(\"Error on: {:?}\", $from);\n                        assert_eq!(output, expected, \"{} != {}\", output, expected);\n                    }\n                }\n                Err(e) => {\n                    println!(\"{:?} failed to parse!\", $from);\n                    panic!(\"Error: {}\", e);\n                }\n            }\n        )+\n    );\n}\n\nmacro_rules! assert_no_parse {\n    ($($from:expr),+ $(,)?) => (\n        $(\n            if let Ok(uri) = from_str($from) {\n                println!(\"{:?} parsed unexpectedly!\", $from);\n                panic!(\"Parsed as: {:?}\", uri);\n            }\n        )+\n    );\n\n    ($($from:expr),+,) => (assert_no_parse!($($from),+))\n}\n\nmacro_rules! assert_parse {\n    ($($from:expr),+ $(,)?) => (\n        $(\n            if let Err(e) = from_str($from) {\n                println!(\"{:?} failed to parse\", $from);\n                panic!(\"{}\", e);\n            }\n        )+\n    );\n}\n\nmacro_rules! assert_displays_eq {\n    ($($string:expr),+ $(,)?) => (\n        $(\n            let string = $string.into();\n            match from_str(string) {\n                Ok(output) => {\n                    let output_string = output.to_string();\n                    if output_string != string {\n                        println!(\"Error on: {:?}\", $string);\n                        println!(\"Got: {:?}\", output_string);\n                        println!(\"Parsed as: {:?}\", output);\n                        panic!(\"failed\");\n                    }\n                }\n                Err(e) => {\n                    println!(\"{:?} failed to parse!\", $string);\n                    panic!(\"Error: {}\", e);\n                }\n            }\n        )+\n    );\n\n    ($($string:expr),+,) => (assert_parse_eq!($($string),+))\n}\n\n#[test]\n#[should_panic]\nfn test_assert_parse_eq() {\n    assert_parse_eq!(\"*\" => Origin::path_only(\"*\"));\n}\n\n#[test]\n#[should_panic]\nfn test_assert_parse_eq_consecutive() {\n    assert_parse_eq! {\n        \"/\" => Origin::root(),\n        \"/\" => Asterisk\n    };\n}\n\n#[test]\n#[should_panic]\nfn test_assert_no_parse() {\n    assert_no_parse!(\"/\");\n}\n\n#[test]\nfn bad_parses() {\n    assert_no_parse! {\n        \"://z7:77777777777777777777777777777`77777777777\",\n\n        // from #1621\n        \":/\",\n\n        // almost URIs\n        \":/\",\n        \"://\",\n        \"::\",\n        \":::\",\n        \"a://a::\",\n    };\n}\n\n#[test]\nfn test_parse_issue_924_samples() {\n    assert_parse!(\"/path?param={value}\",\n        \"/path/?param={value}\",\n        \"/some/path/?param={forgot-to-replace-placeholder}\",\n        \"/path?param={value}&onemore={value}\",\n        \"/some/path/?tags=[]\", \"/some/path/?tags=[rocket,is,perfect]\",\n        \"/some/path/?tags=[rocket|is\\\\perfect^`]&users={arenot}\",\n        \"/rocket/@user/\",\n        \"/rocket/@user/?tags=[rocket,%F0%9F%98%8B]\",\n        \"/rocket/?username=@sergio&tags=[rocket,%F0%9F%98%8B]\",\n        \"/rocket/?Key+With+Spaces=value+too\",\n        \"/rocket/?Key+With+\\'\",\n        \"/rocket/?query=%3E5\",\n    );\n\n    assert_no_parse!(\"/rocket/?query=>5\");\n}\n\n#[test]\nfn single_byte() {\n    assert_parse_eq!(\n        \"*\" => Asterisk,\n        \"/\" => Origin::root(),\n        \".\" => Authority::new(None, \".\", None),\n        \"_\" => Authority::new(None, \"_\", None),\n        \"1\" => Authority::new(None, \"1\", None),\n        \"b\" => Authority::new(None, \"b\", None),\n        \"%\" => Authority::new(None, \"%\", None),\n        \"?\" => Reference::new(None, None, \"\", \"\", None),\n        \"#\" => Reference::new(None, None, \"\", None, \"\"),\n        \":\" => Authority::new(None, \"\", None),\n        \"@\" => Authority::new(\"\", \"\", None),\n    );\n\n    assert_no_parse![\"\\\\\", \"^\"];\n}\n\n#[test]\nfn origin() {\n    assert_parse_eq!(\n        \"/a/b/c\" => Origin::path_only(\"/a/b/c\"),\n        \"//\" => Origin::path_only(\"//\"),\n        \"///\" => Origin::path_only(\"///\"),\n        \"////\" => Origin::path_only(\"////\"),\n        \"/a/b/c?\" => Origin::new(\"/a/b/c\", Some(\"\")),\n        \"/a/b/c?abc\" => Origin::new(\"/a/b/c\", Some(\"abc\")),\n        \"/a/b/c???\" => Origin::new(\"/a/b/c\", Some(\"??\")),\n        \"/a/b/c?a?b?\" => Origin::new(\"/a/b/c\", Some(\"a?b?\")),\n        \"/a/b/c?a?b?/c\" => Origin::new(\"/a/b/c\", Some(\"a?b?/c\")),\n        \"/?abc\" => Origin::new(\"/\", Some(\"abc\")),\n        \"/hi%20there?a=b&c=d\" => Origin::new(\"/hi%20there\", Some(\"a=b&c=d\")),\n        \"/c/d/fa/b/c?abc\" => Origin::new(\"/c/d/fa/b/c\", Some(\"abc\")),\n        \"/xn--ls8h?emoji=poop\" => Origin::new(\"/xn--ls8h\", Some(\"emoji=poop\")),\n        \"/?t=[rocket|is\\\\here^`]&{ok}\" => Origin::new(\"/\", Some(\"t=[rocket|is\\\\here^`]&{ok}\")),\n    );\n}\n\n#[test]\nfn authority() {\n    assert_parse_eq!(\n        \"@:\" => Authority::new(\"\", \"\", None),\n        \"abc\" => Authority::new(None, \"abc\", None),\n        \"@abc\" => Authority::new(\"\", \"abc\", None),\n        \"a@b\" => Authority::new(\"a\", \"b\", None),\n        \"a@\" => Authority::new(\"a\", \"\", None),\n        \":@\" => Authority::new(\":\", \"\", None),\n        \":@:\" => Authority::new(\":\", \"\", None),\n        \"sergio:benitez@spark\" => Authority::new(\"sergio:benitez\", \"spark\", None),\n        \"a:b:c@1.2.3:12121\" => Authority::new(\"a:b:c\", \"1.2.3\", 12121),\n        \"sergio@spark\" => Authority::new(\"sergio\", \"spark\", None),\n        \"sergio@spark:230\" => Authority::new(\"sergio\", \"spark\", 230),\n        \"sergio@[1::]:230\" => Authority::new(\"sergio\", \"[1::]\", 230),\n        \"rocket.rs:8000\" => Authority::new(None, \"rocket.rs\", 8000),\n        \"[1::2::3]:80\" => Authority::new(None, \"[1::2::3]\", 80),\n        \"bar:\" => Authority::new(None, \"bar\", None), // could be absolute too\n    );\n}\n\n#[test]\nfn absolute() {\n    assert_parse_eq! {\n        \"http:/\" => Absolute::new(\"http\", None, \"/\", None),\n        \"http://\" => Absolute::new(\"http\", Authority::new(None, \"\", None), \"\", None),\n        \"http:///\" => Absolute::new(\"http\", Authority::new(None, \"\", None), \"/\", None),\n        \"http://a.com:8000\" => Absolute::new(\"http\", Authority::new(None, \"a.com\", 8000), \"\", None),\n        \"http://foo:8000\" => Absolute::new(\"http\", Authority::new(None, \"foo\", 8000), \"\", None),\n        \"foo:bar\" => Absolute::new(\"foo\", None, \"bar\", None),\n        \"ftp:::\" => Absolute::new(\"ftp\", None, \"::\", None),\n        \"ftp:::?bar\" => Absolute::new(\"ftp\", None, \"::\", \"bar\"),\n        \"http://:::@a.b.c.:8000\" =>\n            Absolute::new(\"http\", Authority::new(\":::\", \"a.b.c.\", 8000), \"\", None),\n        \"http://sergio:pass@foo.com:8000\" =>\n            Absolute::new(\"http\", Authority::new(\"sergio:pass\", \"foo.com\", 8000), \"\", None),\n        \"foo:/sergio/pass?hi\" => Absolute::new(\"foo\", None, \"/sergio/pass\", \"hi\"),\n        \"foo:?hi\" => Absolute::new(\"foo\", None, \"\", \"hi\"),\n        \"foo:a/b\" => Absolute::new(\"foo\", None, \"a/b\", None),\n        \"foo:a/b?\" => Absolute::new(\"foo\", None, \"a/b\", \"\"),\n        \"foo:a/b?hi\" => Absolute::new(\"foo\", None, \"a/b\", \"hi\"),\n        \"foo:/a/b\" => Absolute::new(\"foo\", None, \"/a/b\", None),\n        \"abc://u:p@foo.com:123/a/b?key=value&key2=value2\" =>\n            Absolute::new(\"abc\",\n                Authority::new(\"u:p\", \"foo.com\", 123),\n                \"/a/b\", \"key=value&key2=value2\"),\n        \"ftp://foo.com:21/abc\" =>\n            Absolute::new(\"ftp\", Authority::new(None, \"foo.com\", 21), \"/abc\", None),\n        \"http://rocket.rs/abc\" =>\n            Absolute::new(\"http\", Authority::new(None, \"rocket.rs\", None), \"/abc\", None),\n        \"http://s:b@rocket.rs/abc\" =>\n            Absolute::new(\"http\", Authority::new(\"s:b\", \"rocket.rs\", None), \"/abc\", None),\n        \"http://rocket.rs/abc?q\" =>\n            Absolute::new(\"http\", Authority::new(None, \"rocket.rs\", None), \"/abc\", \"q\"),\n        \"http://rocket.rs\" =>\n            Absolute::new(\"http\", Authority::new(None, \"rocket.rs\", None), \"\", None),\n        \"git://s::@rocket.rs:443/abc?q\" =>\n            Absolute::new(\"git\", Authority::new(\"s::\", \"rocket.rs\", 443), \"/abc\", \"q\"),\n        \"git://:@rocket.rs:443/abc?q\" =>\n            Absolute::new(\"git\", Authority::new(\":\", \"rocket.rs\", 443), \"/abc\", \"q\"),\n        \"a://b?test\" => Absolute::new(\"a\", Authority::new(None, \"b\", None), \"\", \"test\"),\n        \"a://b:?test\" => Absolute::new(\"a\", Authority::new(None, \"b\", None), \"\", \"test\"),\n        \"a://b:1?test\" => Absolute::new(\"a\", Authority::new(None, \"b\", 1), \"\", \"test\"),\n    };\n}\n\n#[test]\nfn reference() {\n    assert_parse_eq!(\n        \"*#\" => Reference::new(None, None, \"*\", None, \"\"),\n        \"*#h\" => Reference::new(None, None, \"*\", None, \"h\"),\n        \"@/\" => Reference::new(None, None, \"@/\", None, None),\n        \"@?\" => Reference::new(None, None, \"@\", \"\", None),\n        \"@?#\" => Reference::new(None, None, \"@\", \"\", \"\"),\n        \"@#foo\" => Reference::new(None, None, \"@\", None, \"foo\"),\n        \"foo/bar\" => Reference::new(None, None, \"foo/bar\", None, None),\n        \"foo/bar?baz\" => Reference::new(None, None, \"foo/bar\", \"baz\", None),\n        \"foo/bar?baz#cat\" => Reference::new(None, None, \"foo/bar\", \"baz\", \"cat\"),\n        \"a?b#c\" => Reference::new(None, None, \"a\", \"b\", \"c\"),\n        \"?#\" => Reference::new(None, None, \"\", \"\", \"\"),\n        \"ftp:foo/bar?baz#\" => Reference::new(\"ftp\", None, \"foo/bar\", \"baz\", \"\"),\n        \"ftp:bar#\" => Reference::new(\"ftp\", None, \"bar\", None, \"\"),\n        \"ftp:?bar#\" => Reference::new(\"ftp\", None, \"\", \"bar\", \"\"),\n        \"ftp:::?bar#\" => Reference::new(\"ftp\", None, \"::\", \"bar\", \"\"),\n        \"#foo\" => Reference::new(None, None, \"\", None, \"foo\"),\n        \"a:/#\" => Reference::new(\"a\", None, \"/\", None, \"\"),\n        \"a:/?a#\" => Reference::new(\"a\", None, \"/\", \"a\", \"\"),\n        \"a:/?a#b\" => Reference::new(\"a\", None, \"/\", \"a\", \"b\"),\n        \"a:?a#b\" => Reference::new(\"a\", None, \"\", \"a\", \"b\"),\n        \"a://?a#b\" => Reference::new(\"a\", Authority::new(None, \"\", None), \"\", \"a\", \"b\"),\n        \"a://:?a#b\" => Reference::new(\"a\", Authority::new(None, \"\", None), \"\", \"a\", \"b\"),\n        \"a://:2000?a#b\" => Reference::new(\"a\", Authority::new(None, \"\", 2000), \"\", \"a\", \"b\"),\n        \"a://a:2000?a#b\" => Reference::new(\"a\", Authority::new(None, \"a\", 2000), \"\", \"a\", \"b\"),\n        \"a://a:@2000?a#b\" => Reference::new(\"a\", Authority::new(\"a:\", \"2000\", None), \"\", \"a\", \"b\"),\n        \"a://a:@:80?a#b\" => Reference::new(\"a\", Authority::new(\"a:\", \"\", 80), \"\", \"a\", \"b\"),\n        \"a://a:@b:80?a#b\" => Reference::new(\"a\", Authority::new(\"a:\", \"b\", 80), \"\", \"a\", \"b\"),\n    );\n}\n\n#[test]\nfn display() {\n    assert_displays_eq! {\n        \"abc\", \"@):0\", \"[a]\",\n        \"http://rocket.rs\", \"http://a:b@rocket.rs\", \"git://a@b:800/foo?bar\",\n        \"git://a@b:800/foo?bar#baz\",\n        \"a:b\", \"a@b\", \"a?b\", \"a?b#c\",\n    }\n}\n"
  },
  {
    "path": "core/http/src/raw_str.rs",
    "content": "use std::fmt;\nuse std::borrow::{Borrow, Cow};\nuse std::cmp::Ordering;\nuse std::str::Utf8Error;\n\nuse ref_cast::RefCast;\nuse stable_pattern::{Pattern, Searcher, ReverseSearcher, Split, SplitInternal};\n\nuse crate::uncased::UncasedStr;\nuse crate::uri::fmt::{DEFAULT_ENCODE_SET, percent_encode, percent_encode_bytes};\n\n/// A reference to a string inside of a raw HTTP message.\n///\n/// A `RawStr` is an unsanitized, unvalidated, and undecoded raw string from an\n/// HTTP message. It exists to separate validated string inputs, represented by\n/// the `String`, `&str`, and `Cow<str>` types, from unvalidated inputs,\n/// represented by `&RawStr`.\n///\n/// # Validation\n///\n/// An `&RawStr` should be converted into one of the validated string input\n/// types through methods on `RawStr`. These methods are summarized below:\n///\n///   * **[`url_decode()`]** - used to decode a raw string in a form value\n///     context\n///   * **[`percent_decode()`], [`percent_decode_lossy()`]** - used to\n///     percent-decode a raw string, typically in a URL context\n///   * **[`html_escape()`]** - used to decode a string for use in HTML\n///     templates\n///   * **[`as_str()`]** - used when the `RawStr` is known to be safe in the\n///     context of its intended use. Use sparingly and with care!\n///   * **[`as_uncased_str()`]** - used when the `RawStr` is known to be safe in\n///     the context of its intended, uncased use\n///\n/// **Note:** Template engines like Tera and Handlebars all functions like\n/// [`html_escape()`] on all rendered template outputs by default.\n///\n/// [`as_str()`]: RawStr::as_str()\n/// [`as_uncased_str()`]: RawStr::as_uncased_str()\n/// [`url_decode()`]: RawStr::url_decode()\n/// [`html_escape()`]: RawStr::html_escape()\n/// [`percent_decode()`]: RawStr::percent_decode()\n/// [`percent_decode_lossy()`]: RawStr::percent_decode_lossy()\n///\n/// # Usage\n///\n/// A `RawStr` is a dynamically sized type (just like `str`). It is always used\n/// through a reference an as `&RawStr` (just like &str).\n#[repr(transparent)]\n#[derive(RefCast, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct RawStr(str);\n\nimpl ToOwned for RawStr {\n    type Owned = RawStrBuf;\n\n    fn to_owned(&self) -> Self::Owned {\n        RawStrBuf(self.to_string())\n    }\n}\n\n/// An owned version of [`RawStr`].\n#[repr(transparent)]\n#[derive(RefCast, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct RawStrBuf(String);\n\nimpl RawStrBuf {\n    /// Cost-free conversion from `self` into a `String`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStrBuf;\n    ///\n    /// let raw = RawStrBuf::from(format!(\"hello {}\", \"world\"));\n    /// let string = raw.into_string();\n    /// ```\n    pub fn into_string(self) -> String {\n        self.0\n    }\n}\n\nimpl RawStr {\n    /// Constructs an `&RawStr` from a string-like type at no cost.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello, world!\");\n    ///\n    /// // `into` can also be used; note that the type must be specified\n    /// let raw_str: &RawStr = \"Hello, world!\".into();\n    /// ```\n    pub fn new<S: AsRef<str> + ?Sized>(string: &S) -> &RawStr {\n        RawStr::ref_cast(string.as_ref())\n    }\n\n    /// Construct a `Cow<RawStr>` from a `Cow<Str>`. Does not allocate.\n    ///\n    /// See [`RawStr::into_cow_str()`] for the inverse operation.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::borrow::Cow;\n    /// use rocket::http::RawStr;\n    ///\n    /// let cow_str = Cow::from(\"hello!\");\n    /// let cow_raw = RawStr::from_cow_str(cow_str);\n    /// assert_eq!(cow_raw.as_str(), \"hello!\");\n    /// ```\n    pub fn from_cow_str(cow: Cow<'_, str>) -> Cow<'_, RawStr> {\n        match cow {\n            Cow::Borrowed(b) => Cow::Borrowed(b.into()),\n            Cow::Owned(b) => Cow::Owned(b.into()),\n        }\n    }\n\n    /// Construct a `Cow<str>` from a `Cow<RawStr>`. Does not allocate.\n    ///\n    /// See [`RawStr::from_cow_str()`] for the inverse operation.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::borrow::Cow;\n    /// use rocket::http::RawStr;\n    ///\n    /// let cow_raw = Cow::from(RawStr::new(\"hello!\"));\n    /// let cow_str = RawStr::into_cow_str(cow_raw);\n    /// assert_eq!(&*cow_str, \"hello!\");\n    /// ```\n    pub fn into_cow_str(cow: Cow<'_, RawStr>) -> Cow<'_, str> {\n        match cow {\n            Cow::Borrowed(b) => Cow::Borrowed(b.as_str()),\n            Cow::Owned(b) => Cow::Owned(b.into_string()),\n        }\n    }\n\n    /// Percent-decodes `self`.\n    fn _percent_decode(&self) -> percent_encoding::PercentDecode<'_> {\n        percent_encoding::percent_decode(self.as_bytes())\n    }\n\n    /// Returns a percent-decoded version of the string.\n    ///\n    /// # Errors\n    ///\n    /// Returns an `Err` if the percent encoded values are not valid UTF-8.\n    ///\n    /// # Example\n    ///\n    /// With a valid string:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello%21\");\n    /// let decoded = raw_str.percent_decode();\n    /// assert_eq!(decoded, Ok(\"Hello!\".into()));\n    /// ```\n    ///\n    /// With an invalid string:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let bad_raw_str = RawStr::new(\"%FF\");\n    /// assert!(bad_raw_str.percent_decode().is_err());\n    /// ```\n    #[inline(always)]\n    pub fn percent_decode(&self) -> Result<Cow<'_, str>, Utf8Error> {\n        // don't let `percent-encoding` return a random empty string\n        if self.is_empty() {\n            return Ok(self.as_str().into());\n        }\n\n        self._percent_decode().decode_utf8()\n    }\n\n    /// Returns a percent-decoded version of the string. Any invalid UTF-8\n    /// percent-encoded byte sequences will be replaced � U+FFFD, the\n    /// replacement character.\n    ///\n    /// # Example\n    ///\n    /// With a valid string:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello%21\");\n    /// let decoded = raw_str.percent_decode_lossy();\n    /// assert_eq!(decoded, \"Hello!\");\n    /// ```\n    ///\n    /// With an invalid string:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let bad_raw_str = RawStr::new(\"a=%FF\");\n    /// assert_eq!(bad_raw_str.percent_decode_lossy(), \"a=�\");\n    /// ```\n    #[inline(always)]\n    pub fn percent_decode_lossy(&self) -> Cow<'_, str> {\n        // don't let `percent-encoding` return a random empty string\n        if self.is_empty() {\n            return self.as_str().into();\n        }\n\n        self._percent_decode().decode_utf8_lossy()\n    }\n\n    /// Replaces '+' with ' ' in `self`, allocating only when necessary.\n    fn _replace_plus(&self) -> Cow<'_, str> {\n        let string = self.as_str();\n        let mut allocated = String::new(); // this is allocation free\n        for i in memchr::memchr_iter(b'+', string.as_bytes()) {\n            if allocated.is_empty() {\n                allocated = string.into();\n            }\n\n            // SAFETY:\n            //\n            // 1. The caller must ensure that the content of the slice is valid\n            //    UTF-8 before the borrow ends and the underlying `str` is used.\n            //\n            //    `allocated[i]` is `+` since that is what we searched for. The\n            //    `+` char is ASCII => the character is one byte wide. ' ' is\n            //    also one byte and ASCII => UTF-8. The replacement of `+` with\n            //    ` ` thus yields a valid UTF-8 string.\n            unsafe { allocated.as_bytes_mut()[i] = b' '; }\n        }\n\n        match allocated.is_empty() {\n            true => Cow::Borrowed(string),\n            false => Cow::Owned(allocated)\n        }\n    }\n\n    /// Returns a percent-encoded version of the string.\n    ///\n    /// # Example\n    ///\n    /// With a valid string:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello/goodbye\");\n    /// let encoded = raw_str.percent_encode();\n    /// assert_eq!(encoded.as_str(), \"Hello%2Fgoodbye\");\n    /// ```\n    #[inline(always)]\n    pub fn percent_encode(&self) -> Cow<'_, RawStr> {\n        Self::from_cow_str(percent_encode::<DEFAULT_ENCODE_SET>(self))\n    }\n\n    /// Returns a percent-encoded version of `bytes`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// // Note: Rocket should never hand you a bad `&RawStr`.\n    /// let bytes = &[93, 12, 0, 13, 1];\n    /// let encoded = RawStr::percent_encode_bytes(&bytes[..]);\n    /// assert_eq!(encoded.as_str(), \"]%0C%00%0D%01\");\n    /// ```\n    #[inline(always)]\n    pub fn percent_encode_bytes(bytes: &[u8]) -> Cow<'_, RawStr> {\n        Self::from_cow_str(percent_encode_bytes::<DEFAULT_ENCODE_SET>(bytes))\n    }\n\n    /// Returns a URL-decoded version of the string. This is identical to\n    /// percent decoding except that `+` characters are converted into spaces.\n    /// This is the encoding used by form values.\n    ///\n    /// # Errors\n    ///\n    /// Returns an `Err` if the percent encoded values are not valid UTF-8.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello%2C+world%21\");\n    /// let decoded = raw_str.url_decode();\n    /// assert_eq!(decoded.unwrap(), \"Hello, world!\");\n    /// ```\n    pub fn url_decode(&self) -> Result<Cow<'_, str>, Utf8Error> {\n        let string = self._replace_plus();\n        match percent_encoding::percent_decode(string.as_bytes()).decode_utf8()? {\n            Cow::Owned(s) => Ok(Cow::Owned(s)),\n            Cow::Borrowed(_) => Ok(string)\n        }\n    }\n\n    /// Returns a URL-decoded version of the string.\n    ///\n    /// Any invalid UTF-8 percent-encoded byte sequences will be replaced �\n    /// U+FFFD, the replacement character. This is identical to lossy percent\n    /// decoding except that `+` characters are converted into spaces. This is\n    /// the encoding used by form values.\n    ///\n    /// # Example\n    ///\n    /// With a valid string:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str: &RawStr = \"Hello%2C+world%21\".into();\n    /// let decoded = raw_str.url_decode_lossy();\n    /// assert_eq!(decoded, \"Hello, world!\");\n    /// ```\n    ///\n    /// With an invalid string:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let bad_raw_str = RawStr::new(\"a+b=%FF\");\n    /// assert_eq!(bad_raw_str.url_decode_lossy(), \"a b=�\");\n    /// ```\n    pub fn url_decode_lossy(&self) -> Cow<'_, str> {\n        let string = self._replace_plus();\n        match percent_encoding::percent_decode(string.as_bytes()).decode_utf8_lossy() {\n            Cow::Owned(s) => Cow::Owned(s),\n            Cow::Borrowed(_) => string\n        }\n    }\n\n    /// Returns an HTML escaped version of `self`. Allocates only when\n    /// characters need to be escaped.\n    ///\n    /// The following characters are escaped: `&`, `<`, `>`, `\"`, `'`, `/`,\n    /// <code>`</code>. **This suffices as long as the escaped string is not\n    /// used in an execution context such as inside of &lt;script> or &lt;style>\n    /// tags!** See the [OWASP XSS Prevention Rules] for more information.\n    ///\n    /// [OWASP XSS Prevention Rules]: https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#XSS_Prevention_Rules\n    ///\n    /// # Example\n    ///\n    /// Strings with HTML sequences are escaped:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str: &RawStr = \"<b>Hi!</b>\".into();\n    /// let escaped = raw_str.html_escape();\n    /// assert_eq!(escaped, \"&lt;b&gt;Hi!&lt;&#x2F;b&gt;\");\n    ///\n    /// let raw_str: &RawStr = \"Hello, <i>world!</i>\".into();\n    /// let escaped = raw_str.html_escape();\n    /// assert_eq!(escaped, \"Hello, &lt;i&gt;world!&lt;&#x2F;i&gt;\");\n    /// ```\n    ///\n    /// Strings without HTML sequences remain untouched:\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str: &RawStr = \"Hello!\".into();\n    /// let escaped = raw_str.html_escape();\n    /// assert_eq!(escaped, \"Hello!\");\n    ///\n    /// let raw_str: &RawStr = \"大阪\".into();\n    /// let escaped = raw_str.html_escape();\n    /// assert_eq!(escaped, \"大阪\");\n    /// ```\n    // NOTE: This is the ~fastest (a table-based implementation is slightly\n    // faster) implementation benchmarked for dense-ish escaping. For sparser\n    // texts, a regex-based-find solution is much faster.\n    pub fn html_escape(&self) -> Cow<'_, str> {\n        let mut escaped = false;\n        let mut allocated = Vec::new(); // this is allocation free\n        for c in self.as_bytes() {\n            match *c {\n                b'&' | b'<' | b'>' | b'\"' | b'\\'' | b'/' | b'`' => {\n                    if !escaped {\n                        let i = (c as *const u8 as usize) - (self.as_ptr() as usize);\n                        allocated = Vec::with_capacity(self.len() * 2);\n                        allocated.extend_from_slice(&self.as_bytes()[..i]);\n                    }\n\n                    match *c {\n                        b'&' => allocated.extend_from_slice(b\"&amp;\"),\n                        b'<' => allocated.extend_from_slice(b\"&lt;\"),\n                        b'>' => allocated.extend_from_slice(b\"&gt;\"),\n                        b'\"' => allocated.extend_from_slice(b\"&quot;\"),\n                        b'\\'' => allocated.extend_from_slice(b\"&#x27;\"),\n                        b'/' => allocated.extend_from_slice(b\"&#x2F;\"),\n                        // Old versions of IE treat a ` as a '.\n                        b'`' => allocated.extend_from_slice(b\"&#96;\"),\n                        _ => unreachable!()\n                    }\n\n                    escaped = true;\n                }\n                _ if escaped => allocated.push(*c),\n                _ => {  }\n            }\n        }\n\n        if escaped {\n            // This use of `unsafe` is only correct if the bytes in `allocated`\n            // form a valid UTF-8 string. We prove this by cases:\n            //\n            // 1. In the `!escaped` branch, capacity for the vector is first\n            //    allocated. No characters are pushed to `allocated` prior to\n            //    this branch running since the `escaped` flag isn't set. To\n            //    enter this branch, the current byte must be a valid ASCII\n            //    character. This implies that every byte preceding forms a\n            //    valid UTF-8 string since ASCII characters in UTF-8 are never\n            //    part of a multi-byte sequence. Thus, extending the `allocated`\n            //    vector with these bytes results in a valid UTF-8 string in\n            //    `allocated`.\n            //\n            // 2. After the `!escaped` branch, `allocated` is extended with a\n            //    byte string of valid ASCII characters. Thus, `allocated` is\n            //    still a valid UTF-8 string.\n            //\n            // 3. In the `_ if escaped` branch, the byte is simply pushed into\n            //    the `allocated` vector. At this point, `allocated` may contain\n            //    an invalid UTF-8 string as we are not a known boundary.\n            //    However, note that this byte is part of a known valid string\n            //    (`self`). If the byte is not part of a multi-byte sequence, it\n            //    is ASCII, and no further justification is needed. If the byte\n            //    _is_ part of a multi-byte sequence, it is _not_ ASCII, and\n            //    thus will not fall into the escaped character set and it will\n            //    be pushed into `allocated` subsequently, resulting in a valid\n            //    UTF-8 string in `allocated`.\n            unsafe { Cow::Owned(String::from_utf8_unchecked(allocated)) }\n        } else {\n            Cow::Borrowed(self.as_str())\n        }\n    }\n\n    /// Returns the length of `self`.\n    ///\n    /// This length is in bytes, not [`char`]s or graphemes. In other words,\n    /// it may not be what a human considers the length of the string.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello, world!\");\n    /// assert_eq!(raw_str.len(), 13);\n    /// ```\n    #[inline]\n    pub const fn len(&self) -> usize {\n        self.0.len()\n    }\n\n    /// Returns `true` if `self` has a length of zero bytes.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello, world!\");\n    /// assert!(!raw_str.is_empty());\n    ///\n    /// let raw_str = RawStr::new(\"\");\n    /// assert!(raw_str.is_empty());\n    /// ```\n    #[inline]\n    pub const fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    /// Converts `self` into an `&str`.\n    ///\n    /// This method should be used sparingly. **Only use this method when you\n    /// are absolutely certain that doing so is safe.**\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Hello, world!\");\n    /// assert_eq!(raw_str.as_str(), \"Hello, world!\");\n    /// ```\n    #[inline(always)]\n    pub const fn as_str(&self) -> &str {\n        &self.0\n    }\n\n    /// Converts `self` into an `&[u8]`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"hi\");\n    /// assert_eq!(raw_str.as_bytes(), &[0x68, 0x69]);\n    /// ```\n    #[inline(always)]\n    pub const fn as_bytes(&self) -> &[u8] {\n        self.0.as_bytes()\n    }\n\n    /// Converts a string slice to a raw pointer.\n    ///\n    /// As string slices are a slice of bytes, the raw pointer points to a\n    /// [`u8`]. This pointer will be pointing to the first byte of the string\n    /// slice.\n    ///\n    /// The caller must ensure that the returned pointer is never written to.\n    /// If you need to mutate the contents of the string slice, use [`as_mut_ptr`].\n    ///\n    /// [`as_mut_ptr`]: str::as_mut_ptr\n    ///\n    /// # Examples\n    ///\n    /// Basic usage:\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"hi\");\n    /// let ptr = raw_str.as_ptr();\n    /// ```\n    pub const fn as_ptr(&self) -> *const u8 {\n        self.as_str().as_ptr()\n    }\n\n    /// Converts `self` into an `&UncasedStr`.\n    ///\n    /// This method should be used sparingly. **Only use this method when you\n    /// are absolutely certain that doing so is safe.**\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let raw_str = RawStr::new(\"Content-Type\");\n    /// assert!(raw_str.as_uncased_str() == \"content-TYPE\");\n    /// ```\n    #[inline(always)]\n    pub fn as_uncased_str(&self) -> &UncasedStr {\n        self.as_str().into()\n    }\n\n    /// Returns `true` if the given pattern matches a sub-slice of\n    /// this string slice.\n    ///\n    /// Returns `false` if it does not.\n    ///\n    /// The pattern can be a `&str`, [`char`], a slice of [`char`]s, or a\n    /// function or closure that determines if a character matches.\n    ///\n    /// [`char`]: prim@char\n    ///\n    /// # Examples\n    ///\n    /// Basic usage:\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let bananas = RawStr::new(\"bananas\");\n    ///\n    /// assert!(bananas.contains(\"nana\"));\n    /// assert!(!bananas.contains(\"apples\"));\n    /// ```\n    #[inline]\n    pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {\n        pat.is_contained_in(self.as_str())\n    }\n\n    /// Returns `true` if the given pattern matches a prefix of this\n    /// string slice.\n    ///\n    /// Returns `false` if it does not.\n    ///\n    /// The pattern can be a `&str`, [`char`], a slice of [`char`]s, or a\n    /// function or closure that determines if a character matches.\n    ///\n    /// [`char`]: prim@char\n    ///\n    /// # Examples\n    ///\n    /// Basic usage:\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let bananas = RawStr::new(\"bananas\");\n    ///\n    /// assert!(bananas.starts_with(\"bana\"));\n    /// assert!(!bananas.starts_with(\"nana\"));\n    /// ```\n    pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {\n        pat.is_prefix_of(self.as_str())\n    }\n\n    /// Returns `true` if the given pattern matches a suffix of this\n    /// string slice.\n    ///\n    /// Returns `false` if it does not.\n    ///\n    /// The pattern can be a `&str`, [`char`], a slice of [`char`]s, or a\n    /// function or closure that determines if a character matches.\n    ///\n    /// [`char`]: prim@char\n    ///\n    /// # Examples\n    ///\n    /// Basic usage:\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let bananas = RawStr::new(\"bananas\");\n    ///\n    /// assert!(bananas.ends_with(\"anas\"));\n    /// assert!(!bananas.ends_with(\"nana\"));\n    /// ```\n    pub fn ends_with<'a, P>(&'a self, pat: P) -> bool\n        where P: Pattern<'a>, <P as Pattern<'a>>::Searcher: ReverseSearcher<'a>\n    {\n        pat.is_suffix_of(self.as_str())\n    }\n\n    /// Returns the byte index of the first character of this string slice that\n    /// matches the pattern.\n    ///\n    /// Returns [`None`] if the pattern doesn't match.\n    ///\n    /// The pattern can be a `&str`, [`char`], a slice of [`char`]s, or a\n    /// function or closure that determines if a character matches.\n    ///\n    /// [`char`]: prim@char\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let s = RawStr::new(\"Löwe 老虎 Léopard Gepardi\");\n    ///\n    /// assert_eq!(s.find('L'), Some(0));\n    /// assert_eq!(s.find('é'), Some(14));\n    /// assert_eq!(s.find(\"pard\"), Some(17));\n    /// ```\n    #[inline]\n    pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {\n        pat.into_searcher(self.as_str()).next_match().map(|(i, _)| i)\n    }\n\n    /// An iterator over substrings of this string slice, separated by\n    /// characters matched by a pattern.\n    ///\n    /// The pattern can be a `&str`, [`char`], a slice of [`char`]s, or a\n    /// function or closure that determines if a character matches.\n    ///\n    /// [`char`]: prim@char\n    ///\n    /// # Examples\n    ///\n    /// Simple patterns:\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let v: Vec<_> = RawStr::new(\"Mary had a little lamb\")\n    ///     .split(' ')\n    ///     .map(|r| r.as_str())\n    ///     .collect();\n    ///\n    /// assert_eq!(v, [\"Mary\", \"had\", \"a\", \"little\", \"lamb\"]);\n    /// ```\n    #[inline]\n    pub fn split<'a, P>(&'a self, pat: P) -> impl DoubleEndedIterator<Item = &'a RawStr>\n        where P: Pattern<'a>,\n              <P as stable_pattern::Pattern<'a>>::Searcher: stable_pattern::DoubleEndedSearcher<'a>\n    {\n        let split: Split<'_, P> = Split(SplitInternal {\n            start: 0,\n            end: self.len(),\n            matcher: pat.into_searcher(self.as_str()),\n            allow_trailing_empty: true,\n            finished: false,\n        });\n\n        split.map(|s| s.into())\n    }\n\n    /// Splits `self` into two pieces: the piece _before_ the first byte `b` and\n    /// the piece _after_ (not including `b`). Returns the tuple (`before`,\n    /// `after`). If `b` is not in `self`, or `b` is not an ASCII characters,\n    /// returns the entire string `self` as `before` and the empty string as\n    /// `after`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let haystack = RawStr::new(\"a good boy!\");\n    ///\n    /// let (before, after) = haystack.split_at_byte(b'a');\n    /// assert_eq!(before, \"\");\n    /// assert_eq!(after, \" good boy!\");\n    ///\n    /// let (before, after) = haystack.split_at_byte(b' ');\n    /// assert_eq!(before, \"a\");\n    /// assert_eq!(after, \"good boy!\");\n    ///\n    /// let (before, after) = haystack.split_at_byte(b'o');\n    /// assert_eq!(before, \"a g\");\n    /// assert_eq!(after, \"od boy!\");\n    ///\n    /// let (before, after) = haystack.split_at_byte(b'!');\n    /// assert_eq!(before, \"a good boy\");\n    /// assert_eq!(after, \"\");\n    ///\n    /// let (before, after) = haystack.split_at_byte(b'?');\n    /// assert_eq!(before, \"a good boy!\");\n    /// assert_eq!(after, \"\");\n    ///\n    /// let haystack = RawStr::new(\"\");\n    /// let (before, after) = haystack.split_at_byte(b' ');\n    /// assert_eq!(before, \"\");\n    /// assert_eq!(after, \"\");\n    /// ```\n    #[inline]\n    pub fn split_at_byte(&self, b: u8) -> (&RawStr, &RawStr) {\n        if !b.is_ascii() {\n            return (self, &self[0..0]);\n        }\n\n        match memchr::memchr(b, self.as_bytes()) {\n            // SAFETY: `b` is a character boundary since it's ASCII, `i` is in\n            // bounds in `self` (or else None), and i is at most len - 1, so i +\n            // 1 is at most len.\n            Some(i) => unsafe {\n                let s = self.as_str();\n                let start = s.get_unchecked(0..i);\n                let end = s.get_unchecked((i + 1)..self.len());\n                (start.into(), end.into())\n            },\n            None => (self, &self[0..0])\n        }\n    }\n\n    /// Returns a string slice with the prefix removed.\n    ///\n    /// If the string starts with the pattern `prefix`, returns substring after\n    /// the prefix, wrapped in `Some`. This method removes the prefix exactly\n    /// once.\n    ///\n    /// If the string does not start with `prefix`, returns `None`.\n    ///\n    /// The pattern can be a `&str`, `char`, a slice of `char`s, or a function\n    /// or closure that determines if a character matches.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// assert_eq!(RawStr::new(\"foo:bar\").strip_prefix(\"foo:\").unwrap(), \"bar\");\n    /// assert_eq!(RawStr::new(\"foofoo\").strip_prefix(\"foo\").unwrap(), \"foo\");\n    /// assert!(RawStr::new(\"foo:bar\").strip_prefix(\"bar\").is_none());\n    /// ```\n    #[inline]\n    pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a RawStr> {\n        prefix.strip_prefix_of(self.as_str()).map(RawStr::new)\n    }\n\n    /// Returns a string slice with the suffix removed.\n    ///\n    /// If the string ends with the pattern `suffix`, returns the substring\n    /// before the suffix, wrapped in `Some`.  Unlike `trim_end_matches`, this\n    /// method removes the suffix exactly once.\n    ///\n    /// If the string does not end with `suffix`, returns `None`.\n    ///\n    /// The pattern can be a `&str`, `char`, a slice of `char`s, or a function\n    /// or closure that determines if a character matches.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// assert_eq!(RawStr::new(\"bar:foo\").strip_suffix(\":foo\").unwrap(), \"bar\");\n    /// assert_eq!(RawStr::new(\"foofoo\").strip_suffix(\"foo\").unwrap(), \"foo\");\n    /// assert!(RawStr::new(\"bar:foo\").strip_suffix(\"bar\").is_none());\n    /// ```\n    #[inline]\n    pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a RawStr>\n        where P: Pattern<'a>,<P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,\n    {\n        suffix.strip_suffix_of(self.as_str()).map(RawStr::new)\n    }\n\n    /// Returns a string slice with leading and trailing whitespace removed.\n    ///\n    /// 'Whitespace' is defined according to the terms of the Unicode Derived\n    /// Core Property `White_Space`, which includes newlines.\n    ///\n    /// # Examples\n    ///\n    /// Basic usage:\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let s = RawStr::new(\"\\n Hello\\tworld\\t\\n\");\n    ///\n    /// assert_eq!(\"Hello\\tworld\", s.trim());\n    /// ```\n    #[inline]\n    pub fn trim(&self) -> &RawStr {\n        RawStr::new(self.as_str().trim_matches(|c: char| c.is_whitespace()))\n    }\n\n    /// Parses this string slice into another type.\n    ///\n    /// Because `parse` is so general, it can cause problems with type\n    /// inference. As such, `parse` is one of the few times you'll see\n    /// the syntax affectionately known as the 'turbofish': `::<>`. This\n    /// helps the inference algorithm understand specifically which type\n    /// you're trying to parse into.\n    ///\n    /// # Errors\n    ///\n    /// Will return `Err` if it's not possible to parse this string slice into\n    /// the desired type.\n    ///\n    /// # Examples\n    ///\n    /// Basic usage\n    ///\n    /// ```\n    /// # extern crate rocket;\n    /// use rocket::http::RawStr;\n    ///\n    /// let four: u32 = RawStr::new(\"4\").parse().unwrap();\n    ///\n    /// assert_eq!(4, four);\n    /// ```\n    #[inline]\n    pub fn parse<F: std::str::FromStr>(&self) -> Result<F, F::Err> {\n        std::str::FromStr::from_str(self.as_str())\n    }\n}\n\n#[cfg(feature = \"serde\")]\nmod serde_impl {\n    use serde::{ser, de, Serialize, Deserialize};\n\n    use super::*;\n\n    impl Serialize for RawStr {\n        fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>\n            where S: ser::Serializer\n        {\n            self.as_str().serialize(ser)\n        }\n    }\n\n    impl<'de: 'a, 'a> Deserialize<'de> for &'a RawStr {\n        fn deserialize<D>(de: D) -> Result<Self, D::Error>\n            where D: de::Deserializer<'de>\n        {\n            <&'a str as Deserialize<'de>>::deserialize(de).map(RawStr::new)\n        }\n    }\n\n}\n\nimpl fmt::Debug for RawStr {\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl<'a> From<&'a str> for &'a RawStr {\n    #[inline(always)]\n    fn from(string: &'a str) -> &'a RawStr {\n        RawStr::new(string)\n    }\n}\n\nimpl<'a> From<&'a RawStr> for Cow<'a, RawStr> {\n    fn from(raw: &'a RawStr) -> Self {\n        Cow::Borrowed(raw)\n    }\n}\n\nimpl From<RawStrBuf> for Cow<'_, RawStr> {\n    fn from(raw: RawStrBuf) -> Self {\n        Cow::Owned(raw)\n    }\n}\n\nmacro_rules! impl_partial {\n    ($A:ty : $B:ty as $T:ty) => (\n        impl PartialEq<$A> for $B {\n            #[inline(always)]\n            fn eq(&self, other: &$A) -> bool {\n                let left: $T = self.as_ref();\n                let right: $T = other.as_ref();\n                left == right\n            }\n        }\n\n        impl PartialOrd<$A> for $B {\n            #[inline(always)]\n            fn partial_cmp(&self, other: &$A) -> Option<Ordering> {\n                let left: $T = self.as_ref();\n                let right: $T = other.as_ref();\n                left.partial_cmp(right)\n            }\n        }\n    );\n    ($A:ty : $B:ty) => (impl_partial!($A : $B as &str);)\n}\n\nimpl_partial!(RawStr : &RawStr);\nimpl_partial!(&RawStr : RawStr);\n\nimpl_partial!(str : RawStr);\nimpl_partial!(str : &RawStr);\nimpl_partial!(&str : RawStr);\nimpl_partial!(&&str : RawStr);\n\nimpl_partial!(Cow<'_, str> : RawStr);\nimpl_partial!(Cow<'_, str> : &RawStr);\nimpl_partial!(RawStr : Cow<'_, str>);\nimpl_partial!(&RawStr : Cow<'_, str>);\n\nimpl_partial!(Cow<'_, RawStr> : RawStr as &RawStr);\nimpl_partial!(Cow<'_, RawStr> : &RawStr as &RawStr);\nimpl_partial!(RawStr : Cow<'_, RawStr> as &RawStr);\nimpl_partial!(&RawStr : Cow<'_, RawStr> as &RawStr);\n\nimpl_partial!(String : RawStr);\nimpl_partial!(String : &RawStr);\n\nimpl_partial!(RawStr : String);\nimpl_partial!(&RawStr : String);\n\nimpl_partial!(RawStr : str);\nimpl_partial!(RawStr : &str);\nimpl_partial!(RawStr : &&str);\nimpl_partial!(&RawStr : str);\n\nimpl AsRef<str> for RawStr {\n    #[inline(always)]\n    fn as_ref(&self) -> &str {\n        self.as_str()\n    }\n}\n\nimpl AsRef<std::ffi::OsStr> for RawStr {\n    #[inline(always)]\n    fn as_ref(&self) -> &std::ffi::OsStr {\n        self.as_str().as_ref()\n    }\n}\n\nimpl AsRef<RawStr> for str {\n    #[inline(always)]\n    fn as_ref(&self) -> &RawStr {\n        RawStr::new(self)\n    }\n}\n\nimpl AsRef<RawStr> for RawStr {\n    #[inline(always)]\n    fn as_ref(&self) -> &RawStr {\n        self\n    }\n}\n\nimpl AsRef<[u8]> for RawStr {\n    #[inline(always)]\n    fn as_ref(&self) -> &[u8] {\n        self.as_bytes()\n    }\n}\n\nimpl<I: core::slice::SliceIndex<str, Output=str>> core::ops::Index<I> for RawStr {\n    type Output = RawStr;\n\n    #[inline]\n    fn index(&self, index: I) -> &Self::Output {\n        self.as_str()[index].into()\n    }\n}\n\nimpl std::borrow::Borrow<str> for RawStr {\n    #[inline(always)]\n    fn borrow(&self) -> &str {\n        self.as_str()\n    }\n}\n\nimpl std::borrow::Borrow<RawStr> for &str {\n    #[inline(always)]\n    fn borrow(&self) -> &RawStr {\n        (*self).into()\n    }\n}\n\nimpl fmt::Display for RawStr {\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl AsRef<RawStr> for RawStrBuf {\n    #[inline(always)]\n    fn as_ref(&self) -> &RawStr {\n        RawStr::new(self.0.as_str())\n    }\n}\n\nimpl Borrow<RawStr> for RawStrBuf {\n    #[inline(always)]\n    fn borrow(&self) -> &RawStr {\n        self.as_ref()\n    }\n}\n\nimpl std::ops::Deref for RawStrBuf {\n    type Target = RawStr;\n\n    #[inline(always)]\n    fn deref(&self) -> &Self::Target {\n        self.as_ref()\n    }\n}\n\nimpl fmt::Display for RawStrBuf {\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl fmt::Debug for RawStrBuf {\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl From<String> for RawStrBuf {\n    #[inline(always)]\n    fn from(string: String) -> Self {\n        RawStrBuf(string)\n    }\n}\n\nimpl From<&str> for RawStrBuf {\n    #[inline(always)]\n    fn from(string: &str) -> Self {\n        string.to_string().into()\n    }\n}\n\nimpl From<&RawStr> for RawStrBuf {\n    #[inline(always)]\n    fn from(raw: &RawStr) -> Self {\n        raw.to_string().into()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::RawStr;\n\n    #[test]\n    fn can_compare() {\n        let raw_str = RawStr::new(\"abc\");\n        assert_eq!(raw_str, \"abc\");\n        assert_eq!(\"abc\", raw_str.as_str());\n        assert_eq!(raw_str, RawStr::new(\"abc\"));\n        assert_eq!(raw_str, \"abc\".to_string());\n        assert_eq!(\"abc\".to_string(), raw_str.as_str());\n    }\n}\n"
  },
  {
    "path": "core/http/src/status.rs",
    "content": "use std::fmt;\n\n/// Enumeration of HTTP status classes.\n#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]\npub enum StatusClass {\n    /// Indicates a provisional response: a status code of 1XX.\n    Informational,\n    /// Indicates that a request has succeeded: a status code of 2XX.\n    Success,\n    /// Indicates that further action needs to be taken by the user agent in\n    /// order to fulfill the request: a status code of 3XX.\n    Redirection,\n    /// Intended for cases in which the client seems to have erred: a status\n    /// code of 4XX.\n    ClientError,\n    /// Indicates cases in which the server is aware that it has erred or is\n    /// incapable of performing the request: a status code of 5XX.\n    ServerError,\n    /// Indicates that the status code is nonstandard and unknown: all other\n    /// status codes.\n    Unknown\n}\n\nmacro_rules! class_check_fn {\n    ($func:ident, $type:expr, $variant:ident) => (\n        /// Returns `true` if `self` is a `StatusClass` of\n        #[doc=$type]\n        /// Returns `false` otherwise.\n        #[inline(always)]\n        pub fn $func(&self) -> bool {\n            *self == StatusClass::$variant\n        }\n    )\n}\n\nimpl StatusClass {\n    class_check_fn!(is_informational, \"`Informational` (1XX).\", Informational);\n    class_check_fn!(is_success, \"`Success` (2XX).\", Success);\n    class_check_fn!(is_redirection, \"`Redirection` (3XX).\", Redirection);\n    class_check_fn!(is_client_error, \"`ClientError` (4XX).\", ClientError);\n    class_check_fn!(is_server_error, \"`ServerError` (5XX).\", ServerError);\n    class_check_fn!(is_unknown, \"`Unknown`.\", Unknown);\n}\n\n/// Structure representing an HTTP status: an integer code.\n///\n/// A `Status` should rarely be created directly. Instead, an associated\n/// constant should be used; one is declared for every status defined in the\n/// HTTP standard. If a custom status code _must_ be created, note that it is\n/// not possible to set a custom reason phrase.\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::Status;\n///\n/// // Create a status from a known constant.\n/// let ok = Status::Ok;\n/// assert_eq!(ok.code, 200);\n/// assert_eq!(ok.reason(), Some(\"OK\"));\n///\n/// let not_found = Status::NotFound;\n/// assert_eq!(not_found.code, 404);\n/// assert_eq!(not_found.reason(), Some(\"Not Found\"));\n///\n/// // Or from a status code: `reason()` returns the phrase when known.\n/// let gone = Status::new(410);\n/// assert_eq!(gone.code, 410);\n/// assert_eq!(gone.reason(), Some(\"Gone\"));\n///\n/// // `reason()` returns `None` when unknown.\n/// let custom = Status::new(599);\n/// assert_eq!(custom.code, 599);\n/// assert_eq!(custom.reason(), None);\n/// ```\n///\n/// # Responding\n///\n/// To set a custom `Status` on a response, use a [`response::status`]\n/// responder, which enforces correct status-based responses. Alternatively,\n/// respond with `(Status, T)` where `T: Responder`, but beware that the\n/// response may be invalid if it requires additional headers.\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::get;\n/// use rocket::http::Status;\n///\n/// #[get(\"/\")]\n/// fn index() -> (Status, &'static str) {\n///     (Status::NotFound, \"Hey, there's no index!\")\n/// }\n/// ```\n///\n/// [`response::status`]: ../response/status/index.html\n///\n/// # (De)serialization\n///\n/// `Status` is both `Serialize` and `Deserialize`, represented as a `u16`. For\n/// example, [`Status::Ok`] (de)serializes from/to `200`. Any integer in the\n/// range `[100, 600)` is allowed to deserialize into a `Status`.`\n///\n/// ```rust\n/// # #[cfg(feature = \"serde\")] mod serde_impl {\n/// # use serde as serde;\n/// use serde::{Serialize, Deserialize};\n/// use rocket::http::Status;\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct Foo {\n///     status: Status,\n/// }\n/// # }\n/// ```\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]\npub struct Status {\n    /// The HTTP status code associated with this status.\n    pub code: u16,\n}\n\nimpl Default for Status {\n    fn default() -> Self {\n        Status::Ok\n    }\n}\n\nmacro_rules! ctrs {\n    ($($code:expr, $code_str:expr, $name:ident => $reason:expr),+) => {\n        $(\n            #[doc=\"[`Status`] with code <b>\"]\n            #[doc=$code_str]\n            #[doc=\"</b>.\"]\n            #[allow(non_upper_case_globals)]\n            pub const $name: Status = Status { code: $code };\n        )+\n\n        /// Creates a new `Status` with `code`. This should be used _only_ to\n        /// construct non-standard HTTP statuses. Use an associated constant for\n        /// standard statuses.\n        ///\n        /// # Example\n        ///\n        /// Create a custom `299` status:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::Status;\n        ///\n        /// let custom = Status::new(299);\n        /// assert_eq!(custom.code, 299);\n        /// ```\n        pub const fn new(code: u16) -> Status {\n            Status { code }\n        }\n\n        /// Returns the class of a given status.\n        ///\n        /// # Example\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::{Status, StatusClass};\n        ///\n        /// let processing = Status::Processing;\n        /// assert_eq!(processing.class(), StatusClass::Informational);\n        ///\n        /// let ok = Status::Ok;\n        /// assert_eq!(ok.class(), StatusClass::Success);\n        ///\n        /// let see_other = Status::SeeOther;\n        /// assert_eq!(see_other.class(), StatusClass::Redirection);\n        ///\n        /// let not_found = Status::NotFound;\n        /// assert_eq!(not_found.class(), StatusClass::ClientError);\n        ///\n        /// let internal_error = Status::InternalServerError;\n        /// assert_eq!(internal_error.class(), StatusClass::ServerError);\n        ///\n        /// let custom = Status::new(600);\n        /// assert_eq!(custom.class(), StatusClass::Unknown);\n        /// ```\n        pub const fn class(self) -> StatusClass {\n            match self.code / 100 {\n                1 => StatusClass::Informational,\n                2 => StatusClass::Success,\n                3 => StatusClass::Redirection,\n                4 => StatusClass::ClientError,\n                5 => StatusClass::ServerError,\n                _ => StatusClass::Unknown\n            }\n        }\n\n        /// Returns a Status given a standard status code `code`. If `code` is\n        /// not a known status code, `None` is returned.\n        ///\n        /// # Example\n        ///\n        /// Create a `Status` from a known `code`:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::Status;\n        ///\n        /// let not_found = Status::from_code(404);\n        /// assert_eq!(not_found, Some(Status::NotFound));\n        /// ```\n        ///\n        /// Create a `Status` from an unknown `code`:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::Status;\n        ///\n        /// let unknown = Status::from_code(600);\n        /// assert!(unknown.is_none());\n        /// ```\n        pub const fn from_code(code: u16) -> Option<Status> {\n            match code {\n                $($code => Some(Status::$name),)+\n                _ => None\n            }\n        }\n\n        /// Returns the canonical reason phrase if `self` corresponds to a\n        /// canonical, known status code. Otherwise, returns `None`.\n        ///\n        /// # Example\n        ///\n        /// Reason phrase from a known `code`:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::Status;\n        ///\n        /// assert_eq!(Status::Created.reason(), Some(\"Created\"));\n        /// assert_eq!(Status::new(200).reason(), Some(\"OK\"));\n        /// ```\n        ///\n        /// Absent phrase from an unknown `code`:\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::Status;\n        ///\n        /// assert_eq!(Status::new(499).reason(), None);\n        /// ```\n        pub const fn reason(&self) -> Option<&'static str> {\n            match self.code {\n                $($code => Some($reason),)+\n                _ => None\n            }\n        }\n\n        /// Returns the canonical reason phrase if `self` corresponds to a\n        /// canonical, known status code, or an unspecified but relevant reason\n        /// phrase otherwise.\n        ///\n        /// # Example\n        ///\n        /// ```rust\n        /// # extern crate rocket;\n        /// use rocket::http::Status;\n        ///\n        /// assert_eq!(Status::NotFound.reason_lossy(), \"Not Found\");\n        /// assert_eq!(Status::new(100).reason_lossy(), \"Continue\");\n        /// assert!(!Status::new(699).reason_lossy().is_empty());\n        /// ```\n        pub const fn reason_lossy(&self) -> &'static str {\n            if let Some(lossless) = self.reason() {\n                return lossless;\n            }\n\n            match self.class() {\n                StatusClass::Informational => \"Informational\",\n                StatusClass::Success => \"Success\",\n                StatusClass::Redirection => \"Redirection\",\n                StatusClass::ClientError => \"Client Error\",\n                StatusClass::ServerError => \"Server Error\",\n                StatusClass::Unknown => \"Unknown\"\n            }\n        }\n    };\n}\n\nimpl Status {\n    ctrs! {\n        100, \"100\", Continue => \"Continue\",\n        101, \"101\", SwitchingProtocols => \"Switching Protocols\",\n        102, \"102\", Processing => \"Processing\",\n        200, \"200\", Ok => \"OK\",\n        201, \"201\", Created => \"Created\",\n        202, \"202\", Accepted => \"Accepted\",\n        203, \"203\", NonAuthoritativeInformation => \"Non-Authoritative Information\",\n        204, \"204\", NoContent => \"No Content\",\n        205, \"205\", ResetContent => \"Reset Content\",\n        206, \"206\", PartialContent => \"Partial Content\",\n        207, \"207\", MultiStatus => \"Multi-Status\",\n        208, \"208\", AlreadyReported => \"Already Reported\",\n        226, \"226\", ImUsed => \"IM Used\",\n        300, \"300\", MultipleChoices => \"Multiple Choices\",\n        301, \"301\", MovedPermanently => \"Moved Permanently\",\n        302, \"302\", Found => \"Found\",\n        303, \"303\", SeeOther => \"See Other\",\n        304, \"304\", NotModified => \"Not Modified\",\n        305, \"305\", UseProxy => \"Use Proxy\",\n        307, \"307\", TemporaryRedirect => \"Temporary Redirect\",\n        308, \"308\", PermanentRedirect => \"Permanent Redirect\",\n        400, \"400\", BadRequest => \"Bad Request\",\n        401, \"401\", Unauthorized => \"Unauthorized\",\n        402, \"402\", PaymentRequired => \"Payment Required\",\n        403, \"403\", Forbidden => \"Forbidden\",\n        404, \"404\", NotFound => \"Not Found\",\n        405, \"405\", MethodNotAllowed => \"Method Not Allowed\",\n        406, \"406\", NotAcceptable => \"Not Acceptable\",\n        407, \"407\", ProxyAuthenticationRequired => \"Proxy Authentication Required\",\n        408, \"408\", RequestTimeout => \"Request Timeout\",\n        409, \"409\", Conflict => \"Conflict\",\n        410, \"410\", Gone => \"Gone\",\n        411, \"411\", LengthRequired => \"Length Required\",\n        412, \"412\", PreconditionFailed => \"Precondition Failed\",\n        413, \"413\", PayloadTooLarge => \"Payload Too Large\",\n        414, \"414\", UriTooLong => \"URI Too Long\",\n        415, \"415\", UnsupportedMediaType => \"Unsupported Media Type\",\n        416, \"416\", RangeNotSatisfiable => \"Range Not Satisfiable\",\n        417, \"417\", ExpectationFailed => \"Expectation Failed\",\n        418, \"418\", ImATeapot => \"I'm a teapot\",\n        421, \"421\", MisdirectedRequest => \"Misdirected Request\",\n        422, \"422\", UnprocessableEntity => \"Unprocessable Entity\",\n        423, \"423\", Locked => \"Locked\",\n        424, \"424\", FailedDependency => \"Failed Dependency\",\n        426, \"426\", UpgradeRequired => \"Upgrade Required\",\n        428, \"428\", PreconditionRequired => \"Precondition Required\",\n        429, \"429\", TooManyRequests => \"Too Many Requests\",\n        431, \"431\", RequestHeaderFieldsTooLarge => \"Request Header Fields Too Large\",\n        451, \"451\", UnavailableForLegalReasons => \"Unavailable For Legal Reasons\",\n        500, \"500\", InternalServerError => \"Internal Server Error\",\n        501, \"501\", NotImplemented => \"Not Implemented\",\n        502, \"502\", BadGateway => \"Bad Gateway\",\n        503, \"503\", ServiceUnavailable => \"Service Unavailable\",\n        504, \"504\", GatewayTimeout => \"Gateway Timeout\",\n        505, \"505\", HttpVersionNotSupported => \"HTTP Version Not Supported\",\n        506, \"506\", VariantAlsoNegotiates => \"Variant Also Negotiates\",\n        507, \"507\", InsufficientStorage => \"Insufficient Storage\",\n        508, \"508\", LoopDetected => \"Loop Detected\",\n        510, \"510\", NotExtended => \"Not Extended\",\n        511, \"511\", NetworkAuthenticationRequired => \"Network Authentication Required\"\n    }\n}\n\nimpl fmt::Display for Status {\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{} {}\", self.code, self.reason_lossy())\n    }\n}\n\n#[cfg(feature = \"serde\")]\nmod serde_impl {\n    use super::*;\n\n    use serde::ser::{Serialize, Serializer};\n    use serde::de::{Deserialize, Deserializer, Error, Visitor, Unexpected};\n\n    impl Serialize for Status {\n        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {\n            serializer.serialize_u16(self.code)\n        }\n    }\n\n    struct DeVisitor;\n\n    impl<'de> Visitor<'de> for DeVisitor {\n        type Value = Status;\n\n        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n            write!(formatter, \"HTTP status code integer in range [100, 600)\")\n        }\n\n        fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {\n            if v < 100 || v >= 600 {\n                return Err(E::invalid_value(Unexpected::Signed(v), &self));\n            }\n\n            Ok(Status::new(v as u16))\n        }\n\n        fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {\n            if v < 100 || v >= 600 {\n                return Err(E::invalid_value(Unexpected::Unsigned(v), &self));\n            }\n\n            Ok(Status::new(v as u16))\n        }\n    }\n\n    impl<'de> Deserialize<'de> for Status {\n        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {\n            deserializer.deserialize_u16(DeVisitor)\n        }\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/absolute.rs",
    "content": "use std::borrow::Cow;\n\nuse crate::ext::IntoOwned;\nuse crate::parse::{Extent, IndexedStr};\nuse crate::uri::{Authority, Path, Query, Data, Error, as_utf8_unchecked, fmt};\n\n/// A URI with a scheme, authority, path, and query.\n///\n/// # Structure\n///\n/// The following diagram illustrates the syntactic structure of an absolute\n/// URI with all optional parts:\n///\n/// ```text\n///  http://user:pass@domain.com:4444/foo/bar?some=query\n///  |--|  |------------------------||------| |--------|\n/// scheme          authority          path      query\n/// ```\n///\n/// Only the scheme part of the URI is required.\n///\n/// # Normalization\n///\n/// Rocket prefers _normalized_ absolute URIs, an absolute URI with the\n/// following properties:\n///\n///   * If there is an authority, the path is empty or absolute.\n///   * The path and query, if any, are normalized with no empty segments except\n///     optionally for one trailing slash.\n///\n/// The [`Absolute::is_normalized()`] method checks for normalization while\n/// [`Absolute::into_normalized()`] normalizes any absolute URI.\n///\n/// As an example, the following URIs are all valid, normalized URIs:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::http::uri::Absolute;\n/// # let valid_uris = [\n/// \"http://rocket.rs\",\n/// \"http://rocket.rs/\",\n/// \"ftp:/a/b/\",\n/// \"ftp:/a/b/?\",\n/// \"scheme:/foo/bar\",\n/// \"scheme:/foo/bar/\",\n/// \"scheme:/foo/bar/?\",\n/// \"scheme:/foo/bar/?abc\",\n/// # ];\n/// # for uri in &valid_uris {\n/// #     let uri = Absolute::parse(uri).unwrap();\n/// #     assert!(uri.is_normalized(), \"{} non-normal?\", uri);\n/// # }\n/// ```\n///\n/// By contrast, the following are valid but non-normal URIs:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::http::uri::Absolute;\n/// # let invalid = [\n/// \"ftp:/a//c//d\",         // two empty segments\n/// \"ftp:/?foo&\",           // trailing empty query segment\n/// \"ftp:/?fooa&&b\",        // empty query segment\n/// # ];\n/// # for uri in &invalid {\n/// #   assert!(!Absolute::parse(uri).unwrap().is_normalized());\n/// # }\n/// ```\n///\n/// # (De)serialization\n///\n/// `Absolute` is both `Serialize` and `Deserialize`:\n///\n/// ```rust\n/// # #[cfg(feature = \"serde\")] mod serde_impl {\n/// # use serde as serde;\n/// use serde::{Serialize, Deserialize};\n/// use rocket::http::uri::Absolute;\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriOwned {\n///     uri: Absolute<'static>,\n/// }\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriBorrowed<'a> {\n///     uri: Absolute<'a>,\n/// }\n/// # }\n/// ```\n#[derive(Debug, Clone)]\npub struct Absolute<'a> {\n    pub(crate) source: Option<Cow<'a, str>>,\n    pub(crate) scheme: IndexedStr<'a>,\n    pub(crate) authority: Option<Authority<'a>>,\n    pub(crate) path: Data<'a, fmt::Path>,\n    pub(crate) query: Option<Data<'a, fmt::Query>>,\n}\n\nimpl<'a> Absolute<'a> {\n    /// Parses the string `string` into an `Absolute`. Parsing will never\n    /// allocate. Returns an `Error` if `string` is not a valid absolute URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Absolute;\n    ///\n    /// // Parse a valid authority URI.\n    /// let uri = Absolute::parse(\"https://rocket.rs\").expect(\"valid URI\");\n    /// assert_eq!(uri.scheme(), \"https\");\n    /// assert_eq!(uri.authority().unwrap().host(), \"rocket.rs\");\n    /// assert_eq!(uri.path(), \"\");\n    /// assert!(uri.query().is_none());\n    ///\n    /// // Prefer to use `uri!()` when the input is statically known:\n    /// let uri = uri!(\"https://rocket.rs\");\n    /// assert_eq!(uri.scheme(), \"https\");\n    /// assert_eq!(uri.authority().unwrap().host(), \"rocket.rs\");\n    /// assert_eq!(uri.path(), \"\");\n    /// assert!(uri.query().is_none());\n    /// ```\n    pub fn parse(string: &'a str) -> Result<Absolute<'a>, Error<'a>> {\n        crate::parse::uri::absolute_from_str(string)\n    }\n\n    /// Parses the string `string` into an `Absolute`. Allocates minimally on\n    /// success and error.\n    ///\n    /// This method should be used instead of [`Absolute::parse()`] when the\n    /// source URI is already a `String`. Returns an `Error` if `string` is not\n    /// a valid absolute URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Absolute;\n    ///\n    /// let source = format!(\"https://rocket.rs/foo/{}/three\", 2);\n    /// let uri = Absolute::parse_owned(source).expect(\"valid URI\");\n    /// assert_eq!(uri.authority().unwrap().host(), \"rocket.rs\");\n    /// assert_eq!(uri.path(), \"/foo/2/three\");\n    /// assert!(uri.query().is_none());\n    /// ```\n    // TODO: Avoid all allocations.\n    pub fn parse_owned(string: String) -> Result<Absolute<'static>, Error<'static>> {\n        let absolute = Absolute::parse(&string).map_err(|e| e.into_owned())?;\n        debug_assert!(absolute.source.is_some(), \"Absolute parsed w/o source\");\n\n        let absolute = Absolute {\n            scheme: absolute.scheme.into_owned(),\n            authority: absolute.authority.into_owned(),\n            query: absolute.query.into_owned(),\n            path: absolute.path.into_owned(),\n            source: Some(Cow::Owned(string)),\n        };\n\n        Ok(absolute)\n    }\n\n    /// Returns the scheme part of the absolute URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"ftp://127.0.0.1\");\n    /// assert_eq!(uri.scheme(), \"ftp\");\n    /// ```\n    #[inline(always)]\n    pub fn scheme(&self) -> &str {\n        self.scheme.from_cow_source(&self.source)\n    }\n\n    /// Returns the authority part of the absolute URI, if there is one.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"https://rocket.rs:80\");\n    /// assert_eq!(uri.scheme(), \"https\");\n    /// let authority = uri.authority().unwrap();\n    /// assert_eq!(authority.host(), \"rocket.rs\");\n    /// assert_eq!(authority.port(), Some(80));\n    ///\n    /// let uri = uri!(\"file:/web/home\");\n    /// assert_eq!(uri.authority(), None);\n    /// ```\n    #[inline(always)]\n    pub fn authority(&self) -> Option<&Authority<'a>> {\n        self.authority.as_ref()\n    }\n\n    /// Returns the path part. May be empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"ftp://rocket.rs/foo/bar\");\n    /// assert_eq!(uri.path(), \"/foo/bar\");\n    ///\n    /// let uri = uri!(\"ftp://rocket.rs\");\n    /// assert!(uri.path().is_empty());\n    /// ```\n    #[inline(always)]\n    pub fn path(&self) -> Path<'_> {\n        Path { source: &self.source, data: &self.path }\n    }\n\n    /// Returns the query part with the leading `?`. May be empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"ftp://rocket.rs/foo?bar\");\n    /// assert_eq!(uri.query().unwrap(), \"bar\");\n    ///\n    /// let uri = uri!(\"ftp://rocket.rs\");\n    /// assert!(uri.query().is_none());\n    /// ```\n    #[inline(always)]\n    pub fn query(&self) -> Option<Query<'_>> {\n        self.query.as_ref().map(|data| Query { source: &self.source, data })\n    }\n\n    /// Removes the query part of this URI, if there is any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let mut uri = uri!(\"ftp://rocket.rs/foo?bar\");\n    /// assert_eq!(uri.query().unwrap(), \"bar\");\n    ///\n    /// uri.clear_query();\n    /// assert!(uri.query().is_none());\n    /// ```\n    #[inline(always)]\n    pub fn clear_query(&mut self) {\n        self.set_query(None);\n    }\n\n    /// Returns `true` if `self` is normalized. Otherwise, returns `false`.\n    ///\n    /// See [Normalization](#normalization) for more information on what it\n    /// means for an absolute URI to be normalized. Note that `uri!()` always\n    /// returns a normalized version of its static input.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Absolute;\n    ///\n    /// assert!(uri!(\"http://rocket.rs\").is_normalized());\n    /// assert!(uri!(\"http://rocket.rs///foo////bar\").is_normalized());\n    ///\n    /// assert!(Absolute::parse(\"http:/\").unwrap().is_normalized());\n    /// assert!(Absolute::parse(\"http://\").unwrap().is_normalized());\n    /// assert!(Absolute::parse(\"http://foo.rs/foo/bar\").unwrap().is_normalized());\n    /// assert!(Absolute::parse(\"foo:bar\").unwrap().is_normalized());\n    /// assert!(Absolute::parse(\"git://rocket.rs/\").unwrap().is_normalized());\n    ///\n    /// assert!(!Absolute::parse(\"http:/foo//bar\").unwrap().is_normalized());\n    /// assert!(!Absolute::parse(\"foo:bar?baz&&bop\").unwrap().is_normalized());\n    /// ```\n    pub fn is_normalized(&self) -> bool {\n        let normalized_query = self.query().map_or(true, |q| q.is_normalized());\n        if self.authority().is_some() && !self.path().is_empty() {\n            self.path().is_normalized(true) && normalized_query\n        } else {\n            self.path().is_normalized(false) && normalized_query\n        }\n    }\n\n    /// Normalizes `self` in-place. Does nothing if `self` is already\n    /// normalized.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::uri::Absolute;\n    ///\n    /// let mut uri = Absolute::parse(\"git://rocket.rs\").unwrap();\n    /// assert!(uri.is_normalized());\n    ///\n    /// let mut uri = Absolute::parse(\"git://rocket.rs/\").unwrap();\n    /// assert!(uri.is_normalized());\n    ///\n    /// let mut uri = Absolute::parse(\"http:/foo//bar\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// uri.normalize();\n    /// assert!(uri.is_normalized());\n    ///\n    /// let mut uri = Absolute::parse(\"foo:bar?baz&&bop\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// uri.normalize();\n    /// assert!(uri.is_normalized());\n    /// ```\n    pub fn normalize(&mut self) {\n        if self.authority().is_some() && !self.path().is_empty() {\n            if !self.path().is_normalized(true) {\n                self.path = self.path().to_normalized(true, true);\n            }\n        } else if !self.path().is_normalized(false) {\n            self.path = self.path().to_normalized(false, true);\n        }\n\n        if let Some(query) = self.query() {\n            if !query.is_normalized() {\n                self.query = Some(query.to_normalized());\n            }\n        }\n    }\n\n    /// Normalizes `self`. This is a no-op if `self` is already normalized.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::uri::Absolute;\n    ///\n    /// let mut uri = Absolute::parse(\"git://rocket.rs/\").unwrap();\n    /// assert!(uri.is_normalized());\n    ///\n    /// let mut uri = Absolute::parse(\"http:/foo//bar\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// assert!(uri.into_normalized().is_normalized());\n    ///\n    /// let mut uri = Absolute::parse(\"foo:bar?baz&&bop\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// assert!(uri.into_normalized().is_normalized());\n    /// ```\n    pub fn into_normalized(mut self) -> Self {\n        self.normalize();\n        self\n    }\n\n    /// Sets the authority in `self` to `authority`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let mut uri = uri!(\"https://rocket.rs:80\");\n    /// let authority = uri.authority().unwrap();\n    /// assert_eq!(authority.host(), \"rocket.rs\");\n    /// assert_eq!(authority.port(), Some(80));\n    ///\n    /// let new_authority = uri!(\"rocket.rs:443\");\n    /// uri.set_authority(new_authority);\n    /// let authority = uri.authority().unwrap();\n    /// assert_eq!(authority.host(), \"rocket.rs\");\n    /// assert_eq!(authority.port(), Some(443));\n    /// ```\n    #[inline(always)]\n    pub fn set_authority(&mut self, authority: Authority<'a>) {\n        self.authority = Some(authority);\n    }\n\n    /// Sets the authority in `self` to `authority` and returns `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"https://rocket.rs:80\");\n    /// let authority = uri.authority().unwrap();\n    /// assert_eq!(authority.host(), \"rocket.rs\");\n    /// assert_eq!(authority.port(), Some(80));\n    ///\n    /// let new_authority = uri!(\"rocket.rs\");\n    /// let uri = uri.with_authority(new_authority);\n    /// let authority = uri.authority().unwrap();\n    /// assert_eq!(authority.host(), \"rocket.rs\");\n    /// assert_eq!(authority.port(), None);\n    /// ```\n    #[inline(always)]\n    pub fn with_authority(mut self, authority: Authority<'a>) -> Self {\n        self.set_authority(authority);\n        self\n    }\n}\n\n/// PRIVATE API.\n#[doc(hidden)]\nimpl<'a> Absolute<'a> {\n    /// PRIVATE. Used by parser.\n    ///\n    /// SAFETY: `source` must be valid UTF-8.\n    /// CORRECTNESS: `scheme` must be non-empty.\n    #[inline]\n    pub(crate) unsafe fn raw(\n        source: Cow<'a, [u8]>,\n        scheme: Extent<&'a [u8]>,\n        authority: Option<Authority<'a>>,\n        path: Extent<&'a [u8]>,\n        query: Option<Extent<&'a [u8]>>,\n    ) -> Absolute<'a> {\n        Absolute {\n            source: Some(as_utf8_unchecked(source)),\n            scheme: scheme.into(),\n            authority,\n            path: Data::raw(path),\n            query: query.map(Data::raw)\n        }\n    }\n\n    /// PRIVATE. Used by tests.\n    #[cfg(test)]\n    pub fn new(\n        scheme: &'a str,\n        authority: impl Into<Option<Authority<'a>>>,\n        path: &'a str,\n        query: impl Into<Option<&'a str>>,\n    ) -> Absolute<'a> {\n        assert!(!scheme.is_empty());\n        Absolute::const_new(scheme, authority.into(), path, query.into())\n    }\n\n    /// PRIVATE. Used by codegen and `Host`.\n    #[doc(hidden)]\n    pub const fn const_new(\n        scheme: &'a str,\n        authority: Option<Authority<'a>>,\n        path: &'a str,\n        query: Option<&'a str>,\n    ) -> Absolute<'a> {\n        Absolute {\n            source: None,\n            scheme: IndexedStr::Concrete(Cow::Borrowed(scheme)),\n            authority,\n            path: Data {\n                value: IndexedStr::Concrete(Cow::Borrowed(path)),\n                decoded_segments: state::InitCell::new(),\n            },\n            query: match query {\n                Some(query) => Some(Data {\n                    value: IndexedStr::Concrete(Cow::Borrowed(query)),\n                    decoded_segments: state::InitCell::new(),\n                }),\n                None => None,\n            },\n        }\n    }\n\n    // TODO: Have a way to get a validated `path` to do this. See `Path`?\n    pub(crate) fn set_path<P>(&mut self, path: P)\n        where P: Into<Cow<'a, str>>\n    {\n        self.path = Data::new(path.into());\n    }\n\n    // TODO: Have a way to get a validated `query` to do this. See `Query`?\n    pub(crate) fn set_query<Q: Into<Option<Cow<'a, str>>>>(&mut self, query: Q) {\n        self.query = query.into().map(Data::new);\n    }\n}\n\nimpl_serde!(Absolute<'a>, \"an absolute-form URI\");\n\nimpl_traits!(Absolute, scheme, authority, path, query);\n\nimpl std::fmt::Display for Absolute<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}:\", self.scheme())?;\n        if let Some(authority) = self.authority() {\n            write!(f, \"//{}\", authority)?;\n        }\n\n        write!(f, \"{}\", self.path())?;\n        if let Some(query) = self.query() {\n            write!(f, \"?{}\", query)?;\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/asterisk.rs",
    "content": "use crate::ext::IntoOwned;\nuse crate::uri::Error;\n\n/// The literal `*` URI.\n///\n/// # (De)serialization\n///\n/// `Asterisk` is both `Serialize` and `Deserialize`:\n///\n/// ```rust\n/// # #[cfg(feature = \"serde\")] mod serde_impl {\n/// # use serde as serde;\n/// use serde::{Serialize, Deserialize};\n/// use rocket::http::uri::Asterisk;\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriOwned {\n///     uri: Asterisk,\n/// }\n/// # }\n/// ```\n#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]\npub struct Asterisk;\n\nimpl Asterisk {\n    /// Parses the string `string` into an `Asterisk`. Parsing will never\n    /// allocate. Returns an `Error` if `string` is not a valid asterisk URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Asterisk;\n    ///\n    /// assert!(Asterisk::parse(\"*\").is_ok());\n    /// assert!(Asterisk::parse(\"/foo/bar\").is_err());\n    ///\n    /// // Prefer to use `uri!()` when the input is statically known:\n    /// let uri = uri!(\"*\");\n    /// assert_eq!(uri, Asterisk);\n    /// ```\n    pub fn parse(string: &str) -> Result<Asterisk, Error<'_>> {\n        crate::parse::uri::asterisk_from_str(string)\n    }\n\n    /// Parses the string `string` into an `Asterisk`. This is equivalent to\n    /// [`Asterisk::parse()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Asterisk;\n    ///\n    /// assert!(Asterisk::parse_owned(\"*\".to_string()).is_ok());\n    /// assert!(Asterisk::parse_owned(\"/foo/bar\".to_string()).is_err());\n    /// ```\n    pub fn parse_owned(string: String) -> Result<Asterisk, Error<'static>> {\n        Asterisk::parse(&string).map_err(|e| e.into_owned())\n    }\n}\n\nimpl std::fmt::Display for Asterisk {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        \"*\".fmt(f)\n    }\n}\n\nimpl_serde!(Asterisk, \"an asterisk-form URI, '*'\");\n"
  },
  {
    "path": "core/http/src/uri/authority.rs",
    "content": "use std::fmt::{self, Display};\nuse std::borrow::Cow;\n\nuse crate::ext::IntoOwned;\nuse crate::parse::{Extent, IndexedStr};\nuse crate::uri::{as_utf8_unchecked, error::Error};\n\n/// A URI with an authority only: `user:pass@host:8000`.\n///\n/// # Structure\n///\n/// The following diagram illustrates the syntactic structure of an authority\n/// URI:\n///\n/// ```text\n/// username:password@some.host:8088\n/// |---------------| |-------| |--|\n///     user info        host   port\n/// ```\n///\n/// Only the host part of the URI is required.\n///\n/// # (De)serialization\n///\n/// `Authority` is both `Serialize` and `Deserialize`:\n///\n/// ```rust\n/// # #[cfg(feature = \"serde\")] mod serde_impl {\n/// # use serde as serde;\n/// use serde::{Serialize, Deserialize};\n/// use rocket::http::uri::Authority;\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriOwned {\n///     uri: Authority<'static>,\n/// }\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriBorrowed<'a> {\n///     uri: Authority<'a>,\n/// }\n/// # }\n/// ```\n#[derive(Debug, Clone)]\npub struct Authority<'a> {\n    pub(crate) source: Option<Cow<'a, str>>,\n    pub(crate) user_info: Option<IndexedStr<'a>>,\n    host: IndexedStr<'a>,\n    port: Option<u16>,\n}\n\nimpl<'a> Authority<'a> {\n    // SAFETY: `source` must be valid UTF-8.\n    // CORRECTNESS: `host` must be non-empty.\n    pub(crate) unsafe fn raw(\n        source: Cow<'a, [u8]>,\n        user_info: Option<Extent<&'a [u8]>>,\n        host: Extent<&'a [u8]>,\n        port: Option<u16>\n    ) -> Authority<'a> {\n        Authority {\n            source: Some(as_utf8_unchecked(source)),\n            user_info: user_info.map(IndexedStr::from),\n            host: IndexedStr::from(host),\n            port,\n        }\n    }\n\n    /// PRIVATE. Used by core.\n    #[doc(hidden)]\n    pub fn new(\n        user_info: impl Into<Option<&'a str>>,\n        host: &'a str,\n        port: impl Into<Option<u16>>,\n    ) -> Self {\n        Authority::const_new(user_info.into(), host, port.into())\n    }\n\n    /// PRIVATE. Used by codegen.\n    #[doc(hidden)]\n    pub const fn const_new(user_info: Option<&'a str>, host: &'a str, port: Option<u16>) -> Self {\n        Authority {\n            source: None,\n            user_info: match user_info {\n                Some(info) => Some(IndexedStr::Concrete(Cow::Borrowed(info))),\n                None => None\n            },\n            host: IndexedStr::Concrete(Cow::Borrowed(host)),\n            port,\n        }\n    }\n\n    /// Parses the string `string` into an `Authority`. Parsing will never\n    /// allocate. Returns an `Error` if `string` is not a valid authority URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Authority;\n    ///\n    /// // Parse a valid authority URI.\n    /// let uri = Authority::parse(\"user:pass@host\").expect(\"valid URI\");\n    /// assert_eq!(uri.user_info(), Some(\"user:pass\"));\n    /// assert_eq!(uri.host(), \"host\");\n    /// assert_eq!(uri.port(), None);\n    ///\n    /// // Invalid authority URIs fail to parse.\n    /// Authority::parse(\"https://rocket.rs\").expect_err(\"invalid authority\");\n    ///\n    /// // Prefer to use `uri!()` when the input is statically known:\n    /// let uri = uri!(\"user:pass@host\");\n    /// assert_eq!(uri.user_info(), Some(\"user:pass\"));\n    /// assert_eq!(uri.host(), \"host\");\n    /// assert_eq!(uri.port(), None);\n    /// ```\n    pub fn parse(string: &'a str) -> Result<Authority<'a>, Error<'a>> {\n        crate::parse::uri::authority_from_str(string)\n    }\n\n    /// Parses the string `string` into an `Authority`. Parsing never allocates\n    /// on success. May allocate on error.\n    ///\n    /// This method should be used instead of [`Authority::parse()`] when\n    /// the source URI is already a `String`. Returns an `Error` if `string` is\n    /// not a valid authority URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Authority;\n    ///\n    /// let source = format!(\"rocket.rs:8000\");\n    /// let uri = Authority::parse_owned(source).expect(\"valid URI\");\n    /// assert!(uri.user_info().is_none());\n    /// assert_eq!(uri.host(), \"rocket.rs\");\n    /// assert_eq!(uri.port(), Some(8000));\n    /// ```\n    pub fn parse_owned(string: String) -> Result<Authority<'static>, Error<'static>> {\n        let authority = Authority::parse(&string).map_err(|e| e.into_owned())?;\n        debug_assert!(authority.source.is_some(), \"Authority parsed w/o source\");\n\n        let authority = Authority {\n            host: authority.host.into_owned(),\n            user_info: authority.user_info.into_owned(),\n            port: authority.port,\n            source: Some(Cow::Owned(string)),\n        };\n\n        Ok(authority)\n    }\n\n    /// Returns the user info part of the authority URI, if there is one.\n    ///\n    /// # Example\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"username:password@host\");\n    /// assert_eq!(uri.user_info(), Some(\"username:password\"));\n    /// ```\n    pub fn user_info(&self) -> Option<&str> {\n        self.user_info.as_ref().map(|u| u.from_cow_source(&self.source))\n    }\n\n    /// Returns the host part of the authority URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"domain.com:123\");\n    /// assert_eq!(uri.host(), \"domain.com\");\n    ///\n    /// let uri = uri!(\"username:password@host:123\");\n    /// assert_eq!(uri.host(), \"host\");\n    ///\n    /// let uri = uri!(\"username:password@[1::2]:123\");\n    /// assert_eq!(uri.host(), \"[1::2]\");\n    /// ```\n    #[inline(always)]\n    pub fn host(&self) -> &str {\n        self.host.from_cow_source(&self.source)\n    }\n\n    /// Returns the `port` part of the authority URI, if there is one.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// // With a port.\n    /// let uri = uri!(\"username:password@host:123\");\n    /// assert_eq!(uri.port(), Some(123));\n    ///\n    /// let uri = uri!(\"domain.com:8181\");\n    /// assert_eq!(uri.port(), Some(8181));\n    ///\n    /// // Without a port.\n    /// let uri = uri!(\"username:password@host\");\n    /// assert_eq!(uri.port(), None);\n    /// ```\n    #[inline(always)]\n    pub fn port(&self) -> Option<u16> {\n        self.port\n    }\n\n    /// Set the `port` of the authority URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let mut uri = uri!(\"username:password@host:123\");\n    /// assert_eq!(uri.port(), Some(123));\n    ///\n    /// uri.set_port(1024);\n    /// assert_eq!(uri.port(), Some(1024));\n    /// assert_eq!(uri, \"username:password@host:1024\");\n    ///\n    /// uri.set_port(None);\n    /// assert_eq!(uri.port(), None);\n    /// assert_eq!(uri, \"username:password@host\");\n    /// ```\n    #[inline(always)]\n    pub fn set_port<T: Into<Option<u16>>>(&mut self, port: T) {\n        self.port = port.into();\n    }\n}\n\nimpl_serde!(Authority<'a>, \"an authority-form URI\");\n\nimpl_traits!(Authority, user_info, host, port);\n\nimpl Display for Authority<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(user_info) = self.user_info() {\n            write!(f, \"{}@\", user_info)?;\n        }\n\n        self.host().fmt(f)?;\n        if let Some(port) = self.port {\n            write!(f, \":{}\", port)?;\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/error.rs",
    "content": "//! Errors arising from parsing invalid URIs.\n\nuse std::fmt;\n\npub use crate::parse::uri::Error;\n\n/// The error type returned when a URI conversion fails.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub struct TryFromUriError(pub(crate) ());\n\nimpl fmt::Display for TryFromUriError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        \"invalid conversion from general to specific URI variant\".fmt(f)\n    }\n}\n\n/// An error interpreting a segment as a [`PathBuf`] component in\n/// [`Segments::to_path_buf()`].\n///\n/// [`PathBuf`]: std::path::PathBuf\n/// [`Segments::to_path_buf()`]: crate::uri::Segments::to_path_buf()\n#[derive(Debug, PartialEq, Eq, Clone)]\npub enum PathError {\n    /// The segment started with the wrapped invalid character.\n    BadStart(char),\n    /// The segment contained the wrapped invalid character.\n    BadChar(char),\n    /// The segment ended with the wrapped invalid character.\n    BadEnd(char),\n}\n\nimpl fmt::Display for PathError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            PathError::BadStart(c) => write!(f, \"invalid initial character: {c:?}\"),\n            PathError::BadChar(c) => write!(f, \"invalid character: {c:?}\"),\n            PathError::BadEnd(c) => write!(f, \"invalid terminal character: {c:?}\"),\n        }\n    }\n}\n\nimpl std::error::Error for PathError { }\n"
  },
  {
    "path": "core/http/src/uri/fmt/encoding.rs",
    "content": "use std::marker::PhantomData;\nuse std::borrow::Cow;\n\nuse percent_encoding::AsciiSet;\n\nuse crate::RawStr;\nuse crate::uri::fmt::{Part, Path, Query};\nuse crate::parse::uri::tables::PATH_CHARS;\n\n#[derive(Clone, Copy)]\n#[allow(non_camel_case_types)]\npub struct UNSAFE_ENCODE_SET<P: Part>(PhantomData<P>);\n\npub trait EncodeSet {\n    const SET: AsciiSet;\n}\n\nconst fn set_from_table(table: &'static [u8; 256]) -> AsciiSet {\n    const ASCII_RANGE_LEN: u8 = 0x80;\n\n    let mut set = percent_encoding::CONTROLS.add(0);\n    let mut i: u8 = 0;\n    while i < ASCII_RANGE_LEN {\n        if table[i as usize] == 0 {\n            set = set.add(i);\n        }\n\n        i += 1;\n    }\n\n    set\n}\n\nconst PATH_SET: AsciiSet = set_from_table(&PATH_CHARS);\n\nimpl<P: Part> Default for UNSAFE_ENCODE_SET<P> {\n    #[inline(always)]\n    fn default() -> Self { UNSAFE_ENCODE_SET(PhantomData) }\n}\n\nimpl EncodeSet for UNSAFE_ENCODE_SET<Path> {\n    const SET: AsciiSet = PATH_SET\n        .add(b'%');\n}\n\nimpl EncodeSet for UNSAFE_ENCODE_SET<Query> {\n    const SET: AsciiSet = PATH_SET\n        .remove(b'?')\n        .add(b'%')\n        .add(b'+');\n}\n\n#[derive(Clone, Copy)]\n#[allow(non_camel_case_types)]\npub struct ENCODE_SET<P: Part>(PhantomData<P>);\n\nimpl EncodeSet for ENCODE_SET<Path> {\n    const SET: AsciiSet = <UNSAFE_ENCODE_SET<Path>>::SET\n        .add(b'/');\n}\n\nimpl EncodeSet for ENCODE_SET<Query> {\n    const SET: AsciiSet = <UNSAFE_ENCODE_SET<Query>>::SET\n        .add(b'&')\n        .add(b'=');\n}\n\n#[derive(Default, Clone, Copy)]\n#[allow(non_camel_case_types)]\npub struct DEFAULT_ENCODE_SET;\n\nimpl EncodeSet for DEFAULT_ENCODE_SET {\n    // DEFAULT_ENCODE_SET Includes:\n    // * ENCODE_SET<Path> (and UNSAFE_ENCODE_SET<Path>)\n    const SET: AsciiSet = <ENCODE_SET<Path>>::SET\n        // * UNSAFE_ENCODE_SET<Query>\n        .add(b'%')\n        .add(b'+')\n        // * ENCODE_SET<Query>\n        .add(b'&')\n        .add(b'=');\n}\n\npub fn percent_encode<S: EncodeSet + Default>(string: &RawStr) -> Cow<'_, str> {\n    percent_encoding::utf8_percent_encode(string.as_str(), &S::SET).into()\n}\n\npub fn percent_encode_bytes<S: EncodeSet + Default>(bytes: &[u8]) -> Cow<'_, str> {\n    percent_encoding::percent_encode(bytes, &S::SET).into()\n}\n"
  },
  {
    "path": "core/http/src/uri/fmt/formatter.rs",
    "content": "use std::fmt::{self, Write};\nuse std::marker::PhantomData;\nuse std::borrow::Cow;\n\nuse crate::uri::{Absolute, Origin, Reference};\nuse crate::uri::fmt::{UriDisplay, Part, Path, Query, Kind};\n\n/// A struct used to format strings for [`UriDisplay`].\n///\n/// # Marker Generic: `Formatter<Path>` vs. `Formatter<Query>`\n///\n/// Like [`UriDisplay`], the [`Part`] parameter `P` in `Formatter<P>` must be\n/// either [`Path`] or [`Query`] resulting in either `Formatter<Path>` or\n/// `Formatter<Query>`. The `Path` version is used when formatting parameters\n/// in the path part of the URI while the `Query` version is used when\n/// formatting parameters in the query part of the URI. The\n/// [`write_named_value()`] method is only available to `UriDisplay<Query>`.\n///\n/// # Overview\n///\n/// A mutable version of this struct is passed to [`UriDisplay::fmt()`]. This\n/// struct properly formats series of values for use in URIs. In particular,\n/// this struct applies the following transformations:\n///\n///   * When **multiple values** are written, they are separated by `/` for\n///     `Path` types and `&` for `Query` types.\n///\n/// Additionally, for `Formatter<Query>`:\n///\n///   * When a **named value** is written with [`write_named_value()`], the name\n///     is written out, followed by a `=`, followed by the value.\n///\n///   * When **nested named values** are written, typically by passing a value\n///     to [`write_named_value()`] whose implementation of `UriDisplay` also\n///     calls `write_named_value()`, the nested names are joined by a `.`,\n///     written out followed by a `=`, followed by the value.\n///\n/// # Usage\n///\n/// Usage is fairly straightforward:\n///\n///   * For every _named value_ you wish to emit, call [`write_named_value()`].\n///   * For every _unnamed value_ you wish to emit, call [`write_value()`].\n///   * To write a string directly, call [`write_raw()`].\n///\n/// The `write_named_value` method automatically prefixes the `name` to the\n/// written value and, along with `write_value` and `write_raw`, handles nested\n/// calls to `write_named_value` automatically, prefixing names when necessary.\n/// Unlike the other methods, `write_raw` does _not_ prefix any nested names\n/// every time it is called. Instead, it only prefixes the _first_ time it is\n/// called, after a call to `write_named_value` or `write_value`, or after a\n/// call to [`refresh()`].\n///\n/// # Example\n///\n/// The following example uses all of the `write` methods in a varied order to\n/// display the semantics of `Formatter<Query>`. Note that `UriDisplay` should\n/// rarely be implemented manually, preferring to use the derive, and that this\n/// implementation is purely demonstrative.\n///\n/// ```rust\n/// # extern crate rocket;\n/// use std::fmt;\n///\n/// use rocket::http::uri::fmt::{Formatter, UriDisplay, Query};\n///\n/// struct Outer {\n///     value: Inner,\n///     another: usize,\n///     extra: usize\n/// }\n///\n/// struct Inner {\n///     value: usize,\n///     extra: usize\n/// }\n///\n/// impl UriDisplay<Query> for Outer {\n///     fn fmt(&self, f: &mut Formatter<Query>) -> fmt::Result {\n///         f.write_named_value(\"outer_field\", &self.value)?;\n///         f.write_named_value(\"another\", &self.another)?;\n///         f.write_raw(\"out\")?;\n///         f.write_raw(\"side\")?;\n///         f.write_value(&self.extra)\n///     }\n/// }\n///\n/// impl UriDisplay<Query> for Inner {\n///     fn fmt(&self, f: &mut Formatter<Query>) -> fmt::Result {\n///         f.write_named_value(\"inner_field\", &self.value)?;\n///         f.write_value(&self.extra)?;\n///         f.write_raw(\"inside\")\n///     }\n/// }\n///\n/// let inner = Inner { value: 0, extra: 1 };\n/// let outer = Outer { value: inner, another: 2, extra: 3 };\n/// let uri_string = format!(\"{}\", &outer as &dyn UriDisplay<Query>);\n/// assert_eq!(uri_string, \"outer_field.inner_field=0&\\\n///                         outer_field=1&\\\n///                         outer_field=inside&\\\n///                         another=2&\\\n///                         outside&\\\n///                         3\");\n/// ```\n///\n/// Note that you can also use the `write!` macro to write directly to the\n/// formatter as long as the [`std::fmt::Write`] trait is in scope. Internally,\n/// the `write!` macro calls [`write_raw()`], so care must be taken to ensure\n/// that the written string is URI-safe.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use std::fmt::{self, Write};\n///\n/// use rocket::http::uri::fmt::{UriDisplay, Formatter, Part, Path, Query};\n///\n/// pub struct Complex(u8, u8);\n///\n/// impl<P: Part> UriDisplay<P> for Complex {\n///     fn fmt(&self, f: &mut Formatter<P>) -> fmt::Result {\n///         write!(f, \"{}+{}\", self.0, self.1)\n///     }\n/// }\n///\n/// let uri_string = format!(\"{}\", &Complex(42, 231) as &dyn UriDisplay<Path>);\n/// assert_eq!(uri_string, \"42+231\");\n///\n/// #[derive(UriDisplayQuery)]\n/// struct Message {\n///     number: Complex,\n/// }\n///\n/// let message = Message { number: Complex(42, 47) };\n/// let uri_string = format!(\"{}\", &message as &dyn UriDisplay<Query>);\n/// assert_eq!(uri_string, \"number=42+47\");\n/// ```\n///\n/// [`write_named_value()`]: Formatter::write_value()\n/// [`write_value()`]: Formatter::write_value()\n/// [`write_raw()`]: Formatter::write_raw()\n/// [`refresh()`]: Formatter::refresh()\npub struct Formatter<'i, P: Part> {\n    prefixes: tinyvec::TinyVec<[&'static str; 3]>,\n    inner: &'i mut (dyn Write + 'i),\n    previous: bool,\n    fresh: bool,\n    _marker: PhantomData<P>,\n}\n\nimpl<'i, P: Part> Formatter<'i, P> {\n    #[inline(always)]\n    pub(crate) fn new(inner: &'i mut (dyn Write + 'i)) -> Self {\n        Formatter {\n            inner,\n            prefixes: Default::default(),\n            previous: false,\n            fresh: true,\n            _marker: PhantomData,\n        }\n    }\n\n    #[inline(always)]\n    fn refreshed<F: FnOnce(&mut Self) -> fmt::Result>(&mut self, f: F) -> fmt::Result {\n        self.refresh();\n        let result = f(self);\n        self.refresh();\n        result\n    }\n\n    /// Writes `string` to `self`.\n    ///\n    /// If `self` is _fresh_ (after a call to other `write_` methods or\n    /// [`refresh()`]), prefixes any names and adds separators as necessary.\n    ///\n    /// This method is called by the `write!` macro.\n    ///\n    /// [`refresh()`]: Formatter::refresh()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::fmt;\n    ///\n    /// use rocket::http::uri::fmt::{Formatter, UriDisplay, Part, Path};\n    ///\n    /// struct Foo;\n    ///\n    /// impl<P: Part> UriDisplay<P> for Foo {\n    ///     fn fmt(&self, f: &mut Formatter<P>) -> fmt::Result {\n    ///         f.write_raw(\"f\")?;\n    ///         f.write_raw(\"o\")?;\n    ///         f.write_raw(\"o\")\n    ///     }\n    /// }\n    ///\n    /// let foo = Foo;\n    /// let uri_string = format!(\"{}\", &foo as &dyn UriDisplay<Path>);\n    /// assert_eq!(uri_string, \"foo\");\n    /// ```\n    pub fn write_raw<S: AsRef<str>>(&mut self, string: S) -> fmt::Result {\n        // This implementation is a bit of a lie to the type system. Instead of\n        // implementing this twice, one for <Path> and again for <Query>, we do\n        // this once here. This is okay since we know that this handles the\n        // cases for both Path and Query, and doing it this way allows us to\n        // keep the uri part generic _generic_ in other implementations that use\n        // `write_raw`.\n        if self.fresh {\n            if self.previous {\n                self.inner.write_char(P::DELIMITER)?;\n            }\n\n            if P::KIND == Kind::Query && !self.prefixes.is_empty() {\n                for (i, prefix) in self.prefixes.iter().enumerate() {\n                    if i != 0 { self.inner.write_char('.')? }\n                    self.inner.write_str(prefix)?;\n                }\n\n                self.inner.write_str(\"=\")?;\n            }\n        }\n\n        self.fresh = false;\n        self.previous = true;\n        self.inner.write_str(string.as_ref())\n    }\n\n    /// Writes the unnamed value `value`. Any nested names are prefixed as\n    /// necessary.\n    ///\n    /// Refreshes `self` before and after the value is written.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::fmt;\n    ///\n    /// use rocket::http::uri::fmt::{Formatter, UriDisplay, Part, Path, Query};\n    ///\n    /// struct Foo(usize);\n    ///\n    /// impl<P: Part> UriDisplay<P> for Foo {\n    ///     fn fmt(&self, f: &mut Formatter<P>) -> fmt::Result {\n    ///         f.write_value(&self.0)\n    ///     }\n    /// }\n    ///\n    /// let foo = Foo(123);\n    ///\n    /// let uri_string = format!(\"{}\", &foo as &dyn UriDisplay<Path>);\n    /// assert_eq!(uri_string, \"123\");\n    ///\n    /// let uri_string = format!(\"{}\", &foo as &dyn UriDisplay<Query>);\n    /// assert_eq!(uri_string, \"123\");\n    /// ```\n    #[inline]\n    pub fn write_value<T: UriDisplay<P>>(&mut self, value: T) -> fmt::Result {\n        self.refreshed(|f| UriDisplay::fmt(&value, f))\n    }\n\n    /// Refreshes the formatter.\n    ///\n    /// After refreshing, [`write_raw()`] will prefix any nested names as well\n    /// as insert a separator.\n    ///\n    /// [`write_raw()`]: Formatter::write_raw()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use std::fmt;\n    ///\n    /// use rocket::http::uri::fmt::{Formatter, UriDisplay, Query, Path};\n    ///\n    /// struct Foo;\n    ///\n    /// impl UriDisplay<Query> for Foo {\n    ///     fn fmt(&self, f: &mut Formatter<Query>) -> fmt::Result {\n    ///         f.write_raw(\"a\")?;\n    ///         f.write_raw(\"raw\")?;\n    ///         f.refresh();\n    ///         f.write_raw(\"format\")\n    ///     }\n    /// }\n    ///\n    /// let uri_string = format!(\"{}\", &Foo as &dyn UriDisplay<Query>);\n    /// assert_eq!(uri_string, \"araw&format\");\n    ///\n    /// impl UriDisplay<Path> for Foo {\n    ///     fn fmt(&self, f: &mut Formatter<Path>) -> fmt::Result {\n    ///         f.write_raw(\"a\")?;\n    ///         f.write_raw(\"raw\")?;\n    ///         f.refresh();\n    ///         f.write_raw(\"format\")\n    ///     }\n    /// }\n    ///\n    /// let uri_string = format!(\"{}\", &Foo as &dyn UriDisplay<Path>);\n    /// assert_eq!(uri_string, \"araw/format\");\n    ///\n    /// #[derive(UriDisplayQuery)]\n    /// struct Message {\n    ///     inner: Foo,\n    /// }\n    ///\n    /// let msg = Message { inner: Foo };\n    /// let uri_string = format!(\"{}\", &msg as &dyn UriDisplay<Query>);\n    /// assert_eq!(uri_string, \"inner=araw&inner=format\");\n    /// ```\n    #[inline(always)]\n    pub fn refresh(&mut self) {\n        self.fresh = true;\n    }\n}\n\nimpl Formatter<'_, Query> {\n    fn with_prefix<F>(&mut self, prefix: &str, f: F) -> fmt::Result\n        where F: FnOnce(&mut Self) -> fmt::Result\n    {\n\n        struct PrefixGuard<'f, 'i>(&'f mut Formatter<'i, Query>);\n\n        impl<'f, 'i> PrefixGuard<'f, 'i> {\n            fn new(prefix: &str, f: &'f mut Formatter<'i, Query>) -> Self {\n                // SAFETY: The `prefix` string is pushed in a `StackVec` for use\n                // by recursive (nested) calls to `write_raw`. The string is\n                // pushed in `PrefixGuard` here and then popped in `Drop`.\n                // `prefixes` is modified nowhere else, and no concrete-lifetime\n                // strings leak from the the vector. As a result, it is\n                // impossible for a `prefix` to be accessed incorrectly as:\n                //\n                //   * Rust _guarantees_ `prefix` is valid for this method\n                //   * `prefix` is only reachable while this method's stack is\n                //     active because it is unconditionally popped before this\n                //     method returns via `PrefixGuard::drop()`.\n                //   * should a panic occur in `f()`, `PrefixGuard::drop()` is\n                //     still called (or the program aborts), ensuring `prefix`\n                //     is no longer in `prefixes` and thus inaccessible.\n                //   * thus, at any point `prefix` is reachable, it is valid\n                //\n                // Said succinctly: `prefixes` shadows a subset of the\n                // `with_prefix` stack, making it reachable to other code.\n                let prefix = unsafe { std::mem::transmute(prefix) };\n                f.prefixes.push(prefix);\n                PrefixGuard(f)\n            }\n        }\n\n        impl Drop for PrefixGuard<'_, '_> {\n            fn drop(&mut self) {\n                self.0.prefixes.pop();\n            }\n        }\n\n        f(PrefixGuard::new(prefix, self).0)\n    }\n\n    /// Writes the named value `value` by prefixing `name` followed by `=` to\n    /// the value. Any nested names are also prefixed as necessary.\n    ///\n    /// Refreshes `self` before the name is written and after the value is\n    /// written.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use std::fmt;\n    ///\n    /// use rocket::http::uri::fmt::{Formatter, UriDisplay, Query};\n    ///\n    /// struct Foo {\n    ///     name: usize\n    /// }\n    ///\n    /// // Note: This is identical to what #[derive(UriDisplayQuery)] would\n    /// // generate! In practice, _always_ use the derive.\n    /// impl UriDisplay<Query> for Foo {\n    ///     fn fmt(&self, f: &mut Formatter<Query>) -> fmt::Result {\n    ///         f.write_named_value(\"name\", &self.name)\n    ///     }\n    /// }\n    ///\n    /// let foo = Foo { name: 123 };\n    /// let uri_string = format!(\"{}\", &foo as &dyn UriDisplay<Query>);\n    /// assert_eq!(uri_string, \"name=123\");\n    /// ```\n    #[inline]\n    pub fn write_named_value<T: UriDisplay<Query>>(&mut self, name: &str, value: T) -> fmt::Result {\n        self.refreshed(|f| f.with_prefix(name, |f| f.write_value(value)))\n    }\n}\n\nimpl<P: Part> fmt::Write for Formatter<'_, P> {\n    fn write_str(&mut self, s: &str) -> fmt::Result {\n        self.write_raw(s)\n    }\n}\n\n// Used by code generation.\n#[doc(hidden)]\npub enum UriArgumentsKind<A> {\n    Static(&'static str),\n    Dynamic(A)\n}\n\n// Used by code generation.\n#[doc(hidden)]\npub enum UriQueryArgument<'a> {\n    Raw(&'a str),\n    NameValue(&'a str, &'a dyn UriDisplay<Query>),\n    Value(&'a dyn UriDisplay<Query>)\n}\n\n/// No prefix at all.\n#[doc(hidden)]\npub struct Void;\n\n// Used by code generation.\n#[doc(hidden)]\npub trait ValidRoutePrefix {\n    type Output;\n\n    fn append(self, path: Cow<'static, str>, query: Option<Cow<'static, str>>) -> Self::Output;\n}\n\nimpl<'a> ValidRoutePrefix for Origin<'a> {\n    type Output = Self;\n\n    fn append(self, path: Cow<'static, str>, query: Option<Cow<'static, str>>) -> Self::Output {\n        // No-op if `self` is already normalized.\n        let mut prefix = self.into_normalized();\n        prefix.clear_query();\n\n        // Avoid a double `//` to start.\n        if prefix.path() == \"/\" {\n            return Origin::new(path, query);\n        }\n\n        // Avoid allocating if the `path` would result in just the prefix.\n        if path == \"/\" {\n            prefix.set_query(query);\n            return prefix;\n        }\n\n        // Avoid a `//` resulting from joining.\n        if prefix.has_trailing_slash() && path.starts_with('/') {\n            return Origin::new(format!(\"{}{}\", prefix.path(), &path[1..]), query);\n        }\n\n        // Join normally.\n        Origin::new(format!(\"{}{}\", prefix.path(), path), query)\n    }\n}\n\nimpl<'a> ValidRoutePrefix for Absolute<'a> {\n    type Output = Self;\n\n    fn append(self, path: Cow<'static, str>, query: Option<Cow<'static, str>>) -> Self::Output {\n        // No-op if `self` is already normalized.\n        let mut prefix = self.into_normalized();\n        prefix.clear_query();\n\n        // Distinguish for routes `/` with bases of `/foo/` and `/foo`. The\n        // latter base, without a trailing slash, should combine as `/foo`.\n        if path == \"/\" {\n            prefix.set_query(query);\n            return prefix;\n        }\n\n        // In these cases, appending `path` would be a no-op or worse.\n        if prefix.path().is_empty() || prefix.path() == \"/\" {\n            prefix.set_path(path);\n            prefix.set_query(query);\n            return prefix;\n        }\n\n        // Create the combined URI.\n        prefix.set_path(format!(\"{}{}\", prefix.path(), path));\n        prefix.set_query(query);\n        prefix\n    }\n}\n\n// `Self` is a valid suffix for `T`.\n#[doc(hidden)]\npub trait ValidRouteSuffix<T> {\n    type Output;\n\n    fn prepend(self, prefix: T) -> Self::Output;\n}\n\nimpl<'a> ValidRouteSuffix<Origin<'a>> for Reference<'a> {\n    type Output = Self;\n\n    fn prepend(self, prefix: Origin<'a>) -> Self::Output {\n        Reference::from(prefix).with_query_fragment_of(self)\n    }\n}\n\nimpl<'a> ValidRouteSuffix<Absolute<'a>> for Reference<'a> {\n    type Output = Self;\n\n    fn prepend(self, prefix: Absolute<'a>) -> Self::Output {\n        Reference::from(prefix).with_query_fragment_of(self)\n    }\n}\n\nimpl<'a> ValidRouteSuffix<Origin<'a>> for Absolute<'a> {\n    type Output = Origin<'a>;\n\n    fn prepend(self, mut prefix: Origin<'a>) -> Self::Output {\n        if let Some(query) = self.query {\n            if prefix.query().is_none() {\n                prefix.set_query(query.value.into_concrete(&self.source));\n            }\n        }\n\n        prefix\n    }\n}\n\nimpl<'a> ValidRouteSuffix<Absolute<'a>> for Absolute<'a> {\n    type Output = Self;\n\n    fn prepend(self, mut prefix: Absolute<'a>) -> Self::Output {\n        if let Some(query) = self.query {\n            if prefix.query().is_none() {\n                prefix.set_query(query.value.into_concrete(&self.source));\n            }\n        }\n\n        prefix\n    }\n}\n\n// Used by code generation.\n#[doc(hidden)]\npub struct RouteUriBuilder {\n    pub path: Cow<'static, str>,\n    pub query: Option<Cow<'static, str>>,\n}\n\n// Used by code generation.\n#[doc(hidden)]\npub struct PrefixedRouteUri<T>(T);\n\n// Used by code generation.\n#[doc(hidden)]\npub struct SuffixedRouteUri<T>(T);\n\n// Used by code generation.\n#[doc(hidden)]\nimpl RouteUriBuilder {\n    /// Create a new `RouteUriBuilder` with the given path/query args.\n    pub fn new(\n        path_args: UriArgumentsKind<&[&dyn UriDisplay<Path>]>,\n        query_args: Option<UriArgumentsKind<&[UriQueryArgument<'_>]>>,\n    ) -> Self {\n        use self::{UriArgumentsKind::*, UriQueryArgument::*};\n\n        let path: Cow<'static, str> = match path_args {\n            Static(path) => path.into(),\n            Dynamic(args) => {\n                let mut string = String::from(\"/\");\n                let mut formatter = Formatter::<Path>::new(&mut string);\n                for value in args {\n                    let _ = formatter.write_value(value);\n                }\n\n                string.into()\n            }\n        };\n\n        let query: Option<Cow<'_, str>> = match query_args {\n            None => None,\n            Some(Static(query)) => Some(query.into()),\n            Some(Dynamic(args)) => {\n                let mut string = String::new();\n                let mut f = Formatter::<Query>::new(&mut string);\n                for arg in args {\n                    let _ = match arg {\n                        Raw(v) => f.write_raw(v),\n                        NameValue(n, v) => f.write_named_value(n, v),\n                        Value(v) => f.write_value(v),\n                    };\n                }\n\n                (!string.is_empty()).then(|| string.into())\n            }\n        };\n\n        RouteUriBuilder { path, query }\n    }\n\n    pub fn with_prefix<P: ValidRoutePrefix>(self, p: P) -> PrefixedRouteUri<P::Output> {\n        PrefixedRouteUri(p.append(self.path, self.query))\n    }\n\n    pub fn with_suffix<S>(self, suffix: S) -> SuffixedRouteUri<S::Output>\n        where S: ValidRouteSuffix<Origin<'static>>\n    {\n        SuffixedRouteUri(suffix.prepend(self.render()))\n    }\n\n    pub fn render(self) -> Origin<'static> {\n        Origin::new(self.path, self.query)\n    }\n}\n\n#[doc(hidden)]\nimpl<T> PrefixedRouteUri<T> {\n    pub fn with_suffix<S: ValidRouteSuffix<T>>(self, suffix: S) -> SuffixedRouteUri<S::Output> {\n        SuffixedRouteUri(suffix.prepend(self.0))\n    }\n\n    pub fn render(self) -> T {\n        self.0\n    }\n}\n\n#[doc(hidden)]\nimpl<T> SuffixedRouteUri<T> {\n    pub fn render(self) -> T {\n        self.0\n    }\n}\n\n// See https://github.com/rwf2/Rocket/issues/1534.\n#[cfg(test)]\nmod prefix_soundness_test {\n    use crate::uri::fmt::{Formatter, UriDisplay, Query};\n\n    struct MyValue;\n\n    impl UriDisplay<Query> for MyValue {\n        fn fmt(&self, _f: &mut Formatter<'_, Query>) -> std::fmt::Result {\n            panic!()\n        }\n    }\n\n    struct MyDisplay;\n\n    impl UriDisplay<Query> for MyDisplay {\n        fn fmt(&self, formatter: &mut Formatter<'_, Query>) -> std::fmt::Result {\n            struct Wrapper<'a, 'b>(&'a mut Formatter<'b, Query>);\n\n            impl<'a, 'b> Drop for Wrapper<'a, 'b> {\n                fn drop(&mut self) {\n                    let _overlap = String::from(\"12345\");\n                    self.0.write_raw(\"world\").ok();\n                    assert!(self.0.prefixes.is_empty());\n                }\n            }\n\n            let wrapper = Wrapper(formatter);\n            let temporary_string = String::from(\"hello\");\n\n            // `write_named_value` will push `temp_string` into a buffer and\n            // call the formatter for `MyValue`, which panics. At the panic\n            // point, `formatter` contains an (illegal) static reference to\n            // `temp_string` in its `prefixes` stack. When unwinding occurs,\n            // `Wrapper` will be dropped. `Wrapper` holds a reference to\n            // `Formatter`, thus `Formatter` must be consistent at this point.\n            let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n                wrapper.0.write_named_value(&temporary_string, MyValue)\n            }));\n\n            Ok(())\n        }\n    }\n\n    #[test]\n    fn check_consistency() {\n        let string = format!(\"{}\", &MyDisplay as &dyn UriDisplay<Query>);\n        assert_eq!(string, \"world\");\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/fmt/from_uri_param.rs",
    "content": "use std::path::{Path, PathBuf};\nuse std::collections::{BTreeMap, HashMap};\n\nuse either::Either;\n\nuse crate::uri::fmt::UriDisplay;\nuse crate::uri::fmt::{self, Part};\n\n/// Conversion trait for parameters used in [`uri!`] invocations.\n///\n/// # Overview\n///\n/// In addition to implementing [`UriDisplay`], to use a custom type in a `uri!`\n/// expression, the `FromUriParam` trait must be implemented. The `UriDisplay`\n/// derive automatically generates _identity_ implementations of `FromUriParam`,\n/// so in the majority of cases, as with `UriDisplay`, this trait is never\n/// implemented manually.\n///\n/// In the rare case that `UriDisplay` is implemented manually, this trait, too,\n/// must be implemented explicitly. In the majority of cases, implementation can\n/// be automated. Rocket provides [`impl_from_uri_param_identity!`] to generate\n/// the _identity_ implementations automatically. For a type `T`, these are:\n///\n///   * `impl<P: Part> FromUriParam<P, T> for T`\n///   * `impl<'x, P: Part> FromUriParam<P, &'x T> for T`\n///   * `impl<'x, P: Part> FromUriParam<P, &'x mut T> for T`\n///\n/// See [`impl_from_uri_param_identity!`] for usage details.\n///\n/// [`impl_from_uri_param_identity!`]: crate::impl_from_uri_param_identity!\n///\n/// # Code Generation\n///\n/// This trait is invoked once per expression passed into a [`uri!`] invocation.\n/// In particular, for a route URI parameter of type `T` and a user-supplied\n/// expression `e` of type `S`, `<T as FromUriParam<S>>::from_uri_param(e)` is\n/// invoked. The returned value of type `T::Target` is used in place of the\n/// user's value and rendered using its [`UriDisplay`] implementation.\n///\n/// This trait allows types that differ from the route URI parameter's types to\n/// be used in their place at no cost. For instance, the following\n/// implementation, provided by Rocket, allows an `&str` to be used in a `uri!`\n/// invocation for route URI parameters declared as `String`:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::http::uri::fmt::{FromUriParam, Part};\n/// # struct S;\n/// # type String = S;\n/// impl<'a, P: Part> FromUriParam<P, &'a str> for String {\n///     type Target = &'a str;\n/// #   fn from_uri_param(s: &'a str) -> Self::Target { \"hi\" }\n/// }\n/// ```\n///\n/// Because the [`FromUriParam::Target`] type is the same as the input type, the\n/// conversion is a no-op and free of cost, allowing an `&str` to be used in\n/// place of a `String` without penalty.\n///\n/// # Provided Implementations\n///\n/// The following types have _identity_ implementations:\n///\n///    * `String`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `u8`, `u16`,\n///      `u32`, `u64`, `u128`, `usize`, `f32`, `f64`, `bool`, `IpAddr`,\n///      `Ipv4Addr`, `Ipv6Addr`, `&str`, `Cow<str>`, `Either<A, B>`\n///\n/// The following types have _identity_ implementations _only in [`Path`]_:\n///\n///   * `&Path`, `PathBuf`\n///\n/// The following types have _identity_ implementations _only in [`Query`]_:\n///\n///   * `Option<T>`, `Result<T, E>`\n///\n/// The following conversions are implemented for both paths and queries,\n/// allowing a value of the type on the left to be used when a type on the right\n/// is expected by a route:\n///\n///   * `&str` to `String`\n///   * `String` to `&str`\n///   * `T` to `Form<T>`\n///\n/// The following conversions are implemented _only in [`Path`]_:\n///\n///   * `&str` to `&Path`\n///   * `&str` to `PathBuf`\n///   * `PathBuf` to `&Path`\n///   * `T` to `Option<T>`\n///   * `T` to `Result<T, E>`\n///\n/// The following conversions are implemented _only in [`Query`]_:\n///\n///   * `Option<T>` to `Result<T, E>` (for any `E`)\n///   * `Result<T, E>` to `Option<T>` (for any `E`)\n///\n/// See [Foreign Impls](#foreign-impls) for all provided implementations.\n///\n/// # Implementing\n///\n/// This trait should only be implemented when you'd like to allow a type\n/// different from the route's declared type to be used in its place in a `uri!`\n/// invocation. For instance, if the route has a type of `T` and you'd like to\n/// use a type of `S` in a `uri!` invocation, you'd implement `FromUriParam<P,\n/// T> for S` where `P` is `Path` for conversions valid in the path part of a\n/// URI, `Uri` for conversions valid in the query part of a URI, or `P: Part`\n/// when a conversion is valid in either case.\n///\n/// This is typically only warranted for owned-value types with corresponding\n/// reference types: `String` and `&str`, for instance. In this case, it's\n/// desirable to allow an `&str` to be used in place of a `String`.\n///\n/// When implementing `FromUriParam`, be aware that Rocket will use the\n/// [`UriDisplay`] implementation of [`FromUriParam::Target`], _not_ of the\n/// source type. Incorrect implementations can result in creating unsafe URIs.\n///\n/// # Example\n///\n/// The following example implements `FromUriParam<Query, (&str, &str)>` for a\n/// `User` type. The implementation allows an `(&str, &str)` type to be used in\n/// a `uri!` invocation where a `User` type is expected in the query part of the\n/// URI.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use std::fmt;\n///\n/// use rocket::http::uri::fmt::{Formatter, UriDisplay, FromUriParam, Query};\n///\n/// #[derive(FromForm)]\n/// struct User<'a> {\n///     name: &'a str,\n///     nickname: String,\n/// }\n///\n/// impl UriDisplay<Query> for User<'_> {\n///     fn fmt(&self, f: &mut Formatter<Query>) -> fmt::Result {\n///         f.write_named_value(\"name\", &self.name)?;\n///         f.write_named_value(\"nickname\", &self.nickname)\n///     }\n/// }\n///\n/// impl<'a, 'b> FromUriParam<Query, (&'a str, &'b str)> for User<'a> {\n///     type Target = User<'a>;\n///\n///     fn from_uri_param((name, nickname): (&'a str, &'b str)) -> User<'a> {\n///         User { name: name.into(), nickname: nickname.to_string() }\n///     }\n/// }\n/// ```\n///\n/// With these implementations, the following typechecks:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use std::fmt;\n/// # use rocket::http::uri::fmt::{Formatter, UriDisplay, FromUriParam, Query};\n/// #\n/// # #[derive(FromForm)]\n/// # struct User<'a> { name: &'a str, nickname: String, }\n/// #\n/// # impl UriDisplay<Query> for User<'_> {\n/// #     fn fmt(&self, f: &mut Formatter<Query>) -> fmt::Result {\n/// #         f.write_named_value(\"name\", &self.name)?;\n/// #         f.write_named_value(\"nickname\", &self.nickname)\n/// #     }\n/// # }\n/// #\n/// # impl<'a, 'b> FromUriParam<Query, (&'a str, &'b str)> for User<'a> {\n/// #     type Target = User<'a>;\n/// #     fn from_uri_param((name, nickname): (&'a str, &'b str)) -> User<'a> {\n/// #         User { name: name.into(), nickname: nickname.to_string() }\n/// #     }\n/// # }\n/// #\n/// #[post(\"/<name>?<user..>\")]\n/// fn some_route(name: &str, user: User<'_>)  { /* .. */ }\n///\n/// let uri = uri!(some_route(name = \"hey\", user = (\"Robert Mike\", \"Bob\")));\n/// assert_eq!(uri.path(), \"/hey\");\n/// assert_eq!(uri.query().unwrap(), \"name=Robert%20Mike&nickname=Bob\");\n/// ```\n///\n/// [`uri!`]: ../../../../rocket/macro.uri.html\n/// [`FromUriParam::Target`]: crate::uri::fmt::FromUriParam::Target\n/// [`Path`]: crate::uri::fmt::Path\n/// [`Query`]: crate::uri::fmt::Query\npub trait FromUriParam<P: Part, T> {\n    /// The resulting type of this conversion.\n    type Target: UriDisplay<P>;\n\n    /// Converts a value of type `T` into a value of type `Self::Target`. The\n    /// resulting value of type `Self::Target` will be rendered into a URI using\n    /// its [`UriDisplay`] implementation.\n    fn from_uri_param(param: T) -> Self::Target;\n}\n\n#[doc(hidden)]\n#[macro_export(local_inner_macros)]\nmacro_rules! impl_conversion_ref {\n    ($(($($l:tt)+) $A:ty => $B:ty),* $(,)?) => (\n        impl_conversion_ref!(@_ $(($($l)+,) $A => $B),*);\n    );\n\n    ($($A:ty => $B:ty),* $(,)?) => (\n        impl_conversion_ref!(@_ $(() $A => $B),*);\n    );\n\n    (@_ $(($($l:tt)*) $A:ty => $B:ty),* $(,)?) => ($(\n        impl_conversion_ref!([P] ($($l)* P: $crate::uri::fmt::Part) $A => $B);\n    )*);\n\n    ($([$P:ty] ($($l:tt)*) $A:ty => $B:ty),* $(,)?) => ($(\n        impl_conversion_ref!(@_ [$P] ($($l)*) $A => $B);\n        impl_conversion_ref!(@_ [$P] ('x, $($l)*) &'x $A => $B);\n        impl_conversion_ref!(@_ [$P] ('x, $($l)*) &'x mut $A => $B);\n    )*);\n\n    ($([$P:ty] $A:ty => $B:ty),* $(,)?) => ( impl_conversion_ref!($([$P] () $A => $B),*););\n\n    (@_ [$P:ty] ($($l:tt)*) $A:ty => $B:ty) => (\n        impl<$($l)*> $crate::uri::fmt::FromUriParam<$P, $A> for $B {\n            type Target = $A;\n            #[inline(always)] fn from_uri_param(param: $A) -> $A { param }\n        }\n    );\n}\n\n/// Macro to automatically generate _identity_ [`FromUriParam`] trait\n/// implementations.\n///\n/// For a type `T`, the _identity_ implementations of `FromUriParam` are:\n///\n///   * `impl<P: Part> FromUriParam<P, T> for T`\n///   * `impl<'x> FromUriParam<P, &'x T> for T`\n///   * `impl<'x> FromUriParam<P, &'x mut T> for T`\n///\n/// where `P` is one of:\n///\n///   * `P: Part` (the generic `P`)\n///   * [`Path`]\n///   * [`Query`]\n///\n/// This macro can be invoked in four ways:\n///\n///   1. `impl_from_uri_param_identity!(Type);`\n///\n///      Generates the three _identity_ implementations for the generic `P`.\n///\n///      * Example: `impl_from_uri_param_identity!(MyType);`\n///      * Generates: `impl<P: Part> FromUriParam<P, _> for MyType { ... }`\n///\n///   2. `impl_from_uri_param_identity!((generics*) Type);`\n///\n///      Generates the three _identity_ implementations for the generic `P`,\n///      adding the tokens `generics` to the `impl` generics of the generated\n///      implementation.\n///\n///      * Example: `impl_from_uri_param_identity!(('a) MyType<'a>);`\n///      * Generates: `impl<'a, P: Part> FromUriParam<P, _> for MyType<'a> { ... }`\n///\n///   3. `impl_from_uri_param_identity!([Part] Type);`\n///\n///      Generates the three _identity_ implementations for the `Part`\n///      `Part`, where `Part` is a path to [`Path`] or [`Query`].\n///\n///      * Example: `impl_from_uri_param_identity!([Path] MyType);`\n///      * Generates: `impl FromUriParam<Path, _> for MyType { ... }`\n///\n///   4. `impl_from_uri_param_identity!([Part] (generics*) Type);`\n///\n///      See 2 and 3.\n///\n///      * Example: `impl_from_uri_param_identity!([Path] ('a) MyType<'a>);`\n///      * Generates: `impl<'a> FromUriParam<Path, _> for MyType<'a> { ... }`\n///\n/// [`FromUriParam`]: crate::uri::fmt::FromUriParam\n/// [`Path`]: crate::uri::fmt::Path\n/// [`Query`]: crate::uri::fmt::Query\n#[macro_export(local_inner_macros)]\nmacro_rules! impl_from_uri_param_identity {\n    ($(($($l:tt)*) $T:ty),* $(,)?) => ($( impl_conversion_ref!(($($l)*) $T => $T); )*);\n    ($([$P:ty] ($($l:tt)*) $T:ty),* $(,)?) => ($( impl_conversion_ref!([$P] ($($l)*) $T => $T); )*);\n    ($([$P:ty] $T:ty),* $(,)?) => ($( impl_conversion_ref!([$P] $T => $T); )*);\n    ($($T:ty),* $(,)?) => ($( impl_conversion_ref!($T => $T); )*);\n}\n\nuse std::borrow::Cow;\nuse std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};\nuse std::num::{\n    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,\n    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,\n};\n\nimpl_from_uri_param_identity! {\n    String,\n    i8, i16, i32, i64, i128, isize,\n    u8, u16, u32, u64, u128, usize,\n    f32, f64, bool,\n    IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6,\n    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,\n    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,\n    time::Date, time::Time, time::PrimitiveDateTime,\n}\n\nimpl_from_uri_param_identity! {\n    ('a) &'a str,\n    ('a) Cow<'a, str>\n}\n\nimpl_conversion_ref! {\n    ('a) &'a str => String,\n\n    ('a) String => &'a str\n}\n\nimpl_from_uri_param_identity!([fmt::Path] ('a) &'a Path);\nimpl_from_uri_param_identity!([fmt::Path] PathBuf);\n\nimpl_conversion_ref! {\n    [fmt::Path] ('a) &'a Path => PathBuf,\n    [fmt::Path] ('a) PathBuf => &'a Path,\n}\n\n// TODO: A specialized `RawBytes` instead of `&[u8]`. Then impl [T] => Vec<T>.\nimpl_from_uri_param_identity!([fmt::Query] ('a) &'a [u8]);\n\nimpl_conversion_ref! {\n    [fmt::Query] (T, A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>) Vec<A> => Vec<T>,\n    [fmt::Query] (\n            T,\n            A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,\n            const N: usize\n        ) Vec<A> => [T; N],\n\n    [fmt::Query] (\n            T,\n            A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,\n            const N: usize\n        ) [A; N] => Vec<T>,\n\n    [fmt::Query] (\n            T,\n            A: FromUriParam<fmt::Query, T> + UriDisplay<fmt::Query>,\n            const N: usize\n        ) [A; N] => [T; N],\n}\n\n/// A no cost conversion allowing an `&str` to be used in place of a `PathBuf`.\nimpl<'a> FromUriParam<fmt::Path, &'a str> for PathBuf {\n    type Target = &'a Path;\n\n    #[inline(always)]\n    fn from_uri_param(param: &'a str) -> &'a Path {\n        Path::new(param)\n    }\n}\n\n/// A no cost conversion allowing an `&&str` to be used in place of a `PathBuf`.\nimpl<'a, 'b> FromUriParam<fmt::Path, &'a &'b str> for PathBuf {\n    type Target = &'b Path;\n\n    #[inline(always)]\n    fn from_uri_param(param: &'a &'b str) -> &'b Path {\n        Path::new(*param)\n    }\n}\n\n/// A no cost conversion allowing any `T` to be used in place of an `Option<T>`.\nimpl<A, T: FromUriParam<fmt::Path, A>> FromUriParam<fmt::Path, A> for Option<T> {\n    type Target = T::Target;\n\n    #[inline(always)]\n    fn from_uri_param(param: A) -> Self::Target {\n        T::from_uri_param(param)\n    }\n}\n\n/// A no cost conversion allowing `T` to be used in place of an `Result<T, E>`.\nimpl<A, E, T> FromUriParam<fmt::Path, A> for Result<T, E>\n    where T: FromUriParam<fmt::Path, A>\n{\n    type Target = T::Target;\n\n    #[inline(always)]\n    fn from_uri_param(param: A) -> Self::Target {\n        T::from_uri_param(param)\n    }\n}\n\nimpl<P: Part, A, B, T, U> FromUriParam<P, Either<A, B>> for Either<T, U>\n    where T: FromUriParam<P, A>, U: FromUriParam<P, B>\n{\n    type Target = Either<T::Target, U::Target>;\n\n    fn from_uri_param(param: Either<A, B>) -> Self::Target {\n        match param {\n            Either::Left(a) => Either::Left(T::from_uri_param(a)),\n            Either::Right(b) => Either::Right(U::from_uri_param(b)),\n        }\n    }\n}\n\nimpl<A, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Option<A>> for Option<T> {\n    type Target = Option<T::Target>;\n\n    #[inline(always)]\n    fn from_uri_param(param: Option<A>) -> Self::Target {\n        param.map(T::from_uri_param)\n    }\n}\n\nimpl<A, E, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Option<A>> for Result<T, E> {\n    type Target = Option<T::Target>;\n\n    #[inline(always)]\n    fn from_uri_param(param: Option<A>) -> Self::Target {\n        param.map(T::from_uri_param)\n    }\n}\n\nimpl<A, E, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Result<A, E>> for Result<T, E> {\n    type Target = Result<T::Target, E>;\n\n    #[inline(always)]\n    fn from_uri_param(param: Result<A, E>) -> Self::Target {\n        param.map(T::from_uri_param)\n    }\n}\n\nimpl<A, E, T: FromUriParam<fmt::Query, A>> FromUriParam<fmt::Query, Result<A, E>> for Option<T> {\n    type Target = Result<T::Target, E>;\n\n    #[inline(always)]\n    fn from_uri_param(param: Result<A, E>) -> Self::Target {\n        param.map(T::from_uri_param)\n    }\n}\n\nmacro_rules! impl_map_conversion {\n    ($From:ident => $To:ident) => (\n        impl<K, V, A, B> FromUriParam<fmt::Query, $From<A, B>> for $To<K, V>\n            where A: UriDisplay<fmt::Query>, K: FromUriParam<fmt::Query, A>,\n                  B: UriDisplay<fmt::Query>, V: FromUriParam<fmt::Query, B>\n        {\n            type Target = $From<A, B>;\n\n            #[inline(always)]\n            fn from_uri_param(param: $From<A, B>) -> Self::Target {\n                param\n            }\n        }\n    );\n\n    (& $([$mut:tt])? $From:ident => $To:ident) => (\n        impl<'a, K, V, A, B> FromUriParam<fmt::Query, &'a $($mut)? $From<A, B>> for $To<K, V>\n            where A: UriDisplay<fmt::Query>, K: FromUriParam<fmt::Query, A>,\n                  B: UriDisplay<fmt::Query>, V: FromUriParam<fmt::Query, B>\n        {\n            type Target = &'a $From<A, B>;\n\n            #[inline(always)]\n            fn from_uri_param(param: &'a $($mut)? $From<A, B>) -> Self::Target {\n                param\n            }\n        }\n    );\n}\n\nimpl_map_conversion!(HashMap => HashMap);\nimpl_map_conversion!(HashMap => BTreeMap);\nimpl_map_conversion!(BTreeMap => BTreeMap);\nimpl_map_conversion!(BTreeMap => HashMap);\n\nimpl_map_conversion!(&HashMap => HashMap);\nimpl_map_conversion!(&HashMap => BTreeMap);\nimpl_map_conversion!(&BTreeMap => BTreeMap);\nimpl_map_conversion!(&BTreeMap => HashMap);\n\nimpl_map_conversion!(&[mut] HashMap => HashMap);\nimpl_map_conversion!(&[mut] HashMap => BTreeMap);\nimpl_map_conversion!(&[mut] BTreeMap => BTreeMap);\nimpl_map_conversion!(&[mut] BTreeMap => HashMap);\n"
  },
  {
    "path": "core/http/src/uri/fmt/mod.rs",
    "content": "//! Type safe and URI safe formatting types and traits.\n\nmod uri_display;\nmod formatter;\nmod from_uri_param;\nmod encoding;\nmod part;\n\npub use self::formatter::*;\npub use self::uri_display::*;\npub use self::from_uri_param::*;\npub use self::part::*;\n\npub(crate) use self::encoding::*;\n"
  },
  {
    "path": "core/http/src/uri/fmt/part.rs",
    "content": "use crate::parse::IndexedStr;\n\n/// Marker trait for types that mark a part of a URI.\n///\n/// This trait exists solely to categorize types that mark a part of the URI,\n/// currently [`Path`] and [`Query`]. Said another way, types that implement\n/// this trait are marker types that represent a part of a URI at the\n/// type-level.\n///\n/// This trait is _sealed_: it cannot be implemented outside of Rocket.\n///\n/// # Usage\n///\n/// You will find this trait in traits like [`UriDisplay`] or structs like\n/// [`Formatter`] as the bound on a generic parameter: `P: Part`. Because the\n/// trait is sealed, the generic type is guaranteed to be instantiated as one of\n/// [`Query`] or [`Path`], effectively creating two instances of the generic\n/// items: `UriDisplay<Query>` and `UriDisplay<Path>`, and `Formatter<Query>`\n/// and `Formatter<Path>`. Unlike having two distinct, non-generic traits, this\n/// approach enables succinct, type-checked generic implementations of these\n/// items.\n///\n/// [`UriDisplay`]: crate::uri::fmt::UriDisplay\n/// [`Formatter`]: crate::uri::fmt::Formatter\npub trait Part: private::Sealed {\n    /// The dynamic version of `Self`.\n    #[doc(hidden)]\n    const KIND: Kind;\n\n    /// The delimiter used to separate components of this URI part.\n    /// Specifically, `/` for `Path` and `&` for `Query`.\n    #[doc(hidden)]\n    const DELIMITER: char;\n\n    /// The raw form of a segment in this part.\n    #[doc(hidden)]\n    type Raw: Send + Sync + 'static;\n}\n\nmod private {\n    pub trait Sealed {}\n    impl Sealed for super::Path {}\n    impl Sealed for super::Query {}\n}\n\n/// Dynamic version of the `Path` and `Query` parts.\n#[doc(hidden)]\n#[derive(Debug, PartialEq, Eq, Copy, Clone)]\npub enum Kind { Path, Query }\n\n/// Marker type indicating use of a type for the path [`Part`] of a URI.\n///\n/// In route URIs, this corresponds to all of the text before a `?`, if any, or\n/// all of the text in the URI otherwise:\n///\n/// ```text\n/// #[get(\"/home/<name>/<page>?<item>\")]\n///        ^------------------ Path\n/// ```\n#[derive(Debug, Clone, Copy)]\npub enum Path {  }\n\n/// Marker type indicating use of a type for the query [`Part`] of a URI.\n///\n/// In route URIs, this corresponds to all of the text after a `?`, if any.\n///\n/// ```text\n/// #[get(\"/home/<name>/<page>?<item>&<form..>\")]\n///                            ^-------------- Query\n/// ```\n#[derive(Debug, Clone, Copy)]\npub enum Query {  }\n\nimpl Part for Path {\n    const KIND: Kind = Kind::Path;\n    const DELIMITER: char = '/';\n    type Raw = IndexedStr<'static>;\n}\n\nimpl Part for Query {\n    const KIND: Kind = Kind::Query;\n    const DELIMITER: char = '&';\n    type Raw = (IndexedStr<'static>, IndexedStr<'static>);\n}\n"
  },
  {
    "path": "core/http/src/uri/fmt/uri_display.rs",
    "content": "use std::collections::{BTreeMap, HashMap};\nuse std::{fmt, path};\nuse std::borrow::Cow;\n\nuse either::Either;\nuse time::{macros::format_description, format_description::FormatItem};\n\nuse crate::RawStr;\nuse crate::uri::fmt::{Part, Path, Query, Formatter};\n\n/// Trait implemented by types that can be displayed as part of a URI in\n/// [`uri!`].\n///\n/// Types implementing this trait can be displayed in a URI-safe manner. Unlike\n/// `Display`, the string written by a `UriDisplay` implementation must be\n/// URI-safe. In practice, this means that the string must either be\n/// percent-encoded or consist only of characters that are alphanumeric, \"-\",\n/// \".\", \"_\", or \"~\" - the \"unreserved\" characters.\n///\n/// # Marker Generic: `Path`, `Query`\n///\n/// The [`Part`] parameter `P` in `UriDisplay<P>` must be either [`Path`] or\n/// [`Query`] (see the [`Part`] documentation for how this is enforced),\n/// resulting in either `UriDisplay<Path>` or `UriDisplay<Query>`.\n///\n/// As the names might imply, the `Path` version of the trait is used when\n/// displaying parameters in the path part of the URI while the `Query` version\n/// is used when displaying parameters in the query part of the URI. These\n/// distinct versions of the trait exist exactly to differentiate, at the\n/// type-level, where in the URI a value is to be written to, allowing for type\n/// safety in the face of differences between the two locations. For example,\n/// while it is valid to use a value of `None` in the query part, omitting the\n/// parameter entirely, doing so is _not_ valid in the path part. By\n/// differentiating in the type system, both of these conditions can be enforced\n/// appropriately through distinct implementations of `UriDisplay<Path>` and\n/// `UriDisplay<Query>`.\n///\n/// Occasionally, the implementation of `UriDisplay` is independent of where the\n/// parameter is to be displayed. When this is the case, the parameter may be\n/// kept generic. That is, implementations can take the form:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use std::fmt;\n/// # use rocket::http::uri::fmt::{Part, UriDisplay, Formatter};\n/// # struct SomeType;\n/// impl<P: Part> UriDisplay<P> for SomeType\n/// # { fn fmt(&self, f: &mut Formatter<P>) -> fmt::Result { Ok(()) } }\n/// ```\n///\n/// # Code Generation\n///\n/// When the [`uri!`] macro is used to generate a URI for a route, the types for\n/// the route's _path_ URI parameters must implement `UriDisplay<Path>`, while\n/// types in the route's query parameters must implement `UriDisplay<Query>`.\n/// Any parameters ignored with `_` must be of a type that implements\n/// [`Ignorable`]. The `UriDisplay` implementation for these types is used when\n/// generating the URI.\n///\n/// To illustrate `UriDisplay`'s role in code generation for `uri!`, consider\n/// the following route:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[get(\"/item/<id>?<track>\")]\n/// fn get_item(id: i32, track: Option<String>) { /* .. */ }\n/// ```\n///\n/// A URI for this route can be generated as follows:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type T = ();\n/// # #[get(\"/item/<id>?<track>\")]\n/// # fn get_item(id: i32, track: Option<String>) { /* .. */ }\n/// #\n/// // With unnamed parameters.\n/// uri!(get_item(100, Some(\"inbound\")));\n///\n/// // With named parameters.\n/// uri!(get_item(id = 100, track = Some(\"inbound\")));\n/// uri!(get_item(track = Some(\"inbound\"), id = 100));\n///\n/// // Ignoring `track`.\n/// uri!(get_item(100, _));\n/// uri!(get_item(100, None as Option<String>));\n/// uri!(get_item(id = 100, track = _));\n/// uri!(get_item(track = _, id = 100));\n/// uri!(get_item(id = 100, track = None as Option<&str>));\n/// ```\n///\n/// After verifying parameters and their types, Rocket will generate code\n/// similar (in spirit) to the following:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::http::uri::Origin;\n/// # use rocket::http::uri::fmt::{UriDisplay, Path, Query};\n/// #\n/// Origin::parse(&format!(\"/item/{}?track={}\",\n///     &100 as &dyn UriDisplay<Path>, &\"inbound\" as &dyn UriDisplay<Query>));\n/// ```\n///\n/// For this expression to typecheck, `i32` must implement `UriDisplay<Path>`\n/// and `&str` must implement `UriDisplay<Query>`. What's more, when `track` is\n/// ignored, `Option<String>` is required to implement [`Ignorable`]. As can be\n/// seen, the implementations will be used to display the value in a URI-safe\n/// manner.\n///\n/// [`uri!`]: ../../../../rocket/macro.uri.html\n///\n/// # Provided Implementations\n///\n/// Rocket implements `UriDisplay<P>` for all `P: Part` for several built-in\n/// types.\n///\n///   * **i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32,\n///     f64, bool, IpAddr, Ipv4Addr, Ipv6Addr**\n///\n///     The implementation of `UriDisplay` for these types is identical to the\n///     `Display` implementation.\n///\n///   * **`String`, `&str`, `Cow<str>`**\n///\n///     The string is percent encoded.\n///\n///   * **`&T`, `&mut T`** _where_ **`T: UriDisplay`**\n///\n///     Uses the implementation of `UriDisplay` for `T`.\n///\n/// Rocket implements `UriDisplay<Path>` (but not `UriDisplay<Query>`) for\n/// several built-in types.\n///\n///   * `T` for **`Option<T>`** _where_ **`T: UriDisplay<Path>`**\n///\n///     Uses the implementation of `UriDisplay` for `T::Target`.\n///\n///     When a type of `Option<T>` appears in a route path, use a type of `T` as\n///     the parameter in `uri!`. Note that `Option<T>` itself _does not_\n///     implement `UriDisplay<Path>`.\n///\n///   * `T` for **`Result<T, E>`** _where_ **`T: UriDisplay<Path>`**\n///\n///     Uses the implementation of `UriDisplay` for `T::Target`.\n///\n///     When a type of `Result<T, E>` appears in a route path, use a type of `T`\n///     as the parameter in `uri!`. Note that `Result<T, E>` itself _does not_\n///     implement `UriDisplay<Path>`.\n///\n/// Rocket implements `UriDisplay<Query>` (but not `UriDisplay<Path>`) for\n/// several built-in types.\n///\n///   * **`Form<T>`, `LenientForm<T>`** _where_ **`T: FromUriParam + FromForm`**\n///\n///     Uses the implementation of `UriDisplay` for `T::Target`.\n///\n///     In general, when a type of `Form<T>` is to be displayed as part of a\n///     URI's query, it suffices to derive `UriDisplay` for `T`. Note that any\n///     type that can be converted into a `T` using [`FromUriParam`] can be used\n///     in place of a `Form<T>` in a `uri!` invocation.\n///\n///   * **`Option<T>`** _where_ **`T: UriDisplay<Query>`**\n///\n///     If the `Option` is `Some`, uses the implementation of `UriDisplay` for\n///     `T`. Otherwise, nothing is rendered.\n///\n///   * **`Result<T, E>`** _where_ **`T: UriDisplay<Query>`**\n///\n///     If the `Result` is `Ok`, uses the implementation of `UriDisplay` for\n///     `T`. Otherwise, nothing is rendered.\n///\n/// [`FromUriParam`]: crate::uri::fmt::FromUriParam\n///\n/// # Deriving\n///\n/// Manually implementing `UriDisplay` should be done with care. For most use\n/// cases, deriving `UriDisplay` will suffice:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use rocket::http::uri::fmt::{UriDisplay, Query, Path};\n/// // Derives `UriDisplay<Query>`\n/// #[derive(UriDisplayQuery)]\n/// struct User {\n///     name: String,\n///     age: usize,\n/// }\n///\n/// let user = User { name: \"Michael Smith\".into(), age: 31 };\n/// let uri_string = format!(\"{}\", &user as &dyn UriDisplay<Query>);\n/// assert_eq!(uri_string, \"name=Michael%20Smith&age=31\");\n///\n/// // Derives `UriDisplay<Path>`\n/// #[derive(UriDisplayPath)]\n/// struct Name(String);\n///\n/// let name = Name(\"Bob Smith\".into());\n/// let uri_string = format!(\"{}\", &name as &dyn UriDisplay<Path>);\n/// assert_eq!(uri_string, \"Bob%20Smith\");\n/// ```\n///\n/// As long as every field in the structure (or enum for [`UriDisplay<Query>`])\n/// implements `UriDisplay`, the trait can be derived. The implementation calls\n/// [`Formatter::write_named_value()`] for every named field and\n/// [`Formatter::write_value()`] for every unnamed field. See the\n/// [`UriDisplay<Path>`] and [`UriDisplay<Query>`] derive documentation for full\n/// details.\n///\n/// [`Ignorable`]: crate::uri::fmt::Ignorable\n/// [`UriDisplay<Path>`]: ../../../derive.UriDisplayPath.html\n/// [`UriDisplay<Query>`]: ../../../derive.UriDisplayQuery.html\n///\n/// # Implementing\n///\n/// Implementing `UriDisplay` is similar to implementing\n/// [`Display`](std::fmt::Display) with the caveat that extra care must be\n/// taken to ensure that the written string is URI-safe. As mentioned before, in\n/// practice, this means that the string must either be percent-encoded or\n/// consist only of characters that are alphanumeric, \"-\", \".\", \"_\", or \"~\".\n///\n/// When manually implementing `UriDisplay` for your types, you should defer to\n/// existing implementations of `UriDisplay` as much as possible. In the example\n/// below, for instance, `Name`'s implementation defers to `String`'s\n/// implementation. To percent-encode a string, use\n/// [`Uri::percent_encode()`](crate::uri::Uri::percent_encode()).\n///\n/// ## Example\n///\n/// The following snippet consists of a `Name` type that implements both\n/// `FromParam` and `UriDisplay<Path>`. The `FromParam` implementation allows\n/// `Name` to be used as the target type of a dynamic parameter, while the\n/// `UriDisplay` implementation allows URIs to be generated for routes with\n/// `Name` as a dynamic path parameter type. Note the custom parsing in the\n/// `FromParam` implementation; as a result of this, a custom (reflexive)\n/// `UriDisplay` implementation is required.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::request::FromParam;\n///\n/// struct Name<'r>(&'r str);\n///\n/// const PREFIX: &str = \"name:\";\n///\n/// impl<'r> FromParam<'r> for Name<'r> {\n///     type Error = &'r str;\n///\n///     /// Validates parameters that start with 'name:', extracting the text\n///     /// after 'name:' as long as there is at least one character.\n///     fn from_param(param: &'r str) -> Result<Self, Self::Error> {\n///         if !param.starts_with(PREFIX) || param.len() < (PREFIX.len() + 1) {\n///             return Err(param);\n///         }\n///\n///         let real_name = &param[PREFIX.len()..];\n///         Ok(Name(real_name))\n///     }\n/// }\n///\n/// use std::fmt;\n/// use rocket::http::impl_from_uri_param_identity;\n/// use rocket::http::uri::fmt::{Formatter, FromUriParam, UriDisplay, Path};\n/// use rocket::response::Redirect;\n///\n/// impl UriDisplay<Path> for Name<'_> {\n///     // Writes the raw string `name:`, which is URI-safe, and then delegates\n///     // to the `UriDisplay` implementation for `str` which ensures that\n///     // string is written in a URI-safe manner. In this case, the string will\n///     // be percent encoded.\n///     fn fmt(&self, f: &mut Formatter<Path>) -> fmt::Result {\n///         f.write_raw(\"name:\")?;\n///         UriDisplay::fmt(&self.0, f)\n///     }\n/// }\n///\n/// impl_from_uri_param_identity!([Path] ('a) Name<'a>);\n///\n/// #[get(\"/name/<name>\")]\n/// fn redirector(name: Name<'_>) -> Redirect {\n///     Redirect::to(uri!(real(name)))\n/// }\n///\n/// #[get(\"/<name>\")]\n/// fn real(name: Name<'_>) -> String {\n///     format!(\"Hello, {}!\", name.0)\n/// }\n///\n/// let uri = uri!(real(Name(\"Mike Smith\".into())));\n/// assert_eq!(uri.path(), \"/name:Mike%20Smith\");\n/// ```\npub trait UriDisplay<P: Part> {\n    /// Formats `self` in a URI-safe manner using the given formatter.\n    fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result;\n}\n\nimpl<P: Part> fmt::Display for &dyn UriDisplay<P> {\n    #[inline(always)]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        UriDisplay::fmt(*self, &mut <Formatter<'_, P>>::new(f))\n    }\n}\n\n// Direct implementations: these are the leaves of a call to `UriDisplay::fmt`.\n\n/// Percent-encodes the raw string.\nimpl<P: Part> UriDisplay<P> for str {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n        f.write_raw(RawStr::new(self).percent_encode().as_str())\n    }\n}\n\n/// Percent-encodes each segment in the path and normalizes separators.\nimpl UriDisplay<Path> for path::Path {\n    fn fmt(&self, f: &mut Formatter<'_, Path>) -> fmt::Result {\n        use std::path::Component;\n\n        for component in self.components() {\n            match component {\n                Component::Prefix(_) | Component::RootDir => continue,\n                _ => f.write_value(&component.as_os_str().to_string_lossy())?\n            }\n        }\n\n        Ok(())\n    }\n}\n\nmacro_rules! impl_with_display {\n    ($($T:ty),+ $(,)?) => {$(\n        /// This implementation is identical to the `Display` implementation.\n        impl<P: Part> UriDisplay<P> for $T  {\n            #[inline(always)]\n            fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n                use std::fmt::Write;\n                write!(f, \"{}\", self)\n            }\n        }\n    )+}\n}\n\nuse std::net::{IpAddr, Ipv4Addr, Ipv6Addr};\nuse std::num::{\n    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,\n    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,\n};\n\n// Keep in-sync with the 'FromUriParam' impls.\nimpl_with_display! {\n    i8, i16, i32, i64, i128, isize,\n    u8, u16, u32, u64, u128, usize,\n    f32, f64, bool,\n    IpAddr, Ipv4Addr, Ipv6Addr,\n    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,\n    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,\n}\n\nmacro_rules! impl_with_string {\n    ($($T:ty => $f:expr),+ $(,)?) => {$(\n        /// This implementation is identical to a percent-encoded version of the\n        /// `Display` implementation.\n        impl<P: Part> UriDisplay<P> for $T  {\n            #[inline(always)]\n            fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n                let func: fn(&$T) -> Result<String, fmt::Error> = $f;\n                func(self).and_then(|s| s.as_str().fmt(f))\n            }\n        }\n    )+}\n}\n\nuse std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};\n\n// Keep formats in sync with 'FromFormField' impls.\nstatic DATE_FMT: &[FormatItem<'_>] = format_description!(\"[year padding:none]-[month]-[day]\");\nstatic TIME_FMT: &[FormatItem<'_>] = format_description!(\"[hour padding:none]:[minute]:[second]\");\nstatic DATE_TIME_FMT: &[FormatItem<'_>] =\n    format_description!(\"[year padding:none]-[month]-[day]T[hour padding:none]:[minute]:[second]\");\n\n// Keep list in sync with the 'FromUriParam' impls.\nimpl_with_string! {\n    time::Date => |d| d.format(&DATE_FMT).map_err(|_| fmt::Error),\n    time::Time => |d| d.format(&TIME_FMT).map_err(|_| fmt::Error),\n    time::PrimitiveDateTime => |d| d.format(&DATE_TIME_FMT).map_err(|_| fmt::Error),\n    SocketAddr => |a| Ok(a.to_string()),\n    SocketAddrV4 => |a| Ok(a.to_string()),\n    SocketAddrV6 => |a| Ok(a.to_string()),\n}\n\n// These are second level implementations: they all defer to an existing\n// implementation. Keep in-sync with `FromUriParam` impls.\n\n/// Percent-encodes the raw string. Defers to `str`.\nimpl<P: Part> UriDisplay<P> for String {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n        self.as_str().fmt(f)\n    }\n}\n\n/// Percent-encodes the raw string. Defers to `str`.\nimpl<P: Part> UriDisplay<P> for Cow<'_, str> {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n        self.as_ref().fmt(f)\n    }\n}\n\n/// Percent-encodes each segment in the path and normalizes separators.\nimpl UriDisplay<Path> for path::PathBuf {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, Path>) -> fmt::Result {\n        self.as_path().fmt(f)\n    }\n}\n\n/// Defers to the `UriDisplay<P>` implementation for `T`.\nimpl<P: Part, T: UriDisplay<P> + ?Sized> UriDisplay<P> for &T {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n        UriDisplay::fmt(*self, f)\n    }\n}\n\n/// Defers to `T` or `U` in `Either<T, U>`.\nimpl<P: Part, T: UriDisplay<P>, U: UriDisplay<P>> UriDisplay<P> for Either<T, U> {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n        match self {\n            Either::Left(t) => UriDisplay::fmt(t, f),\n            Either::Right(u) => UriDisplay::fmt(u, f),\n        }\n    }\n}\n\n/// Defers to the `UriDisplay<P>` implementation for `T`.\nimpl<P: Part, T: UriDisplay<P> + ?Sized> UriDisplay<P> for &mut T {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, P>) -> fmt::Result {\n        UriDisplay::fmt(*self, f)\n    }\n}\n\n/// Defers to the `UriDisplay<Query>` implementation for `T`.\nimpl<T: UriDisplay<Query>> UriDisplay<Query> for Option<T> {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {\n        match self {\n            Some(v) => v.fmt(f),\n            None => Ok(())\n        }\n    }\n}\n\n/// Defers to the `UriDisplay<Query>` implementation for `T`.\nimpl<T: UriDisplay<Query>, E> UriDisplay<Query> for Result<T, E> {\n    #[inline(always)]\n    fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {\n        match self {\n            Ok(v) => v.fmt(f),\n            Err(_) => Ok(())\n        }\n    }\n}\n\nimpl<T: UriDisplay<Query>> UriDisplay<Query> for Vec<T> {\n    fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {\n        self.iter().try_for_each(|v| f.write_value(v))\n    }\n}\n\nimpl<T: UriDisplay<Query>, const N: usize> UriDisplay<Query> for [T; N] {\n    fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {\n        self.iter().try_for_each(|v| f.write_value(v))\n    }\n}\n\nimpl UriDisplay<Query> for [u8] {\n    fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {\n        f.write_raw(RawStr::percent_encode_bytes(self).as_str())\n    }\n}\n\nimpl<K: UriDisplay<Query>, V: UriDisplay<Query>> UriDisplay<Query> for HashMap<K, V> {\n    fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {\n        use std::fmt::Write;\n\n        let mut field_name = String::with_capacity(8);\n        for (i, (key, value)) in self.iter().enumerate() {\n            field_name.truncate(0);\n            write!(field_name, \"k:{}\", i)?;\n            f.write_named_value(&field_name, key)?;\n\n            field_name.replace_range(..1, \"v\");\n            f.write_named_value(&field_name, value)?;\n        }\n\n        Ok(())\n    }\n}\n\nimpl<K: UriDisplay<Query>, V: UriDisplay<Query>> UriDisplay<Query> for BTreeMap<K, V> {\n    fn fmt(&self, f: &mut Formatter<'_, Query>) -> fmt::Result {\n        use std::fmt::Write;\n\n        let mut field_name = String::with_capacity(8);\n        for (i, (key, value)) in self.iter().enumerate() {\n            field_name.truncate(0);\n            write!(field_name, \"k:{}\", i)?;\n            f.write_named_value(&field_name, key)?;\n\n            field_name.replace_range(..1, \"v\");\n            f.write_named_value(&field_name, value)?;\n        }\n\n        Ok(())\n    }\n}\n\n#[cfg(feature = \"uuid\")] impl_with_display!(uuid::Uuid);\n#[cfg(feature = \"uuid\")] crate::impl_from_uri_param_identity!(uuid::Uuid);\n\n// And finally, the `Ignorable` trait, which has sugar of `_` in the `uri!`\n// macro, which expands to a typecheck.\n\n/// Trait implemented by types that can be ignored in `uri!`.\n///\n/// When a parameter is explicitly ignored in `uri!` by supplying `_` as the\n/// parameter's value, that parameter's type is required to implement this\n/// trait for the corresponding `Part`.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[get(\"/item/<id>?<track>\")]\n/// fn get_item(id: i32, track: Option<u8>) { /* .. */ }\n///\n/// // Ignore the `track` parameter: `Option<u8>` must be `Ignorable`.\n/// uri!(get_item(100, _));\n/// uri!(get_item(id = 100, track = _));\n///\n/// // Provide a value for `track`.\n/// uri!(get_item(100, Some(4)));\n/// uri!(get_item(id = 100, track = Some(4)));\n/// ```\n///\n/// # Implementations\n///\n/// Only `Option<T>` and `Result<T, E>` implement this trait. You may implement\n/// this trait for your own ignorable types as well:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::http::uri::fmt::{Ignorable, Query};\n///\n/// # struct MyType;\n/// impl Ignorable<Query> for MyType { }\n/// ```\npub trait Ignorable<P: Part> { }\n\nimpl<T> Ignorable<Query> for Option<T> { }\nimpl<T, E> Ignorable<Query> for Result<T, E> { }\n\n#[doc(hidden)]\npub fn assert_ignorable<P: Part, T: Ignorable<P>>() {  }\n\n#[cfg(test)]\nmod uri_display_tests {\n    use std::path;\n    use crate::uri::fmt::{FromUriParam, UriDisplay};\n    use crate::uri::fmt::{Query, Path};\n\n    macro_rules! uri_display {\n        (<$P:ident, $Target:ty> $source:expr) => ({\n            let tmp = $source;\n            let target = <$Target as FromUriParam<$P, _>>::from_uri_param(tmp);\n            format!(\"{}\", &target as &dyn UriDisplay<$P>)\n        })\n    }\n\n    macro_rules! assert_display {\n        (<$P:ident, $Target:ty> $source:expr, $expected:expr) => ({\n            assert_eq!(uri_display!(<$P, $Target> $source), $expected);\n        })\n    }\n\n    #[test]\n    fn uri_display_encoding() {\n        assert_display!(<Query, String> \"hello\", \"hello\");\n        assert_display!(<Query, String> \"hi hi\", \"hi%20hi\");\n        assert_display!(<Query, &str> \"hi hi\", \"hi%20hi\");\n        assert_display!(<Query, &str> &\"hi hi\", \"hi%20hi\");\n        assert_display!(<Query, usize> 10, \"10\");\n        assert_display!(<Query, u8> 10, \"10\");\n        assert_display!(<Query, i32> 10, \"10\");\n        assert_display!(<Query, isize> 10, \"10\");\n\n        assert_display!(<Path, String> \"hello\", \"hello\");\n        assert_display!(<Path, String> \"hi hi\", \"hi%20hi\");\n        assert_display!(<Path, &str> \"hi hi\", \"hi%20hi\");\n        assert_display!(<Path, &str> &\"hi hi\", \"hi%20hi\");\n        assert_display!(<Path, usize> 10, \"10\");\n        assert_display!(<Path, u8> 10, \"10\");\n        assert_display!(<Path, i32> 10, \"10\");\n        assert_display!(<Path, isize> 10, \"10\");\n\n        assert_display!(<Query, &str> &\"hi there\", \"hi%20there\");\n        assert_display!(<Query, isize> &10, \"10\");\n        assert_display!(<Query, u8> &10, \"10\");\n\n        assert_display!(<Path, &str> &\"hi there\", \"hi%20there\");\n        assert_display!(<Path, isize> &10, \"10\");\n        assert_display!(<Path, u8> &10, \"10\");\n\n        assert_display!(<Path, Option<&str>> &\"hi there\", \"hi%20there\");\n        assert_display!(<Path, Option<isize>> &10, \"10\");\n        assert_display!(<Path, Option<u8>> &10, \"10\");\n        assert_display!(<Query, Option<&str>> Some(&\"hi there\"), \"hi%20there\");\n        assert_display!(<Query, Option<isize>> Some(&10), \"10\");\n        assert_display!(<Query, Option<u8>> Some(&10), \"10\");\n\n        assert_display!(<Path, Result<&str, usize>> &\"hi there\", \"hi%20there\");\n        assert_display!(<Path, Result<isize, &str>> &10, \"10\");\n        assert_display!(<Path, Result<u8, String>> &10, \"10\");\n        assert_display!(<Query, Result<&str, usize>> Ok(&\"hi there\"), \"hi%20there\");\n        assert_display!(<Query, Result<isize, &str>> Ok(&10), \"10\");\n        assert_display!(<Query, Result<u8, String>> Ok(&10), \"10\");\n    }\n\n    #[test]\n    fn paths() {\n        assert_display!(<Path, path::PathBuf> \"hello\", \"hello\");\n        assert_display!(<Path, path::PathBuf> \"hi there\", \"hi%20there\");\n        assert_display!(<Path, path::PathBuf> \"hello/world\", \"hello/world\");\n        assert_display!(<Path, path::PathBuf> \"hello//world\", \"hello/world\");\n        assert_display!(<Path, path::PathBuf> \"hello/ world\", \"hello/%20world\");\n\n        assert_display!(<Path, path::PathBuf> \"hi/wo rld\", \"hi/wo%20rld\");\n\n        assert_display!(<Path, path::PathBuf> &\"hi/wo rld\", \"hi/wo%20rld\");\n        assert_display!(<Path, path::PathBuf> &\"hi there\", \"hi%20there\");\n    }\n\n    struct Wrapper<T>(T);\n\n    impl<A, T: FromUriParam<Query, A>> FromUriParam<Query, A> for Wrapper<T> {\n        type Target = T::Target;\n\n        #[inline(always)]\n        fn from_uri_param(param: A) -> Self::Target {\n            T::from_uri_param(param)\n        }\n    }\n\n    impl FromUriParam<Path, usize> for Wrapper<usize> {\n        type Target = usize;\n\n        #[inline(always)]\n        fn from_uri_param(param: usize) -> Self::Target {\n            param\n        }\n    }\n\n    #[test]\n    fn uri_display_encoding_wrapped() {\n        assert_display!(<Query, Option<Wrapper<&str>>> Some(&\"hi there\"), \"hi%20there\");\n        assert_display!(<Query, Option<Wrapper<&str>>> Some(\"hi there\"), \"hi%20there\");\n\n        assert_display!(<Query, Option<Wrapper<isize>>> Some(10), \"10\");\n        assert_display!(<Query, Option<Wrapper<usize>>> Some(18), \"18\");\n        assert_display!(<Path, Option<Wrapper<usize>>> 238, \"238\");\n\n        assert_display!(<Path, Result<Option<Wrapper<usize>>, usize>> 238, \"238\");\n        assert_display!(<Path, Option<Result<Wrapper<usize>, usize>>> 123, \"123\");\n    }\n\n    #[test]\n    fn check_ignorables() {\n        use crate::uri::fmt::assert_ignorable;\n\n        assert_ignorable::<Query, Option<usize>>();\n        assert_ignorable::<Query, Option<Wrapper<usize>>>();\n        assert_ignorable::<Query, Result<Wrapper<usize>, usize>>();\n        assert_ignorable::<Query, Option<Result<Wrapper<usize>, usize>>>();\n        assert_ignorable::<Query, Result<Option<Wrapper<usize>>, usize>>();\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/host.rs",
    "content": "use std::fmt::{self, Display};\n\nuse crate::uncased::UncasedStr;\nuse crate::uri::error::Error;\nuse crate::uri::{Absolute, Authority};\n\n/// A domain and port identified by a client as the server being messaged.\n///\n/// For requests made via HTTP/1.1, a host is identified via the `HOST` header.\n/// In HTTP/2 and HTTP/3, this information is instead communicated via the\n/// `:authority` and `:port` pseudo-header request fields. It is a\n/// client-controlled value via which the client communicates to the server the\n/// domain name and port it is attempting to communicate with. The following\n/// diagram illustrates the syntactic structure of a `Host`:\n///\n/// ```text\n/// some.domain.foo:8088\n/// |-------------| |--|\n///      domain     port\n/// ```\n///\n/// Only the domain part is required. Its value is case-insensitive.\n///\n/// # URI Construction\n///\n/// A `Host` is _not_ a [`Uri`](crate::uri::Uri), and none of Rocket's APIs will\n/// accept a `Host` value as such. This is because doing so would facilitate the\n/// construction of URIs to internal routes in a manner controllable by an\n/// attacker, inevitably leading to \"HTTP Host header attacks\".\n///\n/// Instead, a `Host` must be checked before being converted to a [`Uri`]\n/// value. The [`Host::to_authority`] and [`Host::to_absolute`] methods provide\n/// these mechanisms:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type Token = String;\n/// use rocket::http::uri::Host;\n///\n/// // A sensitive URI we want to prefix with safe hosts.\n/// #[get(\"/token?<secret>\")]\n/// fn token(secret: Token) { /* .. */ }\n///\n/// // Whitelist of known hosts. In a real setting, you might retrieve this\n/// // list from config at ignite-time using tools like `AdHoc::config()`.\n/// const WHITELIST: [Host<'static>; 4] = [\n///     Host::new(uri!(\"rocket.rs\")),\n///     Host::new(uri!(\"rocket.rs:443\")),\n///     Host::new(uri!(\"guide.rocket.rs\")),\n///     Host::new(uri!(\"guide.rocket.rs:443\")),\n/// ];\n///\n/// // Use `Host::to_absolute()` to case-insensitively check a host against a\n/// // whitelist, returning an `Absolute` usable as a `uri!()` prefix.\n/// let host = Host::new(uri!(\"guide.ROCKET.rs\"));\n/// let prefix = host.to_absolute(\"https\", &WHITELIST);\n///\n/// // Since `guide.rocket.rs` is in the whitelist, `prefix` is `Some`.\n/// assert!(prefix.is_some());\n/// if let Some(prefix) = prefix {\n///     // We can use this prefix to safely construct URIs.\n///     let uri = uri!(prefix, token(\"some-secret-token\"));\n///     assert_eq!(uri, \"https://guide.ROCKET.rs/token?secret=some-secret-token\");\n/// }\n/// ```\n///\n/// # (De)serialization\n///\n/// `Host` is both `Serialize` and `Deserialize`:\n///\n/// ```rust\n/// # #[cfg(feature = \"serde\")] mod serde_impl {\n/// # use serde as serde;\n/// use serde::{Serialize, Deserialize};\n/// use rocket::http::uri::Host;\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriOwned {\n///     uri: Host<'static>,\n/// }\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriBorrowed<'a> {\n///     uri: Host<'a>,\n/// }\n/// # }\n/// ```\n#[derive(Debug, Clone)]\npub struct Host<'a>(Authority<'a>);\n\nimpl<'a> Host<'a> {\n    /// Create a new `Host` from an `Authority`. Only the `host` and `port`\n    /// parts are preserved.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Host;\n    ///\n    /// let host = Host::new(uri!(\"developer.mozilla.org\"));\n    /// assert_eq!(host.to_string(), \"developer.mozilla.org\");\n    ///\n    /// let host = Host::new(uri!(\"foo:bar@developer.mozilla.org:1234\"));\n    /// assert_eq!(host.to_string(), \"developer.mozilla.org:1234\");\n    ///\n    /// let host = Host::new(uri!(\"rocket.rs:443\"));\n    /// assert_eq!(host.to_string(), \"rocket.rs:443\");\n    /// ```\n    pub const fn new(authority: Authority<'a>) -> Self {\n        Host(authority)\n    }\n\n    /// Parses the string `string` into a `Host`. Parsing will never allocate.\n    /// Returns an `Error` if `string` is not a valid authority URI, meaning\n    /// that this parser accepts a `user_info` part for compatibility but\n    /// discards it.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Host;\n    ///\n    /// // Parse from a valid authority URI.\n    /// let host = Host::parse(\"user:pass@domain\").expect(\"valid host\");\n    /// assert_eq!(host.domain(), \"domain\");\n    /// assert_eq!(host.port(), None);\n    ///\n    /// // Parse from a valid host.\n    /// let host = Host::parse(\"domain:311\").expect(\"valid host\");\n    /// assert_eq!(host.domain(), \"doMaIN\");\n    /// assert_eq!(host.port(), Some(311));\n    ///\n    /// // Invalid hosts fail to parse.\n    /// Host::parse(\"https://rocket.rs\").expect_err(\"invalid host\");\n    ///\n    /// // Prefer to use `uri!()` when the input is statically known:\n    /// let host = Host::new(uri!(\"domain\"));\n    /// assert_eq!(host.domain(), \"domain\");\n    /// assert_eq!(host.port(), None);\n    /// ```\n    pub fn parse(string: &'a str) -> Result<Host<'a>, Error<'a>> {\n        Host::parse_bytes(string.as_bytes())\n    }\n\n    /// PRIVATE: Used by core.\n    #[doc(hidden)]\n    pub fn parse_bytes(bytes: &'a [u8]) -> Result<Host<'a>, Error<'a>> {\n        crate::parse::uri::authority_from_bytes(bytes).map(Host::new)\n    }\n\n    /// Parses the string `string` into an `Host`. Parsing never allocates\n    /// on success. May allocate on error.\n    ///\n    /// This method should be used instead of [`Host::parse()`] when the source\n    /// is already a `String`. Returns an `Error` if `string` is not a valid\n    /// authority URI, meaning that this parser accepts a `user_info` part for\n    /// compatibility but discards it.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Host;\n    ///\n    /// let source = format!(\"rocket.rs:8000\");\n    /// let host = Host::parse_owned(source).expect(\"valid host\");\n    /// assert_eq!(host.domain(), \"rocket.rs\");\n    /// assert_eq!(host.port(), Some(8000));\n    /// ```\n    pub fn parse_owned(string: String) -> Result<Host<'static>, Error<'static>> {\n        Authority::parse_owned(string).map(Host::new)\n    }\n\n    /// Returns the case-insensitive domain part of the host.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Host;\n    ///\n    /// let host = Host::new(uri!(\"domain.com:123\"));\n    /// assert_eq!(host.domain(), \"domain.com\");\n    ///\n    /// let host = Host::new(uri!(\"username:password@domain:123\"));\n    /// assert_eq!(host.domain(), \"domain\");\n    ///\n    /// let host = Host::new(uri!(\"[1::2]:123\"));\n    /// assert_eq!(host.domain(), \"[1::2]\");\n    /// ```\n    #[inline]\n    pub fn domain(&self) -> &UncasedStr {\n        self.0.host().into()\n    }\n\n    /// Returns the port part of the host, if there is one.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Host;\n    ///\n    /// // With a port.\n    /// let host = Host::new(uri!(\"domain:123\"));\n    /// assert_eq!(host.port(), Some(123));\n    ///\n    /// let host = Host::new(uri!(\"domain.com:8181\"));\n    /// assert_eq!(host.port(), Some(8181));\n    ///\n    /// // Without a port.\n    /// let host = Host::new(uri!(\"domain.foo.bar.tld\"));\n    /// assert_eq!(host.port(), None);\n    /// ```\n    #[inline(always)]\n    pub fn port(&self) -> Option<u16> {\n        self.0.port()\n    }\n\n    /// Checks `self` against `whitelist`. If `self` is in `whitelist`, returns\n    /// an [`Authority`] URI representing self. Otherwise, returns `None`.\n    /// Domain comparison is case-insensitive.\n    ///\n    /// See [URI construction](Self#uri-construction) for more.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Host;\n    ///\n    /// let whitelist = &[Host::new(uri!(\"domain.tld\"))];\n    ///\n    /// // A host in the whitelist returns `Some`.\n    /// let host = Host::new(uri!(\"domain.tld\"));\n    /// let uri = host.to_authority(whitelist);\n    /// assert!(uri.is_some());\n    /// assert_eq!(uri.unwrap().to_string(), \"domain.tld\");\n    ///\n    /// let host = Host::new(uri!(\"foo:bar@doMaIN.tLd\"));\n    /// let uri = host.to_authority(whitelist);\n    /// assert!(uri.is_some());\n    /// assert_eq!(uri.unwrap().to_string(), \"doMaIN.tLd\");\n    ///\n    /// // A host _not_ in the whitelist returns `None`.\n    /// let host = Host::new(uri!(\"domain.tld:1234\"));\n    /// let uri = host.to_authority(whitelist);\n    /// assert!(uri.is_none());\n    /// ```\n    pub fn to_authority<'h, W>(&self, whitelist: W) -> Option<Authority<'a>>\n        where W: IntoIterator<Item = &'h Host<'h>>\n    {\n        let mut auth = whitelist.into_iter().any(|h| h == self).then(|| self.0.clone())?;\n        auth.user_info = None;\n        Some(auth)\n    }\n\n    /// Checks `self` against `whitelist`. If `self` is in `whitelist`, returns\n    /// an [`Absolute`] URI representing `self` with scheme `scheme`. Otherwise,\n    /// returns `None`. Domain comparison is case-insensitive.\n    ///\n    /// See [URI construction](Self#uri-construction) for more.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Host;\n    ///\n    /// let whitelist = &[Host::new(uri!(\"domain.tld:443\"))];\n    ///\n    /// // A host in the whitelist returns `Some`.\n    /// let host = Host::new(uri!(\"user@domain.tld:443\"));\n    /// let uri = host.to_absolute(\"http\", whitelist);\n    /// assert!(uri.is_some());\n    /// assert_eq!(uri.unwrap().to_string(), \"http://domain.tld:443\");\n    ///\n    /// let host = Host::new(uri!(\"domain.TLD:443\"));\n    /// let uri = host.to_absolute(\"https\", whitelist);\n    /// assert!(uri.is_some());\n    /// assert_eq!(uri.unwrap().to_string(), \"https://domain.TLD:443\");\n    ///\n    /// // A host _not_ in the whitelist returns `None`.\n    /// let host = Host::new(uri!(\"domain.tld\"));\n    /// let uri = host.to_absolute(\"http\", whitelist);\n    /// assert!(uri.is_none());\n    /// ```\n    pub fn to_absolute<'h, W>(&self, scheme: &'a str, whitelist: W) -> Option<Absolute<'a>>\n        where W: IntoIterator<Item = &'h Host<'h>>\n    {\n        let scheme = crate::parse::uri::scheme_from_str(scheme).ok()?;\n        let authority = self.to_authority(whitelist)?;\n        Some(Absolute::const_new(scheme, Some(authority), \"\", None))\n    }\n}\n\nimpl_serde!(Host<'a>, \"an HTTP host\");\n\nimpl_base_traits!(Host, domain, port);\n\nimpl crate::ext::IntoOwned for Host<'_> {\n    type Owned = Host<'static>;\n\n    fn into_owned(self) -> Host<'static> {\n        Host(self.0.into_owned())\n    }\n}\n\nimpl<'a> From<Authority<'a>> for Host<'a> {\n    fn from(auth: Authority<'a>) -> Self {\n        Host::new(auth)\n    }\n}\n\nimpl Display for Host<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.domain().fmt(f)?;\n        if let Some(port) = self.port() {\n            write!(f, \":{}\", port)?;\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/mod.rs",
    "content": "//! Types for URIs and traits for rendering URI components.\n\n#[macro_use]\nmod uri;\nmod origin;\nmod reference;\nmod authority;\nmod absolute;\nmod segments;\nmod path_query;\nmod asterisk;\nmod host;\n\npub mod error;\npub mod fmt;\n\n#[doc(inline)]\npub use self::error::Error;\n\npub use self::uri::*;\npub use self::authority::*;\npub use self::origin::*;\npub use self::absolute::*;\npub use self::segments::*;\npub use self::reference::*;\npub use self::path_query::*;\npub use self::asterisk::*;\npub use self::host::*;\n"
  },
  {
    "path": "core/http/src/uri/origin.rs",
    "content": "use std::borrow::Cow;\n\nuse crate::ext::IntoOwned;\nuse crate::parse::{Extent, IndexedStr, uri::tables::is_pchar};\nuse crate::uri::{Error, Path, Query, Data, as_utf8_unchecked, fmt};\nuse crate::{RawStr, RawStrBuf};\n\n/// A URI with an absolute path and optional query: `/path?query`.\n///\n/// Origin URIs are the primary type of URI encountered in Rocket applications.\n/// They are also the _simplest_ type of URIs, made up of only a path and an\n/// optional query.\n///\n/// # Structure\n///\n/// The following diagram illustrates the syntactic structure of an origin URI:\n///\n/// ```text\n/// /first_segment/second_segment/third?optional=query\n/// |---------------------------------| |------------|\n///                 path                    query\n/// ```\n///\n/// The URI must begin with a `/`, can be followed by any number of _segments_,\n/// and an optional `?` query separator and query string.\n///\n/// # Normalization\n///\n/// Rocket prefers, and will sometimes require, origin URIs to be _normalized_.\n/// A normalized origin URI is a valid origin URI that contains no empty\n/// segments except optionally a trailing slash.\n///\n/// As an example, the following URIs are all valid, normalized URIs:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::http::uri::Origin;\n/// # let valid_uris = [\n/// \"/\",\n/// \"/?\",\n/// \"/a/b/\",\n/// \"/a/b/c\",\n/// \"/a/b/c/\",\n/// \"/a/b/c?\",\n/// \"/a/b/c?q\",\n/// \"/hello?lang=en\",\n/// \"/hello/?lang=en\",\n/// \"/some%20thing?q=foo&lang=fr\",\n/// # ];\n/// # for uri in &valid_uris {\n/// #   assert!(Origin::parse(uri).unwrap().is_normalized());\n/// # }\n/// ```\n///\n/// By contrast, the following are valid but _non-normal_ URIs:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::http::uri::Origin;\n/// # let invalid = [\n/// \"//\",               // an empty segment\n/// \"/a/ab//c//d\",      // two empty segments\n/// \"/?a&&b\",           // empty query segment\n/// \"/?foo&\",           // trailing empty query segment\n/// # ];\n/// # for uri in &invalid {\n/// #   assert!(!Origin::parse(uri).unwrap().is_normalized());\n/// # }\n/// ```\n///\n/// The [`Origin::into_normalized()`](crate::uri::Origin::into_normalized())\n/// method can be used to normalize any `Origin`:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::http::uri::Origin;\n/// # let invalid = [\n/// // non-normal versions\n/// \"//\", \"/a/b//c\", \"/a/ab//c//d/\", \"/a?a&&b&\",\n///\n/// // normalized versions\n/// \"/\",  \"/a/b/c\",  \"/a/ab/c/d/\", \"/a?a&b\",\n/// # ];\n/// # for i in 0..(invalid.len() / 2) {\n/// #     let abnormal = Origin::parse(invalid[i]).unwrap();\n/// #     let expected = Origin::parse(invalid[i + (invalid.len() / 2)]).unwrap();\n/// #     assert_eq!(abnormal.into_normalized(), expected);\n/// # }\n/// ```\n///\n/// # (De)serialization\n///\n/// `Origin` is both `Serialize` and `Deserialize`:\n///\n/// ```rust\n/// # #[cfg(feature = \"serde\")] mod serde_impl {\n/// # use serde as serde;\n/// use serde::{Serialize, Deserialize};\n/// use rocket::http::uri::Origin;\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriOwned {\n///     uri: Origin<'static>,\n/// }\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriBorrowed<'a> {\n///     uri: Origin<'a>,\n/// }\n/// # }\n/// ```\n#[derive(Debug, Clone)]\npub struct Origin<'a> {\n    pub(crate) source: Option<Cow<'a, str>>,\n    pub(crate) path: Data<'a, fmt::Path>,\n    pub(crate) query: Option<Data<'a, fmt::Query>>,\n}\n\nimpl<'a> Origin<'a> {\n    /// The root: `'/'`.\n    #[doc(hidden)]\n    pub fn root() -> &'static Origin<'static> {\n        static ROOT_ORIGIN: Origin<'static> = Origin::const_new(\"/\", None);\n        &ROOT_ORIGIN\n    }\n\n    /// SAFETY: `source` must be UTF-8.\n    #[inline]\n    pub(crate) unsafe fn raw(\n        source: Cow<'a, [u8]>,\n        path: Extent<&'a [u8]>,\n        query: Option<Extent<&'a [u8]>>\n    ) -> Origin<'a> {\n        Origin {\n            source: Some(as_utf8_unchecked(source)),\n            path: Data::raw(path),\n            query: query.map(Data::raw)\n        }\n    }\n\n    // Used mostly for testing and to construct known good URIs from other parts\n    // of Rocket. This should _really_ not be used outside of Rocket because the\n    // resulting `Origin's` are not guaranteed to be valid origin URIs!\n    #[doc(hidden)]\n    pub fn new<P, Q>(path: P, query: Option<Q>) -> Origin<'a>\n        where P: Into<Cow<'a, str>>, Q: Into<Cow<'a, str>>\n    {\n        Origin {\n            source: None,\n            path: Data::new(path.into()),\n            query: query.map(Data::new),\n        }\n    }\n\n    // Used mostly for testing and to construct known good URIs from other parts\n    // of Rocket. This should _really_ not be used outside of Rocket because the\n    // resulting `Origin's` are not guaranteed to be valid origin URIs!\n    #[doc(hidden)]\n    pub fn path_only<P: Into<Cow<'a, str>>>(path: P) -> Origin<'a> {\n        Origin::new(path, None::<&'a str>)\n    }\n\n    // Used mostly for testing and to construct known good URIs from other parts\n    // of Rocket. This should _really_ not be used outside of Rocket because the\n    // resulting `Origin's` are not guaranteed to be valid origin URIs!\n    #[doc(hidden)]\n    pub const fn const_new(path: &'a str, query: Option<&'a str>) -> Origin<'a> {\n        Origin {\n            source: None,\n            path: Data {\n                value: IndexedStr::Concrete(Cow::Borrowed(path)),\n                decoded_segments: state::InitCell::new(),\n            },\n            query: match query {\n                Some(query) => Some(Data {\n                    value: IndexedStr::Concrete(Cow::Borrowed(query)),\n                    decoded_segments: state::InitCell::new(),\n                }),\n                None => None,\n            },\n        }\n    }\n\n    pub(crate) fn set_query<Q: Into<Option<Cow<'a, str>>>>(&mut self, query: Q) {\n        self.query = query.into().map(Data::new);\n    }\n\n    /// Parses the string `string` into an `Origin`. Parsing will never\n    /// allocate. Returns an `Error` if `string` is not a valid origin URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// // Parse a valid origin URI.\n    /// let uri = Origin::parse(\"/a/b/c?query\").expect(\"valid URI\");\n    /// assert_eq!(uri.path(), \"/a/b/c\");\n    /// assert_eq!(uri.query().unwrap(), \"query\");\n    ///\n    /// // Invalid URIs fail to parse.\n    /// Origin::parse(\"foo bar\").expect_err(\"invalid URI\");\n    ///\n    /// // Prefer to use `uri!()` when the input is statically known:\n    /// let uri = uri!(\"/a/b/c?query\");\n    /// assert_eq!(uri.path(), \"/a/b/c\");\n    /// assert_eq!(uri.query().unwrap(), \"query\");\n    /// ```\n    pub fn parse(string: &'a str) -> Result<Origin<'a>, Error<'a>> {\n        crate::parse::uri::origin_from_str(string)\n    }\n\n    // Parses an `Origin` which is allowed to contain _any_ `UTF-8` character.\n    // The path must still be absolute `/..`. Don't use this outside of Rocket!\n    #[doc(hidden)]\n    pub fn parse_route(string: &'a str) -> Result<Origin<'a>, Error<'a>> {\n        use pear::error::Expected;\n\n        if !string.starts_with('/') {\n            return Err(Error {\n                expected: Expected::token(Some(&b'/'), string.as_bytes().first().cloned()),\n                index: 0,\n            });\n        }\n\n        let (path, query) = string.split_once('?')\n            .map(|(path, query)| (path, Some(query)))\n            .unwrap_or((string, None));\n\n        Ok(Origin::new(path, query))\n    }\n\n    /// Parses the string `string` into an `Origin`. Never allocates on success.\n    /// May allocate on error.\n    ///\n    /// This method should be used instead of [`Origin::parse()`] when\n    /// the source URI is already a `String`. Returns an `Error` if `string` is\n    /// not a valid origin URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let source = format!(\"/foo/{}/three\", 2);\n    /// let uri = Origin::parse_owned(source).expect(\"valid URI\");\n    /// assert_eq!(uri.path(), \"/foo/2/three\");\n    /// assert!(uri.query().is_none());\n    /// ```\n    pub fn parse_owned(string: String) -> Result<Origin<'static>, Error<'static>> {\n        let origin = Origin::parse(&string).map_err(|e| e.into_owned())?;\n        debug_assert!(origin.source.is_some(), \"Origin parsed w/o source\");\n\n        Ok(Origin {\n            path: origin.path.into_owned(),\n            query: origin.query.into_owned(),\n            source: Some(Cow::Owned(string))\n        })\n    }\n\n    /// Returns the path part of this URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/a/b/c\");\n    /// assert_eq!(uri.path(), \"/a/b/c\");\n    ///\n    /// let uri = uri!(\"/a/b/c?name=bob\");\n    /// assert_eq!(uri.path(), \"/a/b/c\");\n    /// ```\n    #[inline]\n    pub fn path(&self) -> Path<'_> {\n        Path { source: &self.source, data: &self.path }\n    }\n\n    /// Returns the query part of this URI without the question mark, if there\n    /// is any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/a/b/c?alphabet=true\");\n    /// assert_eq!(uri.query().unwrap(), \"alphabet=true\");\n    ///\n    /// let uri = uri!(\"/a/b/c\");\n    /// assert!(uri.query().is_none());\n    /// ```\n    #[inline]\n    pub fn query(&self) -> Option<Query<'_>> {\n        self.query.as_ref().map(|data| Query { source: &self.source, data })\n    }\n\n    /// Applies the function `f` to the internal `path` and returns a new\n    /// `Origin` with the new path. If the path returned from `f` is invalid,\n    /// returns `None`. Otherwise, returns `Some`, even if the new path is\n    /// _abnormal_.\n    ///\n    /// ### Examples\n    ///\n    /// Affix a trailing slash if one isn't present.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/a/b/c\");\n    /// let expected_uri = uri!(\"/a/b/c/d\");\n    /// assert_eq!(uri.map_path(|p| format!(\"{}/d\", p)), Some(expected_uri));\n    ///\n    /// let uri = uri!(\"/a/b/c\");\n    /// let abnormal_map = uri.map_path(|p| format!(\"{}///d\", p));\n    /// assert_eq!(abnormal_map.unwrap(), \"/a/b/c///d\");\n    ///\n    /// let uri = uri!(\"/a/b/c\");\n    /// let expected = uri!(\"/b/c\");\n    /// let mapped = uri.map_path(|p| p.strip_prefix(\"/a\").unwrap_or(p));\n    /// assert_eq!(mapped, Some(expected));\n    ///\n    /// let uri = uri!(\"/a\");\n    /// assert_eq!(uri.map_path(|p| p.strip_prefix(\"/a\").unwrap_or(p)), None);\n    ///\n    /// let uri = uri!(\"/a/b/c\");\n    /// assert_eq!(uri.map_path(|p| format!(\"hi/{}\", p)), None);\n    /// ```\n    #[inline]\n    pub fn map_path<'s, F, P>(&'s self, f: F) -> Option<Self>\n        where F: FnOnce(&'s RawStr) -> P, P: Into<RawStrBuf> + 's\n    {\n        let path = f(self.path().raw()).into();\n        if !path.starts_with('/') || !path.as_bytes().iter().all(is_pchar) {\n            return None;\n        }\n\n        Some(Origin {\n            source: self.source.clone(),\n            path: Data::new(Cow::from(path.into_string())),\n            query: self.query.clone(),\n        })\n    }\n\n    /// Removes the query part of this URI, if there is any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let mut uri = uri!(\"/a/b/c?query=some\");\n    /// assert_eq!(uri.query().unwrap(), \"query=some\");\n    ///\n    /// uri.clear_query();\n    /// assert!(uri.query().is_none());\n    /// ```\n    pub fn clear_query(&mut self) {\n        self.set_query(None);\n    }\n\n    /// Returns `true` if `self` is normalized. Otherwise, returns `false`.\n    ///\n    /// See [Normalization](Self#normalization) for more information on what it\n    /// means for an origin URI to be normalized. Note that `uri!()` always\n    /// normalizes static input.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// assert!(Origin::parse(\"/\").unwrap().is_normalized());\n    /// assert!(Origin::parse(\"/a/b/c\").unwrap().is_normalized());\n    /// assert!(Origin::parse(\"/a/b/c?a=b&c\").unwrap().is_normalized());\n    ///\n    /// assert!(!Origin::parse(\"/a/b/c//d\").unwrap().is_normalized());\n    /// assert!(!Origin::parse(\"/a?q&&b\").unwrap().is_normalized());\n    ///\n    /// assert!(uri!(\"/a/b/c//d\").is_normalized());\n    /// assert!(uri!(\"/a?q&&b\").is_normalized());\n    /// ```\n    pub fn is_normalized(&self) -> bool {\n        self.path().is_normalized(true) && self.query().map_or(true, |q| q.is_normalized())\n    }\n\n    fn _normalize(&mut self, allow_trail: bool) {\n        if !self.path().is_normalized(true) {\n            self.path = self.path().to_normalized(true, allow_trail);\n        }\n\n        if let Some(query) = self.query() {\n            if !query.is_normalized() {\n                self.query = Some(query.to_normalized());\n            }\n        }\n    }\n\n    /// Normalizes `self`. This is a no-op if `self` is already normalized.\n    ///\n    /// See [Normalization](#normalization) for more information on what it\n    /// means for an origin URI to be normalized.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let mut abnormal = Origin::parse(\"/a/b/c//d\").unwrap();\n    /// assert!(!abnormal.is_normalized());\n    /// abnormal.normalize();\n    /// assert!(abnormal.is_normalized());\n    /// ```\n    pub fn normalize(&mut self) {\n        self._normalize(true);\n    }\n\n    /// Consumes `self` and returns a normalized version.\n    ///\n    /// This is a no-op if `self` is already normalized. See\n    /// [Normalization](#normalization) for more information on what it means\n    /// for an origin URI to be normalized.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let abnormal = Origin::parse(\"/a/b/c//d\").unwrap();\n    /// assert!(!abnormal.is_normalized());\n    /// assert!(abnormal.into_normalized().is_normalized());\n    /// ```\n    pub fn into_normalized(mut self) -> Self {\n        self.normalize();\n        self\n    }\n\n    /// Returns `true` if `self` has a _trailing_ slash.\n    ///\n    /// This is defined as `path.len() > 1` && `path.ends_with('/')`. This\n    /// implies that the URI `/` is _not_ considered to have a trailing slash.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    ///\n    /// assert!(!uri!(\"/\").has_trailing_slash());\n    /// assert!(!uri!(\"/a\").has_trailing_slash());\n    /// assert!(!uri!(\"/foo/bar/baz\").has_trailing_slash());\n    ///\n    /// assert!(uri!(\"/a/\").has_trailing_slash());\n    /// assert!(uri!(\"/foo/\").has_trailing_slash());\n    /// assert!(uri!(\"/foo/bar/baz/\").has_trailing_slash());\n    /// ```\n    pub fn has_trailing_slash(&self) -> bool {\n        self.path().len() > 1 && self.path().ends_with('/')\n    }\n\n    /// Returns `true` if `self` is normalized ([`Origin::is_normalized()`]) and\n    /// **does not** have a trailing slash ([Origin::has_trailing_slash()]).\n    /// Otherwise returns `false`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let origin = Origin::parse(\"/\").unwrap();\n    /// assert!(origin.is_normalized_nontrailing());\n    ///\n    /// let origin = Origin::parse(\"/foo/bar\").unwrap();\n    /// assert!(origin.is_normalized_nontrailing());\n    ///\n    /// let origin = Origin::parse(\"//\").unwrap();\n    /// assert!(!origin.is_normalized_nontrailing());\n    ///\n    /// let origin = Origin::parse(\"/foo/bar//baz/\").unwrap();\n    /// assert!(!origin.is_normalized_nontrailing());\n    ///\n    /// let origin = Origin::parse(\"/foo/bar/\").unwrap();\n    /// assert!(!origin.is_normalized_nontrailing());\n    /// ```\n    pub fn is_normalized_nontrailing(&self) -> bool {\n        self.is_normalized() && !self.has_trailing_slash()\n    }\n\n    /// Converts `self` into a normalized origin path without a trailing slash.\n    /// Does nothing is `self` is already [`normalized_nontrailing`].\n    ///\n    /// [`normalized_nontrailing`]: Origin::is_normalized_nontrailing()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let origin = Origin::parse(\"/\").unwrap();\n    /// assert!(origin.is_normalized_nontrailing());\n    ///\n    /// let normalized = origin.into_normalized_nontrailing();\n    /// assert_eq!(normalized, uri!(\"/\"));\n    ///\n    /// let origin = Origin::parse(\"//\").unwrap();\n    /// assert!(!origin.is_normalized_nontrailing());\n    ///\n    /// let normalized = origin.into_normalized_nontrailing();\n    /// assert_eq!(normalized, uri!(\"/\"));\n    ///\n    /// let origin = Origin::parse_owned(\"/foo/bar//baz/\".into()).unwrap();\n    /// assert!(!origin.is_normalized_nontrailing());\n    ///\n    /// let normalized = origin.into_normalized_nontrailing();\n    /// assert_eq!(normalized, uri!(\"/foo/bar/baz\"));\n    ///\n    /// let origin = Origin::parse(\"/foo/bar/\").unwrap();\n    /// assert!(!origin.is_normalized_nontrailing());\n    ///\n    /// let normalized = origin.into_normalized_nontrailing();\n    /// assert_eq!(normalized, uri!(\"/foo/bar\"));\n    /// ```\n    pub fn into_normalized_nontrailing(mut self) -> Self {\n        if !self.is_normalized_nontrailing() {\n            if self.is_normalized() && self.has_trailing_slash() {\n                let indexed = match self.path.value {\n                    IndexedStr::Indexed(i, j) => IndexedStr::Indexed(i, j - 1),\n                    IndexedStr::Concrete(cow) => IndexedStr::Concrete(match cow {\n                        Cow::Borrowed(s) => Cow::Borrowed(&s[..s.len() - 1]),\n                        Cow::Owned(mut s) => Cow::Owned({ s.pop(); s }),\n                    })\n                };\n\n                self.path = Data {\n                    value: indexed,\n                    decoded_segments: state::InitCell::new(),\n                };\n            } else {\n                self._normalize(false);\n            }\n        }\n\n        self\n\n    }\n}\n\nimpl_serde!(Origin<'a>, \"an origin-form URI\");\n\nimpl_traits!(Origin [parse_route], path, query);\n\nimpl std::fmt::Display for Origin<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.path())?;\n        if let Some(query) = self.query() {\n            write!(f, \"?{}\", query)?;\n        }\n\n        Ok(())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::Origin;\n\n    fn seg_count(path: &str, expected: usize) -> bool {\n        let origin = Origin::parse(path).unwrap();\n        let segments = origin.path().segments();\n        let actual = segments.num();\n        if actual != expected {\n            eprintln!(\"Count mismatch: expected {}, got {}.\", expected, actual);\n            eprintln!(\"{}\", if actual != expected { \"lifetime\" } else { \"buf\" });\n            eprintln!(\"Segments (for {}):\", path);\n            for (i, segment) in segments.enumerate() {\n                eprintln!(\"{}: {}\", i, segment);\n            }\n        }\n\n        actual == expected\n    }\n\n    fn eq_segments(path: &str, expected: &[&str]) -> bool {\n        let uri = match Origin::parse(path) {\n            Ok(uri) => uri,\n            Err(e) => panic!(\"failed to parse {}: {}\", path, e)\n        };\n\n        let actual: Vec<&str> = uri.path().segments().collect();\n        actual == expected\n    }\n\n    #[test]\n    fn send_and_sync() {\n        fn assert<T: Send + Sync>() {}\n        assert::<Origin<'_>>();\n    }\n\n    #[test]\n    fn simple_segment_count() {\n        assert!(seg_count(\"/\", 1));\n        assert!(seg_count(\"/a\", 1));\n        assert!(seg_count(\"/a/\", 2));\n        assert!(seg_count(\"/a/b\", 2));\n        assert!(seg_count(\"/a/b/\", 3));\n        assert!(seg_count(\"/ab/\", 2));\n    }\n\n    #[test]\n    fn segment_count() {\n        assert!(seg_count(\"////\", 1));\n        assert!(seg_count(\"//a//\", 2));\n        assert!(seg_count(\"//abc//\", 2));\n        assert!(seg_count(\"//abc/def/\", 3));\n        assert!(seg_count(\"//////abc///def//////////\", 3));\n        assert!(seg_count(\"/a/b/c/d/e/f/g\", 7));\n        assert!(seg_count(\"/a/b/c/d/e/f/g\", 7));\n        assert!(seg_count(\"/a/b/c/d/e/f/g/\", 8));\n        assert!(seg_count(\"/a/b/cdjflk/d/e/f/g\", 7));\n        assert!(seg_count(\"//aaflja/b/cdjflk/d/e/f/g\", 7));\n        assert!(seg_count(\"/a/b\", 2));\n    }\n\n    #[test]\n    fn single_segments_match() {\n        assert!(eq_segments(\"/\", &[\"\"]));\n        assert!(eq_segments(\"/a\", &[\"a\"]));\n        assert!(eq_segments(\"/a/\", &[\"a\", \"\"]));\n        assert!(eq_segments(\"///a/\", &[\"a\", \"\"]));\n        assert!(eq_segments(\"///a///////\", &[\"a\", \"\"]));\n        assert!(eq_segments(\"/a///////\", &[\"a\", \"\"]));\n        assert!(eq_segments(\"//a\", &[\"a\"]));\n        assert!(eq_segments(\"/abc\", &[\"abc\"]));\n        assert!(eq_segments(\"/abc/\", &[\"abc\", \"\"]));\n        assert!(eq_segments(\"///abc/\", &[\"abc\", \"\"]));\n        assert!(eq_segments(\"///abc///////\", &[\"abc\", \"\"]));\n        assert!(eq_segments(\"/abc///////\", &[\"abc\", \"\"]));\n        assert!(eq_segments(\"//abc\", &[\"abc\"]));\n    }\n\n    #[test]\n    fn multi_segments_match() {\n        assert!(eq_segments(\"/a/b/c\", &[\"a\", \"b\", \"c\"]));\n        assert!(eq_segments(\"/a/b\", &[\"a\", \"b\"]));\n        assert!(eq_segments(\"/a///b\", &[\"a\", \"b\"]));\n        assert!(eq_segments(\"/a/b/c/d\", &[\"a\", \"b\", \"c\", \"d\"]));\n        assert!(eq_segments(\"///a///////d////c\", &[\"a\", \"d\", \"c\"]));\n        assert!(eq_segments(\"/abc/abc\", &[\"abc\", \"abc\"]));\n        assert!(eq_segments(\"/abc/abc/\", &[\"abc\", \"abc\", \"\"]));\n        assert!(eq_segments(\"///abc///////a\", &[\"abc\", \"a\"]));\n        assert!(eq_segments(\"/////abc/b\", &[\"abc\", \"b\"]));\n        assert!(eq_segments(\"//abc//c////////d\", &[\"abc\", \"c\", \"d\"]));\n        assert!(eq_segments(\"//abc//c////////d/\", &[\"abc\", \"c\", \"d\", \"\"]));\n    }\n\n    #[test]\n    fn multi_segments_match_funky_chars() {\n        assert!(eq_segments(\"/a/b/c!!!\", &[\"a\", \"b\", \"c!!!\"]));\n    }\n\n    #[test]\n    fn segment_mismatch() {\n        assert!(!eq_segments(\"/\", &[\"a\"]));\n        assert!(!eq_segments(\"/a\", &[]));\n        assert!(!eq_segments(\"/a/a\", &[\"a\"]));\n        assert!(!eq_segments(\"/a/b\", &[\"b\", \"a\"]));\n        assert!(!eq_segments(\"/a/a/b\", &[\"a\", \"b\"]));\n        assert!(!eq_segments(\"///a/\", &[]));\n        assert!(!eq_segments(\"///a/\", &[\"a\"]));\n        assert!(!eq_segments(\"///a/\", &[\"a\", \"a\"]));\n    }\n\n    fn test_query(uri: &str, query: Option<&str>) {\n        let uri = Origin::parse(uri).unwrap();\n        assert_eq!(uri.query().map(|q| q.as_str()), query);\n    }\n\n    #[test]\n    fn query_does_not_exist() {\n        test_query(\"/test\", None);\n        test_query(\"/a/b/c/d/e\", None);\n        test_query(\"/////\", None);\n        test_query(\"//a///\", None);\n        test_query(\"/a/b/c\", None);\n        test_query(\"/\", None);\n    }\n\n    #[test]\n    fn query_exists() {\n        test_query(\"/test?abc\", Some(\"abc\"));\n        test_query(\"/a/b/c?abc\", Some(\"abc\"));\n        test_query(\"/a/b/c/d/e/f/g/?abc\", Some(\"abc\"));\n        test_query(\"/?123\", Some(\"123\"));\n        test_query(\"/?\", Some(\"\"));\n        test_query(\"/?\", Some(\"\"));\n        test_query(\"/?hi\", Some(\"hi\"));\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/path_query.rs",
    "content": "use std::hash::Hash;\nuse std::borrow::Cow;\n\nuse state::InitCell;\n\nuse crate::{RawStr, ext::IntoOwned};\nuse crate::uri::Segments;\nuse crate::uri::fmt::{self, Part};\nuse crate::parse::{IndexedStr, Extent};\n\n// INTERNAL DATA STRUCTURE.\n#[doc(hidden)]\n#[derive(Debug, Clone)]\npub struct Data<'a, P: Part> {\n    pub(crate) value: IndexedStr<'a>,\n    pub(crate) decoded_segments: InitCell<Vec<P::Raw>>,\n}\n\nimpl<'a, P: Part> Data<'a, P> {\n    pub(crate) fn raw(value: Extent<&'a [u8]>) -> Self {\n        Data { value: value.into(), decoded_segments: InitCell::new() }\n    }\n\n    // INTERNAL METHOD.\n    #[doc(hidden)]\n    pub fn new<S: Into<Cow<'a, str>>>(value: S) -> Self {\n        Data {\n            value: IndexedStr::from(value.into()),\n            decoded_segments: InitCell::new(),\n        }\n    }\n}\n\n/// A URI path: `/foo/bar`, `foo/bar`, etc.\n#[derive(Debug, Clone, Copy)]\npub struct Path<'a> {\n    pub(crate) source: &'a Option<Cow<'a, str>>,\n    pub(crate) data: &'a Data<'a, fmt::Path>,\n}\n\n/// A URI query: `?foo&bar`.\n#[derive(Debug, Clone, Copy)]\npub struct Query<'a> {\n    pub(crate) source: &'a Option<Cow<'a, str>>,\n    pub(crate) data: &'a Data<'a, fmt::Query>,\n}\n\nfn decode_to_indexed_str<P: fmt::Part>(\n    value: &RawStr,\n    (indexed, source): (&IndexedStr<'_>, &RawStr)\n) -> IndexedStr<'static> {\n    let decoded = match P::KIND {\n        fmt::Kind::Path => value.percent_decode_lossy(),\n        fmt::Kind::Query => value.url_decode_lossy(),\n    };\n\n    match decoded {\n        Cow::Borrowed(b) if indexed.is_indexed() => {\n            let checked = IndexedStr::checked_from(b, source.as_str());\n            debug_assert!(checked.is_some(), \"\\nunindexed {:?} in {:?} {:?}\", b, indexed, source);\n            checked.unwrap_or_else(|| IndexedStr::from(Cow::Borrowed(\"\")))\n        }\n        cow => IndexedStr::from(Cow::Owned(cow.into_owned())),\n    }\n}\n\nimpl<'a> Path<'a> {\n    /// Returns the raw path value.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo%20bar%2dbaz\");\n    /// assert_eq!(uri.path(), \"/foo%20bar%2dbaz\");\n    /// assert_eq!(uri.path().raw(), \"/foo%20bar%2dbaz\");\n    /// ```\n    pub fn raw(&self) -> &'a RawStr {\n        self.data.value.from_cow_source(self.source).into()\n    }\n\n    /// Returns the raw, undecoded path value as an `&str`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo%20bar%2dbaz\");\n    /// assert_eq!(uri.path(), \"/foo%20bar%2dbaz\");\n    /// assert_eq!(uri.path().as_str(), \"/foo%20bar%2dbaz\");\n    /// ```\n    pub fn as_str(&self) -> &'a str {\n        self.raw().as_str()\n    }\n\n    /// Whether `self` is normalized, i.e, it has no empty segments except the\n    /// last one.\n    ///\n    /// If `absolute`, then a starting  `/` is required.\n    pub(crate) fn is_normalized(&self, absolute: bool) -> bool {\n        if absolute && !self.raw().starts_with('/') {\n            return false;\n        }\n\n        self.raw_segments()\n            .rev()\n            .skip(1)\n            .all(|s| !s.is_empty())\n    }\n\n    /// Normalizes `self`. If `absolute`, a starting  `/` is required. If\n    /// `trail`, a trailing slash is allowed. Otherwise it is not.\n    pub(crate) fn to_normalized(self, absolute: bool, trail: bool) -> Data<'static, fmt::Path> {\n        let raw = self.raw().trim();\n        let mut path = String::with_capacity(raw.len());\n\n        if absolute || raw.starts_with('/') {\n            path.push('/');\n        }\n\n        for (i, segment) in self.raw_segments().filter(|s| !s.is_empty()).enumerate() {\n            if i != 0 { path.push('/'); }\n            path.push_str(segment.as_str());\n        }\n\n        if trail && raw.len() > 1 && raw.ends_with('/') && !path.ends_with('/') {\n            path.push('/');\n        }\n\n        Data {\n            value: IndexedStr::from(Cow::Owned(path)),\n            decoded_segments: InitCell::new(),\n        }\n    }\n\n    /// Returns an iterator over the raw, undecoded segments, potentially empty\n    /// segments.\n    ///\n    /// ### Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let uri = Origin::parse(\"/\").unwrap();\n    /// let segments: Vec<_> = uri.path().raw_segments().collect();\n    /// assert_eq!(segments, &[\"\"]);\n    ///\n    /// let uri = Origin::parse(\"//\").unwrap();\n    /// let segments: Vec<_> = uri.path().raw_segments().collect();\n    /// assert_eq!(segments, &[\"\", \"\"]);\n    ///\n    /// let uri = Origin::parse(\"/foo\").unwrap();\n    /// let segments: Vec<_> = uri.path().raw_segments().collect();\n    /// assert_eq!(segments, &[\"foo\"]);\n    ///\n    /// let uri = Origin::parse(\"/a/\").unwrap();\n    /// let segments: Vec<_> = uri.path().raw_segments().collect();\n    /// assert_eq!(segments, &[\"a\", \"\"]);\n    ///\n    /// // Recall that `uri!()` normalizes static inputs.\n    /// let uri = uri!(\"//\");\n    /// let segments: Vec<_> = uri.path().raw_segments().collect();\n    /// assert_eq!(segments, &[\"\"]);\n    ///\n    /// let uri = Origin::parse(\"/a//b///c/d?query&param\").unwrap();\n    /// let segments: Vec<_> = uri.path().raw_segments().collect();\n    /// assert_eq!(segments, &[\"a\", \"\", \"b\", \"\", \"\", \"c\", \"d\"]);\n    /// ```\n    #[inline]\n    pub fn raw_segments(&self) -> impl DoubleEndedIterator<Item = &'a RawStr> {\n        let raw = self.raw().trim();\n        raw.strip_prefix(fmt::Path::DELIMITER)\n            .unwrap_or(raw)\n            .split(fmt::Path::DELIMITER)\n    }\n\n    /// Returns a (smart) iterator over the percent-decoded segments. Empty\n    /// segments between non-empty segments are skipped. A trailing slash will\n    /// result in an empty segment emitted as the final item.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let uri = Origin::parse(\"/\").unwrap();\n    /// let path_segs: Vec<&str> = uri.path().segments().collect();\n    /// assert_eq!(path_segs, &[\"\"]);\n    ///\n    /// let uri = Origin::parse(\"/a\").unwrap();\n    /// let path_segs: Vec<&str> = uri.path().segments().collect();\n    /// assert_eq!(path_segs, &[\"a\"]);\n    ///\n    /// let uri = Origin::parse(\"/a/\").unwrap();\n    /// let path_segs: Vec<&str> = uri.path().segments().collect();\n    /// assert_eq!(path_segs, &[\"a\", \"\"]);\n    ///\n    /// let uri = Origin::parse(\"/foo/bar\").unwrap();\n    /// let path_segs: Vec<&str> = uri.path().segments().collect();\n    /// assert_eq!(path_segs, &[\"foo\", \"bar\"]);\n    ///\n    /// let uri = Origin::parse(\"/foo///bar\").unwrap();\n    /// let path_segs: Vec<&str> = uri.path().segments().collect();\n    /// assert_eq!(path_segs, &[\"foo\", \"bar\"]);\n    ///\n    /// let uri = Origin::parse(\"/foo///bar//\").unwrap();\n    /// let path_segs: Vec<&str> = uri.path().segments().collect();\n    /// assert_eq!(path_segs, &[\"foo\", \"bar\", \"\"]);\n    ///\n    /// let uri = Origin::parse(\"/a%20b/b%2Fc/d//e?query=some\").unwrap();\n    /// let path_segs: Vec<&str> = uri.path().segments().collect();\n    /// assert_eq!(path_segs, &[\"a b\", \"b/c\", \"d\", \"e\"]);\n    /// ```\n    pub fn segments(&self) -> Segments<'a, fmt::Path> {\n        let raw = self.raw();\n        let cached = self.data.decoded_segments.get_or_init(|| {\n            let mut segments = vec![];\n            let mut raw_segments = self.raw_segments().peekable();\n            while let Some(s) = raw_segments.next() {\n                // Only allow an empty segment if it's the last one.\n                if s.is_empty() && raw_segments.peek().is_some() {\n                    continue;\n                }\n\n                segments.push(decode_to_indexed_str::<fmt::Path>(s, (&self.data.value, raw)));\n            }\n\n            segments\n        });\n\n        Segments::new(raw, cached)\n    }\n}\n\nimpl<'a> Query<'a> {\n    /// Returns the raw, undecoded query value.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo?baz+bar\");\n    /// assert_eq!(uri.query().unwrap(), \"baz+bar\");\n    /// assert_eq!(uri.query().unwrap().raw(), \"baz+bar\");\n    /// ```\n    pub fn raw(&self) -> &'a RawStr {\n        self.data.value.from_cow_source(self.source).into()\n    }\n\n    /// Returns the raw, undecoded query value as an `&str`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo/bar?baz+bar\");\n    /// assert_eq!(uri.query().unwrap(), \"baz+bar\");\n    /// assert_eq!(uri.query().unwrap().as_str(), \"baz+bar\");\n    /// ```\n    pub fn as_str(&self) -> &'a str {\n        self.raw().as_str()\n    }\n\n    /// Whether `self` is normalized, i.e, it has no empty segments.\n    pub(crate) fn is_normalized(&self) -> bool {\n        self.raw_segments().all(|s| !s.is_empty())\n    }\n\n    /// Normalizes `self`.\n    pub(crate) fn to_normalized(self) -> Data<'static, fmt::Query> {\n        let mut query = String::with_capacity(self.raw().trim().len());\n        for (i, seg) in self.raw_segments().filter(|s| !s.is_empty()).enumerate() {\n            if i != 0 { query.push('&'); }\n            query.push_str(seg.as_str());\n        }\n\n        Data {\n            value: IndexedStr::from(Cow::Owned(query)),\n            decoded_segments: InitCell::new(),\n        }\n    }\n\n    /// Returns an iterator over the undecoded, potentially empty `(name,\n    /// value)` pairs of this query. If there is no query, the iterator is\n    /// empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let uri = Origin::parse(\"/\").unwrap();\n    /// assert!(uri.query().is_none());\n    ///\n    /// let uri = Origin::parse(\"/?\").unwrap();\n    /// let query_segs: Vec<_> = uri.query().unwrap().raw_segments().collect();\n    /// assert!(query_segs.is_empty());\n    ///\n    /// let uri = Origin::parse(\"/?foo\").unwrap();\n    /// let query_segs: Vec<_> = uri.query().unwrap().raw_segments().collect();\n    /// assert_eq!(query_segs, &[\"foo\"]);\n    ///\n    /// let uri = Origin::parse(\"/?a=b&dog\").unwrap();\n    /// let query_segs: Vec<_> = uri.query().unwrap().raw_segments().collect();\n    /// assert_eq!(query_segs, &[\"a=b\", \"dog\"]);\n    ///\n    /// let uri = Origin::parse(\"/?&\").unwrap();\n    /// let query_segs: Vec<_> = uri.query().unwrap().raw_segments().collect();\n    /// assert_eq!(query_segs, &[\"\", \"\"]);\n    ///\n    /// // Recall that `uri!()` normalizes, so this is equivalent to `/?`.\n    /// let uri = uri!(\"/?&\");\n    /// let query_segs: Vec<_> = uri.query().unwrap().raw_segments().collect();\n    /// assert!(query_segs.is_empty());\n    ///\n    /// // These are raw and undecoded. Use `segments()` for decoded variant.\n    /// let uri = Origin::parse(\"/foo/bar?a+b%2F=some+one%40gmail.com&&%26%3D2\").unwrap();\n    /// let query_segs: Vec<_> = uri.query().unwrap().raw_segments().collect();\n    /// assert_eq!(query_segs, &[\"a+b%2F=some+one%40gmail.com\", \"\", \"%26%3D2\"]);\n    /// ```\n    #[inline]\n    pub fn raw_segments(&self) -> impl Iterator<Item = &'a RawStr> {\n        let query = match self.raw().trim() {\n            q if q.is_empty() => None,\n            q => Some(q)\n        };\n\n        query.map(|p| p.split(fmt::Query::DELIMITER))\n            .into_iter()\n            .flatten()\n    }\n\n    /// Returns a (smart) iterator over the non-empty, url-decoded `(name,\n    /// value)` pairs of this query. If there is no query, the iterator is\n    /// empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Origin;\n    ///\n    /// let uri = Origin::parse(\"/\").unwrap();\n    /// assert!(uri.query().is_none());\n    ///\n    /// let uri = Origin::parse(\"/foo/bar?a+b%2F=some+one%40gmail.com&&%26%3D2\").unwrap();\n    /// let query_segs: Vec<_> = uri.query().unwrap().segments().collect();\n    /// assert_eq!(query_segs, &[(\"a b/\", \"some one@gmail.com\"), (\"&=2\", \"\")]);\n    /// ```\n    pub fn segments(&self) -> Segments<'a, fmt::Query> {\n        let cached = self.data.decoded_segments.get_or_init(|| {\n            let (indexed, query) = (&self.data.value, self.raw());\n            self.raw_segments()\n                .filter(|s| !s.is_empty())\n                .map(|s| s.split_at_byte(b'='))\n                .map(|(k, v)| {\n                    let key = decode_to_indexed_str::<fmt::Query>(k, (indexed, query));\n                    let val = decode_to_indexed_str::<fmt::Query>(v, (indexed, query));\n                    (key, val)\n                })\n                .collect()\n        });\n\n        Segments::new(self.raw(), cached)\n    }\n}\n\nmacro_rules! impl_partial_eq {\n    ($A:ty = $B:ty) => (\n        impl PartialEq<$A> for $B {\n            #[inline(always)]\n            fn eq(&self, other: &$A) -> bool {\n                let left: &RawStr = self.as_ref();\n                let right: &RawStr = other.as_ref();\n                left == right\n            }\n        }\n    )\n}\n\nmacro_rules! impl_traits {\n    ($T:ident) => (\n        impl Hash for $T<'_> {\n            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n                self.raw().hash(state);\n            }\n        }\n\n        impl Eq for $T<'_> { }\n\n        impl IntoOwned for Data<'_, fmt::$T> {\n            type Owned = Data<'static, fmt::$T>;\n\n            fn into_owned(self) -> Self::Owned {\n                Data {\n                    value: self.value.into_owned(),\n                    decoded_segments: self.decoded_segments.map(|v| v.into_owned()),\n                }\n            }\n        }\n\n        impl std::ops::Deref for $T<'_> {\n            type Target = RawStr;\n\n            fn deref(&self) -> &Self::Target {\n                self.raw()\n            }\n        }\n\n        impl AsRef<RawStr> for $T<'_> {\n            fn as_ref(&self) -> &RawStr {\n                self.raw()\n            }\n        }\n\n        impl AsRef<std::ffi::OsStr> for $T<'_> {\n            fn as_ref(&self) -> &std::ffi::OsStr {\n                self.raw().as_ref()\n            }\n        }\n\n        impl std::fmt::Display for $T<'_> {\n            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n                write!(f, \"{}\", self.raw())\n            }\n        }\n\n        impl_partial_eq!($T<'_> = $T<'_>);\n        impl_partial_eq!(str = $T<'_>);\n        impl_partial_eq!(&str = $T<'_>);\n        impl_partial_eq!($T<'_> = str);\n        impl_partial_eq!($T<'_> = &str);\n        impl_partial_eq!(RawStr = $T<'_>);\n        impl_partial_eq!(&RawStr = $T<'_>);\n        impl_partial_eq!($T<'_> = RawStr);\n        impl_partial_eq!($T<'_> = &RawStr);\n    )\n}\n\nimpl_traits!(Path);\nimpl_traits!(Query);\n"
  },
  {
    "path": "core/http/src/uri/reference.rs",
    "content": "use std::borrow::Cow;\n\nuse crate::RawStr;\nuse crate::ext::IntoOwned;\nuse crate::uri::{Authority, Data, Origin, Absolute, Asterisk};\nuse crate::uri::{Path, Query, Error, as_utf8_unchecked, fmt};\nuse crate::parse::{Extent, IndexedStr};\n\n/// A URI-reference with optional scheme, authority, relative path, query, and\n/// fragment parts.\n///\n/// # Structure\n///\n/// The following diagram illustrates the syntactic structure of a URI reference\n/// with all optional parts:\n///\n/// ```text\n///  http://user:pass@domain.com:4444/foo/bar?some=query#and-fragment\n///  |--|  |------------------------||------| |--------| |----------|\n/// scheme          authority          path      query     fragment\n/// ```\n///\n/// All parts are optional. When a scheme and authority are not present, the\n/// path may be relative: `foo/bar?baz#cat`.\n///\n/// # Conversion\n///\n/// All other URI types ([`Origin`], [`Absolute`], and so on) are valid URI\n/// references. As such, conversion between the types is lossless:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::http::uri::Reference;\n///\n/// let absolute = uri!(\"http://rocket.rs\");\n/// let reference: Reference = absolute.into();\n/// assert_eq!(reference.scheme(), Some(\"http\"));\n/// assert_eq!(reference.authority().unwrap().host(), \"rocket.rs\");\n///\n/// let origin = uri!(\"/foo/bar\");\n/// let reference: Reference = origin.into();\n/// assert_eq!(reference.path(), \"/foo/bar\");\n/// ```\n///\n/// Note that `uri!()` macro _always_ prefers the more specific URI variant to\n/// `Reference` when possible, as is demonstrated above for `absolute` and\n/// `origin`.\n///\n/// # (De)serialization\n///\n/// `Reference` is both `Serialize` and `Deserialize`:\n///\n/// ```rust\n/// # #[cfg(feature = \"serde\")] mod serde_impl {\n/// # use serde as serde;\n/// use serde::{Serialize, Deserialize};\n/// use rocket::http::uri::Reference;\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriOwned {\n///     uri: Reference<'static>,\n/// }\n///\n/// #[derive(Deserialize, Serialize)]\n/// # #[serde(crate = \"serde\")]\n/// struct UriBorrowed<'a> {\n///     uri: Reference<'a>,\n/// }\n/// # }\n/// ```\n#[derive(Debug, Clone)]\npub struct Reference<'a> {\n    source: Option<Cow<'a, str>>,\n    scheme: Option<IndexedStr<'a>>,\n    authority: Option<Authority<'a>>,\n    path: Data<'a, fmt::Path>,\n    query: Option<Data<'a, fmt::Query>>,\n    fragment: Option<IndexedStr<'a>>,\n}\n\nimpl<'a> Reference<'a> {\n    #[inline]\n    pub(crate) unsafe fn raw(\n        source: Cow<'a, [u8]>,\n        scheme: Option<Extent<&'a [u8]>>,\n        authority: Option<Authority<'a>>,\n        path: Extent<&'a [u8]>,\n        query: Option<Extent<&'a [u8]>>,\n        fragment: Option<Extent<&'a [u8]>>,\n    ) -> Reference<'a> {\n        Reference {\n            source: Some(as_utf8_unchecked(source)),\n            scheme: scheme.map(|s| s.into()),\n            authority,\n            path: Data::raw(path),\n            query: query.map(Data::raw),\n            fragment: fragment.map(|f| f.into()),\n        }\n    }\n\n    /// PRIVATE. Used during test.\n    #[cfg(test)]\n    pub fn new(\n        scheme: impl Into<Option<&'a str>>,\n        auth: impl Into<Option<Authority<'a>>>,\n        path: &'a str,\n        query: impl Into<Option<&'a str>>,\n        frag: impl Into<Option<&'a str>>,\n    ) -> Reference<'a> {\n        Reference::const_new(scheme.into(), auth.into(), path, query.into(), frag.into())\n    }\n\n    /// PRIVATE. Used by codegen.\n    #[doc(hidden)]\n    pub const fn const_new(\n        scheme: Option<&'a str>,\n        authority: Option<Authority<'a>>,\n        path: &'a str,\n        query: Option<&'a str>,\n        fragment: Option<&'a str>,\n    ) -> Reference<'a> {\n        Reference {\n            source: None,\n            scheme: match scheme {\n                Some(scheme) => Some(IndexedStr::Concrete(Cow::Borrowed(scheme))),\n                None => None\n            },\n            authority,\n            path: Data {\n                value: IndexedStr::Concrete(Cow::Borrowed(path)),\n                decoded_segments: state::InitCell::new(),\n            },\n            query: match query {\n                Some(query) => Some(Data {\n                    value: IndexedStr::Concrete(Cow::Borrowed(query)),\n                    decoded_segments: state::InitCell::new(),\n                }),\n                None => None,\n            },\n            fragment: match fragment {\n                Some(frag) => Some(IndexedStr::Concrete(Cow::Borrowed(frag))),\n                None => None,\n            },\n        }\n    }\n\n    /// Parses the string `string` into an `Reference`. Parsing will never\n    /// allocate. Returns an `Error` if `string` is not a valid origin URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Reference;\n    ///\n    /// // Parse a valid URI reference.\n    /// let uri = Reference::parse(\"/a/b/c?query\").expect(\"valid URI\");\n    /// assert_eq!(uri.path(), \"/a/b/c\");\n    /// assert_eq!(uri.query().unwrap(), \"query\");\n    ///\n    /// // Invalid URIs fail to parse.\n    /// Reference::parse(\"foo bar\").expect_err(\"invalid URI\");\n    ///\n    /// // Prefer to use `uri!()` when the input is statically known:\n    /// let uri = uri!(\"/a/b/c?query#fragment\");\n    /// assert_eq!(uri.path(), \"/a/b/c\");\n    /// assert_eq!(uri.query().unwrap(), \"query\");\n    /// assert_eq!(uri.fragment().unwrap(), \"fragment\");\n    /// ```\n    pub fn parse(string: &'a str) -> Result<Reference<'a>, Error<'a>> {\n        crate::parse::uri::reference_from_str(string)\n    }\n\n    /// Parses the string `string` into a `Reference`. Allocates minimally on\n    /// success and error.\n    ///\n    /// This method should be used instead of [`Reference::parse()`] when the\n    /// source URI is already a `String`. Returns an `Error` if `string` is not\n    /// a valid URI reference.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::uri::Reference;\n    ///\n    /// let source = format!(\"/foo?{}#3\", 2);\n    /// let uri = Reference::parse_owned(source).unwrap();\n    /// assert_eq!(uri.path(), \"/foo\");\n    /// assert_eq!(uri.query().unwrap(), \"2\");\n    /// assert_eq!(uri.fragment().unwrap(), \"3\");\n    /// ```\n    // TODO: Avoid all allocations.\n    pub fn parse_owned(string: String) -> Result<Reference<'static>, Error<'static>> {\n        let uri_ref = Reference::parse(&string).map_err(|e| e.into_owned())?;\n        debug_assert!(uri_ref.source.is_some(), \"Reference parsed w/o source\");\n\n        Ok(Reference {\n            scheme: uri_ref.scheme.into_owned(),\n            authority: uri_ref.authority.into_owned(),\n            path: uri_ref.path.into_owned(),\n            query: uri_ref.query.into_owned(),\n            fragment: uri_ref.fragment.into_owned(),\n            source: Some(Cow::Owned(string)),\n        })\n    }\n\n    /// Returns the scheme. If `Some`, is non-empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"http://rocket.rs?foo#bar\");\n    /// assert_eq!(uri.scheme(), Some(\"http\"));\n    ///\n    /// let uri = uri!(\"ftp:/?foo#bar\");\n    /// assert_eq!(uri.scheme(), Some(\"ftp\"));\n    ///\n    /// let uri = uri!(\"?foo#bar\");\n    /// assert_eq!(uri.scheme(), None);\n    /// ```\n    #[inline]\n    pub fn scheme(&self) -> Option<&str> {\n        self.scheme.as_ref().map(|s| s.from_cow_source(&self.source))\n    }\n\n    /// Returns the authority part.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"http://rocket.rs:4444?foo#bar\");\n    /// let auth = uri!(\"rocket.rs:4444\");\n    /// assert_eq!(uri.authority().unwrap(), &auth);\n    ///\n    /// let uri = uri!(\"?foo#bar\");\n    /// assert_eq!(uri.authority(), None);\n    /// ```\n    #[inline(always)]\n    pub fn authority(&self) -> Option<&Authority<'a>> {\n        self.authority.as_ref()\n    }\n\n    /// Returns the path part. May be empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"http://rocket.rs/guide?foo#bar\");\n    /// assert_eq!(uri.path(), \"/guide\");\n    /// ```\n    #[inline(always)]\n    pub fn path(&self) -> Path<'_> {\n        Path { source: &self.source, data: &self.path }\n    }\n\n    /// Returns the query part. May be empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"http://rocket.rs/guide\");\n    /// assert!(uri.query().is_none());\n    ///\n    /// let uri = uri!(\"http://rocket.rs/guide?\");\n    /// assert_eq!(uri.query().unwrap(), \"\");\n    ///\n    /// let uri = uri!(\"http://rocket.rs/guide?foo#bar\");\n    /// assert_eq!(uri.query().unwrap(), \"foo\");\n    ///\n    /// let uri = uri!(\"http://rocket.rs/guide?q=bar\");\n    /// assert_eq!(uri.query().unwrap(), \"q=bar\");\n    /// ```\n    #[inline(always)]\n    pub fn query(&self) -> Option<Query<'_>> {\n        self.query.as_ref().map(|data| Query { source: &self.source, data })\n    }\n\n    /// Returns the fragment part, if any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"http://rocket.rs/guide?foo#bar\");\n    /// assert_eq!(uri.fragment().unwrap(), \"bar\");\n    ///\n    /// // Fragment parts aren't normalized away, unlike query parts.\n    /// let uri = uri!(\"http://rocket.rs/guide?foo#\");\n    /// assert_eq!(uri.fragment().unwrap(), \"\");\n    /// ```\n    #[inline(always)]\n    pub fn fragment(&self) -> Option<&RawStr> {\n        self.fragment.as_ref()\n            .map(|frag| frag.from_cow_source(&self.source).into())\n    }\n\n    /// Returns `true` if `self` is normalized. Otherwise, returns `false`.\n    ///\n    /// Normalization for a URI reference is equivalent to normalization for an\n    /// absolute URI. See [`Absolute#normalization`] for more information on\n    /// what it means for an absolute URI to be normalized.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::Reference;\n    ///\n    /// assert!(Reference::parse(\"foo/bar\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"foo/bar#\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"http://\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"http://foo.rs/foo/bar\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"foo:bar#baz\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"http://rocket.rs#foo\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"http://?\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"git://rocket.rs/\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"http://rocket.rs?#foo\").unwrap().is_normalized());\n    /// assert!(Reference::parse(\"http://rocket.rs#foo\").unwrap().is_normalized());\n    ///\n    /// assert!(!Reference::parse(\"http:/foo//bar\").unwrap().is_normalized());\n    /// assert!(!Reference::parse(\"foo:bar?baz&&bop#c\").unwrap().is_normalized());\n    ///\n    /// // Recall that `uri!()` normalizes static input.\n    /// assert!(uri!(\"http:/foo//bar\").is_normalized());\n    /// assert!(uri!(\"foo:bar?baz&&bop#c\").is_normalized());\n    /// assert!(uri!(\"http://rocket.rs///foo////bar#cat\").is_normalized());\n    /// ```\n    pub fn is_normalized(&self) -> bool {\n        let normalized_query = self.query().map_or(true, |q| q.is_normalized());\n        if self.authority().is_some() && !self.path().is_empty() {\n            self.path().is_normalized(true) && normalized_query\n        } else {\n            self.path().is_normalized(false) && normalized_query\n        }\n    }\n\n    /// Normalizes `self` in-place. Does nothing if `self` is already\n    /// normalized.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::uri::Reference;\n    ///\n    /// let mut uri = Reference::parse(\"git://rocket.rs/\").unwrap();\n    /// assert!(uri.is_normalized());\n    ///\n    /// let mut uri = Reference::parse(\"http:/foo//bar?baz&&#cat\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// uri.normalize();\n    /// assert!(uri.is_normalized());\n    ///\n    /// let mut uri = Reference::parse(\"foo:bar?baz&&bop\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// uri.normalize();\n    /// assert!(uri.is_normalized());\n    /// ```\n    pub fn normalize(&mut self) {\n        if self.authority().is_some() && !self.path().is_empty() {\n            if !self.path().is_normalized(true) {\n                self.path = self.path().to_normalized(true, true);\n            }\n        } else if !self.path().is_normalized(false) {\n            self.path = self.path().to_normalized(false, true);\n        }\n\n        if let Some(query) = self.query() {\n            if !query.is_normalized() {\n                self.query = Some(query.to_normalized());\n            }\n        }\n    }\n\n    /// Normalizes `self`. This is a no-op if `self` is already normalized.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::uri::Reference;\n    ///\n    /// let mut uri = Reference::parse(\"git://rocket.rs/\").unwrap();\n    /// assert!(uri.is_normalized());\n    /// assert!(uri.into_normalized().is_normalized());\n    ///\n    /// let mut uri = Reference::parse(\"http:/foo//bar?baz&&#cat\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// assert!(uri.into_normalized().is_normalized());\n    ///\n    /// let mut uri = Reference::parse(\"foo:bar?baz&&bop\").unwrap();\n    /// assert!(!uri.is_normalized());\n    /// assert!(uri.into_normalized().is_normalized());\n    /// ```\n    pub fn into_normalized(mut self) -> Self {\n        self.normalize();\n        self\n    }\n\n    #[allow(unused)]\n    pub(crate) fn set_path<P>(&mut self, path: P)\n        where P: Into<Cow<'a, str>>\n    {\n        self.path = Data::new(path.into());\n    }\n\n    /// Returns the concrete path and query.\n    pub(crate) fn with_query_fragment_of(mut self, other: Reference<'a>) -> Self {\n        if let Some(query) = other.query {\n            if self.query().is_none() {\n                self.query = Some(Data::new(query.value.into_concrete(&self.source)));\n            }\n        }\n\n        if let Some(frag) = other.fragment {\n            if self.fragment().is_none() {\n                self.fragment = Some(IndexedStr::from(frag.into_concrete(&self.source)));\n            }\n        }\n\n        self\n    }\n}\n\nimpl_traits!(Reference, authority, scheme, path, query, fragment);\n\nimpl_serde!(Reference<'a>, \"a URI-reference\");\n\nimpl<'a> From<Absolute<'a>> for Reference<'a> {\n    fn from(absolute: Absolute<'a>) -> Self {\n        Reference {\n            source: absolute.source,\n            scheme: Some(absolute.scheme),\n            authority: absolute.authority,\n            path: absolute.path,\n            query: absolute.query,\n            fragment: None,\n        }\n    }\n}\n\nimpl<'a> From<Origin<'a>> for Reference<'a> {\n    fn from(origin: Origin<'a>) -> Self {\n        Reference {\n            source: origin.source,\n            scheme: None,\n            authority: None,\n            path: origin.path,\n            query: origin.query,\n            fragment: None,\n        }\n    }\n}\n\nimpl<'a> From<Authority<'a>> for Reference<'a> {\n    fn from(authority: Authority<'a>) -> Self {\n        Reference {\n            source: match authority.source {\n                Some(Cow::Borrowed(b)) => Some(Cow::Borrowed(b)),\n                _ => None\n            },\n            authority: Some(authority),\n            scheme: None,\n            path: Data::new(\"\"),\n            query: None,\n            fragment: None,\n        }\n    }\n}\n\nimpl From<Asterisk> for Reference<'_> {\n    fn from(_: Asterisk) -> Self {\n        Reference {\n            source: None,\n            authority: None,\n            scheme: None,\n            path: Data::new(\"*\"),\n            query: None,\n            fragment: None,\n        }\n    }\n}\n\nimpl std::fmt::Display for Reference<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        if let Some(scheme) = self.scheme() {\n            write!(f, \"{}:\", scheme)?;\n        }\n\n        if let Some(authority) = self.authority() {\n            write!(f, \"//{}\", authority)?;\n        }\n\n        write!(f, \"{}\", self.path())?;\n\n        if let Some(query) = self.query() {\n            write!(f, \"?{}\", query)?;\n        }\n\n        if let Some(frag) = self.fragment() {\n            write!(f, \"#{}\", frag)?;\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "core/http/src/uri/segments.rs",
    "content": "use std::path::PathBuf;\n\nuse crate::RawStr;\nuse crate::uri::fmt::{Part, Path, Query};\nuse crate::uri::error::PathError;\n\n/// Iterator over the non-empty, percent-decoded segments of a URI component.\n///\n/// Returned by [`Path::segments()`] and [`Query::segments()`].\n///\n/// [`Path::segments()`]: crate::uri::Path::segments()\n/// [`Query::segments()`]: crate::uri::Query::segments()\n///\n/// # Example\n///\n/// ```rust\n/// # extern crate rocket;\n/// use rocket::http::uri::Origin;\n///\n/// let uri = Origin::parse(\"/a%20z/////b/c////////d\").unwrap();\n/// let segments = uri.path().segments();\n/// for (i, segment) in segments.enumerate() {\n///     match i {\n///         0 => assert_eq!(segment, \"a z\"),\n///         1 => assert_eq!(segment, \"b\"),\n///         2 => assert_eq!(segment, \"c\"),\n///         3 => assert_eq!(segment, \"d\"),\n///         _ => panic!(\"only four segments\")\n///     }\n/// }\n/// # assert_eq!(uri.path().segments().num(), 4);\n/// # assert_eq!(uri.path().segments().count(), 4);\n/// # assert_eq!(uri.path().segments().next(), Some(\"a z\"));\n/// ```\n#[derive(Debug, Clone)]\npub struct Segments<'a, P: Part> {\n    pub(super) source: &'a RawStr,\n    pub(super) segments: &'a [P::Raw],\n    pub(super) pos: usize,\n}\n\nimpl<P: Part> Segments<'_, P> {\n    #[doc(hidden)]\n    #[inline(always)]\n    pub fn new<'a>(source: &'a RawStr, segments: &'a [P::Raw]) -> Segments<'a, P> {\n        Segments { source, segments, pos: 0, }\n    }\n\n    /// Returns the number of path segments left.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo/bar?baz&cat&car\");\n    ///\n    /// let mut segments = uri.path().segments();\n    /// assert_eq!(segments.num(), 2);\n    ///\n    /// segments.next();\n    /// assert_eq!(segments.num(), 1);\n    ///\n    /// segments.next();\n    /// assert_eq!(segments.num(), 0);\n    ///\n    /// segments.next();\n    /// assert_eq!(segments.num(), 0);\n    /// ```\n    #[inline]\n    pub fn num(&self) -> usize {\n        let max_pos = std::cmp::min(self.pos, self.segments.len());\n        self.segments.len() - max_pos\n    }\n\n    /// Returns `true` if there are no segments left.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo/bar?baz&cat&car\");\n    ///\n    /// let mut segments = uri.path().segments();\n    /// assert!(!segments.is_empty());\n    ///\n    /// segments.next();\n    /// segments.next();\n    /// assert!(segments.is_empty());\n    /// ```\n    #[inline]\n    pub fn is_empty(&self) -> bool {\n        self.num() == 0\n    }\n\n    /// Returns a new `Segments` with `n` segments skipped.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo/bar/baz/cat\");\n    ///\n    /// let mut segments = uri.path().segments();\n    /// assert_eq!(segments.num(), 4);\n    /// assert_eq!(segments.next(), Some(\"foo\"));\n    ///\n    /// let mut segments = segments.skip(2);\n    /// assert_eq!(segments.num(), 1);\n    /// assert_eq!(segments.next(), Some(\"cat\"));\n    /// ```\n    #[inline]\n    pub fn skip(mut self, n: usize) -> Self {\n        self.pos = std::cmp::min(self.pos + n, self.segments.len());\n        self\n    }\n}\n\nimpl<'a> Segments<'a, Path> {\n    /// Returns the `n`th segment, 0-indexed, from the current position.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/foo/bar/baaaz/cat\");\n    ///\n    /// let segments = uri.path().segments();\n    /// assert_eq!(segments.get(0), Some(\"foo\"));\n    /// assert_eq!(segments.get(1), Some(\"bar\"));\n    /// assert_eq!(segments.get(2), Some(\"baaaz\"));\n    /// assert_eq!(segments.get(3), Some(\"cat\"));\n    /// assert_eq!(segments.get(4), None);\n    /// ```\n    #[inline]\n    pub fn get(&self, n: usize) -> Option<&'a str> {\n        self.segments.get(self.pos + n)\n            .map(|i| i.from_source(Some(self.source.as_str())))\n    }\n\n    /// Returns `true` if `self` is a prefix of `other`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let a = uri!(\"/\");\n    /// let b = uri!(\"/\");\n    /// assert!(a.path().segments().prefix_of(b.path().segments()));\n    /// assert!(b.path().segments().prefix_of(a.path().segments()));\n    ///\n    /// let a = uri!(\"/\");\n    /// let b = uri!(\"/foo\");\n    /// assert!(a.path().segments().prefix_of(b.path().segments()));\n    /// assert!(!b.path().segments().prefix_of(a.path().segments()));\n    ///\n    /// let a = uri!(\"/foo\");\n    /// let b = uri!(\"/foo/\");\n    /// assert!(a.path().segments().prefix_of(b.path().segments()));\n    /// assert!(!b.path().segments().prefix_of(a.path().segments()));\n    ///\n    /// let a = uri!(\"/foo/bar/baaaz/cat\");\n    /// let b = uri!(\"/foo/bar\");\n    ///\n    /// assert!(b.path().segments().prefix_of(a.path().segments()));\n    /// assert!(!a.path().segments().prefix_of(b.path().segments()));\n    ///\n    /// let a = uri!(\"/foo/bar/baaaz/cat\");\n    /// let b = uri!(\"/dog/foo/bar\");\n    /// assert!(b.path().segments().skip(1).prefix_of(a.path().segments()));\n    /// ```\n    #[inline]\n    pub fn prefix_of(self, other: Segments<'_, Path>) -> bool {\n        if self.num() > other.num() {\n            return false;\n        }\n\n        self.zip(other).all(|(a, b)| a.is_empty() || a == b)\n    }\n\n    /// Creates a `PathBuf` from `self`. The returned `PathBuf` is\n    /// percent-decoded and guaranteed to be relative. If a segment is equal to\n    /// `.`, it is skipped. If a segment is equal to `..`, the previous segment\n    /// (if any) is skipped.\n    ///\n    /// For security purposes, if a segment meets any of the following\n    /// conditions, an `Err` is returned indicating the condition met:\n    ///\n    ///   * Decoded segment starts with any of: `*`\n    ///   * Decoded segment ends with any of: `:`, `>`, `<`\n    ///   * Decoded segment contains any of: `/`\n    ///   * On Windows, decoded segment contains any of: `\\`, `:`\n    ///   * Percent-encoding results in invalid UTF-8.\n    ///\n    /// Additionally, if `allow_dotfiles` is `false`, an `Err` is returned if\n    /// the following condition is met:\n    ///\n    ///   * Decoded segment starts with any of: `.` (except `..` and `.`)\n    ///\n    /// As a result of these conditions, a `PathBuf` derived via `FromSegments`\n    /// is safe to interpolate within, or use as a suffix of, a path without\n    /// additional checks.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use std::path::Path;\n    ///\n    /// let uri = uri!(\"/a/b/c/d/.pass\");\n    ///\n    /// let path = uri.path().segments().to_path_buf(true);\n    /// assert_eq!(path.unwrap(), Path::new(\"a/b/c/d/.pass\"));\n    ///\n    /// let path = uri.path().segments().to_path_buf(false);\n    /// assert!(path.is_err());\n    /// ```\n    pub fn to_path_buf(&self, allow_dotfiles: bool) -> Result<PathBuf, PathError> {\n        let mut buf = PathBuf::new();\n        for segment in self.clone() {\n            if segment == \".\" {\n                continue;\n            } else if segment == \"..\" {\n                buf.pop();\n            } else if !allow_dotfiles && segment.starts_with('.') {\n                return Err(PathError::BadStart('.'))\n            } else if segment.starts_with('*') {\n                return Err(PathError::BadStart('*'))\n            } else if segment.ends_with(':') {\n                return Err(PathError::BadEnd(':'))\n            } else if segment.ends_with('>') {\n                return Err(PathError::BadEnd('>'))\n            } else if segment.ends_with('<') {\n                return Err(PathError::BadEnd('<'))\n            } else if segment.contains('/') {\n                return Err(PathError::BadChar('/'))\n            } else if cfg!(windows) && segment.contains('\\\\') {\n                return Err(PathError::BadChar('\\\\'))\n            } else if cfg!(windows) && segment.contains(':') {\n                return Err(PathError::BadChar(':'))\n            } else {\n                buf.push(segment)\n            }\n        }\n\n        // TODO: Should we check the filename against the list in `FileName`?\n        // That list is mostly for writing, while this is likely to be read.\n        // TODO: Add an option to allow/disallow shell characters?\n\n        Ok(buf)\n    }\n}\n\nimpl<'a> Segments<'a, Query> {\n    /// Returns the `n`th segment, 0-indexed, from the current position.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// let uri = uri!(\"/?foo=1&bar=hi+there&baaaz&cat=dog&=oh\");\n    ///\n    /// let segments = uri.query().unwrap().segments();\n    /// assert_eq!(segments.get(0), Some((\"foo\", \"1\")));\n    /// assert_eq!(segments.get(1), Some((\"bar\", \"hi there\")));\n    /// assert_eq!(segments.get(2), Some((\"baaaz\", \"\")));\n    /// assert_eq!(segments.get(3), Some((\"cat\", \"dog\")));\n    /// assert_eq!(segments.get(4), Some((\"\", \"oh\")));\n    /// assert_eq!(segments.get(5), None);\n    /// ```\n    #[inline]\n    pub fn get(&self, n: usize) -> Option<(&'a str, &'a str)> {\n        let (name, val) = self.segments.get(self.pos + n)?;\n        let source = Some(self.source.as_str());\n        let name = name.from_source(source);\n        let val = val.from_source(source);\n        Some((name, val))\n    }\n}\n\nmacro_rules! impl_iterator {\n    ($T:ty => $I:ty) => (\n        impl<'a> Iterator for Segments<'a, $T> {\n            type Item = $I;\n\n            fn next(&mut self) -> Option<Self::Item> {\n                let item = self.get(0)?;\n                self.pos += 1;\n                Some(item)\n            }\n\n            fn size_hint(&self) -> (usize, Option<usize>) {\n                (self.num(), Some(self.num()))\n            }\n\n            fn count(self) -> usize {\n                self.num()\n            }\n        }\n    )\n}\n\nimpl_iterator!(Path => &'a str);\nimpl_iterator!(Query => (&'a str, &'a str));\n"
  },
  {
    "path": "core/http/src/uri/uri.rs",
    "content": "use std::fmt::{self, Display};\nuse std::borrow::Cow;\n\nuse crate::ext::IntoOwned;\nuse crate::uri::{Origin, Authority, Absolute, Reference, Asterisk};\nuse crate::uri::error::{Error, TryFromUriError};\n\n/// An `enum` encapsulating any of the possible URI variants.\n///\n/// # Usage\n///\n/// In Rocket, this type will rarely be used directly. Instead, you will\n/// typically encounter URIs via the [`Origin`] type. This is because all\n/// incoming requests accepted by Rocket contain URIs in origin-form.\n///\n/// ## Parsing\n///\n/// The `Uri` type implements a full, zero-allocation, zero-copy [RFC 7230]\n/// compliant \"request target\" parser with limited liberties for real-world\n/// deviations. In particular, the parser deviates as follows:\n///\n///   * It accepts `%` characters without two trailing hex-digits.\n///\n///   * It accepts the following additional unencoded characters in query parts,\n///     to match real-world browser behavior:\n///\n///     `{`, `}`, `[`,  `]`, `\\`,  `^`,  <code>&#96;</code>, `|`\n///\n/// To parse an `&str` into a `Uri`, use [`Uri::parse()`]. Alternatively, you\n/// may also use the `TryFrom<&str>` and `TryFrom<String>` trait implementation.\n/// To inspect the parsed type, match on the resulting `enum` and use the\n/// methods of the internal structure.\n///\n/// [RFC 7230]: https://tools.ietf.org/html/rfc7230\n#[derive(Debug, PartialEq, Clone)]\npub enum Uri<'a> {\n    /// An asterisk: exactly `*`.\n    Asterisk(Asterisk),\n    /// An origin URI.\n    Origin(Origin<'a>),\n    /// An authority URI.\n    Authority(Authority<'a>),\n    /// An absolute URI.\n    Absolute(Absolute<'a>),\n    /// A URI reference.\n    Reference(Reference<'a>),\n}\n\nimpl<'a> Uri<'a> {\n    /// Parses the string `string` into a `Uri` of kind `T`.\n    ///\n    /// This is identical to `T::parse(string).map(Uri::from)`.\n    ///\n    /// `T` is typically one of [`Asterisk`], [`Origin`], [`Authority`],\n    /// [`Absolute`], or [`Reference`]. Parsing never allocates. Returns an\n    /// `Error` if `string` is not a valid URI of kind `T`.\n    ///\n    /// To perform an ambiguous parse into _any_ valid URI type, use\n    /// [`Uri::parse_any()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::{Uri, Origin};\n    ///\n    /// // Parse a valid origin URI (note: in practice, use `Origin::parse()`).\n    /// let uri = Uri::parse::<Origin>(\"/a/b/c?query\").expect(\"valid URI\");\n    /// let origin = uri.origin().expect(\"origin URI\");\n    /// assert_eq!(origin.path(), \"/a/b/c\");\n    /// assert_eq!(origin.query().unwrap(), \"query\");\n    ///\n    /// // Prefer to use the `uri!()` macro for static inputs. The return value\n    /// // is of the specific type, not `Uri`.\n    /// let origin = uri!(\"/a/b/c?query\");\n    /// assert_eq!(origin.path(), \"/a/b/c\");\n    /// assert_eq!(origin.query().unwrap(), \"query\");\n    ///\n    /// // Invalid URIs fail to parse.\n    /// Uri::parse::<Origin>(\"foo bar\").expect_err(\"invalid URI\");\n    /// ```\n    pub fn parse<T>(string: &'a str) -> Result<Uri<'a>, Error<'a>>\n        where T: Into<Uri<'a>> + TryFrom<&'a str, Error = Error<'a>>\n    {\n        T::try_from(string).map(|v| v.into())\n    }\n\n    /// Parse `string` into a the \"best fit\" URI type.\n    ///\n    /// Always prefer to use `uri!()` for statically known inputs.\n    ///\n    /// Because URI parsing is ambiguous (that is, there isn't a one-to-one\n    /// mapping between strings and a URI type), the internal type returned by\n    /// this method _may_ not be the desired type. This method chooses the \"best\n    /// fit\" type for a given string by preferring to parse in the following\n    /// order:\n    ///\n    ///   * `Asterisk`\n    ///   * `Origin`\n    ///   * `Authority`\n    ///   * `Absolute`\n    ///   * `Reference`\n    ///\n    /// Thus, even though `*` is a valid `Asterisk` _and_ `Reference` URI, it\n    /// will parse as an `Asterisk`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::{Uri, Origin, Reference};\n    ///\n    /// // An absolute path is an origin _unless_ it contains a fragment.\n    /// let uri = Uri::parse_any(\"/a/b/c?query\").expect(\"valid URI\");\n    /// let origin = uri.origin().expect(\"origin URI\");\n    /// assert_eq!(origin.path(), \"/a/b/c\");\n    /// assert_eq!(origin.query().unwrap(), \"query\");\n    ///\n    /// let uri = Uri::parse_any(\"/a/b/c?query#fragment\").expect(\"valid URI\");\n    /// let reference = uri.reference().expect(\"reference URI\");\n    /// assert_eq!(reference.path(), \"/a/b/c\");\n    /// assert_eq!(reference.query().unwrap(), \"query\");\n    /// assert_eq!(reference.fragment().unwrap(), \"fragment\");\n    ///\n    /// // Prefer to use the `uri!()` macro for static inputs. The return type\n    /// // is the internal type, not `Uri`. The explicit type is not required.\n    /// let uri: Origin = uri!(\"/a/b/c?query\");\n    /// let uri: Reference = uri!(\"/a/b/c?query#fragment\");\n    /// ```\n    pub fn parse_any(string: &'a str) -> Result<Uri<'a>, Error<'a>> {\n        crate::parse::uri::from_str(string)\n    }\n\n    /// Returns the internal instance of `Origin` if `self` is a `Uri::Origin`.\n    /// Otherwise, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::{Uri, Absolute, Origin};\n    ///\n    /// let uri = Uri::parse::<Origin>(\"/a/b/c?query\").expect(\"valid URI\");\n    /// assert!(uri.origin().is_some());\n    ///\n    /// let uri = Uri::from(uri!(\"/a/b/c?query\"));\n    /// assert!(uri.origin().is_some());\n    ///\n    /// let uri = Uri::parse::<Absolute>(\"https://rocket.rs\").expect(\"valid URI\");\n    /// assert!(uri.origin().is_none());\n    ///\n    /// let uri = Uri::from(uri!(\"https://rocket.rs\"));\n    /// assert!(uri.origin().is_none());\n    /// ```\n    pub fn origin(&self) -> Option<&Origin<'a>> {\n        match self {\n            Uri::Origin(ref inner) => Some(inner),\n            _ => None\n        }\n    }\n\n    /// Returns the internal instance of `Authority` if `self` is a\n    /// `Uri::Authority`. Otherwise, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::{Uri, Absolute, Authority};\n    ///\n    /// let uri = Uri::parse::<Authority>(\"user:pass@domain.com\").expect(\"valid URI\");\n    /// assert!(uri.authority().is_some());\n    ///\n    /// let uri = Uri::from(uri!(\"user:pass@domain.com\"));\n    /// assert!(uri.authority().is_some());\n    ///\n    /// let uri = Uri::parse::<Absolute>(\"https://rocket.rs\").expect(\"valid URI\");\n    /// assert!(uri.authority().is_none());\n    ///\n    /// let uri = Uri::from(uri!(\"https://rocket.rs\"));\n    /// assert!(uri.authority().is_none());\n    /// ```\n    pub fn authority(&self) -> Option<&Authority<'a>> {\n        match self {\n            Uri::Authority(ref inner) => Some(inner),\n            _ => None\n        }\n    }\n\n    /// Returns the internal instance of `Absolute` if `self` is a\n    /// `Uri::Absolute`. Otherwise, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::{Uri, Absolute, Origin};\n    ///\n    /// let uri = Uri::parse::<Absolute>(\"http://rocket.rs\").expect(\"valid URI\");\n    /// assert!(uri.absolute().is_some());\n    ///\n    /// let uri = Uri::from(uri!(\"http://rocket.rs\"));\n    /// assert!(uri.absolute().is_some());\n    ///\n    /// let uri = Uri::parse::<Origin>(\"/path\").expect(\"valid URI\");\n    /// assert!(uri.absolute().is_none());\n    ///\n    /// let uri = Uri::from(uri!(\"/path\"));\n    /// assert!(uri.absolute().is_none());\n    /// ```\n    pub fn absolute(&self) -> Option<&Absolute<'a>> {\n        match self {\n            Uri::Absolute(ref inner) => Some(inner),\n            _ => None\n        }\n    }\n\n    /// Returns the internal instance of `Reference` if `self` is a\n    /// `Uri::Reference`. Otherwise, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::uri::{Uri, Absolute, Reference};\n    ///\n    /// let uri = Uri::parse::<Reference>(\"foo/bar\").expect(\"valid URI\");\n    /// assert!(uri.reference().is_some());\n    ///\n    /// let uri = Uri::from(uri!(\"foo/bar\"));\n    /// assert!(uri.reference().is_some());\n    ///\n    /// let uri = Uri::parse::<Absolute>(\"https://rocket.rs\").expect(\"valid URI\");\n    /// assert!(uri.reference().is_none());\n    ///\n    /// let uri = Uri::from(uri!(\"https://rocket.rs\"));\n    /// assert!(uri.reference().is_none());\n    /// ```\n    pub fn reference(&self) -> Option<&Reference<'a>> {\n        match self {\n            Uri::Reference(ref inner) => Some(inner),\n            _ => None\n        }\n    }\n}\n\npub(crate) unsafe fn as_utf8_unchecked(input: Cow<'_, [u8]>) -> Cow<'_, str> {\n    match input {\n        Cow::Borrowed(bytes) => Cow::Borrowed(std::str::from_utf8_unchecked(bytes)),\n        Cow::Owned(bytes) => Cow::Owned(String::from_utf8_unchecked(bytes))\n    }\n}\n\n// impl<'a> TryFrom<&'a str> for Uri<'a> {\n//     type Error = Error<'a>;\n//\n//     #[inline]\n//     fn try_from(string: &'a str) -> Result<Uri<'a>, Self::Error> {\n//         Uri::parse(string)\n//     }\n// }\n//\n// impl TryFrom<String> for Uri<'static> {\n//     type Error = Error<'static>;\n//\n//     #[inline]\n//     fn try_from(string: String) -> Result<Uri<'static>, Self::Error> {\n//         // TODO: Potentially optimize this like `Origin::parse_owned`.\n//         Uri::parse(&string)\n//             .map(|u| u.into_owned())\n//             .map_err(|e| e.into_owned())\n//     }\n// }\n\nimpl IntoOwned for Uri<'_> {\n    type Owned = Uri<'static>;\n\n    fn into_owned(self) -> Uri<'static> {\n        match self {\n            Uri::Origin(origin) => Uri::Origin(origin.into_owned()),\n            Uri::Authority(authority) => Uri::Authority(authority.into_owned()),\n            Uri::Absolute(absolute) => Uri::Absolute(absolute.into_owned()),\n            Uri::Reference(reference) => Uri::Reference(reference.into_owned()),\n            Uri::Asterisk(asterisk) => Uri::Asterisk(asterisk)\n        }\n    }\n}\n\nimpl Display for Uri<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            Uri::Origin(ref origin) => write!(f, \"{}\", origin),\n            Uri::Authority(ref authority) => write!(f, \"{}\", authority),\n            Uri::Absolute(ref absolute) => write!(f, \"{}\", absolute),\n            Uri::Reference(ref reference) => write!(f, \"{}\", reference),\n            Uri::Asterisk(ref asterisk) => write!(f, \"{}\", asterisk)\n        }\n    }\n}\n\nmacro_rules! impl_uri_from {\n    ($T:ident $(<$lt:lifetime>)?) => (\n        impl<'a> From<$T $(<$lt>)?> for Uri<'a> {\n            fn from(other: $T $(<$lt>)?) -> Uri<'a> {\n                Uri::$T(other)\n            }\n        }\n\n        impl<'a> TryFrom<Uri<'a>> for $T $(<$lt>)? {\n            type Error = TryFromUriError;\n\n            fn try_from(uri: Uri<'a>) -> Result<Self, Self::Error> {\n                match uri {\n                    Uri::$T(inner) => Ok(inner),\n                    _ => Err(TryFromUriError(()))\n                }\n            }\n        }\n\n        impl<'b, $($lt)?> PartialEq<$T $(<$lt>)?> for Uri<'b> {\n            fn eq(&self, other: &$T $(<$lt>)?) -> bool {\n                match self {\n                    Uri::$T(inner) => inner == other,\n                    _ => false\n                }\n            }\n        }\n\n        impl<'b, $($lt)?> PartialEq<Uri<'b>> for $T $(<$lt>)? {\n            fn eq(&self, other: &Uri<'b>) -> bool {\n                match other {\n                    Uri::$T(inner) => inner == self,\n                    _ => false\n                }\n            }\n        }\n\n        impl<'b, $($lt)?> PartialEq<&$T $(<$lt>)?> for Uri<'b> {\n            fn eq(&self, other: &&$T $(<$lt>)?) -> bool {\n                match self {\n                    Uri::$T(inner) => inner == *other,\n                    _ => false\n                }\n            }\n        }\n\n        impl<'b, $($lt)?> PartialEq<Uri<'b>> for &$T $(<$lt>)? {\n            fn eq(&self, other: &Uri<'b>) -> bool {\n                match other {\n                    Uri::$T(inner) => inner == *self,\n                    _ => false\n                }\n            }\n        }\n    )\n}\n\nimpl_uri_from!(Origin<'a>);\nimpl_uri_from!(Authority<'a>);\nimpl_uri_from!(Absolute<'a>);\nimpl_uri_from!(Reference<'a>);\nimpl_uri_from!(Asterisk);\n\n/// Implements Serialize and Deserialize for any 'URI' looking type.\nmacro_rules! impl_serde {\n    ($T:ty, $expected:literal) => {\n        #[cfg(feature = \"serde\")]\n        mod serde_impl {\n            use std::fmt;\n            use std::marker::PhantomData;\n            use super::*;\n\n            use serde::ser::{Serialize, Serializer};\n            use serde::de::{Deserialize, Deserializer, Error, Visitor};\n\n            impl<'a> Serialize for $T {\n                fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {\n                    serializer.serialize_str(&self.to_string())\n                }\n            }\n\n            struct DeVisitor<'a>(PhantomData<&'a $T>);\n\n            impl<'de, 'a> Visitor<'de> for DeVisitor<'a> {\n                type Value = $T;\n\n                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n                    write!(formatter, $expected)\n                }\n\n                fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {\n                    <$T>::parse_owned(v.to_string()).map_err(Error::custom)\n                }\n\n                fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {\n                    <$T>::parse_owned(v).map_err(Error::custom)\n                }\n            }\n\n            impl<'a, 'de> Deserialize<'de> for $T {\n                fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {\n                    deserializer.deserialize_str(DeVisitor(PhantomData))\n                }\n            }\n        }\n    };\n}\n\n/// Implements traits from `impl_base_traits` and IntoOwned for a URI.\nmacro_rules! impl_traits {\n    ($T:ident, $($field:ident),* $(,)?) => {\n        impl_traits!($T [parse], $($field),*);\n    };\n    ($T:ident [$partial_eq_parse:ident], $($field:ident),* $(,)?) => {\n        impl_base_traits!($T [$partial_eq_parse], $($field),*);\n\n        impl crate::ext::IntoOwned for $T<'_> {\n            type Owned = $T<'static>;\n\n            fn into_owned(self) -> $T<'static> {\n                $T {\n                    source: self.source.into_owned(),\n                    $($field: self.$field.into_owned()),*\n                }\n            }\n        }\n    }\n}\n\n/// Implements PartialEq, Eq, Hash, and TryFrom.\nmacro_rules! impl_base_traits {\n    ($T:ident, $($field:ident),* $(,)?) => {\n        impl_base_traits!($T [parse], $($field),*);\n    };\n    ($T:ident [$partial_eq_parse:ident], $($field:ident),* $(,)?) => {\n        impl std::convert::TryFrom<String> for $T<'static> {\n            type Error = Error<'static>;\n\n            fn try_from(value: String) -> Result<Self, Self::Error> {\n                $T::parse_owned(value)\n            }\n        }\n\n        // Because inference doesn't take `&String` to `&str`.\n        impl<'a> std::convert::TryFrom<&'a String> for $T<'a> {\n            type Error = Error<'a>;\n\n            fn try_from(value: &'a String) -> Result<Self, Self::Error> {\n                $T::parse(value.as_str())\n            }\n        }\n\n        impl<'a> std::convert::TryFrom<&'a str> for $T<'a> {\n            type Error = Error<'a>;\n\n            fn try_from(value: &'a str) -> Result<Self, Self::Error> {\n                $T::parse(value)\n            }\n        }\n\n        impl<'a, 'b> PartialEq<$T<'b>> for $T<'a> {\n            fn eq(&self, other: &$T<'b>) -> bool {\n                true $(&& self.$field() == other.$field())*\n            }\n        }\n\n        impl PartialEq<str> for $T<'_> {\n            fn eq(&self, string: &str) -> bool {\n                $T::$partial_eq_parse(string).map_or(false, |v| &v == self)\n            }\n        }\n\n        impl PartialEq<&str> for $T<'_> {\n            fn eq(&self, other: &&str) -> bool {\n                self.eq(*other)\n            }\n        }\n\n        impl PartialEq<$T<'_>> for str {\n            fn eq(&self, other: &$T<'_>) -> bool {\n                other.eq(self)\n            }\n        }\n\n        impl Eq for $T<'_> { }\n\n        impl std::hash::Hash for $T<'_> {\n            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n                $(self.$field().hash(state);)*\n            }\n        }\n    }\n}\n\nmod tests {\n    #[test]\n    fn normalization() {\n        fn normalize(uri: &str) -> String {\n            use crate::uri::Uri;\n\n            match Uri::parse_any(uri).unwrap() {\n                Uri::Origin(uri) => uri.into_normalized().to_string(),\n                Uri::Absolute(uri) => uri.into_normalized().to_string(),\n                Uri::Reference(uri) => uri.into_normalized().to_string(),\n                uri => uri.to_string(),\n            }\n        }\n\n        assert_eq!(normalize(\"/#\"), \"/#\");\n\n        assert_eq!(normalize(\"/\"), \"/\");\n        assert_eq!(normalize(\"//\"), \"/\");\n        assert_eq!(normalize(\"//////a/\"), \"/a/\");\n        assert_eq!(normalize(\"//ab\"), \"/ab\");\n        assert_eq!(normalize(\"//a\"), \"/a\");\n        assert_eq!(normalize(\"/a/b///c\"), \"/a/b/c\");\n        assert_eq!(normalize(\"/a/b///c/\"), \"/a/b/c/\");\n        assert_eq!(normalize(\"/a///b/c/d///\"), \"/a/b/c/d/\");\n\n        assert_eq!(normalize(\"/?\"), \"/?\");\n        assert_eq!(normalize(\"/?foo\"), \"/?foo\");\n        assert_eq!(normalize(\"/a/?\"), \"/a/?\");\n        assert_eq!(normalize(\"/a/?foo\"), \"/a/?foo\");\n    }\n}\n"
  },
  {
    "path": "core/lib/Cargo.toml",
    "content": "[package]\nname = \"rocket\"\nversion = \"0.6.0-dev\"\nauthors = [\"Sergio Benitez <sb@sergio.bz>\"]\ndescription = \"\"\"\nWeb framework with a focus on usability, security, extensibility, and speed.\n\"\"\"\ndocumentation = \"https://api.rocket.rs/master/rocket/\"\nhomepage = \"https://rocket.rs\"\nrepository = \"https://github.com/rwf2/Rocket\"\nreadme = \"../../README.md\"\nkeywords = [\"rocket\", \"web\", \"framework\", \"server\"]\nlicense = \"MIT OR Apache-2.0\"\nbuild = \"build.rs\"\ncategories = [\"web-programming::http-server\"]\nedition = \"2021\"\nrust-version = \"1.75\"\n\n[package.metadata.docs.rs]\nall-features = true\n\n[lints]\nworkspace = true\n\n[features]\ndefault = [\"http2\", \"tokio-macros\", \"trace\"]\nhttp2 = [\"hyper/http2\", \"hyper-util/http2\"]\nhttp3-preview = [\"s2n-quic\", \"s2n-quic-h3\", \"tls\"]\nsecrets = [\"cookie/private\", \"cookie/key-expansion\"]\njson = [\"serde_json\"]\nmsgpack = [\"rmp-serde\"]\nuuid = [\"uuid_\", \"rocket_http/uuid\"]\ntls = [\"rustls\", \"tokio-rustls\", \"rustls-pemfile\"]\nmtls = [\"tls\", \"x509-parser\"]\ntokio-macros = [\"tokio/macros\"]\ntrace = [\"tracing-subscriber\", \"tinyvec\", \"thread_local\", \"rustls?/logging\", \"tokio-rustls?/logging\", \"multer/log\", \"s2n-quic-h3?/tracing\"]\n\n[dependencies]\n# Optional serialization dependencies.\nserde_json = { version = \"1.0.26\", optional = true }\nrmp-serde = { version = \"1\", optional = true }\nuuid_ = { package = \"uuid\", version = \"1\", optional = true, features = [\"serde\"] }\n\n# Optional MTLS dependencies\nx509-parser = { version = \"0.16\", optional = true }\n\n# Hyper dependencies\nhttp = \"1\"\nbytes = \"1.4\"\nhyper = { version = \"1.1\", default-features = false, features = [\"http1\", \"server\"] }\nhyper-util = { version = \"0.1.3\", default-features = false, features = [\"http1\", \"server\", \"tokio\"] }\n\n# Non-optional, core dependencies from here on out.\nyansi = { version = \"1.0.1\", features = [\"detect-tty\"] }\nnum_cpus = \"1.0\"\ntime = { version = \"0.3\", features = [\"macros\", \"parsing\"] }\nmemchr = \"2\" # TODO: Use pear instead.\nbinascii = \"0.1\"\nref-cast = \"1.0\"\nref-swap = \"0.1.2\"\nparking_lot = \"0.12\"\nubyte = {version = \"0.10.2\", features = [\"serde\"] }\nserde = { version = \"1.0\", features = [\"derive\"] }\nfigment = { version = \"0.10.17\", features = [\"toml\", \"env\"] }\nrand = \"0.9\"\neither = \"1\"\npin-project-lite = \"0.2\"\nindexmap = { version = \"2\", features = [\"serde\"] }\ntempfile = \"3\"\nasync-trait = \"0.1.43\"\nasync-stream = \"0.3.2\"\nmulter = { version = \"3.1.0\", features = [\"tokio-io\"] }\ntokio-stream = { version = \"0.1.6\", features = [\"signal\", \"time\"] }\ncookie = { version = \"0.18\", features = [\"percent-encode\"] }\nfutures = { version = \"0.3.30\", default-features = false, features = [\"std\"] }\nstate = \"0.6\"\n\n# tracing\ntracing = { version = \"0.1.40\", default-features = false, features = [\"std\", \"attributes\"] }\ntinyvec = { version = \"1.6\", optional = true, features = [\"std\", \"rustc_1_57\"] }\nthread_local = { version = \"1.1\", optional = true }\n\n[dependencies.tracing-subscriber]\nversion = \"0.3.18\"\noptional = true\ndefault-features = false\nfeatures = [\"fmt\", \"tracing-log\", \"parking_lot\"]\n\n[dependencies.rocket_codegen]\nversion = \"0.6.0-dev\"\npath = \"../codegen\"\n\n[dependencies.rocket_http]\nversion = \"0.6.0-dev\"\npath = \"../http\"\nfeatures = [\"serde\"]\n\n[dependencies.tokio]\nversion = \"1.35.1\"\nfeatures = [\"rt-multi-thread\", \"net\", \"io-util\", \"fs\", \"time\", \"sync\", \"signal\", \"parking_lot\"]\n\n[dependencies.tokio-util]\nversion = \"0.7\"\ndefault-features = false\nfeatures = [\"io\"]\n\n[dependencies.rustls]\nversion = \"0.23\"\ndefault-features = false\nfeatures = [\"ring\", \"std\", \"tls12\"]\noptional = true\n\n[dependencies.tokio-rustls]\nversion = \"0.26\"\ndefault-features = false\nfeatures = [\"tls12\", \"ring\"]\noptional = true\n\n[dependencies.rustls-pemfile]\nversion = \"2.1.0\"\noptional = true\n\n[dependencies.s2n-quic]\nversion = \"1.51\"\ndefault-features = false\nfeatures = [\"provider-address-token-default\", \"provider-tls-rustls\"]\noptional = true\n\n[dependencies.s2n-quic-h3]\ngit = \"https://github.com/SergioBenitez/s2n-quic-h3.git\"\nrev = \"f832471\"\noptional = true\n\n[target.'cfg(unix)'.dependencies]\nlibc = \"0.2.149\"\n\n[build-dependencies]\nversion_check = \"0.9.1\"\n\n[dev-dependencies]\ntokio = { version = \"1\", features = [\"macros\", \"io-std\"] }\nfigment = { version = \"0.10.17\", features = [\"test\"] }\npretty_assertions = \"1\"\n"
  },
  {
    "path": "core/lib/build.rs",
    "content": "fn main() {\n    if let Some((version, channel, _)) = version_check::triple() {\n        if channel.supports_features() {\n            println!(\"cargo:rustc-cfg=nightly\");\n        }\n\n        if version.at_least(\"1.67\") && version.at_most(\"1.68.2\") {\n            println!(\"cargo:rustc-cfg=broken_fmt\");\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/fuzz/.gitignore",
    "content": "target\ncorpus/*/*\nartifacts\n!*.seed\n"
  },
  {
    "path": "core/lib/fuzz/Cargo.toml",
    "content": "[package]\nname = \"rocket-fuzz\"\nversion = \"0.0.0\"\nauthors = [\"Automatically generated\"]\npublish = false\nedition = \"2021\"\n\n[package.metadata]\ncargo-fuzz = true\n\n[lints.rust]\nunexpected_cfgs = { level = \"warn\", check-cfg = ['cfg(honggfuzz)', 'cfg(afl)'] }\n\n[dependencies]\nlibfuzzer-sys = \"0.4\"\narbitrary = { version = \"1.3\", features = [\"derive\"] }\n\n[target.'cfg(afl)'.dependencies]\nafl = \"*\"\n\n[target.'cfg(honggfuzz)'.dependencies]\nhonggfuzz = \"*\"\n\n[dependencies.rocket]\npath = \"..\"\n\n# Prevent this from interfering with workspaces\n[workspace]\nmembers = [\".\"]\n\n[[bin]]\nname = \"uri-parsing\"\npath = \"targets/uri-parsing.rs\"\ntest = false\ndoc = false\n\n[[bin]]\nname = \"uri-roundtrip\"\npath = \"targets/uri-roundtrip.rs\"\ntest = false\ndoc = false\n\n[[bin]]\nname = \"uri-normalization\"\npath = \"targets/uri-normalization.rs\"\ntest = false\ndoc = false\n\n[[bin]]\nname = \"collision-matching\"\npath = \"targets/collision-matching.rs\"\ntest = false\ndoc = false\n"
  },
  {
    "path": "core/lib/fuzz/README.md",
    "content": "# Fuzzing\n\nInstall `cargo-fuzz`:\n\n```sh\ncargo install -f cargo-fuzz\n```\n\nRun any available target where `$target` is the name of the target and `$n` is\nthe number of CPUs to use for fuzzing:\n\n```sh\ncargo fuzz list # get list of targets\ncargo fuzz run $target -j $n\n```\n"
  },
  {
    "path": "core/lib/fuzz/corpus/collision-matching/another.seed",
    "content": "01//foo/bar/b01/foo/a/b1/text/html\n"
  },
  {
    "path": "core/lib/fuzz/corpus/collision-matching/base.seed",
    "content": "01//a/b01//a/b0/a/b\n"
  },
  {
    "path": "core/lib/fuzz/corpus/collision-matching/complex.seed",
    "content": "44/foo/bar/applicatiom/json1bazb01/foo/a/btext/plain1/fooktext/html\n"
  },
  {
    "path": "core/lib/fuzz/corpus/collision-matching/large.seed",
    "content": "------------------------------------------------------\n"
  },
  {
    "path": "core/lib/fuzz/corpus/uri-parsing/absolute.seed",
    "content": "http://user:pass@domain.com:4444/foo/bar?some=query\n"
  },
  {
    "path": "core/lib/fuzz/corpus/uri-parsing/asterisk.seed",
    "content": "*\n"
  },
  {
    "path": "core/lib/fuzz/corpus/uri-parsing/authority.seed",
    "content": "username:password@some.host:8088\n"
  },
  {
    "path": "core/lib/fuzz/corpus/uri-parsing/origin.seed",
    "content": "/first_segment/second_segment/third?optional=query\n"
  },
  {
    "path": "core/lib/fuzz/corpus/uri-parsing/reference.seed",
    "content": "http://user:pass@domain.com:4444/foo/bar?some=query#and-fragment\n"
  },
  {
    "path": "core/lib/fuzz/targets/collision-matching.rs",
    "content": "#![cfg_attr(all(not(honggfuzz), not(afl)), no_main)]\n\nuse arbitrary::{Arbitrary, Unstructured, Result, Error};\n\nuse rocket::http::QMediaType;\nuse rocket::local::blocking::{LocalRequest, Client};\nuse rocket::http::{Method, Accept, ContentType, MediaType, uri::Origin};\nuse rocket::route::{Route, RouteUri, dummy_handler};\n\n#[derive(Arbitrary)]\nstruct ArbitraryRequestData<'a> {\n    method: ArbitraryMethod,\n    origin: ArbitraryOrigin<'a>,\n    format: Result<ArbitraryAccept, ArbitraryContentType>,\n}\n\n#[derive(Arbitrary)]\nstruct ArbitraryRouteData<'a> {\n    method: Option<ArbitraryMethod>,\n    uri: ArbitraryRouteUri<'a>,\n    format: Option<ArbitraryMediaType>,\n}\n\nimpl std::fmt::Debug for ArbitraryRouteData<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.debug_struct(\"ArbitraryRouteData\")\n            .field(\"method\", &self.method.map(|v| v.0))\n            .field(\"base\", &self.uri.0.base())\n            .field(\"unmounted\", &self.uri.0.unmounted().to_string())\n            .field(\"uri\", &self.uri.0.to_string())\n            .field(\"format\", &self.format.as_ref().map(|v| v.0.to_string()))\n            .finish()\n    }\n}\n\nimpl std::fmt::Debug for ArbitraryRequestData<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.debug_struct(\"ArbitraryRequestData\")\n            .field(\"method\", &self.method.0)\n            .field(\"origin\", &self.origin.0.to_string())\n            .field(\"format\", &self.format.as_ref()\n                .map_err(|v| v.0.to_string())\n                .map(|v| v.0.to_string()))\n            .finish()\n    }\n}\n\nimpl<'c, 'a: 'c> ArbitraryRequestData<'a> {\n    fn into_local_request(self, client: &'c Client) -> LocalRequest<'c> {\n        let mut req = client.req(self.method.0, self.origin.0);\n        match self.format {\n            Ok(accept) => req.add_header(accept.0),\n            Err(content_type) => req.add_header(content_type.0),\n        }\n\n        req\n    }\n}\n\nimpl<'a> ArbitraryRouteData<'a> {\n    fn into_route(self) -> Route {\n        let method = self.method.map(|m| m.0);\n        let mut r = Route::ranked(0, method, &self.uri.0.to_string(), dummy_handler);\n        r.format = self.format.map(|f| f.0);\n        r\n    }\n}\n\n#[derive(Clone, Copy)]\nstruct ArbitraryMethod(Method);\n\nstruct ArbitraryOrigin<'a>(Origin<'a>);\n\nstruct ArbitraryAccept(Accept);\n\nstruct ArbitraryContentType(ContentType);\n\nstruct ArbitraryMediaType(MediaType);\n\nstruct ArbitraryRouteUri<'a>(RouteUri<'a>);\n\nimpl<'a> Arbitrary<'a> for ArbitraryMethod {\n    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {\n        Ok(ArbitraryMethod(*u.choose(Method::ALL_VARIANTS)?))\n    }\n\n    fn size_hint(_: usize) -> (usize, Option<usize>) {\n        (1, None)\n    }\n}\n\nimpl<'a> Arbitrary<'a> for ArbitraryOrigin<'a> {\n    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {\n        let string = u.arbitrary::<&str>()?;\n        if string.is_empty() {\n            return Err(Error::NotEnoughData);\n        }\n\n        Origin::parse(string)\n            .map(ArbitraryOrigin)\n            .map_err(|_| Error::IncorrectFormat)\n    }\n\n    fn size_hint(_: usize) -> (usize, Option<usize>) {\n        (1, None)\n    }\n}\n\nimpl<'a> Arbitrary<'a> for ArbitraryAccept {\n    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {\n        let media_type: ArbitraryMediaType = u.arbitrary()?;\n        Ok(Self(Accept::new(QMediaType(media_type.0, None))))\n    }\n\n    fn size_hint(depth: usize) -> (usize, Option<usize>) {\n        ArbitraryMediaType::size_hint(depth)\n    }\n}\n\nimpl<'a> Arbitrary<'a> for ArbitraryContentType {\n    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {\n        let media_type: ArbitraryMediaType = u.arbitrary()?;\n        Ok(ArbitraryContentType(ContentType(media_type.0)))\n    }\n\n    fn size_hint(depth: usize) -> (usize, Option<usize>) {\n        ArbitraryMediaType::size_hint(depth)\n    }\n}\n\nimpl<'a> Arbitrary<'a> for ArbitraryMediaType {\n    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {\n        let known = [\n            \"txt\", \"html\", \"htm\", \"xml\", \"opf\", \"xhtml\", \"csv\", \"js\", \"css\", \"json\",\n            \"png\", \"gif\", \"bmp\", \"jpeg\", \"jpg\", \"webp\", \"avif\", \"svg\", \"ico\", \"flac\", \"wav\",\n            \"webm\", \"weba\", \"ogg\", \"ogv\", \"pdf\", \"ttf\", \"otf\", \"woff\", \"woff2\", \"mp3\", \"mp4\",\n            \"mpeg4\", \"wasm\", \"aac\", \"ics\", \"bin\", \"mpg\", \"mpeg\", \"tar\", \"gz\", \"tif\", \"tiff\", \"mov\",\n            \"zip\", \"cbz\", \"cbr\", \"rar\", \"epub\", \"md\", \"markdown\"\n        ];\n\n        let choice = u.choose(&known[..])?;\n        let known = MediaType::from_extension(choice).unwrap();\n\n        let top = u.ratio(1, 100)?.then_some(\"*\".into()).unwrap_or(known.top().to_string());\n        let sub = u.ratio(1, 100)?.then_some(\"*\".into()).unwrap_or(known.sub().to_string());\n        let params = u.ratio(1, 10)?\n            .then_some(vec![])\n            .unwrap_or(known.params().map(|(k, v)| (k.to_string(), v.to_owned())).collect());\n\n        let media_type = MediaType::new(top, sub).with_params(params);\n        Ok(ArbitraryMediaType(media_type))\n    }\n\n    fn size_hint(_: usize) -> (usize, Option<usize>) {\n        (3, None)\n    }\n}\n\nimpl<'a> Arbitrary<'a> for ArbitraryRouteUri<'a> {\n    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {\n        let (base, path) = (u.arbitrary::<&str>()?, u.arbitrary::<&str>()?);\n        if base.is_empty() || path.is_empty() {\n            return Err(Error::NotEnoughData);\n        }\n\n        RouteUri::try_new(base, path)\n            .map(ArbitraryRouteUri)\n            .map_err(|_| Error::IncorrectFormat)\n    }\n\n    fn size_hint(_: usize) -> (usize, Option<usize>) {\n        (2, None)\n    }\n}\n\ntype TestData<'a> = (\n    ArbitraryRouteData<'a>,\n    ArbitraryRouteData<'a>,\n    ArbitraryRequestData<'a>\n);\n\nfn fuzz((route_a, route_b, req): TestData<'_>) {\n    let rocket = rocket::custom(rocket::Config {\n        workers: 2,\n        log_level: None,\n        cli_colors: rocket::config::CliColors::Never,\n        ..rocket::Config::debug_default()\n    });\n\n    let client = Client::untracked(rocket).expect(\"debug rocket is okay\");\n    let (route_a, route_b) = (route_a.into_route(), route_b.into_route());\n    let local_request = req.into_local_request(&client);\n    let request = local_request.inner();\n\n    if route_a.matches(request) && route_b.matches(request) {\n        assert!(route_a.collides_with(&route_b));\n        assert!(route_b.collides_with(&route_a));\n    }\n}\n\n#[cfg(all(not(honggfuzz), not(afl)))]\nlibfuzzer_sys::fuzz_target!(|data: TestData| fuzz(data));\n\n#[cfg(honggfuzz)]\nfn main() {\n    loop {\n        honggfuzz::fuzz!(|data: TestData| fuzz(data));\n    }\n}\n\n#[cfg(afl)]\nfn main() {\n    afl::fuzz!(|data: TestData| fuzz(data));\n}\n"
  },
  {
    "path": "core/lib/fuzz/targets/uri-normalization.rs",
    "content": "#![no_main]\n\nuse rocket::http::uri::*;\nuse libfuzzer_sys::fuzz_target;\n\nfn fuzz(data: &str) {\n    if let Ok(uri) = Uri::parse_any(data) {\n        match uri {\n            Uri::Origin(uri) if uri.is_normalized() => {\n                assert_eq!(uri.clone(), uri.into_normalized());\n            }\n            Uri::Absolute(uri) if uri.is_normalized() => {\n                assert_eq!(uri.clone(), uri.into_normalized());\n            }\n            Uri::Reference(uri) if uri.is_normalized() => {\n                assert_eq!(uri.clone(), uri.into_normalized());\n            }\n            _ => { /* not normalizable */ },\n        }\n    }\n}\n\nfuzz_target!(|data: &str| fuzz(data));\n"
  },
  {
    "path": "core/lib/fuzz/targets/uri-parsing.rs",
    "content": "#![no_main]\n\nuse rocket::http::uri::*;\nuse libfuzzer_sys::fuzz_target;\n\nfn fuzz(data: &str) {\n    // Fuzz the top-level parser.\n    if let Ok(uri) = Uri::parse_any(data) {\n        // Ensure Uri::parse::<T>() => T::parse().\n        match uri {\n            Uri::Asterisk(_) => { Asterisk::parse(data).expect(\"Asterisk\"); },\n            Uri::Origin(_) => { Origin::parse(data).expect(\"Origin\"); },\n            Uri::Authority(_) => { Authority::parse(data).expect(\"Authority\"); },\n            Uri::Absolute(_) => { Absolute::parse(data).expect(\"Absolute\"); },\n            Uri::Reference(_) => { Reference::parse(data).expect(\"Reference\"); },\n        }\n    }\n}\n\nfuzz_target!(|data: &[u8]| {\n    let _ = std::str::from_utf8(data).map(fuzz);\n});\n"
  },
  {
    "path": "core/lib/fuzz/targets/uri-roundtrip.rs",
    "content": "#![no_main]\n\nuse rocket::http::uri::*;\nuse libfuzzer_sys::fuzz_target;\n\nfn fuzz(data: &str) {\n    if let Ok(uri) = Uri::parse_any(data) {\n        let string = uri.to_string();\n        let _ = match uri {\n            Uri::Asterisk(_) => Asterisk::parse_owned(string).expect(\"Asterisk\").to_string(),\n            Uri::Origin(_) => Origin::parse_owned(string).expect(\"Origin\").to_string(),\n            Uri::Authority(_) => Authority::parse_owned(string).expect(\"Authority\").to_string(),\n            Uri::Absolute(_) => Absolute::parse_owned(string).expect(\"Absolute\").to_string(),\n            Uri::Reference(_) => Reference::parse_owned(string).expect(\"Reference\").to_string(),\n        };\n    }\n}\n\nfuzz_target!(|data: &[u8]| {\n    let _ = std::str::from_utf8(data).map(fuzz);\n});\n"
  },
  {
    "path": "core/lib/src/catcher/catcher.rs",
    "content": "use std::fmt;\nuse std::io::Cursor;\n\nuse crate::http::uri::Path;\nuse crate::http::ext::IntoOwned;\nuse crate::response::Response;\nuse crate::request::Request;\nuse crate::http::{Status, ContentType, uri};\nuse crate::catcher::{Handler, BoxFuture};\n\n/// An error catching route.\n///\n/// Catchers are routes that run when errors are produced by the application.\n/// They consist of a [`Handler`] and an optional status code to match against\n/// arising errors. Errors arise from the the following sources:\n///\n///   * A failing guard.\n///   * A failing responder.\n///   * A forwarding guard.\n///   * Routing failure.\n///\n/// Each error or forward is paired with a status code. Guards and responders\n/// indicate the status code themselves via their `Err` and `Outcome` return\n/// value. A complete routing failure is always a `404`. Rocket invokes the\n/// error handler for the catcher with an error's status code, or in the case of\n/// every route resulting in a forward, the last forwarded status code.\n///\n/// ### Error Handler Restrictions\n///\n/// Because error handlers are a last resort, they should not fail to produce a\n/// response. If an error handler _does_ fail, Rocket invokes its default `500`\n/// error catcher. Error handlers cannot forward.\n///\n/// # Routing\n///\n/// If a route fails by returning an error [`Outcome`], Rocket routes the\n/// erroring request to the highest precedence catcher among all the catchers\n/// that [match](Catcher::matches()). See [`Catcher::matches()`] for details on\n/// matching. Precedence is determined by the catcher's _base_, which is\n/// provided as the first argument to [`Rocket::register()`]. Catchers with more\n/// non-empty segments have a higher precedence.\n///\n/// Rocket provides [built-in defaults](#built-in-default), but _default_\n/// catchers can also be registered. A _default_ catcher is a catcher with no\n/// explicit status code: `None`.\n///\n/// [`Outcome`]: crate::request::Outcome\n/// [`Rocket::register()`]: crate::Rocket::register()\n///\n/// ## Collisions\n///\n/// Two catchers are said to _collide_ if there exists an error that matches\n/// both catchers. Colliding catchers present a routing ambiguity and are thus\n/// disallowed by Rocket. Because catchers can be constructed dynamically,\n/// collision checking is done at [`ignite`](crate::Rocket::ignite()) time,\n/// after it becomes statically impossible to register any more catchers on an\n/// instance of `Rocket`.\n///\n/// ## Built-In Default\n///\n/// Rocket's provides a built-in default catcher that can handle all errors. It\n/// produces HTML or JSON, depending on the value of the `Accept` header. As\n/// such, catchers only need to be registered if an error needs to be handled in\n/// a custom fashion. The built-in default never conflicts with any\n/// user-registered catchers.\n///\n/// # Code Generation\n///\n/// Catchers should rarely be constructed or used directly. Instead, they are\n/// typically generated via the [`catch`] attribute, as follows:\n///\n/// ```rust,no_run\n/// #[macro_use] extern crate rocket;\n///\n/// use rocket::Request;\n/// use rocket::http::Status;\n///\n/// #[catch(500)]\n/// fn internal_error() -> &'static str {\n///     \"Whoops! Looks like we messed up.\"\n/// }\n///\n/// #[catch(404)]\n/// fn not_found(req: &Request) -> String {\n///     format!(\"I couldn't find '{}'. Try something else?\", req.uri())\n/// }\n///\n/// #[catch(default)]\n/// fn default(status: Status, req: &Request) -> String {\n///     format!(\"{} ({})\", status, req.uri())\n/// }\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().register(\"/\", catchers![internal_error, not_found, default])\n/// }\n/// ```\n///\n/// A function decorated with `#[catch]` may take zero, one, or two arguments.\n/// It's type signature must be one of the following, where `R:`[`Responder`]:\n///\n///   * `fn() -> R`\n///   * `fn(`[`&Request`]`) -> R`\n///   * `fn(`[`Status`]`, `[`&Request`]`) -> R`\n///\n/// See the [`catch`] documentation for full details.\n///\n/// [`catch`]: crate::catch\n/// [`Responder`]: crate::response::Responder\n/// [`&Request`]: crate::request::Request\n/// [`Status`]: crate::http::Status\n#[derive(Clone)]\npub struct Catcher {\n    /// The name of this catcher, if one was given.\n    pub name: Option<Cow<'static, str>>,\n\n    /// The HTTP status to match against if this route is not `default`.\n    pub code: Option<u16>,\n\n    /// The catcher's associated error handler.\n    pub handler: Box<dyn Handler>,\n\n    /// The mount point.\n    pub(crate) base: uri::Origin<'static>,\n\n    /// The catcher's calculated rank.\n    ///\n    /// This is -(number of nonempty segments in base).\n    pub(crate) rank: isize,\n\n    /// The catcher's file, line, and column location.\n    pub(crate) location: Option<(&'static str, u32, u32)>,\n}\n\n// The rank is computed as -(number of nonempty segments in base) => catchers\n// with more nonempty segments have lower ranks => higher precedence.\nfn rank(base: Path<'_>) -> isize {\n    -(base.segments().filter(|s| !s.is_empty()).count() as isize)\n}\n\nimpl Catcher {\n    /// Creates a catcher for the given `status`, or a default catcher if\n    /// `status` is `None`, using the given error handler. This should only be\n    /// used when routing manually.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use rocket::request::Request;\n    /// use rocket::catcher::{Catcher, BoxFuture};\n    /// use rocket::response::Responder;\n    /// use rocket::http::Status;\n    ///\n    /// fn handle_404<'r>(status: Status, req: &'r Request<'_>) -> BoxFuture<'r> {\n    ///    let res = (status, format!(\"404: {}\", req.uri()));\n    ///    Box::pin(async move { res.respond_to(req) })\n    /// }\n    ///\n    /// fn handle_500<'r>(_: Status, req: &'r Request<'_>) -> BoxFuture<'r> {\n    ///     Box::pin(async move{ \"Whoops, we messed up!\".respond_to(req) })\n    /// }\n    ///\n    /// fn handle_default<'r>(status: Status, req: &'r Request<'_>) -> BoxFuture<'r> {\n    ///    let res = (status, format!(\"{}: {}\", status, req.uri()));\n    ///    Box::pin(async move { res.respond_to(req) })\n    /// }\n    ///\n    /// let not_found_catcher = Catcher::new(404, handle_404);\n    /// let internal_server_error_catcher = Catcher::new(500, handle_500);\n    /// let default_error_catcher = Catcher::new(None, handle_default);\n    /// ```\n    ///\n    /// # Panics\n    ///\n    /// Panics if `code` is not in the HTTP status code error range `[400,\n    /// 600)`.\n    #[inline(always)]\n    pub fn new<S, H>(code: S, handler: H) -> Catcher\n        where S: Into<Option<u16>>, H: Handler\n    {\n        let code = code.into();\n        if let Some(code) = code {\n            assert!(code >= 400 && code < 600);\n        }\n\n        Catcher {\n            name: None,\n            base: uri::Origin::root().clone(),\n            handler: Box::new(handler),\n            rank: rank(uri::Origin::root().path()),\n            code,\n            location: None,\n        }\n    }\n\n    /// Returns the mount point (base) of the catcher, which defaults to `/`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::request::Request;\n    /// use rocket::catcher::{Catcher, BoxFuture};\n    /// use rocket::response::Responder;\n    /// use rocket::http::Status;\n    ///\n    /// fn handle_404<'r>(status: Status, req: &'r Request<'_>) -> BoxFuture<'r> {\n    ///    let res = (status, format!(\"404: {}\", req.uri()));\n    ///    Box::pin(async move { res.respond_to(req) })\n    /// }\n    ///\n    /// let catcher = Catcher::new(404, handle_404);\n    /// assert_eq!(catcher.base(), \"/\");\n    ///\n    /// let catcher = catcher.map_base(|base| format!(\"/foo/bar/{}\", base)).unwrap();\n    /// assert_eq!(catcher.base(), \"/foo/bar\");\n    /// ```\n    pub fn base(&self) -> Path<'_> {\n        self.base.path()\n    }\n\n    /// Prefix `base` to the current `base` in `self.`\n    ///\n    /// If the the current base is `/`, then the base is replaced by `base`.\n    /// Otherwise, `base` is prefixed to the existing `base`.\n    ///\n    /// ```rust\n    /// use rocket::request::Request;\n    /// use rocket::catcher::{Catcher, BoxFuture};\n    /// use rocket::response::Responder;\n    /// use rocket::http::Status;\n    /// # use rocket::uri;\n    ///\n    /// fn handle_404<'r>(status: Status, req: &'r Request<'_>) -> BoxFuture<'r> {\n    ///    let res = (status, format!(\"404: {}\", req.uri()));\n    ///    Box::pin(async move { res.respond_to(req) })\n    /// }\n    ///\n    /// let catcher = Catcher::new(404, handle_404);\n    /// assert_eq!(catcher.base(), \"/\");\n    ///\n    /// // Since the base is `/`, rebasing replaces the base.\n    /// let rebased = catcher.rebase(uri!(\"/boo\"));\n    /// assert_eq!(rebased.base(), \"/boo\");\n    ///\n    /// // Now every rebase prefixes.\n    /// let rebased = rebased.rebase(uri!(\"/base\"));\n    /// assert_eq!(rebased.base(), \"/base/boo\");\n    ///\n    /// // Note that trailing slashes have no effect and are thus removed:\n    /// let catcher = Catcher::new(404, handle_404);\n    /// let rebased = catcher.rebase(uri!(\"/boo/\"));\n    /// assert_eq!(rebased.base(), \"/boo\");\n    /// ```\n    pub fn rebase(mut self, mut base: uri::Origin<'_>) -> Self {\n        self.base = if self.base.path() == \"/\" {\n            base.clear_query();\n            base.into_normalized_nontrailing().into_owned()\n        } else {\n            uri::Origin::parse_owned(format!(\"{}{}\", base.path(), self.base))\n                .expect(\"catcher rebase: {new}{old} is valid origin URI\")\n                .into_normalized_nontrailing()\n        };\n\n        self.rank = rank(self.base());\n        self\n    }\n\n    /// Maps the `base` of this catcher using `mapper`, returning a new\n    /// `Catcher` with the returned base.\n    ///\n    /// **Note:** Prefer to use [`Catcher::rebase()`] whenever possible!\n    ///\n    /// `mapper` is called with the current base. The returned `String` is used\n    /// as the new base if it is a valid URI. If the returned base URI contains\n    /// a query, it is ignored. Returns an error if the base produced by\n    /// `mapper` is not a valid origin URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::request::Request;\n    /// use rocket::catcher::{Catcher, BoxFuture};\n    /// use rocket::response::Responder;\n    /// use rocket::http::Status;\n    ///\n    /// fn handle_404<'r>(status: Status, req: &'r Request<'_>) -> BoxFuture<'r> {\n    ///    let res = (status, format!(\"404: {}\", req.uri()));\n    ///    Box::pin(async move { res.respond_to(req) })\n    /// }\n    ///\n    /// let catcher = Catcher::new(404, handle_404);\n    /// assert_eq!(catcher.base(), \"/\");\n    ///\n    /// let catcher = catcher.map_base(|_| format!(\"/bar\")).unwrap();\n    /// assert_eq!(catcher.base(), \"/bar\");\n    ///\n    /// let catcher = catcher.map_base(|base| format!(\"/foo{}\", base)).unwrap();\n    /// assert_eq!(catcher.base(), \"/foo/bar\");\n    ///\n    /// let catcher = catcher.map_base(|base| format!(\"/foo ? {}\", base));\n    /// assert!(catcher.is_err());\n    /// ```\n    pub fn map_base<'a, F>(mut self, mapper: F) -> Result<Self, uri::Error<'static>>\n        where F: FnOnce(uri::Origin<'a>) -> String\n    {\n        let new_base = uri::Origin::parse_owned(mapper(self.base))?;\n        self.base = new_base.into_normalized_nontrailing();\n        self.base.clear_query();\n        self.rank = rank(self.base());\n        Ok(self)\n    }\n}\n\nimpl Default for Catcher {\n    fn default() -> Self {\n        fn handler<'r>(s: Status, req: &'r Request<'_>) -> BoxFuture<'r> {\n            Box::pin(async move { Ok(default_handler(s, req)) })\n        }\n\n        let mut catcher = Catcher::new(None, handler);\n        catcher.name = Some(\"<Rocket Catcher>\".into());\n        catcher\n    }\n}\n\n/// Information generated by the `catch` attribute during codegen.\n#[doc(hidden)]\npub struct StaticInfo {\n    /// The catcher's name, i.e, the name of the function.\n    pub name: &'static str,\n    /// The catcher's status code.\n    pub code: Option<u16>,\n    /// The catcher's handler, i.e, the annotated function.\n    pub handler: for<'r> fn(Status, &'r Request<'_>) -> BoxFuture<'r>,\n    /// The file, line, and column where the catcher was defined.\n    pub location: (&'static str, u32, u32),\n}\n\n#[doc(hidden)]\nimpl From<StaticInfo> for Catcher {\n    #[inline]\n    fn from(info: StaticInfo) -> Catcher {\n        let mut catcher = Catcher::new(info.code, info.handler);\n        catcher.name = Some(info.name.into());\n        catcher.location = Some(info.location);\n        catcher\n    }\n}\n\nimpl fmt::Debug for Catcher {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Catcher\")\n            .field(\"name\", &self.name)\n            .field(\"base\", &self.base)\n            .field(\"code\", &self.code)\n            .field(\"rank\", &self.rank)\n            .finish()\n    }\n}\n\nmacro_rules! html_error_template {\n    ($code:expr, $reason:expr, $description:expr) => (\n        concat!(\nr#\"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"color-scheme\" content=\"light dark\">\n    <title>\"#, $code, \" \", $reason, r#\"</title>\n</head>\n<body align=\"center\">\n    <div role=\"main\" align=\"center\">\n        <h1>\"#, $code, \": \", $reason, r#\"</h1>\n        <p>\"#, $description, r#\"</p>\n        <hr />\n    </div>\n    <div role=\"contentinfo\" align=\"center\">\n        <small>Rocket</small>\n    </div>\n</body>\n</html>\"#\n        )\n    )\n}\n\nmacro_rules! json_error_template {\n    ($code:expr, $reason:expr, $description:expr) => (\n        concat!(\nr#\"{\n  \"error\": {\n    \"code\": \"#, $code, r#\",\n    \"reason\": \"\"#, $reason, r#\"\",\n    \"description\": \"\"#, $description, r#\"\"\n  }\n}\"#\n        )\n    )\n}\n\n// This is unfortunate, but the `{`, `}` above make it unusable for `format!`.\nmacro_rules! json_error_fmt_template {\n    ($code:expr, $reason:expr, $description:expr) => (\n        concat!(\nr#\"{{\n  \"error\": {{\n    \"code\": \"#, $code, r#\",\n    \"reason\": \"\"#, $reason, r#\"\",\n    \"description\": \"\"#, $description, r#\"\"\n  }}\n}}\"#\n        )\n    )\n}\n\nmacro_rules! default_handler_fn {\n    ($($code:expr, $reason:expr, $description:expr),+) => (\n        use std::borrow::Cow;\n\n        pub(crate) fn default_handler<'r>(\n            status: Status,\n            req: &'r Request<'_>\n        ) -> Response<'r> {\n            let preferred = req.accept().map(|a| a.preferred());\n            let (mime, text) = if preferred.map_or(false, |a| a.is_json()) {\n                let json: Cow<'_, str> = match status.code {\n                    $($code => json_error_template!($code, $reason, $description).into(),)*\n                    code => format!(json_error_fmt_template!(\"{}\", \"Unknown Error\",\n                            \"An unknown error has occurred.\"), code).into()\n                };\n\n                (ContentType::JSON, json)\n            } else {\n                let html: Cow<'_, str> = match status.code {\n                    $($code => html_error_template!($code, $reason, $description).into(),)*\n                    code => format!(html_error_template!(\"{}\", \"Unknown Error\",\n                            \"An unknown error has occurred.\"), code, code).into(),\n                };\n\n                (ContentType::HTML, html)\n            };\n\n            let mut r = Response::build().status(status).header(mime).finalize();\n            match text {\n                Cow::Owned(v) => r.set_sized_body(v.len(), Cursor::new(v)),\n                Cow::Borrowed(v) => r.set_sized_body(v.len(), Cursor::new(v)),\n            };\n\n            r\n        }\n    )\n}\n\ndefault_handler_fn! {\n    400, \"Bad Request\", \"The request could not be understood by the server due \\\n        to malformed syntax.\",\n    401, \"Unauthorized\", \"The request requires user authentication.\",\n    402, \"Payment Required\", \"The request could not be processed due to lack of payment.\",\n    403, \"Forbidden\", \"The server refused to authorize the request.\",\n    404, \"Not Found\", \"The requested resource could not be found.\",\n    405, \"Method Not Allowed\", \"The request method is not supported for the requested resource.\",\n    406, \"Not Acceptable\", \"The requested resource is capable of generating only content not \\\n        acceptable according to the Accept headers sent in the request.\",\n    407, \"Proxy Authentication Required\", \"Authentication with the proxy is required.\",\n    408, \"Request Timeout\", \"The server timed out waiting for the request.\",\n    409, \"Conflict\", \"The request could not be processed because of a conflict in the request.\",\n    410, \"Gone\", \"The resource requested is no longer available and will not be available again.\",\n    411, \"Length Required\", \"The request did not specify the length of its content, which is \\\n        required by the requested resource.\",\n    412, \"Precondition Failed\", \"The server does not meet one of the \\\n        preconditions specified in the request.\",\n    413, \"Payload Too Large\", \"The request is larger than the server is \\\n        willing or able to process.\",\n    414, \"URI Too Long\", \"The URI provided was too long for the server to process.\",\n    415, \"Unsupported Media Type\", \"The request entity has a media type which \\\n        the server or resource does not support.\",\n    416, \"Range Not Satisfiable\", \"The portion of the requested file cannot be \\\n        supplied by the server.\",\n    417, \"Expectation Failed\", \"The server cannot meet the requirements of the \\\n        Expect request-header field.\",\n    418, \"I'm a teapot\", \"I was requested to brew coffee, and I am a teapot.\",\n    421, \"Misdirected Request\", \"The server cannot produce a response for this request.\",\n    422, \"Unprocessable Entity\", \"The request was well-formed but was unable to \\\n        be followed due to semantic errors.\",\n    426, \"Upgrade Required\", \"Switching to the protocol in the Upgrade header field is required.\",\n    428, \"Precondition Required\", \"The server requires the request to be conditional.\",\n    429, \"Too Many Requests\", \"Too many requests have been received recently.\",\n    431, \"Request Header Fields Too Large\", \"The server is unwilling to process \\\n        the request because either an individual header field, or all the header \\\n        fields collectively, are too large.\",\n    451, \"Unavailable For Legal Reasons\", \"The requested resource is unavailable \\\n        due to a legal demand to deny access to this resource.\",\n    500, \"Internal Server Error\", \"The server encountered an internal error while \\\n        processing this request.\",\n    501, \"Not Implemented\", \"The server either does not recognize the request \\\n        method, or it lacks the ability to fulfill the request.\",\n    503, \"Service Unavailable\", \"The server is currently unavailable.\",\n    504, \"Gateway Timeout\", \"The server did not receive a timely response from an upstream server.\",\n    510, \"Not Extended\", \"Further extensions to the request are required for \\\n        the server to fulfill it.\"\n}\n"
  },
  {
    "path": "core/lib/src/catcher/handler.rs",
    "content": "use crate::{Request, Response};\nuse crate::http::Status;\n\n/// Type alias for the return type of a [`Catcher`](crate::Catcher)'s\n/// [`Handler::handle()`].\npub type Result<'r> = std::result::Result<Response<'r>, crate::http::Status>;\n\n/// Type alias for the return type of a _raw_ [`Catcher`](crate::Catcher)'s\n/// [`Handler`].\npub type BoxFuture<'r, T = Result<'r>> = futures::future::BoxFuture<'r, T>;\n\n/// Trait implemented by [`Catcher`](crate::Catcher) error handlers.\n///\n/// This trait is exactly like a [`Route`](crate::Route)'s\n/// [`Handler`](crate::route::Handler) except it handles errors instead of\n/// requests. Thus, the documentation for\n/// [`route::Handler`](crate::route::Handler) applies to this trait as well. We\n/// defer to it for full details.\n///\n/// ## Async Trait\n///\n/// This is an _async_ trait. Implementations must be decorated\n/// [`#[rocket::async_trait]`](crate::async_trait).\n///\n/// # Example\n///\n/// Say you'd like to write a handler that changes its functionality based on a\n/// `Kind` enum value that the user provides. Such a handler might be written\n/// and used as follows:\n///\n/// ```rust,no_run\n/// use rocket::{Request, Catcher, catcher};\n/// use rocket::response::{Response, Responder};\n/// use rocket::http::Status;\n///\n/// #[derive(Copy, Clone)]\n/// enum Kind {\n///     Simple,\n///     Intermediate,\n///     Complex,\n/// }\n///\n/// #[derive(Clone)]\n/// struct CustomHandler(Kind);\n///\n/// #[rocket::async_trait]\n/// impl catcher::Handler for CustomHandler {\n///     async fn handle<'r>(&self, status: Status, req: &'r Request<'_>) -> catcher::Result<'r> {\n///         let inner = match self.0 {\n///             Kind::Simple => \"simple\".respond_to(req)?,\n///             Kind::Intermediate => \"intermediate\".respond_to(req)?,\n///             Kind::Complex => \"complex\".respond_to(req)?,\n///         };\n///\n///         Response::build_from(inner).status(status).ok()\n///     }\n/// }\n///\n/// impl CustomHandler {\n///     /// Returns a `default` catcher that uses `CustomHandler`.\n///     fn default(kind: Kind) -> Vec<Catcher> {\n///         vec![Catcher::new(None, CustomHandler(kind))]\n///     }\n///\n///     /// Returns a catcher for code `status` that uses `CustomHandler`.\n///     fn catch(status: Status, kind: Kind) -> Vec<Catcher> {\n///         vec![Catcher::new(status.code, CustomHandler(kind))]\n///     }\n/// }\n///\n/// #[rocket::launch]\n/// fn rocket() -> _ {\n///     rocket::build()\n///         // to handle only `404`\n///         .register(\"/\", CustomHandler::catch(Status::NotFound, Kind::Simple))\n///         // or to register as the default\n///         .register(\"/\", CustomHandler::default(Kind::Simple))\n/// }\n/// ```\n///\n/// Note the following:\n///\n///   1. `CustomHandler` implements `Clone`. This is required so that\n///      `CustomHandler` implements `Cloneable` automatically. The `Cloneable`\n///      trait serves no other purpose but to ensure that every `Handler`\n///      can be cloned, allowing `Catcher`s to be cloned.\n///   2. `CustomHandler`'s methods return `Vec<Route>`, allowing for use\n///      directly as the parameter to `rocket.register(\"/\", )`.\n///   3. Unlike static-function-based handlers, this custom handler can make use\n///      of internal state.\n#[crate::async_trait]\npub trait Handler: Cloneable + Send + Sync + 'static {\n    /// Called by Rocket when an error with `status` for a given `Request`\n    /// should be handled by this handler.\n    ///\n    /// Error handlers _should not_ fail and thus _should_ always return `Ok`.\n    /// Nevertheless, failure is allowed, both for convenience and necessity. If\n    /// an error handler fails, Rocket's default `500` catcher is invoked. If it\n    /// succeeds, the returned `Response` is used to respond to the client.\n    async fn handle<'r>(&self, status: Status, req: &'r Request<'_>) -> Result<'r>;\n}\n\n// We write this manually to avoid double-boxing.\nimpl<F: Clone + Sync + Send + 'static> Handler for F\n    where for<'x> F: Fn(Status, &'x Request<'_>) -> BoxFuture<'x>,\n{\n    fn handle<'r, 'life0, 'life1, 'async_trait>(\n        &'life0 self,\n        status: Status,\n        req: &'r Request<'life1>,\n    ) -> BoxFuture<'r>\n        where 'r: 'async_trait,\n              'life0: 'async_trait,\n              'life1: 'async_trait,\n              Self: 'async_trait,\n    {\n        self(status, req)\n    }\n}\n\n// Used in tests! Do not use, please.\n#[doc(hidden)]\npub fn dummy_handler<'r>(_: Status, _: &'r Request<'_>) -> BoxFuture<'r> {\n   Box::pin(async move { Ok(Response::new()) })\n}\n\nmod private {\n    pub trait Sealed {}\n    impl<T: super::Handler + Clone> Sealed for T {}\n}\n\n/// Helper trait to make a [`Catcher`](crate::Catcher)'s `Box<dyn Handler>`\n/// `Clone`.\n///\n/// This trait cannot be implemented directly. Instead, implement `Clone` and\n/// [`Handler`]; all types that implement `Clone` and `Handler` automatically\n/// implement `Cloneable`.\npub trait Cloneable: private::Sealed {\n    #[doc(hidden)]\n    fn clone_handler(&self) -> Box<dyn Handler>;\n}\n\nimpl<T: Handler + Clone> Cloneable for T {\n    fn clone_handler(&self) -> Box<dyn Handler> {\n        Box::new(self.clone())\n    }\n}\n\nimpl Clone for Box<dyn Handler> {\n    fn clone(&self) -> Box<dyn Handler> {\n        self.clone_handler()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/catcher/mod.rs",
    "content": "//! Types and traits for error catchers and their handlers and return types.\n\nmod catcher;\nmod handler;\n\npub use catcher::*;\npub use handler::*;\n"
  },
  {
    "path": "core/lib/src/config/cli_colors.rs",
    "content": "use std::fmt;\n\nuse serde::{de, Deserialize, Serialize};\n\n/// Enable or disable coloring when logging.\n///\n/// Valid configuration values are:\n///\n///   * `\"always\"` - [`CliColors::Always`]\n///   * `\"auto\"`, `1`, or `true` - [`CliColors::Auto`] _(default)_\n///   * `\"never\"`, `0`, or `false` - [`CliColors::Never`]\n#[derive(Debug, Copy, Clone, Default, Serialize, PartialEq, Eq, Hash)]\npub enum CliColors {\n    /// Always enable colors, irrespective of `stdout` and `stderr`.\n    ///\n    /// Case-insensitive string values of `\"always\"` parse as this value.\n    Always,\n\n    /// Enable colors _only if_ `stdout` and `stderr` support coloring.\n    ///\n    /// Case-insensitive string values of `\"auto\"`, the boolean `true`, and the\n    /// integer `1` all parse as this value.\n    ///\n    /// Only Unix-like systems (Linux, macOS, BSD, etc.), this is equivalent to\n    /// checking if `stdout` and `stderr` are both TTYs. On Windows, the console\n    /// is queried for ANSI escape sequence based coloring support and enabled\n    /// if support is successfully enabled.\n    #[default]\n    Auto,\n\n    /// Never enable colors, even if `stdout` and `stderr` support them.\n    ///\n    /// Case-insensitive string values of `\"never\"`, the boolean `false`, and\n    /// the integer `0` all parse as this value.\n    Never,\n}\n\nimpl fmt::Display for CliColors {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            CliColors::Always => write!(f, \"always\"),\n            CliColors::Auto => write!(f, \"auto\"),\n            CliColors::Never => write!(f, \"never\")\n        }\n    }\n}\n\nimpl<'de> Deserialize<'de> for CliColors {\n    fn deserialize<D: de::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = CliColors;\n\n            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n                f.write_str(\"0, 1, false, true, always, auto, or never\")\n            }\n\n            fn visit_str<E: de::Error>(self, val: &str) -> Result<CliColors, E> {\n                match val.to_lowercase().as_str() {\n                    \"true\" => Ok(CliColors::Auto),\n                    \"false\" => Ok(CliColors::Never),\n                    \"1\" => Ok(CliColors::Auto),\n                    \"0\" => Ok(CliColors::Never),\n                    \"always\" => Ok(CliColors::Always),\n                    \"auto\" => Ok(CliColors::Auto),\n                    \"never\" => Ok(CliColors::Never),\n                    _ => Err(E::invalid_value(de::Unexpected::Str(val), &self)),\n                }\n            }\n\n            fn visit_bool<E: de::Error>(self, val: bool) -> Result<CliColors, E> {\n                match val {\n                    true => Ok(CliColors::Auto),\n                    false => Ok(CliColors::Never),\n                }\n            }\n\n            fn visit_i64<E: de::Error>(self, val: i64) -> Result<CliColors, E> {\n                match val {\n                    1 => Ok(CliColors::Auto),\n                    0 => Ok(CliColors::Never),\n                    _ => Err(E::invalid_value(de::Unexpected::Signed(val), &self)),\n                }\n            }\n\n            fn visit_u64<E: de::Error>(self, val: u64) -> Result<CliColors, E> {\n                match val {\n                    1 => Ok(CliColors::Auto),\n                    0 => Ok(CliColors::Never),\n                    _ => Err(E::invalid_value(de::Unexpected::Unsigned(val), &self)),\n                }\n            }\n        }\n\n        de.deserialize_any(Visitor)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/config/config.rs",
    "content": "use figment::{Figment, Profile, Provider, Metadata, error::Result};\nuse figment::providers::{Serialized, Env, Toml, Format};\nuse figment::value::{Map, Dict, magic::RelativePathBuf};\nuse serde::{Deserialize, Serialize};\n\n#[cfg(feature = \"secrets\")]\nuse crate::config::SecretKey;\nuse crate::config::{ShutdownConfig, Level, TraceFormat, Ident, CliColors};\nuse crate::request::{self, Request, FromRequest};\nuse crate::http::uncased::Uncased;\nuse crate::data::Limits;\n\n/// Rocket server configuration.\n///\n/// See the [module level docs](crate::config) as well as the [configuration\n/// guide] for further details.\n///\n/// [configuration guide]: https://rocket.rs/master/guide/configuration/\n///\n/// # Defaults\n///\n/// All configuration values have a default, documented in the [fields](#fields)\n/// section below. [`Config::debug_default()`] returns the default values for\n/// the debug profile while [`Config::release_default()`] the default values for\n/// the release profile. The [`Config::default()`] method automatically selects\n/// the appropriate of the two based on the selected profile. With the exception\n/// of `log_level` and `log_format`, which are `info` / `pretty` in `debug` and\n/// `error` / `compact` in `release`, and `secret_key`, which is regenerated\n/// from a random value if not set in \"debug\" mode only, all default values are\n/// identical in all profiles.\n///\n/// # Provider Details\n///\n/// `Config` is a Figment [`Provider`] with the following characteristics:\n///\n///   * **Profile**\n///\n///     The profile is set to the value of the `profile` field.\n///\n///   * **Metadata**\n///\n///     This provider is named `Rocket Config`. It does not specify a\n///     [`Source`](figment::Source) and uses default interpolation.\n///\n///   * **Data**\n///\n///     The data emitted by this provider are the keys and values corresponding\n///     to the fields and values of the structure. The dictionary is emitted to\n///     the \"default\" meta-profile.\n///\n/// Note that these behaviors differ from those of [`Config::figment()`].\n#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]\npub struct Config {\n    /// The selected profile. **(default: _debug_ `debug` / _release_ `release`)**\n    ///\n    /// _**Note:** This field is never serialized nor deserialized. When a\n    /// `Config` is merged into a `Figment` as a `Provider`, this profile is\n    /// selected on the `Figment`. When a `Config` is extracted, this field is\n    /// set to the extracting Figment's selected `Profile`._\n    #[serde(skip)]\n    pub profile: Profile,\n    /// Number of threads to use for executing futures. **(default: `num_cores`)**\n    ///\n    /// _**Note:** Rocket only reads this value from sources in the [default\n    /// provider](Config::figment())._\n    pub workers: usize,\n    /// Limit on threads to start for blocking tasks. **(default: `512`)**\n    pub max_blocking: usize,\n    /// How, if at all, to identify the server via the `Server` header.\n    /// **(default: `\"Rocket\"`)**\n    pub ident: Ident,\n    /// The name of a header, whose value is typically set by an intermediary\n    /// server or proxy, which contains the real IP address of the connecting\n    /// client. Used internally and by [`Request::client_ip()`] and\n    /// [`Request::real_ip()`].\n    ///\n    /// To disable using any header for this purpose, set this value to `false`\n    /// or `None`. Deserialization semantics are identical to those of [`Ident`]\n    /// except that the value must syntactically be a valid HTTP header name.\n    ///\n    /// **(default: `\"X-Real-IP\"`)**\n    #[serde(deserialize_with = \"crate::config::http_header::deserialize\")]\n    pub ip_header: Option<Uncased<'static>>,\n    /// The name of a header, whose value is typically set by an intermediary\n    /// server or proxy, which contains the protocol (\"http\" or \"https\") used by\n    /// the connecting client. This is usually [`\"X-Forwarded-Proto\"`], as that\n    /// is the de-facto standard.\n    ///\n    /// The header value is parsed into a [`ProxyProto`], accessible via\n    /// [`Request::proxy_proto()`]. The value influences\n    /// [`Request::context_is_likely_secure()`] and the default value for the\n    /// `Secure` flag in cookies added to [`CookieJar`]s.\n    ///\n    /// To disable using any header for this purpose, set this value to `false`\n    /// or `None`. Deserialization semantics are identical to those of\n    /// [`Config::ip_header`] (the value must be a valid HTTP header name).\n    ///\n    /// **(default: `None`)**\n    ///\n    /// [`CookieJar`]: crate::http::CookieJar\n    /// [`ProxyProto`]: crate::http::ProxyProto\n    /// [`\"X-Forwarded-Proto\"`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto\n    #[serde(deserialize_with = \"crate::config::http_header::deserialize\")]\n    pub proxy_proto_header: Option<Uncased<'static>>,\n    /// Streaming read size limits. **(default: [`Limits::default()`])**\n    pub limits: Limits,\n    /// Directory to store temporary files in. **(default:\n    /// [`std::env::temp_dir()`])**\n    #[serde(serialize_with = \"RelativePathBuf::serialize_relative\")]\n    pub temp_dir: RelativePathBuf,\n    /// Keep-alive timeout in seconds; disabled when `0`. **(default: `5`)**\n    pub keep_alive: u32,\n    /// The secret key for signing and encrypting. **(default: `0`)**\n    ///\n    /// _**Note:** This field _always_ serializes as a 256-bit array of `0`s to\n    /// aid in preventing leakage of the secret key._\n    #[cfg(feature = \"secrets\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\n    #[serde(serialize_with = \"SecretKey::serialize_zero\")]\n    pub secret_key: SecretKey,\n    /// Graceful shutdown configuration. **(default: [`ShutdownConfig::default()`])**\n    pub shutdown: ShutdownConfig,\n    /// Max level to log. **(default: _debug_ `info` / _release_ `error`)**\n    #[serde(with = \"crate::trace::level\")]\n    pub log_level: Option<Level>,\n    /// Format to use when logging. **(default: _debug_ `pretty` / _release_ `compact`)**\n    pub log_format: TraceFormat,\n    /// Whether to use colors and emoji when logging. **(default:\n    /// [`CliColors::Auto`])**\n    pub cli_colors: CliColors,\n    /// PRIVATE: This structure may grow (but never change otherwise) in a\n    /// non-breaking release. As such, constructing this structure should\n    /// _always_ be done using a public constructor or update syntax:\n    ///\n    /// ```rust\n    /// use rocket::Config;\n    ///\n    /// let config = Config {\n    ///     keep_alive: 10,\n    ///     ..Default::default()\n    /// };\n    /// ```\n    #[doc(hidden)]\n    #[serde(skip)]\n    pub __non_exhaustive: (),\n}\n\nimpl Default for Config {\n    /// Returns the default configuration based on the Rust compilation profile.\n    /// This is [`Config::debug_default()`] in `debug` and\n    /// [`Config::release_default()`] in `release`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Config;\n    ///\n    /// let config = Config::default();\n    /// ```\n    fn default() -> Config {\n        #[cfg(debug_assertions)] { Config::debug_default() }\n        #[cfg(not(debug_assertions))] { Config::release_default() }\n    }\n}\n\nimpl Config {\n    /// Returns the default configuration for the `debug` profile, _irrespective\n    /// of the Rust compilation profile_ and `ROCKET_PROFILE`.\n    ///\n    /// This may differ from the configuration used by default,\n    /// [`Config::default()`], which is selected based on the Rust compilation\n    /// profile. See [defaults](#defaults) and [provider\n    /// details](#provider-details) for specifics.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Config;\n    ///\n    /// let config = Config::debug_default();\n    /// ```\n    pub fn debug_default() -> Config {\n        Config {\n            profile: Self::DEBUG_PROFILE,\n            workers: num_cpus::get(),\n            max_blocking: 512,\n            ident: Ident::default(),\n            ip_header: Some(Uncased::from_borrowed(\"X-Real-IP\")),\n            proxy_proto_header: None,\n            limits: Limits::default(),\n            temp_dir: std::env::temp_dir().into(),\n            keep_alive: 5,\n            #[cfg(feature = \"secrets\")]\n            secret_key: SecretKey::zero(),\n            shutdown: ShutdownConfig::default(),\n            log_level: Some(Level::INFO),\n            log_format: TraceFormat::Pretty,\n            cli_colors: CliColors::Auto,\n            __non_exhaustive: (),\n        }\n    }\n\n    /// Returns the default configuration for the `release` profile,\n    /// _irrespective of the Rust compilation profile_ and `ROCKET_PROFILE`.\n    ///\n    /// This may differ from the configuration used by default,\n    /// [`Config::default()`], which is selected based on the Rust compilation\n    /// profile. See [defaults](#defaults) and [provider\n    /// details](#provider-details) for specifics.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Config;\n    ///\n    /// let config = Config::release_default();\n    /// ```\n    pub fn release_default() -> Config {\n        Config {\n            profile: Self::RELEASE_PROFILE,\n            log_level: Some(Level::ERROR),\n            log_format: TraceFormat::Compact,\n            ..Config::debug_default()\n        }\n    }\n\n    /// Returns the default provider figment used by [`rocket::build()`].\n    ///\n    /// The default figment reads from the following sources, in ascending\n    /// priority order:\n    ///\n    ///   1. [`Config::default()`] (see [defaults](#defaults))\n    ///   2. `Rocket.toml` _or_ filename in `ROCKET_CONFIG` environment variable\n    ///   3. `ROCKET_` prefixed environment variables\n    ///\n    /// The profile selected is the value set in the `ROCKET_PROFILE`\n    /// environment variable. If it is not set, it defaults to `debug` when\n    /// compiled in debug mode and `release` when compiled in release mode.\n    ///\n    /// [`rocket::build()`]: crate::build()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Config;\n    /// use serde::Deserialize;\n    ///\n    /// #[derive(Deserialize)]\n    /// struct MyConfig {\n    ///     app_key: String,\n    /// }\n    ///\n    /// let my_config = Config::figment().extract::<MyConfig>();\n    /// ```\n    pub fn figment() -> Figment {\n        Figment::from(Config::default())\n            .merge(Toml::file(Env::var_or(\"ROCKET_CONFIG\", \"Rocket.toml\")).nested())\n            .merge(Env::prefixed(\"ROCKET_\").ignore(&[\"PROFILE\"]).global())\n            .select(Profile::from_env_or(\"ROCKET_PROFILE\", Self::DEFAULT_PROFILE))\n    }\n\n    /// Attempts to extract a `Config` from `provider`, returning the result.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Config;\n    /// use rocket::figment::providers::{Toml, Format, Env};\n    ///\n    /// // Use Rocket's default `Figment`, but allow values from `MyApp.toml`\n    /// // and `MY_APP_` prefixed environment variables to supersede its values.\n    /// let figment = Config::figment()\n    ///     .merge((\"some-thing\", 123))\n    ///     .merge(Env::prefixed(\"CONFIG_\"));\n    ///\n    /// let config = Config::try_from(figment);\n    /// ```\n    pub fn try_from<T: Provider>(provider: T) -> Result<Self> {\n        let figment = Figment::from(provider);\n        let mut config = figment.extract::<Self>()?;\n        config.profile = figment.profile().clone();\n        Ok(config)\n    }\n\n    /// Extract a `Config` from `provider`, panicking if extraction fails.\n    ///\n    /// # Panics\n    ///\n    /// If extraction fails, logs an error message indicating the error and\n    /// panics. For a version that doesn't panic, use [`Config::try_from()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Config;\n    /// use rocket::figment::providers::{Toml, Format, Env};\n    ///\n    /// // Use Rocket's default `Figment`, but allow values from `MyApp.toml`\n    /// // and `MY_APP_` prefixed environment variables to supersede its values.\n    /// let figment = Config::figment()\n    ///     .merge(Toml::file(\"MyApp.toml\").nested())\n    ///     .merge(Env::prefixed(\"MY_APP_\"));\n    ///\n    /// let config = Config::from(figment);\n    /// ```\n    pub fn from<T: Provider>(provider: T) -> Self {\n        use crate::trace::Trace;\n\n        Self::try_from(provider).unwrap_or_else(|e| {\n            e.trace_error();\n            panic!(\"aborting due to configuration error(s)\")\n        })\n    }\n}\n\n/// Associated constants for default profiles.\nimpl Config {\n    /// The default debug profile: `debug`.\n    pub const DEBUG_PROFILE: Profile = Profile::const_new(\"debug\");\n\n    /// The default release profile: `release`.\n    pub const RELEASE_PROFILE: Profile = Profile::const_new(\"release\");\n\n    /// The default profile: \"debug\" on `debug`, \"release\" on `release`.\n    #[cfg(debug_assertions)]\n    pub const DEFAULT_PROFILE: Profile = Self::DEBUG_PROFILE;\n\n    /// The default profile: \"debug\" on `debug`, \"release\" on `release`.\n    #[cfg(not(debug_assertions))]\n    pub const DEFAULT_PROFILE: Profile = Self::RELEASE_PROFILE;\n}\n\n/// Associated constants for stringy versions of configuration parameters.\nimpl Config {\n    /// The stringy parameter name for setting/extracting [`Config::workers`].\n    pub const WORKERS: &'static str = \"workers\";\n\n    /// The stringy parameter name for setting/extracting [`Config::max_blocking`].\n    pub const MAX_BLOCKING: &'static str = \"max_blocking\";\n\n    /// The stringy parameter name for setting/extracting [`Config::keep_alive`].\n    pub const KEEP_ALIVE: &'static str = \"keep_alive\";\n\n    /// The stringy parameter name for setting/extracting [`Config::ident`].\n    pub const IDENT: &'static str = \"ident\";\n\n    /// The stringy parameter name for setting/extracting [`Config::ip_header`].\n    pub const IP_HEADER: &'static str = \"ip_header\";\n\n    /// The stringy parameter name for setting/extracting [`Config::proxy_proto_header`].\n    pub const PROXY_PROTO_HEADER: &'static str = \"proxy_proto_header\";\n\n    /// The stringy parameter name for setting/extracting [`Config::limits`].\n    pub const LIMITS: &'static str = \"limits\";\n\n    /// The stringy parameter name for setting/extracting [`Config::secret_key`].\n    pub const SECRET_KEY: &'static str = \"secret_key\";\n\n    /// The stringy parameter name for setting/extracting [`Config::temp_dir`].\n    pub const TEMP_DIR: &'static str = \"temp_dir\";\n\n    /// The stringy parameter name for setting/extracting [`Config::log_level`].\n    pub const LOG_LEVEL: &'static str = \"log_level\";\n\n    /// The stringy parameter name for setting/extracting [`Config::log_format`].\n    pub const LOG_FORMAT: &'static str = \"log_format\";\n\n    /// The stringy parameter name for setting/extracting [`Config::shutdown`].\n    pub const SHUTDOWN: &'static str = \"shutdown\";\n\n    /// The stringy parameter name for setting/extracting [`Config::cli_colors`].\n    pub const CLI_COLORS: &'static str = \"cli_colors\";\n\n    /// An array of all of the stringy parameter names.\n    pub const PARAMETERS: &'static [&'static str] = &[\n        Self::WORKERS, Self::MAX_BLOCKING, Self::KEEP_ALIVE, Self::IDENT,\n        Self::IP_HEADER, Self::PROXY_PROTO_HEADER, Self::LIMITS,\n        Self::SECRET_KEY, Self::TEMP_DIR, Self::LOG_LEVEL, Self::LOG_FORMAT,\n        Self::SHUTDOWN, Self::CLI_COLORS,\n    ];\n\n    /// The stringy parameter name for setting/extracting [`Config::profile`].\n    ///\n    /// This isn't `pub` because setting it directly does nothing.\n    const PROFILE: &'static str = \"profile\";\n\n    /// An array of deprecated stringy parameter names.\n    pub(crate) const DEPRECATED_KEYS: &'static [(&'static str, Option<&'static str>)] = &[\n        (\"env\", Some(Self::PROFILE)), (\"log\", Some(Self::LOG_LEVEL)),\n        (\"read_timeout\", None), (\"write_timeout\", None),\n    ];\n\n    /// Secret keys that have been used in docs or leaked otherwise.\n    #[cfg(feature = \"secrets\")]\n    pub(crate) const KNOWN_SECRET_KEYS: &'static [&'static str] = &[\n        \"hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk=\"\n    ];\n}\n\nimpl Provider for Config {\n    #[track_caller]\n    fn metadata(&self) -> Metadata {\n        if self == &Config::default() {\n            Metadata::named(\"rocket::Config::default()\")\n        } else {\n            Metadata::named(\"rocket::Config\")\n        }\n    }\n\n    #[track_caller]\n    fn data(&self) -> Result<Map<Profile, Dict>> {\n        #[allow(unused_mut)]\n        let mut map: Map<Profile, Dict> = Serialized::defaults(self).data()?;\n\n        // We need to special-case `secret_key` since its serializer zeroes.\n        #[cfg(feature = \"secrets\")]\n        if !self.secret_key.is_zero() {\n            if let Some(map) = map.get_mut(&Profile::Default) {\n                map.insert(\"secret_key\".into(), self.secret_key.key.master().into());\n            }\n        }\n\n        Ok(map)\n    }\n\n    fn profile(&self) -> Option<Profile> {\n        Some(self.profile.clone())\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r Config {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n        request::Outcome::Success(req.rocket().config())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/config/http_header.rs",
    "content": "use std::fmt;\n\nuse serde::de;\n\nuse crate::http::Header;\nuse crate::http::uncased::Uncased;\n\npub(crate) fn deserialize<'de, D>(de: D) -> Result<Option<Uncased<'static>>, D::Error>\n    where D: de::Deserializer<'de>\n{\n    struct Visitor;\n\n    impl<'de> de::Visitor<'de> for Visitor {\n        type Value = Option<Uncased<'static>>;\n\n        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n            formatter.write_str(\"a valid header name or `false`\")\n        }\n\n        fn visit_bool<E: de::Error>(self, v: bool) -> Result<Self::Value, E> {\n            if !v {\n                return Ok(None);\n            }\n\n            Err(E::invalid_value(de::Unexpected::Bool(v), &self))\n        }\n\n        fn visit_some<D>(self, de: D) -> Result<Self::Value, D::Error>\n            where D: de::Deserializer<'de>\n        {\n            de.deserialize_string(self)\n        }\n\n        fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {\n            Ok(None)\n        }\n\n        fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {\n            Ok(None)\n        }\n\n        fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {\n            self.visit_string(v.into())\n        }\n\n        fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {\n            if Header::is_valid_name(&v) {\n                Ok(Some(Uncased::from_owned(v)))\n            } else {\n                Err(E::invalid_value(de::Unexpected::Str(&v), &self))\n            }\n        }\n    }\n\n    de.deserialize_string(Visitor)\n}\n"
  },
  {
    "path": "core/lib/src/config/ident.rs",
    "content": "use std::fmt;\n\nuse serde::{Deserialize, Serialize};\nuse serde::de::{self, Deserializer};\n\nuse crate::http::Header;\n\n/// An identifier (or `None`) to send as the `Server` header.\n///\n/// # Deserialization\n///\n/// An `Ident` deserializes from any of the following:\n///\n/// * `string`\n///\n///   The string must be a valid `Ident`. See [`Ident::try_new()`] for details.\n///\n/// * `boolean`\n///\n///   The boolean must be `false`. The value will be [`Ident::none()`].\n///\n/// * `Option<string>`\n///\n///   If `Some`, this is the same as deserializing from the inner string. If\n///   `None`, the value is [`Ident::none()`].\n///\n/// * `unit`\n///\n///   Always deserializes as [`Ident::none()`].\n///\n/// # Examples\n///\n/// As with all Rocket configuration options, when using the default\n/// [`Config::figment()`](crate::Config::figment()), `Ident` can be configured\n/// via a `Rocket.toml` file. When no value for `ident` is provided, the value\n/// defaults to `\"Rocket\"`. Because a default is provided, configuration only\n/// needs to provided to customize or remove the value.\n///\n/// ```rust\n/// # use rocket::figment::{Figment, providers::{Format, Toml}};\n/// use rocket::config::{Config, Ident};\n///\n/// // If these are the contents of `Rocket.toml`...\n/// # let toml = Toml::string(r#\"\n/// [default]\n/// ident = false\n/// # \"#).nested();\n///\n/// // The config parses as follows:\n/// # let config = Config::from(Figment::from(Config::debug_default()).merge(toml));\n/// assert_eq!(config.ident, Ident::none());\n///\n/// // If these are the contents of `Rocket.toml`...\n/// # let toml = Toml::string(r#\"\n/// [default]\n/// ident = \"My Server\"\n/// # \"#).nested();\n///\n/// // The config parses as follows:\n/// # let config = Config::from(Figment::from(Config::debug_default()).merge(toml));\n/// assert_eq!(config.ident, Ident::try_new(\"My Server\").unwrap());\n/// ```\n///\n/// The following example illustrates manual configuration:\n///\n/// ```rust\n/// use rocket::config::{Config, Ident};\n///\n/// let figment = rocket::Config::figment().merge((\"ident\", false));\n/// let config = rocket::Config::from(figment);\n/// assert_eq!(config.ident, Ident::none());\n///\n/// let figment = rocket::Config::figment().merge((\"ident\", \"Fancy/1.0\"));\n/// let config = rocket::Config::from(figment);\n/// assert_eq!(config.ident, Ident::try_new(\"Fancy/1.0\").unwrap());\n/// ```\n#[derive(Debug, Clone, PartialEq, Serialize)]\npub struct Ident(Option<String>);\n\nmacro_rules! ident {\n    ($value:expr) => {\n        {\n            #[allow(unknown_lints)]\n            const _: [(); 0 - !{\n                const ASSERT: bool = $crate::http::Header::is_valid_value($value, false);\n                ASSERT\n            } as usize] = [];\n\n            $crate::config::Ident::try_new($value).unwrap()\n        }\n    }\n}\n\nimpl Ident {\n    /// Returns a new `Ident` with the string `ident`.\n    ///\n    /// When configured as the [`Config::ident`](crate::Config::ident), Rocket\n    /// will set a `Server` header with the `ident` value on all responses.\n    ///\n    /// # Errors\n    ///\n    /// The string `ident` must be non-empty and may only contain visible ASCII\n    /// characters. The first character cannot be whitespace. The only\n    /// whitespace characters allowed are ` ` (space) and `\\t` (horizontal tab).\n    /// The string is returned wrapped in `Err` if it contains any invalid\n    /// characters.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::Ident;\n    ///\n    /// let ident = Ident::try_new(\"Rocket\").unwrap();\n    /// assert_eq!(ident.as_str(), Some(\"Rocket\"));\n    ///\n    /// let ident = Ident::try_new(\"Rocket Run\").unwrap();\n    /// assert_eq!(ident.as_str(), Some(\"Rocket Run\"));\n    ///\n    /// let ident = Ident::try_new(\" Rocket\");\n    /// assert!(ident.is_err());\n    ///\n    /// let ident = Ident::try_new(\"Rocket\\nRun\");\n    /// assert!(ident.is_err());\n    ///\n    /// let ident = Ident::try_new(\"\\tShip\");\n    /// assert!(ident.is_err());\n    /// ```\n    pub fn try_new<S: Into<String>>(ident: S) -> Result<Ident, String> {\n        // This is a little more lenient than reality.\n        let ident = ident.into();\n        if !Header::is_valid_value(&ident, false) {\n            return Err(ident);\n        }\n\n        Ok(Ident(Some(ident)))\n    }\n\n    /// Returns a new `Ident` which is `None`.\n    ///\n    /// When configured as the [`Config::ident`](crate::Config::ident), Rocket\n    /// will not set a `Server` header on any response. Any `Server` header\n    /// emitted by the application will still be written out.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::Ident;\n    ///\n    /// let ident = Ident::none();\n    /// assert_eq!(ident.as_str(), None);\n    /// ```\n    pub const fn none() -> Ident {\n        Ident(None)\n    }\n\n    /// Returns `self` as an `Option<&str>`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::Ident;\n    ///\n    /// let ident = Ident::try_new(\"Rocket\").unwrap();\n    /// assert_eq!(ident.as_str(), Some(\"Rocket\"));\n    ///\n    /// let ident = Ident::try_new(\"Rocket/1 (Unix)\").unwrap();\n    /// assert_eq!(ident.as_str(), Some(\"Rocket/1 (Unix)\"));\n    ///\n    /// let ident = Ident::none();\n    /// assert_eq!(ident.as_str(), None);\n    /// ```\n    pub fn as_str(&self) -> Option<&str> {\n        self.0.as_deref()\n    }\n}\n\nimpl<'de> Deserialize<'de> for Ident {\n    fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = Ident;\n\n            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n                formatter.write_str(\"a server ident string or `false`\")\n            }\n\n            fn visit_bool<E: de::Error>(self, v: bool) -> Result<Self::Value, E> {\n                if !v {\n                    return Ok(Ident::none());\n                }\n\n                Err(E::invalid_value(de::Unexpected::Bool(v), &self))\n            }\n\n            fn visit_some<D>(self, de: D) -> Result<Self::Value, D::Error>\n                where D: Deserializer<'de>\n            {\n                de.deserialize_string(self)\n            }\n\n            fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {\n                Ok(Ident::none())\n            }\n\n            fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {\n                Ok(Ident::none())\n            }\n\n            fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {\n                Ident::try_new(v)\n                    .map_err(|s| E::invalid_value(de::Unexpected::Str(&s), &self))\n            }\n\n            fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {\n                self.visit_string(v.into())\n            }\n        }\n\n        de.deserialize_string(Visitor)\n    }\n}\n\nimpl fmt::Display for Ident {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self.as_str() {\n            Some(name) => name.fmt(f),\n            None => \"disabled\".fmt(f),\n        }\n    }\n}\n\n/// The default `Ident` is `\"Rocket\"`.\nimpl Default for Ident {\n    fn default() -> Self {\n        ident!(\"Rocket\")\n    }\n}\n"
  },
  {
    "path": "core/lib/src/config/mod.rs",
    "content": "//! Server and application configuration.\n//!\n//! See the [configuration guide] for full details.\n//!\n//! [configuration guide]: https://rocket.rs/master/guide/configuration/\n//!\n//! ## Extracting Configuration Parameters\n//!\n//! Rocket exposes the active [`Figment`] via [`Rocket::figment()`]. Any value\n//! that implements [`Deserialize`] can be extracted from the figment:\n//!\n//! ```rust\n//! use rocket::fairing::AdHoc;\n//!\n//! #[derive(serde::Deserialize)]\n//! struct AppConfig {\n//!     id: Option<usize>,\n//!     port: u16,\n//! }\n//!\n//! #[rocket::launch]\n//! fn rocket() -> _ {\n//!     rocket::build().attach(AdHoc::config::<AppConfig>())\n//! }\n//! ```\n//!\n//! [`Figment`]: figment::Figment\n//! [`Rocket::figment()`]: crate::Rocket::figment()\n//! [`Rocket::figment()`]: crate::Rocket::figment()\n//! [`Deserialize`]: serde::Deserialize\n//!\n//! ## Workers\n//!\n//! The `workers` parameter sets the number of threads used for parallel task\n//! execution; there is no limit to the number of concurrent tasks. Due to a\n//! limitation in upstream async executers, unlike other values, the `workers`\n//! configuration value cannot be reconfigured or be configured from sources\n//! other than those provided by [`Config::figment()`]. In other words, only the\n//! values set by the `ROCKET_WORKERS` environment variable or in the `workers`\n//! property of `Rocket.toml` will be considered - all other `workers` values\n//! are ignored.\n//!\n//! ## Custom Providers\n//!\n//! A custom provider can be set via [`rocket::custom()`], which replaces calls to\n//! [`rocket::build()`]. The configured provider can be built on top of\n//! [`Config::figment()`], [`Config::default()`], both, or neither. The\n//! [Figment](figment) documentation has full details on instantiating existing\n//! providers like [`Toml`]() and [`Env`] as well as creating custom providers for\n//! more complex cases.\n//!\n//! Configuration values can be overridden at runtime by merging figment's tuple\n//! providers with Rocket's default provider:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use rocket::data::{Limits, ToByteUnit};\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//!     let figment = rocket::Config::figment()\n//!         .merge((\"port\", 1111))\n//!         .merge((\"limits\", Limits::new().limit(\"json\", 2.mebibytes())));\n//!\n//!     rocket::custom(figment).mount(\"/\", routes![/* .. */])\n//! }\n//! ```\n//!\n//! An application that wants to use Rocket's defaults for [`Config`], but not\n//! its configuration sources, while allowing the application to be configured\n//! via an `App.toml` file that uses top-level keys as profiles (`.nested()`)\n//! and `APP_` environment variables as global overrides (`.global()`), and\n//! `APP_PROFILE` to configure the selected profile, can be structured as\n//! follows:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use serde::{Serialize, Deserialize};\n//! use figment::{Figment, Profile, providers::{Format, Toml, Serialized, Env}};\n//! use rocket::fairing::AdHoc;\n//!\n//! #[derive(Debug, Deserialize, Serialize)]\n//! struct Config {\n//!     app_value: usize,\n//!     /* and so on.. */\n//! }\n//!\n//! impl Default for Config {\n//!     fn default() -> Config {\n//!         Config { app_value: 3, }\n//!     }\n//! }\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//!     let figment = Figment::from(rocket::Config::default())\n//!         .merge(Serialized::defaults(Config::default()))\n//!         .merge(Toml::file(\"App.toml\").nested())\n//!         .merge(Env::prefixed(\"APP_\").global())\n//!         .select(Profile::from_env_or(\"APP_PROFILE\", \"default\"));\n//!\n//!     rocket::custom(figment)\n//!         .mount(\"/\", routes![/* .. */])\n//!         .attach(AdHoc::config::<Config>())\n//! }\n//! ```\n//!\n//! [`rocket::custom()`]: crate::custom()\n//! [`rocket::build()`]: crate::build()\n//! [`Toml`]: figment::providers::Toml\n//! [`Env`]: figment::providers::Env\n\n#[macro_use]\nmod ident;\nmod config;\nmod cli_colors;\nmod http_header;\n#[cfg(test)]\nmod tests;\n\npub use ident::Ident;\npub use config::Config;\npub use cli_colors::CliColors;\n\npub use crate::trace::{TraceFormat, Level};\npub use crate::shutdown::ShutdownConfig;\n\n#[cfg(feature = \"tls\")]\npub use crate::tls::TlsConfig;\n\n#[cfg(feature = \"mtls\")]\npub use crate::mtls::MtlsConfig;\n\n#[cfg(feature = \"secrets\")]\nmod secret_key;\n\n#[cfg(unix)]\npub use crate::shutdown::Sig;\n\n#[cfg(feature = \"secrets\")]\npub use secret_key::SecretKey;\n"
  },
  {
    "path": "core/lib/src/config/secret_key.rs",
    "content": "use std::fmt;\n\nuse cookie::Key;\nuse serde::{de, ser, Deserialize};\n\nuse crate::request::{Outcome, Request, FromRequest};\n\n/// A cryptographically secure secret key.\n///\n/// A `SecretKey` is primarily used by [private cookies]. See the [configuration\n/// guide] for further details. It can be configured from 256-bit random\n/// material or a 512-bit master key, each as either a base64-encoded string or\n/// raw bytes.\n///\n/// ```rust\n/// use rocket::config::Config;\n///\n/// // NOTE: Don't (!) use this key! Generate your own and keep it private!\n/// //       e.g. via `head -c64 /dev/urandom | base64`\n/// let figment = Config::figment()\n///     # .merge((\"secret_key\", \"hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk=\"));\n///     # /*\n///     .merge((\"secret_key\", \"hPrYyЭRiMyµ5sBB1π+CMæ1køFsåqKvBiQJxBVHQk=\"));\n///     # */\n///\n/// let config = Config::from(figment);\n/// assert!(!config.secret_key.is_zero());\n/// ```\n///\n/// When configured in the debug profile with the `secrets` feature enabled, a\n/// key set as `0` is automatically regenerated at launch time from the OS's\n/// random source if available.\n///\n/// ```rust\n/// use rocket::config::Config;\n/// use rocket::local::blocking::Client;\n///\n/// let figment = Config::figment()\n///     .merge((\"secret_key\", vec![0u8; 64]))\n///     .select(\"debug\");\n///\n/// let rocket = rocket::custom(figment);\n/// let client = Client::tracked(rocket).expect(\"okay in debug\");\n/// assert!(!client.rocket().config().secret_key.is_zero());\n/// ```\n///\n/// When running in any other profile with the `secrets` feature enabled,\n/// providing a key of `0` or not provided a key at all results in an error at\n/// launch-time:\n///\n/// ```rust\n/// use rocket::config::Config;\n/// use rocket::figment::Profile;\n/// use rocket::local::blocking::Client;\n/// use rocket::error::ErrorKind;\n///\n/// let profile = Profile::const_new(\"staging\");\n/// let figment = Config::figment()\n///     .merge((\"secret_key\", vec![0u8; 64]))\n///     .select(profile.clone());\n///\n/// let rocket = rocket::custom(figment);\n/// let error = Client::tracked(rocket).expect_err(\"error in non-debug\");\n/// assert!(matches!(error.kind(), ErrorKind::InsecureSecretKey(profile)));\n/// ```\n///\n/// [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies\n/// [configuration guide]: https://rocket.rs/master/guide/configuration/#secret-key\n#[derive(Clone)]\n#[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\npub struct SecretKey {\n    pub(crate) key: Key,\n    provided: bool,\n}\n\nimpl SecretKey {\n    /// Returns a secret key that is all zeroes.\n    pub(crate) fn zero() -> SecretKey {\n        SecretKey { key: Key::from(&[0; 64]), provided: false }\n    }\n\n    /// Creates a `SecretKey` from a 512-bit `master` key. For security,\n    /// `master` _must_ be cryptographically random.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `master` < 64 bytes.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::SecretKey;\n    ///\n    /// # let master = vec![0u8; 64];\n    /// let key = SecretKey::from(&master);\n    /// ```\n    pub fn from(master: &[u8]) -> SecretKey {\n        SecretKey { key: Key::from(master), provided: true }\n    }\n\n    /// Derives a `SecretKey` from 256 bits of cryptographically random\n    /// `material`. For security, `material` _must_ be cryptographically random.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `material` < 32 bytes.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::SecretKey;\n    ///\n    /// # let material = vec![0u8; 32];\n    /// let key = SecretKey::derive_from(&material);\n    /// ```\n    pub fn derive_from(material: &[u8]) -> SecretKey {\n        SecretKey { key: Key::derive_from(material), provided: true }\n    }\n\n    /// Attempts to generate a `SecretKey` from randomness retrieved from the\n    /// OS. If randomness from the OS isn't available, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::SecretKey;\n    ///\n    /// let key = SecretKey::generate();\n    /// ```\n    pub fn generate() -> Option<SecretKey> {\n        Some(SecretKey { key: Key::try_generate()?, provided: false })\n    }\n\n    /// Returns `true` if `self` is the `0`-key.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::SecretKey;\n    ///\n    /// let master = vec![0u8; 64];\n    /// let key = SecretKey::from(&master);\n    /// assert!(key.is_zero());\n    /// ```\n    pub fn is_zero(&self) -> bool {\n        self == &Self::zero()\n    }\n\n    /// Returns `true` if `self` was not automatically generated and is not zero.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::SecretKey;\n    ///\n    /// let master = vec![0u8; 64];\n    /// let key = SecretKey::generate().unwrap();\n    /// assert!(!key.is_provided());\n    ///\n    /// let master = vec![0u8; 64];\n    /// let key = SecretKey::from(&master);\n    /// assert!(!key.is_provided());\n    /// ```\n    pub fn is_provided(&self) -> bool {\n        self.provided && !self.is_zero()\n    }\n\n    /// Serialize as `zero` to avoid key leakage.\n    pub(crate) fn serialize_zero<S>(&self, ser: S) -> Result<S::Ok, S::Error>\n        where S: ser::Serializer\n    {\n        ser.serialize_bytes(&[0; 32][..])\n    }\n}\n\nimpl PartialEq for SecretKey {\n    fn eq(&self, other: &Self) -> bool {\n        // `Key::partial_eq()` is a constant-time op.\n        self.key == other.key\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r SecretKey {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n        Outcome::Success(&req.rocket().config().secret_key)\n    }\n}\n\nimpl<'de> Deserialize<'de> for SecretKey {\n    fn deserialize<D: de::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {\n        use {binascii::{b64decode, hex2bin}, de::Unexpected::Str};\n\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = SecretKey;\n\n            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n                f.write_str(\"256-bit base64 or hex string, or 32-byte slice\")\n            }\n\n            fn visit_str<E: de::Error>(self, val: &str) -> Result<SecretKey, E> {\n                let e = |s| E::invalid_value(Str(s), &\"256-bit base64 or hex\");\n\n                // `binascii` requires a more space than actual output for padding\n                let mut buf = [0u8; 96];\n                let bytes = match val.len() {\n                    44 | 88 => b64decode(val.as_bytes(), &mut buf).map_err(|_| e(val))?,\n                    64 => hex2bin(val.as_bytes(), &mut buf).map_err(|_| e(val))?,\n                    n => Err(E::invalid_length(n, &\"44 or 88 for base64, 64 for hex\"))?\n                };\n\n                self.visit_bytes(bytes)\n            }\n\n            fn visit_bytes<E: de::Error>(self, bytes: &[u8]) -> Result<SecretKey, E> {\n                if bytes.len() < 32 {\n                    Err(E::invalid_length(bytes.len(), &\"at least 32\"))\n                } else if bytes.iter().all(|b| *b == 0) {\n                    Ok(SecretKey::zero())\n                } else if bytes.len() >= 64 {\n                    Ok(SecretKey::from(bytes))\n                } else {\n                    Ok(SecretKey::derive_from(bytes))\n                }\n            }\n\n            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>\n                where A: de::SeqAccess<'de>\n            {\n                let mut bytes = Vec::with_capacity(seq.size_hint().unwrap_or(0));\n                while let Some(byte) = seq.next_element()? {\n                    bytes.push(byte);\n                }\n\n                self.visit_bytes(&bytes)\n            }\n        }\n\n        de.deserialize_any(Visitor)\n    }\n}\n\nimpl fmt::Display for SecretKey {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if self.is_zero() {\n            f.write_str(\"[zero]\")\n        } else {\n            match self.provided {\n                true => f.write_str(\"[provided]\"),\n                false => f.write_str(\"[generated]\"),\n            }\n        }\n    }\n}\n\nimpl fmt::Debug for SecretKey {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        <Self as fmt::Display>::fmt(self, f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/config/tests.rs",
    "content": "use figment::{Figment, Profile};\nuse pretty_assertions::assert_eq;\nuse tracing::Level;\n\n// use crate::log::LogLevel;\nuse crate::data::{Limits, ToByteUnit};\nuse crate::config::{Config, CliColors};\n\n#[test]\nfn test_figment_is_default() {\n    figment::Jail::expect_with(|_| {\n        let mut default: Config = Config::figment().extract().unwrap();\n        default.profile = Config::default().profile;\n        assert_eq!(default, Config::default());\n        Ok(())\n    });\n}\n\n#[test]\nfn test_default_round_trip() {\n    figment::Jail::expect_with(|_| {\n        let original = Config::figment();\n        let roundtrip = Figment::from(Config::from(&original));\n        for figment in &[original, roundtrip] {\n            let config = Config::from(figment);\n            assert_eq!(config, Config::default());\n        }\n\n        Ok(())\n    });\n}\n\n#[test]\nfn test_profile_env() {\n    figment::Jail::expect_with(|jail| {\n        jail.set_env(\"ROCKET_PROFILE\", \"debug\");\n        let figment = Config::figment();\n        assert_eq!(figment.profile(), \"debug\");\n\n        jail.set_env(\"ROCKET_PROFILE\", \"release\");\n        let figment = Config::figment();\n        assert_eq!(figment.profile(), \"release\");\n\n        jail.set_env(\"ROCKET_PROFILE\", \"random\");\n        let figment = Config::figment();\n        assert_eq!(figment.profile(), \"random\");\n\n        Ok(())\n    });\n}\n\n#[test]\nfn test_toml_file() {\n    figment::Jail::expect_with(|jail| {\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                ident = \"Something Cool\"\n                workers = 20\n                keep_alive = 10\n                log_level = \"off\"\n                cli_colors = 0\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            workers: 20,\n            ident: ident!(\"Something Cool\"),\n            keep_alive: 10,\n            log_level: None,\n            cli_colors: CliColors::Never,\n            ..Config::default()\n        });\n\n        jail.create_file(\"Rocket.toml\", r#\"\n                [global]\n                ident = \"Something Else Cool\"\n                workers = 20\n                keep_alive = 10\n                log_level = \"trace\"\n                cli_colors = 0\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            workers: 20,\n            ident: ident!(\"Something Else Cool\"),\n            keep_alive: 10,\n            log_level: Some(Level::TRACE),\n            cli_colors: CliColors::Never,\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_CONFIG\", \"Other.toml\");\n        jail.create_file(\"Other.toml\", r#\"\n                [default]\n                workers = 20\n                keep_alive = 10\n                log_level = 2\n                cli_colors = 0\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            workers: 20,\n            keep_alive: 10,\n            log_level: Some(Level::WARN),\n            cli_colors: CliColors::Never,\n            ..Config::default()\n        });\n\n        Ok(())\n    });\n}\n\n#[test]\nfn test_cli_colors() {\n    figment::Jail::expect_with(|jail| {\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                cli_colors = \"never\"\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Never);\n\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                cli_colors = \"auto\"\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Auto);\n\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                cli_colors = \"always\"\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Always);\n\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                cli_colors = true\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Auto);\n\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                cli_colors = false\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Never);\n\n        jail.create_file(\"Rocket.toml\", r#\"[default]\"#)?;\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Auto);\n\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                cli_colors = 1\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Auto);\n\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default]\n                cli_colors = 0\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Never);\n\n        jail.set_env(\"ROCKET_CLI_COLORS\", 1);\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Auto);\n\n        jail.set_env(\"ROCKET_CLI_COLORS\", 0);\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Never);\n\n        jail.set_env(\"ROCKET_CLI_COLORS\", true);\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Auto);\n\n        jail.set_env(\"ROCKET_CLI_COLORS\", false);\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Never);\n\n        jail.set_env(\"ROCKET_CLI_COLORS\", \"always\");\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Always);\n\n        jail.set_env(\"ROCKET_CLI_COLORS\", \"NEveR\");\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Never);\n\n        jail.set_env(\"ROCKET_CLI_COLORS\", \"auTO\");\n        let config = Config::from(Config::figment());\n        assert_eq!(config.cli_colors, CliColors::Auto);\n\n        Ok(())\n    })\n}\n\n#[test]\nfn test_profiles_merge() {\n    figment::Jail::expect_with(|jail| {\n        jail.create_file(\"Rocket.toml\", r#\"\n                [default.limits]\n                stream = \"50kb\"\n\n                [global]\n                limits = { forms = \"2kb\" }\n\n                [debug.limits]\n                file = \"100kb\"\n            \"#)?;\n\n        jail.set_env(\"ROCKET_PROFILE\", \"unknown\");\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            profile: Profile::const_new(\"unknown\"),\n            limits: Limits::default()\n                .limit(\"stream\", 50.kilobytes())\n                .limit(\"forms\", 2.kilobytes()),\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_PROFILE\", \"debug\");\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            profile: Profile::const_new(\"debug\"),\n            limits: Limits::default()\n                .limit(\"stream\", 50.kilobytes())\n                .limit(\"forms\", 2.kilobytes())\n                .limit(\"file\", 100.kilobytes()),\n            ..Config::default()\n        });\n\n        Ok(())\n    });\n}\n\n#[test]\nfn test_env_vars_merge() {\n    use crate::config::{Ident, ShutdownConfig};\n\n    figment::Jail::expect_with(|jail| {\n        jail.set_env(\"ROCKET_KEEP_ALIVE\", 9999);\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            keep_alive: 9999,\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_SHUTDOWN\", r#\"{grace=7}\"#);\n        let first_figment = Config::figment();\n        jail.set_env(\"ROCKET_SHUTDOWN\", r#\"{mercy=10}\"#);\n        let prev_figment = Config::figment().join(&first_figment);\n        let config = Config::from(&prev_figment);\n        assert_eq!(config, Config {\n            keep_alive: 9999,\n            shutdown: ShutdownConfig { grace: 7, mercy: 10, ..Default::default() },\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_SHUTDOWN\", r#\"{mercy=20}\"#);\n        let config = Config::from(Config::figment().join(&prev_figment));\n        assert_eq!(config, Config {\n            keep_alive: 9999,\n            shutdown: ShutdownConfig { grace: 7, mercy: 20, ..Default::default() },\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_LIMITS\", r#\"{stream=100kiB}\"#);\n        let config = Config::from(Config::figment().join(&prev_figment));\n        assert_eq!(config, Config {\n            keep_alive: 9999,\n            shutdown: ShutdownConfig { grace: 7, mercy: 20, ..Default::default() },\n            limits: Limits::default().limit(\"stream\", 100.kibibytes()),\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_IDENT\", false);\n        let config = Config::from(Config::figment().join(&prev_figment));\n        assert_eq!(config, Config {\n            keep_alive: 9999,\n            shutdown: ShutdownConfig { grace: 7, mercy: 20, ..Default::default() },\n            limits: Limits::default().limit(\"stream\", 100.kibibytes()),\n            ident: Ident::none(),\n            ..Config::default()\n        });\n\n        Ok(())\n    });\n}\n\n#[test]\nfn test_precedence() {\n    figment::Jail::expect_with(|jail| {\n        jail.create_file(\"Rocket.toml\", r#\"\n                [global.limits]\n                forms = \"1mib\"\n                stream = \"50kb\"\n                file = \"100kb\"\n            \"#)?;\n\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            limits: Limits::default()\n                .limit(\"forms\", 1.mebibytes())\n                .limit(\"stream\", 50.kilobytes())\n                .limit(\"file\", 100.kilobytes()),\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_LIMITS\", r#\"{stream=3MiB,capture=2MiB}\"#);\n        let config = Config::from(Config::figment());\n        assert_eq!(config, Config {\n            limits: Limits::default()\n                .limit(\"file\", 100.kilobytes())\n                .limit(\"forms\", 1.mebibytes())\n                .limit(\"stream\", 3.mebibytes())\n                .limit(\"capture\", 2.mebibytes()),\n            ..Config::default()\n        });\n\n        jail.set_env(\"ROCKET_PROFILE\", \"foo\");\n        let val: Result<String, _> = Config::figment().extract_inner(\"profile\");\n        assert!(val.is_err());\n\n        Ok(())\n    });\n}\n\n#[test]\n#[cfg(feature = \"secrets\")]\nfn test_err_on_non_debug_and_no_secret_key() {\n    figment::Jail::expect_with(|jail| {\n        jail.set_env(\"ROCKET_PROFILE\", \"release\");\n        let rocket = crate::custom(Config::figment());\n        crate::local::blocking::Client::untracked(rocket).expect_err(\"release secret key\");\n        Ok(())\n    });\n}\n\n#[test]\n#[cfg(feature = \"secrets\")]\nfn test_err_on_non_debug2_and_no_secret_key() {\n    figment::Jail::expect_with(|jail| {\n        jail.set_env(\"ROCKET_PROFILE\", \"boop\");\n        let rocket = crate::custom(Config::figment());\n        crate::local::blocking::Client::tracked(rocket).expect_err(\"boop secret key\");\n        Ok(())\n    });\n}\n\n#[test]\nfn test_no_err_on_debug_and_no_secret_key() {\n    figment::Jail::expect_with(|jail| {\n        jail.set_env(\"ROCKET_PROFILE\", \"debug\");\n        let figment = Config::figment();\n        assert!(crate::local::blocking::Client::untracked(crate::custom(&figment)).is_ok());\n        crate::async_main(async {\n            let rocket = crate::custom(&figment);\n            assert!(crate::local::asynchronous::Client::tracked(rocket).await.is_ok());\n        });\n\n        Ok(())\n    });\n}\n\n#[test]\nfn test_no_err_on_release_and_custom_secret_key() {\n    figment::Jail::expect_with(|jail| {\n        jail.set_env(\"ROCKET_PROFILE\", \"release\");\n        let key = \"Bx4Gb+aSIfuoEyMHD4DvNs92+wmzfQK98qc6MiwyPY4=\";\n        let figment = Config::figment().merge((\"secret_key\", key));\n\n        assert!(crate::local::blocking::Client::tracked(crate::custom(&figment)).is_ok());\n        crate::async_main(async {\n            let rocket = crate::custom(&figment);\n            assert!(crate::local::asynchronous::Client::untracked(rocket).await.is_ok());\n        });\n\n        Ok(())\n    });\n}\n"
  },
  {
    "path": "core/lib/src/data/capped.rs",
    "content": "/// Number of bytes read/written and whether that consisted of the entire\n/// stream.\n#[derive(Debug, Copy, Clone)]\npub struct N {\n    /// The number of bytes written out.\n    pub written: u64,\n    /// Whether the entire stream was read and written out.\n    pub complete: bool,\n}\n\nimpl std::fmt::Display for N {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.written.fmt(f)\n    }\n}\n\nimpl std::ops::Deref for N {\n    type Target = u64;\n\n    fn deref(&self) -> &Self::Target {\n        &self.written\n    }\n}\n\n/// Encapsulates a value capped to a data limit.\n///\n/// A `Capped<T>` type represents a `T` that has been limited (capped) to some\n/// number of bytes. The internal [`N`] specifies whether the value is complete\n/// (also [`Capped::is_complete()`]) or whether it was capped prematurely. A\n/// [`Capped`] is returned by various methods of [`DataStream`]. Some\n/// `Capped<T>` types, like `Capped<String>` and `Capped<TempFile>`, implement\n/// traits like [`FromData`] and [`FromForm`].\n///\n/// # Example\n///\n/// Since `Capped<TempFile>` implements `FromData`, it can be used as a data\n/// guard. The following Rocket route accepts a raw upload and stores the upload\n/// in a different directory depending on whether the file exceeded the data\n/// limit or not. See [`TempFile`] for details on temporary file storage\n/// locations and limits.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::data::Capped;\n/// use rocket::fs::TempFile;\n///\n/// #[post(\"/upload\", data = \"<file>\")]\n/// async fn upload(mut file: Capped<TempFile<'_>>) -> std::io::Result<()> {\n///     if file.is_complete() {\n///         file.persist_to(\"/tmp/complete/file.txt\").await?;\n///     } else {\n///         file.persist_to(\"/tmp/incomplete/file.txt\").await?;\n///     }\n///\n///     Ok(())\n/// }\n/// ```\n///\n/// [`DataStream`]: crate::data::DataStream\n/// [`FromData`]: crate::data::FromData\n/// [`FromForm`]: crate::form::FromForm\n/// [`TempFile`]: crate::fs::TempFile\n// TODO: `Capped` not particularly usable outside Rocket due to coherence.\n#[derive(Debug, Copy, Clone)]\npub struct Capped<T> {\n    /// The capped value itself.\n    pub value: T,\n    /// The number of bytes written and whether `value` is complete.\n    pub n: N\n}\n\nimpl<T> Capped<T> {\n    /// Creates a new `Capped` from a `value` and an `n`. Prefer to use\n    /// [`Capped::from()`] when possible.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Capped, N};\n    ///\n    /// let n = N { written: 2, complete: true };\n    /// let capped = Capped::new(\"hi\".to_string(), n);\n    /// ```\n    #[inline(always)]\n    pub fn new(value: T, n: N) -> Self {\n        Capped { value, n, }\n    }\n\n    /// Creates a new `Capped` from a `value` and the length of `value` `n`,\n    /// marking `value` as complete. Prefer to use [`Capped::from()`] when\n    /// possible.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Capped, N};\n    ///\n    /// let string = \"hi\";\n    /// let capped = Capped::complete(\"hi\", string.len());\n    /// ```\n    #[inline(always)]\n    pub fn complete(value: T, len: usize) -> Self {\n        Capped { value, n: N { written: len as u64, complete: true } }\n    }\n\n    /// Converts a `Capped<T>` to `Capped<U>` by applying `f` to the contained\n    /// value.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Capped, N};\n    ///\n    /// let n = N { written: 2, complete: true };\n    /// let capped: Capped<usize> = Capped::new(10usize, n);\n    /// let mapped: Capped<String> = capped.map(|n| n.to_string());\n    /// ```\n    #[inline(always)]\n    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Capped<U> {\n        Capped { value: f(self.value), n: self.n }\n    }\n\n    /// Returns `true` if `self.n.written` is `0`, that is, no bytes were\n    /// written to `value`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Capped, N};\n    ///\n    /// let n = N { written: 2, complete: true };\n    /// let capped = Capped::new(\"hi\".to_string(), n);\n    /// assert!(!capped.is_empty());\n    ///\n    /// let n = N { written: 0, complete: true };\n    /// let capped = Capped::new(\"\".to_string(), n);\n    /// assert!(capped.is_empty());\n    /// ```\n    #[inline(always)]\n    pub fn is_empty(&self) -> bool {\n        self.n.written == 0\n    }\n\n    /// Returns `true` if `self.n.complete`, that is, `value` represents the\n    /// entire data stream.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Capped, N};\n    ///\n    /// let n = N { written: 2, complete: true };\n    /// let capped = Capped::new(\"hi\".to_string(), n);\n    /// assert!(capped.is_complete());\n    ///\n    /// let n = N { written: 4, complete: false };\n    /// let capped = Capped::new(\"hell\".to_string(), n);\n    /// assert!(!capped.is_complete());\n    /// ```\n    #[inline(always)]\n    pub fn is_complete(&self) -> bool {\n        self.n.complete\n    }\n\n    /// Returns the internal value.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Capped, N};\n    ///\n    /// let n = N { written: 2, complete: true };\n    /// let capped = Capped::new(\"hi\".to_string(), n);\n    /// assert_eq!(capped.into_inner(), \"hi\");\n    /// ```\n    #[inline(always)]\n    pub fn into_inner(self) -> T {\n        self.value\n    }\n}\n\nimpl<T> std::ops::Deref for Capped<T> {\n    type Target = T;\n\n    fn deref(&self) -> &Self::Target {\n        &self.value\n    }\n}\n\nimpl<T> std::ops::DerefMut for Capped<T> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.value\n    }\n}\n\nimpl<T: AsRef<[u8]>> From<T> for Capped<T> {\n    /// Creates a `Capped<T>` from a `value`, setting `complete` to `true`.\n    fn from(value: T) -> Self {\n        let len = value.as_ref().len();\n        Capped::complete(value, len)\n    }\n}\n\nuse crate::response::{self, Responder};\nuse crate::request::Request;\n\nimpl<'r, 'o: 'r, T: Responder<'r, 'o>> Responder<'r, 'o> for Capped<T> {\n    fn respond_to(self, request: &'r Request<'_>) -> response::Result<'o> {\n        self.value.respond_to(request)\n    }\n}\n\nmacro_rules! impl_strict_from_form_field_from_capped {\n    ($T:ty) => (const _: () = {\n        use $crate::form::{FromFormField, ValueField, DataField, Result};\n        use $crate::data::Capped;\n\n        #[crate::async_trait]\n        impl<'v> FromFormField<'v> for $T {\n            fn default() -> Option<Self> {\n                <Capped<$T> as FromFormField<'v>>::default().map(|c| c.value)\n            }\n\n            fn from_value(f: ValueField<'v>) -> Result<'v, Self> {\n                let capped = <Capped<$T> as FromFormField<'v>>::from_value(f)?;\n                if !capped.is_complete() {\n                    Err((None, Some(capped.n.written)))?;\n                }\n\n                Ok(capped.value)\n            }\n\n            async fn from_data(field: DataField<'v, '_>) -> Result<'v, Self> {\n                let capped = <Capped<$T> as FromFormField<'v>>::from_data(field);\n                let capped = capped.await?;\n                if !capped.is_complete() {\n                    Err((None, Some(capped.n.written)))?;\n                }\n\n                Ok(capped.value)\n            }\n        }\n    };)\n}\n\nmacro_rules! impl_strict_from_data_from_capped {\n    ($T:ty) => (\n        #[crate::async_trait]\n        impl<'r> $crate::data::FromData<'r> for $T {\n            type Error = <$crate::data::Capped<Self> as $crate::data::FromData<'r>>::Error;\n\n            async fn from_data(\n                r: &'r $crate::Request<'_>,\n                d: $crate::Data<'r>\n            ) -> $crate::data::Outcome<'r, Self> {\n                use $crate::outcome::Outcome::*;\n                use std::io::{Error, ErrorKind::UnexpectedEof};\n\n                match <$crate::data::Capped<$T> as FromData>::from_data(r, d).await {\n                    Success(p) if p.is_complete() => Success(p.into_inner()),\n                    Success(_) => {\n                        let e = Error::new(UnexpectedEof, \"data limit exceeded\");\n                        Error((Status::BadRequest, e.into()))\n                    },\n                    Forward(d) => Forward(d),\n                    Error((s, e)) => Error((s, e)),\n                }\n            }\n        }\n    )\n}\n"
  },
  {
    "path": "core/lib/src/data/data.rs",
    "content": "use std::io;\nuse std::pin::Pin;\n\nuse crate::data::ByteUnit;\nuse crate::data::data_stream::{DataStream, RawReader, RawStream};\nuse crate::data::peekable::Peekable;\nuse crate::data::transform::{Transform, TransformBuf, Inspect, InPlaceMap};\n\n/// Type representing the body data of a request.\n///\n/// This type is the only means by which the body of a request can be retrieved.\n/// This type is not usually used directly. Instead, data guards (types that\n/// implement [`FromData`](crate::data::FromData)) are created indirectly via\n/// code generation by specifying the `data = \"<var>\"` route parameter as\n/// follows:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type DataGuard = String;\n/// #[post(\"/submit\", data = \"<var>\")]\n/// fn submit(var: DataGuard) { /* ... */ }\n/// # fn main() { }\n/// ```\n///\n/// Above, `DataGuard` can be any type that implements `FromData`. Note that\n/// `Data` itself implements `FromData`.\n///\n/// # Reading Data\n///\n/// Data may be read from a `Data` object by calling either the\n/// [`open()`](Data::open()) or [`peek()`](Data::peek()) methods.\n///\n/// The `open` method consumes the `Data` object and returns the raw data\n/// stream. The `Data` object is consumed for safety reasons: consuming the\n/// object ensures that holding a `Data` object means that all of the data is\n/// available for reading.\n///\n/// The `peek` method returns a slice containing at most 512 bytes of buffered\n/// body data. This enables partially or fully reading from a `Data` object\n/// without consuming the `Data` object.\npub struct Data<'r> {\n    stream: Peekable<512, RawReader<'r>>,\n    transforms: Vec<Pin<Box<dyn Transform + Send + Sync + 'r>>>,\n}\n\n// TODO: Before `async`, we had a read timeout of 5s. Such a short read timeout\n// is likely no longer necessary, but an idle timeout should be implemented.\nimpl<'r> Data<'r> {\n    #[inline]\n    pub(crate) fn new(stream: Peekable<512, RawReader<'r>>) -> Self {\n        Self { stream, transforms: Vec::new() }\n    }\n\n    #[inline]\n    pub(crate) fn from<S: Into<RawStream<'r>>>(stream: S) -> Data<'r> {\n        Data::new(Peekable::new(RawReader::new(stream.into())))\n    }\n\n    /// This creates a `data` object from a local data source `data`.\n    #[inline]\n    pub(crate) fn local(data: Vec<u8>) -> Data<'r> {\n        Data::new(Peekable::with_buffer(data, true, RawReader::new(RawStream::Empty)))\n    }\n\n    /// Returns the raw data stream, limited to `limit` bytes.\n    ///\n    /// The stream contains all of the data in the body of the request,\n    /// including that in the `peek` buffer. The method consumes the `Data`\n    /// instance. This ensures that a `Data` type _always_ represents _all_ of\n    /// the data in a request.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Data, ToByteUnit};\n    ///\n    /// # const SIZE_LIMIT: u64 = 2 << 20; // 2MiB\n    /// fn handler(data: Data<'_>) {\n    ///     let stream = data.open(2.mebibytes());\n    /// }\n    /// ```\n    #[inline(always)]\n    pub fn open(self, limit: ByteUnit) -> DataStream<'r> {\n        DataStream::new(self.transforms, self.stream, limit.into())\n    }\n\n    /// Fills the peek buffer with body data until it contains at least `num`\n    /// bytes (capped to 512), or the complete body data, whichever is less, and\n    /// returns it. If the buffer already contains either at least `num` bytes\n    /// or all of the body data, no I/O is performed and the buffer is simply\n    /// returned. If `num` is greater than `512`, it is artificially capped to\n    /// `512`.\n    ///\n    /// No guarantees are made about the actual size of the returned buffer\n    /// except that it will not exceed the length of the body data. It may be:\n    ///\n    ///   * Less than `num` if `num > 512` or the complete body data is `< 512`\n    ///     or an error occurred while reading the body.\n    ///   * Equal to `num` if `num` is `<= 512` and exactly `num` bytes of the\n    ///     body data were successfully read.\n    ///   * Greater than `num` if `> num` bytes of the body data have\n    ///     successfully been read, either by this request, a previous request,\n    ///     or opportunistically.\n    ///\n    /// [`Data::peek_complete()`] can be used to determine if this buffer\n    /// contains the complete body data.\n    ///\n    /// # Examples\n    ///\n    /// In a data guard:\n    ///\n    /// ```rust\n    /// use rocket::request::{self, Request, FromRequest};\n    /// use rocket::data::{Data, FromData, Outcome};\n    /// use rocket::http::Status;\n    /// # struct MyType;\n    /// # type MyError = String;\n    ///\n    /// #[rocket::async_trait]\n    /// impl<'r> FromData<'r> for MyType {\n    ///     type Error = MyError;\n    ///\n    ///     async fn from_data(r: &'r Request<'_>, mut data: Data<'r>) -> Outcome<'r, Self> {\n    ///         if data.peek(2).await != b\"hi\" {\n    ///             return Outcome::Forward((data, Status::BadRequest))\n    ///         }\n    ///\n    ///         /* .. */\n    ///         # unimplemented!()\n    ///     }\n    /// }\n    /// ```\n    ///\n    /// In a fairing:\n    ///\n    /// ```\n    /// use rocket::{Rocket, Request, Data, Response};\n    /// use rocket::fairing::{Fairing, Info, Kind};\n    /// # struct MyType;\n    ///\n    /// #[rocket::async_trait]\n    /// impl Fairing for MyType {\n    ///     fn info(&self) -> Info {\n    ///         Info {\n    ///             name: \"Data Peeker\",\n    ///             kind: Kind::Request\n    ///         }\n    ///     }\n    ///\n    ///     async fn on_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {\n    ///         if data.peek(2).await == b\"hi\" {\n    ///             /* do something; body data starts with `\"hi\"` */\n    ///         }\n    ///\n    ///         /* .. */\n    ///         # unimplemented!()\n    ///     }\n    /// }\n    /// ```\n    #[inline(always)]\n    pub async fn peek(&mut self, num: usize) -> &[u8] {\n        self.stream.peek(num).await\n    }\n\n    /// Returns true if the `peek` buffer contains all of the data in the body\n    /// of the request. Returns `false` if it does not or it is not known.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::Data;\n    ///\n    /// async fn handler(mut data: Data<'_>) {\n    ///     if data.peek_complete() {\n    ///         println!(\"All of the data: {:?}\", data.peek(512).await);\n    ///     }\n    /// }\n    /// ```\n    #[inline(always)]\n    pub fn peek_complete(&self) -> bool {\n        self.stream.complete\n    }\n\n    /// Chains the [`Transform`] `transform` to `self`.\n    ///\n    /// Note that transforms do nothing until the data is\n    /// [`open()`ed](Data::open()) and read.\n    #[inline(always)]\n    pub fn chain_transform<T>(&mut self, transform: T) -> &mut Self\n        where T: Transform + Send + Sync + 'static\n    {\n        self.transforms.push(Box::pin(transform));\n        self\n    }\n\n    /// Chain a [`Transform`] that can inspect the data as it streams.\n    pub fn chain_inspect<F>(&mut self, f: F) -> &mut Self\n        where F: FnMut(&[u8]) + Send + Sync + 'static\n    {\n        self.chain_transform(Inspect(Box::new(f)))\n    }\n\n    /// Chain a [`Transform`] that can in-place map the data as it streams.\n    /// Unlike [`Data::chain_try_inplace_map()`], this version assumes the\n    /// mapper is infallible.\n    pub fn chain_inplace_map<F>(&mut self, mut f: F) -> &mut Self\n        where F: FnMut(&mut TransformBuf<'_, '_>) + Send + Sync + 'static\n    {\n        self.chain_transform(InPlaceMap(Box::new(move |buf| Ok(f(buf)))))\n    }\n\n    /// Chain a [`Transform`] that can in-place map the data as it streams.\n    /// Unlike [`Data::chain_inplace_map()`], this version allows the mapper to\n    /// be infallible.\n    pub fn chain_try_inplace_map<F>(&mut self, f: F) -> &mut Self\n        where F: FnMut(&mut TransformBuf<'_, '_>) -> io::Result<()> + Send + Sync + 'static\n    {\n        self.chain_transform(InPlaceMap(Box::new(f)))\n    }\n}\n"
  },
  {
    "path": "core/lib/src/data/data_stream.rs",
    "content": "use std::pin::Pin;\nuse std::task::{Context, Poll};\nuse std::path::Path;\nuse std::io::{self, Cursor};\n\nuse futures::ready;\nuse futures::stream::Stream;\nuse tokio::fs::File;\nuse tokio::io::{AsyncRead, AsyncWrite, AsyncReadExt, ReadBuf, Take};\nuse tokio_util::io::StreamReader;\nuse hyper::body::{Body, Bytes, Incoming as HyperBody};\n\nuse crate::data::{Capped, N};\nuse crate::data::transform::Transform;\nuse crate::util::Chain;\n\nuse super::peekable::Peekable;\nuse super::transform::TransformBuf;\n\n/// Raw data stream of a request body.\n///\n/// This stream can only be obtained by calling\n/// [`Data::open()`](crate::data::Data::open()) with a data limit. The stream\n/// contains all of the data in the body of the request.\n///\n/// Reading from a `DataStream` is accomplished via the various methods on the\n/// structure. In general, methods exists in two variants: those that _check_\n/// whether the entire stream was read and those that don't. The former either\n/// directly or indirectly (via [`Capped`]) return an [`N`] which allows\n/// checking if the stream was read to completion while the latter do not.\n///\n/// | Read Into | Method                               | Notes                            |\n/// |-----------|--------------------------------------|----------------------------------|\n/// | `String`  | [`DataStream::into_string()`]        | Completeness checked. Preferred. |\n/// | `String`  | [`AsyncReadExt::read_to_string()`]   | Unchecked w/existing `String`.   |\n/// | `Vec<u8>` | [`DataStream::into_bytes()`]         | Checked. Preferred.              |\n/// | `Vec<u8>` | [`DataStream::stream_to(&mut vec)`]  | Checked w/existing `Vec`.        |\n/// | `Vec<u8>` | [`DataStream::stream_precise_to()`]  | Unchecked w/existing `Vec`.      |\n/// | `File`    | [`DataStream::into_file()`]          | Checked. Preferred.              |\n/// | `File`    | [`DataStream::stream_to(&mut file)`] | Checked w/ existing `File`.      |\n/// | `File`    | [`DataStream::stream_precise_to()`]  | Unchecked w/ existing `File`.    |\n/// | `T`       | [`DataStream::stream_to()`]          | Checked. Any `T: AsyncWrite`.    |\n/// | `T`       | [`DataStream::stream_precise_to()`]  | Unchecked. Any `T: AsyncWrite`.  |\n///\n/// [`DataStream::stream_to(&mut vec)`]: DataStream::stream_to()\n/// [`DataStream::stream_to(&mut file)`]: DataStream::stream_to()\n#[non_exhaustive]\npub enum DataStream<'r> {\n    #[doc(hidden)]\n    Base(BaseReader<'r>),\n    #[doc(hidden)]\n    Transform(TransformReader<'r>),\n}\n\n/// A data stream that has a `transformer` applied to it.\npub struct TransformReader<'r> {\n    transformer: Pin<Box<dyn Transform + Send + Sync + 'r>>,\n    stream: Pin<Box<DataStream<'r>>>,\n    inner_done: bool,\n}\n\n/// Limited, pre-buffered reader to the underlying data stream.\npub type BaseReader<'r> = Take<Chain<Cursor<Vec<u8>>, RawReader<'r>>>;\n\n/// Direct reader to the underlying data stream. Not limited in any manner.\npub type RawReader<'r> = StreamReader<RawStream<'r>, Bytes>;\n\n/// Raw underlying data stream.\npub enum RawStream<'r> {\n    Empty,\n    Body(HyperBody),\n    #[cfg(feature = \"http3-preview\")]\n    H3Body(crate::listener::Cancellable<crate::listener::quic::QuicRx>),\n    Multipart(multer::Field<'r>),\n}\n\nimpl<'r> TransformReader<'r> {\n    /// Returns the underlying `BaseReader`.\n    fn base_mut(&mut self) -> &mut BaseReader<'r> {\n        match self.stream.as_mut().get_mut() {\n            DataStream::Base(base) => base,\n            DataStream::Transform(inner) => inner.base_mut(),\n        }\n    }\n\n    /// Returns the underlying `BaseReader`.\n    fn base(&self) -> &BaseReader<'r> {\n        match self.stream.as_ref().get_ref() {\n            DataStream::Base(base) => base,\n            DataStream::Transform(inner) => inner.base(),\n        }\n    }\n}\n\nimpl<'r> DataStream<'r> {\n    pub(crate) fn new(\n        transformers: Vec<Pin<Box<dyn Transform + Send + Sync + 'r>>>,\n        Peekable { buffer, reader, .. }: Peekable<512, RawReader<'r>>,\n        limit: u64\n    ) -> Self {\n        let mut stream = DataStream::Base(Chain::new(Cursor::new(buffer), reader).take(limit));\n        for transformer in transformers {\n            stream = DataStream::Transform(TransformReader {\n                transformer,\n                stream: Box::pin(stream),\n                inner_done: false,\n            });\n        }\n\n        stream\n    }\n\n    /// Returns the underlying `BaseReader`.\n    fn base_mut(&mut self) -> &mut BaseReader<'r> {\n        match self {\n            DataStream::Base(base) => base,\n            DataStream::Transform(transform) => transform.base_mut(),\n        }\n    }\n\n    /// Returns the underlying `BaseReader`.\n    fn base(&self) -> &BaseReader<'r> {\n        match self {\n            DataStream::Base(base) => base,\n            DataStream::Transform(transform) => transform.base(),\n        }\n    }\n\n    /// Whether a previous read exhausted the set limit _and then some_.\n    async fn limit_exceeded(&mut self) -> io::Result<bool> {\n        let base = self.base_mut();\n\n        #[cold]\n        async fn _limit_exceeded(base: &mut BaseReader<'_>) -> io::Result<bool> {\n            // Read one more byte after reaching limit to see if we cut early.\n            base.set_limit(1);\n            let mut buf = [0u8; 1];\n            let exceeded = base.read(&mut buf).await? != 0;\n            base.set_limit(0);\n            Ok(exceeded)\n        }\n\n        Ok(base.limit() == 0 && _limit_exceeded(base).await?)\n    }\n\n    /// Number of bytes a full read from `self` will _definitely_ read.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Data, ToByteUnit};\n    ///\n    /// async fn f(data: Data<'_>) {\n    ///     let definitely_have_n_bytes = data.open(1.kibibytes()).hint();\n    /// }\n    /// ```\n    pub fn hint(&self) -> usize {\n        let base = self.base();\n        if let (Some(cursor), _) = base.get_ref().get_ref() {\n            let len = cursor.get_ref().len() as u64;\n            let position = cursor.position().min(len);\n            let remaining = len - position;\n            remaining.min(base.limit()) as usize\n        } else {\n            0\n        }\n    }\n\n    /// A helper method to write the body of the request to any `AsyncWrite`\n    /// type. Returns an [`N`] which indicates how many bytes were written and\n    /// whether the entire stream was read. An additional read from `self` may\n    /// be required to check if all of the stream has been read. If that\n    /// information is not needed, use [`DataStream::stream_precise_to()`].\n    ///\n    /// This method is identical to `tokio::io::copy(&mut self, &mut writer)`\n    /// except in that it returns an `N` to check for completeness.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::data::{Data, ToByteUnit};\n    ///\n    /// async fn data_guard(mut data: Data<'_>) -> io::Result<String> {\n    ///     // write all of the data to stdout\n    ///     let written = data.open(512.kibibytes())\n    ///         .stream_to(tokio::io::stdout()).await?;\n    ///\n    ///     Ok(format!(\"Wrote {} bytes.\", written))\n    /// }\n    /// ```\n    #[inline(always)]\n    pub async fn stream_to<W>(mut self, mut writer: W) -> io::Result<N>\n        where W: AsyncWrite + Unpin\n    {\n        let written = tokio::io::copy(&mut self, &mut writer).await?;\n        Ok(N { written, complete: !self.limit_exceeded().await? })\n    }\n\n    /// Like [`DataStream::stream_to()`] except that no end-of-stream check is\n    /// conducted and thus read/write completeness is unknown.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::data::{Data, ToByteUnit};\n    ///\n    /// async fn data_guard(mut data: Data<'_>) -> io::Result<String> {\n    ///     // write all of the data to stdout\n    ///     let written = data.open(512.kibibytes())\n    ///         .stream_precise_to(tokio::io::stdout()).await?;\n    ///\n    ///     Ok(format!(\"Wrote {} bytes.\", written))\n    /// }\n    /// ```\n    #[inline(always)]\n    pub async fn stream_precise_to<W>(mut self, mut writer: W) -> io::Result<u64>\n        where W: AsyncWrite + Unpin\n    {\n        tokio::io::copy(&mut self, &mut writer).await\n    }\n\n    /// A helper method to write the body of the request to a `Vec<u8>`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::data::{Data, ToByteUnit};\n    ///\n    /// async fn data_guard(data: Data<'_>) -> io::Result<Vec<u8>> {\n    ///     let bytes = data.open(4.kibibytes()).into_bytes().await?;\n    ///     if !bytes.is_complete() {\n    ///         println!(\"there are bytes remaining in the stream\");\n    ///     }\n    ///\n    ///     Ok(bytes.into_inner())\n    /// }\n    /// ```\n    pub async fn into_bytes(self) -> io::Result<Capped<Vec<u8>>> {\n        let mut vec = Vec::with_capacity(self.hint());\n        let n = self.stream_to(&mut vec).await?;\n        Ok(Capped { value: vec, n })\n    }\n\n    /// A helper method to write the body of the request to a `String`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::data::{Data, ToByteUnit};\n    ///\n    /// async fn data_guard(data: Data<'_>) -> io::Result<String> {\n    ///     let string = data.open(10.bytes()).into_string().await?;\n    ///     if !string.is_complete() {\n    ///         println!(\"there are bytes remaining in the stream\");\n    ///     }\n    ///\n    ///     Ok(string.into_inner())\n    /// }\n    /// ```\n    pub async fn into_string(mut self) -> io::Result<Capped<String>> {\n        let mut string = String::with_capacity(self.hint());\n        let written = self.read_to_string(&mut string).await?;\n        let n = N { written: written as u64, complete: !self.limit_exceeded().await? };\n        Ok(Capped { value: string, n })\n    }\n\n    /// A helper method to write the body of the request to a file at the path\n    /// determined by `path`. If a file at the path already exists, it is\n    /// overwritten. The opened file is returned.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::data::{Data, ToByteUnit};\n    ///\n    /// async fn data_guard(mut data: Data<'_>) -> io::Result<String> {\n    ///     let file = data.open(1.megabytes()).into_file(\"/static/file\").await?;\n    ///     if !file.is_complete() {\n    ///         println!(\"there are bytes remaining in the stream\");\n    ///     }\n    ///\n    ///     Ok(format!(\"Wrote {} bytes to /static/file\", file.n))\n    /// }\n    /// ```\n    pub async fn into_file<P: AsRef<Path>>(self, path: P) -> io::Result<Capped<File>> {\n        let mut file = File::create(path).await?;\n        let n = self.stream_to(&mut tokio::io::BufWriter::new(&mut file)).await?;\n        Ok(Capped { value: file, n })\n    }\n}\n\nimpl AsyncRead for DataStream<'_> {\n    fn poll_read(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        match self.get_mut() {\n            DataStream::Base(inner) => Pin::new(inner).poll_read(cx, buf),\n            DataStream::Transform(inner) => Pin::new(inner).poll_read(cx, buf),\n        }\n    }\n}\n\nimpl AsyncRead for TransformReader<'_> {\n    fn poll_read(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        let init_fill = buf.filled().len();\n        if !self.inner_done {\n            ready!(Pin::new(&mut self.stream).poll_read(cx, buf))?;\n            self.inner_done = init_fill == buf.filled().len();\n        }\n\n        if self.inner_done {\n            return self.transformer.as_mut().poll_finish(cx, buf);\n        }\n\n        let mut tbuf = TransformBuf { buf, cursor: init_fill };\n        self.transformer.as_mut().transform(&mut tbuf)?;\n        if buf.filled().len() == init_fill {\n            cx.waker().wake_by_ref();\n            return Poll::Pending;\n        }\n\n        Poll::Ready(Ok(()))\n    }\n}\n\nimpl Stream for RawStream<'_> {\n    type Item = io::Result<Bytes>;\n\n    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {\n        match self.get_mut() {\n            // TODO: Expose trailer headers, somehow.\n            RawStream::Body(body) => {\n                Pin::new(body)\n                    .poll_frame(cx)\n                    .map_ok(|frame| frame.into_data().unwrap_or_else(|_| Bytes::new()))\n                    .map_err(io::Error::other)\n            },\n            #[cfg(feature = \"http3-preview\")]\n            RawStream::H3Body(stream) => Pin::new(stream).poll_next(cx),\n            RawStream::Multipart(s) => Pin::new(s).poll_next(cx).map_err(io::Error::other),\n            RawStream::Empty => Poll::Ready(None),\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        match self {\n            RawStream::Body(body) => {\n                let hint = body.size_hint();\n                let (lower, upper) = (hint.lower(), hint.upper());\n                (lower as usize, upper.map(|x| x as usize))\n            },\n            #[cfg(feature = \"http3-preview\")]\n            RawStream::H3Body(_) => (0, Some(0)),\n            RawStream::Multipart(mp) => mp.size_hint(),\n            RawStream::Empty => (0, Some(0)),\n        }\n    }\n}\n\nimpl std::fmt::Display for RawStream<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            RawStream::Empty => f.write_str(\"empty stream\"),\n            RawStream::Body(_) => f.write_str(\"request body\"),\n            #[cfg(feature = \"http3-preview\")]\n            RawStream::H3Body(_) => f.write_str(\"http3 quic stream\"),\n            RawStream::Multipart(_) => f.write_str(\"multipart form field\"),\n        }\n    }\n}\n\nimpl<'r> From<HyperBody> for RawStream<'r> {\n    fn from(value: HyperBody) -> Self {\n        Self::Body(value)\n    }\n}\n\n#[cfg(feature = \"http3-preview\")]\nimpl<'r> From<crate::listener::Cancellable<crate::listener::quic::QuicRx>> for RawStream<'r> {\n    fn from(value: crate::listener::Cancellable<crate::listener::quic::QuicRx>) -> Self {\n        Self::H3Body(value)\n    }\n}\n\nimpl<'r> From<multer::Field<'r>> for RawStream<'r> {\n    fn from(value: multer::Field<'r>) -> Self {\n        Self::Multipart(value)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/data/from_data.rs",
    "content": "use crate::http::{RawStr, Status};\nuse crate::request::{Request, local_cache};\nuse crate::data::{Data, Limits};\nuse crate::outcome::{self, IntoOutcome, try_outcome, Outcome::*};\n\n/// Type alias for the `Outcome` of [`FromData`].\n///\n/// [`FromData`]: crate::data::FromData\npub type Outcome<'r, T, E = <T as FromData<'r>>::Error>\n    = outcome::Outcome<T, (Status, E), (Data<'r>, Status)>;\n\n/// Trait implemented by data guards to derive a value from request body data.\n///\n/// # Data Guards\n///\n/// A data guard is a guard that operates on a request's body data. Data guards\n/// validate and parse request body data via implementations of `FromData`. In\n/// other words, a type is a data guard _iff_ it implements `FromData`.\n///\n/// Data guards are the target of the `data` route attribute parameter:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type DataGuard = String;\n/// #[post(\"/submit\", data = \"<var>\")]\n/// fn submit(var: DataGuard) { /* ... */ }\n/// ```\n///\n/// A route can have at most one data guard. Above, `var` is used as the\n/// argument name for the data guard type `DataGuard`. When the `submit` route\n/// matches, Rocket will call the `FromData` implementation for the type `T`.\n/// The handler will only be called if the guard returns successfully.\n///\n/// ## Build-In Guards\n///\n/// Rocket provides implementations for `FromData` for many types. Their\n/// behavior is documented here:\n///\n///   * `Data`: Returns the untouched `Data`.\n///\n///     - **Fails:** Never.\n///\n///     - **Succeeds:** Always.\n///\n///     - **Forwards:** Never.\n///\n///   * Strings: `Cow<str>`, `&str`, `&RawStr`, `String`\n///\n///     _Limited by the `string` [data limit]._\n///\n///     Reads the body data into a string via [`DataStream::into_string()`].\n///\n///     - **Fails:** If the body data is not valid UTF-8 or on I/O errors while\n///     reading. The error type is [`io::Error`].\n///\n///     - **Succeeds:** If the body data _is_ valid UTF-8. If the limit is\n///     exceeded, the string is truncated to the limit.\n///\n///     - **Forwards:** Never.\n///\n///   * Bytes: `&[u8]`, `Vec<u8>`\n///\n///     _Limited by the `bytes` [data limit]._\n///\n///     Reads the body data into a byte vector via [`DataStream::into_bytes()`].\n///\n///     - **Fails:** On I/O errors while reading. The error type is\n///     [`io::Error`].\n///\n///     - **Succeeds:** As long as no I/O error occurs. If the limit is\n///     exceeded, the slice is truncated to the limit.\n///\n///     - **Forwards:** Never.\n///\n///   * [`TempFile`](crate::fs::TempFile)\n///\n///     _Limited by the `file` and/or `file/$ext` [data limit]._\n///\n///     Streams the body data directly into a temporary file. The data is never\n///     buffered in memory.\n///\n///     - **Fails:** On I/O errors while reading data or creating the temporary\n///     file. The error type is [`io::Error`].\n///\n///     - **Succeeds:** As long as no I/O error occurs and the temporary file\n///     could be created. If the limit is exceeded, only data up to the limit is\n///     read and subsequently written.\n///\n///     - **Forwards:** Never.\n///\n///   * Deserializers: [`Json<T>`], [`MsgPack<T>`]\n///\n///     _Limited by the `json`, `msgpack` [data limit], respectively._\n///\n///     Reads up to the configured limit and deserializes the read data into `T`\n///     using the respective format's parser.\n///\n///     - **Fails:** On I/O errors while reading the data, or if the data fails\n///     to parse as a `T` according to the deserializer. The error type for\n///     `Json` is [`json::Error`](crate::serde::json::Error) and the error type\n///     for `MsgPack` is [`msgpack::Error`](crate::serde::msgpack::Error).\n///\n///     - **Succeeds:** As long as no I/O error occurs and the (limited) body\n///     data was successfully deserialized as a `T`.\n///\n///     - **Forwards:** Never.\n///\n///   * Forms: [`Form<T>`]\n///\n///     _Limited by the `form` or `data-form` [data limit]._\n///\n///     Parses the incoming data stream into fields according to Rocket's [field\n///     wire format], pushes each field to `T`'s [`FromForm`] [push parser], and\n///     finalizes the form. Parsing is done on the stream without reading the\n///     data into memory. If the request has as a [`ContentType::Form`], the\n///     `form` limit is applied, otherwise if the request has a\n///     [`ContentType::FormData`], the `data-form` limit is applied.\n///\n///     - **Fails:** On I/O errors while reading the data, or if the data fails\n///     to parse as a `T` according to its `FromForm` implementation. The errors\n///     are collected into an [`Errors`](crate::form::Errors), the error type.\n///\n///     - **Succeeds:** As long as no I/O error occurs and the (limited) body\n///     data was successfully parsed as a `T`.\n///\n///     - **Forwards:** If the request's `Content-Type` is neither\n///     [`ContentType::Form`] nor [`ContentType::FormData`].\n///\n///   * `Option<T>`\n///\n///     Forwards to `T`'s `FromData` implementation, capturing the outcome.\n///\n///     - **Fails:** Never.\n///\n///     - **Succeeds:** Always. If `T`'s `FromData` implementation succeeds, the\n///     parsed value is returned in `Some`. If its implementation forwards or\n///     fails, `None` is returned.\n///\n///     - **Forwards:** Never.\n///\n///   * `Result<T, T::Error>`\n///\n///     Forwards to `T`'s `FromData` implementation, capturing the outcome.\n///\n///     - **Fails:** Never.\n///\n///     - **Succeeds:** If `T`'s `FromData` implementation succeeds or fails. If\n///     it succeeds, the value is returned in `Ok`. If it fails, the error value\n///     is returned in `Err`.\n///\n///     - **Forwards:** If `T`'s implementation forwards.\n///\n///   * [`Capped<T>`]\n///\n///     Forwards to `T`'s `FromData` implementation, recording whether the data\n///     was truncated (a.k.a. capped) due to `T`'s limit being exceeded.\n///\n///     - **Fails:** If `T`'s implementation fails.\n///     - **Succeeds:** If `T`'s implementation succeeds.\n///     - **Forwards:** If `T`'s implementation forwards.\n///\n/// [data limit]: crate::data::Limits#built-in-limits\n/// [`DataStream::into_string()`]: crate::data::DataStream::into_string()\n/// [`DataStream::into_bytes()`]: crate::data::DataStream::into_bytes()\n/// [`io::Error`]: std::io::Error\n/// [`Json<T>`]: crate::serde::json::Json\n/// [`MsgPack<T>`]: crate::serde::msgpack::MsgPack\n/// [`Form<T>`]: crate::form::Form\n/// [field wire format]: crate::form#field-wire-format\n/// [`FromForm`]: crate::form::FromForm\n/// [push parser]: crate::form::FromForm#push-parsing\n/// [`ContentType::Form`]: crate::http::ContentType::Form\n/// [`ContentType::FormData`]: crate::http::ContentType::FormData\n///\n/// ## Async Trait\n///\n/// [`FromData`] is an _async_ trait. Implementations of `FromData` must be\n/// decorated with an attribute of `#[rocket::async_trait]`:\n///\n/// ```rust\n/// use rocket::request::Request;\n/// use rocket::data::{self, Data, FromData};\n/// # struct MyType;\n/// # type MyError = String;\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromData<'r> for MyType {\n///     type Error = MyError;\n///\n///     async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {\n///         /* .. */\n///         # unimplemented!()\n///     }\n/// }\n/// ```\n///\n/// # Example\n///\n/// Say that you have a custom type, `Person`:\n///\n/// ```rust\n/// struct Person<'r> {\n///     name: &'r str,\n///     age: u16\n/// }\n/// ```\n///\n/// `Person` has a custom serialization format, so the built-in `Json` type\n/// doesn't suffice. The format is `<name>:<age>` with `Content-Type:\n/// application/x-person`. You'd like to use `Person` as a data guard, so that\n/// you can retrieve it directly from a client's request body:\n///\n/// ```rust\n/// # use rocket::post;\n/// # type Person<'r> = &'r rocket::http::RawStr;\n/// #[post(\"/person\", data = \"<person>\")]\n/// fn person(person: Person<'_>) -> &'static str {\n///     \"Saved the new person to the database!\"\n/// }\n/// ```\n///\n/// A `FromData` implementation for such a type might look like:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// # #[derive(Debug)]\n/// # struct Person<'r> { name: &'r str, age: u16 }\n/// #\n/// use rocket::request::{self, Request};\n/// use rocket::data::{self, Data, FromData, ToByteUnit};\n/// use rocket::http::{Status, ContentType};\n/// use rocket::outcome::Outcome;\n///\n/// #[derive(Debug)]\n/// enum Error {\n///     TooLarge,\n///     NoColon,\n///     InvalidAge,\n///     Io(std::io::Error),\n/// }\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromData<'r> for Person<'r> {\n///     type Error = Error;\n///\n///     async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {\n///         use Error::*;\n///\n///         // Ensure the content type is correct before opening the data.\n///         let person_ct = ContentType::new(\"application\", \"x-person\");\n///         if req.content_type() != Some(&person_ct) {\n///             return Outcome::Forward((data, Status::UnsupportedMediaType));\n///         }\n///\n///         // Use a configured limit with name 'person' or fallback to default.\n///         let limit = req.limits().get(\"person\").unwrap_or(256.bytes());\n///\n///         // Read the data into a string.\n///         let string = match data.open(limit).into_string().await {\n///             Ok(string) if string.is_complete() => string.into_inner(),\n///             Ok(_) => return Outcome::Error((Status::PayloadTooLarge, TooLarge)),\n///             Err(e) => return Outcome::Error((Status::InternalServerError, Io(e))),\n///         };\n///\n///         // We store `string` in request-local cache for long-lived borrows.\n///         let string = request::local_cache!(req, string);\n///\n///         // Split the string into two pieces at ':'.\n///         let (name, age) = match string.find(':') {\n///             Some(i) => (&string[..i], &string[(i + 1)..]),\n///             None => return Outcome::Error((Status::UnprocessableEntity, NoColon)),\n///         };\n///\n///         // Parse the age.\n///         let age: u16 = match age.parse() {\n///             Ok(age) => age,\n///             Err(_) => return Outcome::Error((Status::UnprocessableEntity, InvalidAge)),\n///         };\n///\n///         Outcome::Success(Person { name, age })\n///     }\n/// }\n///\n/// // The following routes now typecheck...\n///\n/// #[post(\"/person\", data = \"<person>\")]\n/// fn person(person: Person<'_>) { /* .. */ }\n///\n/// #[post(\"/person\", data = \"<person>\")]\n/// fn person2(person: Result<Person<'_>, Error>) { /* .. */ }\n///\n/// #[post(\"/person\", data = \"<person>\")]\n/// fn person3(person: Option<Person<'_>>) { /* .. */ }\n///\n/// #[post(\"/person\", data = \"<person>\")]\n/// fn person4(person: Person<'_>) -> &str {\n///     // Note that this is only possible because the data in `person` live\n///     // as long as the request through request-local cache.\n///     person.name\n/// }\n/// ```\n#[crate::async_trait]\npub trait FromData<'r>: Sized {\n    /// The associated error to be returned when the guard fails.\n    type Error: Send + std::fmt::Debug;\n\n    /// Asynchronously validates, parses, and converts an instance of `Self`\n    /// from the incoming request body data.\n    ///\n    /// If validation and parsing succeeds, an outcome of `Success` is returned.\n    /// If the data is not appropriate given the type of `Self`, `Forward` is\n    /// returned. If parsing fails, `Error` is returned.\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self>;\n}\n\nuse crate::data::Capped;\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Capped<String> {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        let limit = req.limits().get(\"string\").unwrap_or(Limits::STRING);\n        data.open(limit).into_string().await.or_error(Status::BadRequest)\n    }\n}\n\nimpl_strict_from_data_from_capped!(String);\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Capped<&'r str> {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        let capped = try_outcome!(<Capped<String>>::from_data(req, data).await);\n        let string = capped.map(|s| local_cache!(req, s));\n        Success(string)\n    }\n}\n\nimpl_strict_from_data_from_capped!(&'r str);\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Capped<&'r RawStr> {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        let capped = try_outcome!(<Capped<String>>::from_data(req, data).await);\n        let raw = capped.map(|s| RawStr::new(local_cache!(req, s)));\n        Success(raw)\n    }\n}\n\nimpl_strict_from_data_from_capped!(&'r RawStr);\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Capped<std::borrow::Cow<'_, str>> {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        let capped = try_outcome!(<Capped<String>>::from_data(req, data).await);\n        Success(capped.map(|s| s.into()))\n    }\n}\n\nimpl_strict_from_data_from_capped!(std::borrow::Cow<'_, str>);\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Capped<&'r [u8]> {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        let capped = try_outcome!(<Capped<Vec<u8>>>::from_data(req, data).await);\n        let raw = capped.map(|b| local_cache!(req, b));\n        Success(raw)\n    }\n}\n\nimpl_strict_from_data_from_capped!(&'r [u8]);\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Capped<Vec<u8>> {\n    type Error = std::io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        let limit = req.limits().get(\"bytes\").unwrap_or(Limits::BYTES);\n        data.open(limit).into_bytes().await.or_error(Status::BadRequest)\n    }\n}\n\nimpl_strict_from_data_from_capped!(Vec<u8>);\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Data<'r> {\n    type Error = std::convert::Infallible;\n\n    async fn from_data(_: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        Success(data)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: FromData<'r> + 'r> FromData<'r> for Result<T, T::Error> {\n    type Error = std::convert::Infallible;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        match T::from_data(req, data).await {\n            Success(v) => Success(Ok(v)),\n            Error((_, e)) => Success(Err(e)),\n            Forward(d) => Forward(d),\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: FromData<'r>> FromData<'r> for Option<T> {\n    type Error = std::convert::Infallible;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        match T::from_data(req, data).await {\n            Success(v) => Success(Some(v)),\n            Error(..) | Forward(..) => Success(None),\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/data/io_stream.rs",
    "content": "use std::io;\nuse std::task::{Context, Poll};\nuse std::pin::Pin;\n\nuse tokio::io::{AsyncRead, AsyncWrite, ReadBuf};\nuse hyper::upgrade::Upgraded;\nuse hyper_util::rt::TokioIo;\n\n/// A bidirectional, raw stream to the client.\n///\n/// An instance of `IoStream` is passed to an [`IoHandler`] in response to a\n/// successful upgrade request initiated by responders via\n/// [`Response::add_upgrade()`] or the equivalent builder method\n/// [`Builder::upgrade()`]. For details on upgrade connections, see\n/// [`Response`#upgrading].\n///\n/// An `IoStream` is guaranteed to be [`AsyncRead`], [`AsyncWrite`], and\n/// `Unpin`. Bytes written to the stream are sent directly to the client. Bytes\n/// read from the stream are those sent directly _by_ the client. See\n/// [`IoHandler`] for one example of how values of this type are used.\n///\n/// [`Response::add_upgrade()`]: crate::Response::add_upgrade()\n/// [`Builder::upgrade()`]: crate::response::Builder::upgrade()\n/// [`Response`#upgrading]: crate::response::Response#upgrading\npub struct IoStream {\n    kind: IoStreamKind,\n}\n\n/// Just in case we want to add stream kinds in the future.\nenum IoStreamKind {\n    Upgraded(TokioIo<Upgraded>)\n}\n\n/// An upgraded connection I/O handler.\n///\n/// An I/O handler performs raw I/O via the passed in [`IoStream`], which is\n/// [`AsyncRead`], [`AsyncWrite`], and `Unpin`.\n///\n/// # Example\n///\n/// The example below implements an `EchoHandler` that echos the raw bytes back\n/// to the client.\n///\n/// ```rust\n/// use std::pin::Pin;\n///\n/// use rocket::tokio::io;\n/// use rocket::data::{IoHandler, IoStream};\n///\n/// struct EchoHandler;\n///\n/// #[rocket::async_trait]\n/// impl IoHandler for EchoHandler {\n///     async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {\n///         let (mut reader, mut writer) = io::split(io);\n///         io::copy(&mut reader, &mut writer).await?;\n///         Ok(())\n///     }\n/// }\n///\n/// # use rocket::Response;\n/// # rocket::async_test(async {\n/// # let mut response = Response::new();\n/// # response.add_upgrade(\"raw-echo\", EchoHandler);\n/// # assert!(response.upgrade(\"raw-echo\").is_some());\n/// # })\n/// ```\n#[crate::async_trait]\npub trait IoHandler: Send {\n    /// Performs the raw I/O.\n    async fn io(self: Box<Self>, io: IoStream) -> io::Result<()>;\n}\n\n#[crate::async_trait]\nimpl IoHandler for () {\n    async fn io(self: Box<Self>, _: IoStream) -> io::Result<()> {\n        Ok(())\n    }\n}\n\n#[doc(hidden)]\nimpl From<Upgraded> for IoStream {\n    fn from(io: Upgraded) -> Self {\n        IoStream { kind: IoStreamKind::Upgraded(TokioIo::new(io)) }\n    }\n}\n\n/// A \"trait alias\" of sorts so we can use `AsyncRead + AsyncWrite + Unpin` in `dyn`.\npub trait AsyncReadWrite: AsyncRead + AsyncWrite + Unpin { }\n\n/// Implemented for all `AsyncRead + AsyncWrite + Unpin`, of course.\nimpl<T: AsyncRead + AsyncWrite + Unpin> AsyncReadWrite for T {  }\n\nimpl IoStream {\n    /// Returns the internal I/O stream.\n    fn inner_mut(&mut self) -> Pin<&mut dyn AsyncReadWrite> {\n        match self.kind {\n            IoStreamKind::Upgraded(ref mut io) => Pin::new(io),\n        }\n    }\n\n    /// Returns `true` if the inner I/O stream is write vectored.\n    fn inner_is_write_vectored(&self) -> bool {\n        match self.kind {\n            IoStreamKind::Upgraded(ref io) => io.is_write_vectored(),\n        }\n    }\n}\n\nimpl AsyncRead for IoStream {\n    fn poll_read(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        self.get_mut().inner_mut().poll_read(cx, buf)\n    }\n}\n\nimpl AsyncWrite for IoStream {\n    fn poll_write(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &[u8],\n    ) -> Poll<io::Result<usize>> {\n        self.get_mut().inner_mut().poll_write(cx, buf)\n    }\n\n    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {\n        self.get_mut().inner_mut().poll_flush(cx)\n    }\n\n    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {\n        self.get_mut().inner_mut().poll_shutdown(cx)\n    }\n\n    fn poll_write_vectored(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        bufs: &[io::IoSlice<'_>],\n    ) -> Poll<io::Result<usize>> {\n        self.get_mut().inner_mut().poll_write_vectored(cx, bufs)\n    }\n\n    fn is_write_vectored(&self) -> bool {\n        self.inner_is_write_vectored()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn is_unpin() {\n        fn check_traits<T: AsyncRead + AsyncWrite + Unpin + Send>() {}\n        check_traits::<IoStream>();\n    }\n}\n"
  },
  {
    "path": "core/lib/src/data/limits.rs",
    "content": "use serde::{Serialize, Deserialize};\nuse crate::request::{Request, FromRequest, Outcome};\n\nuse crate::data::ByteUnit;\nuse crate::http::uncased::Uncased;\n\n/// Mapping from (hierarchical) data types to size limits.\n///\n/// A `Limits` structure contains a mapping from a given hierarchical data type\n/// (\"form\", \"data-form\", \"ext/pdf\", and so on) to the maximum size in bytes\n/// that should be accepted by Rocket for said data type. For instance, if the\n/// limit for \"form\" is set to `256`, only 256 bytes from an incoming non-data\n/// form (that is, url-encoded) will be accepted.\n///\n/// To help in preventing DoS attacks, all incoming data reads must capped by a\n/// limit. As such, all data guards impose a limit. The _name_ of the limit is\n/// dictated by the data guard or type itself. For instance, [`Form`] imposes\n/// the `form` limit for value-based forms and `data-form` limit for data-based\n/// forms.\n///\n/// If a limit is exceeded, a guard will typically fail. The [`Capped`] type\n/// allows retrieving some data types even when the limit is exceeded.\n///\n/// [`Capped`]: crate::data::Capped\n/// [`Form`]: crate::form::Form\n///\n/// # Hierarchy\n///\n/// Data limits are hierarchical. The `/` (forward slash) character delimits the\n/// levels, or layers, of a given limit. To obtain a limit value for a given\n/// name, layers are peeled from right to left until a match is found, if any.\n/// For example, fetching the limit named `pet/dog/bingo` will return the first\n/// of `pet/dog/bingo`, `pet/dog` or `pet`:\n///\n/// ```rust\n/// use rocket::data::{Limits, ToByteUnit};\n///\n/// let limits = Limits::default()\n///     .limit(\"pet\", 64.kibibytes())\n///     .limit(\"pet/dog\", 128.kibibytes())\n///     .limit(\"pet/dog/bingo\", 96.kibibytes());\n///\n/// assert_eq!(limits.get(\"pet/dog/bingo\"), Some(96.kibibytes()));\n/// assert_eq!(limits.get(\"pet/dog/ralph\"), Some(128.kibibytes()));\n/// assert_eq!(limits.get(\"pet/cat/bingo\"), Some(64.kibibytes()));\n///\n/// assert_eq!(limits.get(\"pet/dog/bingo/hat\"), Some(96.kibibytes()));\n/// ```\n///\n/// # Built-in Limits\n///\n/// The following table details recognized built-in limits used by Rocket.\n///\n/// | Limit Name        | Default | Type         | Description                           |\n/// |-------------------|---------|--------------|---------------------------------------|\n/// | `form`            | 32KiB   | [`Form`]     | entire non-data-based form            |\n/// | `data-form`       | 2MiB    | [`Form`]     | entire data-based form                |\n/// | `file`            | 1MiB    | [`TempFile`] | [`TempFile`] data guard or form field |\n/// | `file/$ext`       | _N/A_   | [`TempFile`] | file form field with extension `$ext` |\n/// | `string`          | 8KiB    | [`String`]   | data guard or form field              |\n/// | `string`          | 8KiB    | [`&str`]     | data guard or form field              |\n/// | `bytes`           | 8KiB    | [`Vec<u8>`]  | data guard                            |\n/// | `bytes`           | 8KiB    | [`&[u8]`]    | data guard or form field              |\n/// | `json`            | 1MiB    | [`Json`]     | JSON data and form payloads           |\n/// | `msgpack`         | 1MiB    | [`MsgPack`]  | MessagePack data and form payloads    |\n///\n/// [`TempFile`]: crate::fs::TempFile\n/// [`Json`]: crate::serde::json::Json\n/// [`MsgPack`]: crate::serde::msgpack::MsgPack\n///\n/// # Usage\n///\n/// A `Limits` structure is created following the builder pattern:\n///\n/// ```rust\n/// use rocket::data::{Limits, ToByteUnit};\n///\n/// // Set a limit of 64KiB for forms, 3MiB for PDFs, and 1MiB for JSON.\n/// let limits = Limits::default()\n///     .limit(\"form\", 64.kibibytes())\n///     .limit(\"file/pdf\", 3.mebibytes())\n///     .limit(\"json\", 2.mebibytes());\n/// ```\n///\n/// The [`Limits::default()`](#impl-Default) method populates the `Limits`\n/// structure with default limits in the [table above](#built-in-limits). A\n/// configured limit can be retrieved via the `&Limits` request guard:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use std::io;\n///\n/// use rocket::data::{Data, Limits, ToByteUnit};\n///\n/// #[post(\"/echo\", data = \"<data>\")]\n/// async fn echo(data: Data<'_>, limits: &Limits) -> io::Result<String> {\n///     let limit = limits.get(\"data\").unwrap_or(1.mebibytes());\n///     Ok(data.open(limit).into_string().await?.value)\n/// }\n/// ```\n///\n/// ...or via the [`Request::limits()`] method:\n///\n/// ```\n/// # #[macro_use] extern crate rocket;\n/// use rocket::request::Request;\n/// use rocket::data::{self, Data, FromData};\n///\n/// # struct MyType;\n/// # type MyError = ();\n/// #[rocket::async_trait]\n/// impl<'r> FromData<'r> for MyType {\n///     type Error = MyError;\n///\n///     async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {\n///         let limit = req.limits().get(\"my-data-type\");\n///         /* .. */\n///         # unimplemented!()\n///     }\n/// }\n/// ```\n#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]\n#[serde(transparent)]\npub struct Limits {\n    #[serde(deserialize_with = \"Limits::deserialize\")]\n    #[serde(serialize_with = \"figment::util::vec_tuple_map::serialize\")]\n    pub(crate) limits: Vec<(Uncased<'static>, ByteUnit)>,\n}\n\nimpl Default for Limits {\n    fn default() -> Limits {\n        Limits::new()\n            .limit(\"form\", Limits::FORM)\n            .limit(\"data-form\", Limits::DATA_FORM)\n            .limit(\"file\", Limits::FILE)\n            .limit(\"string\", Limits::STRING)\n            .limit(\"bytes\", Limits::BYTES)\n            .limit(\"json\", Limits::JSON)\n            .limit(\"msgpack\", Limits::MESSAGE_PACK)\n    }\n}\n\nimpl Limits {\n    /// Default limit for value-based forms.\n    pub const FORM: ByteUnit = ByteUnit::Kibibyte(32);\n\n    /// Default limit for data-based forms.\n    pub const DATA_FORM: ByteUnit = ByteUnit::Mebibyte(2);\n\n    /// Default limit for temporary files.\n    pub const FILE: ByteUnit = ByteUnit::Mebibyte(1);\n\n    /// Default limit for strings.\n    pub const STRING: ByteUnit = ByteUnit::Kibibyte(8);\n\n    /// Default limit for bytes.\n    pub const BYTES: ByteUnit = ByteUnit::Kibibyte(8);\n\n    /// Default limit for JSON payloads.\n    pub const JSON: ByteUnit = ByteUnit::Mebibyte(1);\n\n    /// Default limit for MessagePack payloads.\n    pub const MESSAGE_PACK: ByteUnit = ByteUnit::Mebibyte(1);\n\n    /// Construct a new `Limits` structure with no limits set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Limits, ToByteUnit};\n    ///\n    /// let limits = Limits::default();\n    /// assert_eq!(limits.get(\"form\"), Some(32.kibibytes()));\n    ///\n    /// let limits = Limits::new();\n    /// assert_eq!(limits.get(\"form\"), None);\n    /// ```\n    #[inline]\n    pub fn new() -> Self {\n        Limits { limits: vec![] }\n    }\n\n    /// Adds or replaces a limit in `self`, consuming `self` and returning a new\n    /// `Limits` structure with the added or replaced limit.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Limits, ToByteUnit};\n    ///\n    /// let limits = Limits::default();\n    /// assert_eq!(limits.get(\"form\"), Some(32.kibibytes()));\n    /// assert_eq!(limits.get(\"json\"), Some(1.mebibytes()));\n    /// assert_eq!(limits.get(\"cat\"), None);\n    ///\n    /// let limits = limits.limit(\"cat\", 1.mebibytes());\n    /// assert_eq!(limits.get(\"form\"), Some(32.kibibytes()));\n    /// assert_eq!(limits.get(\"cat\"), Some(1.mebibytes()));\n    ///\n    /// let limits = limits.limit(\"json\", 64.mebibytes());\n    /// assert_eq!(limits.get(\"json\"), Some(64.mebibytes()));\n    /// ```\n    pub fn limit<S: Into<Uncased<'static>>>(mut self, name: S, limit: ByteUnit) -> Self {\n        let name = name.into();\n        match self.limits.binary_search_by(|(k, _)| k.cmp(&name)) {\n            Ok(i) => self.limits[i].1 = limit,\n            Err(i) => self.limits.insert(i, (name, limit))\n        }\n\n        self\n    }\n\n    /// Returns the limit named `name`, proceeding hierarchically from right\n    /// to left until one is found, or returning `None` if none is found.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Limits, ToByteUnit};\n    ///\n    /// let limits = Limits::default()\n    ///     .limit(\"json\", 2.mebibytes())\n    ///     .limit(\"file/jpeg\", 4.mebibytes())\n    ///     .limit(\"file/jpeg/special\", 8.mebibytes());\n    ///\n    /// assert_eq!(limits.get(\"form\"), Some(32.kibibytes()));\n    /// assert_eq!(limits.get(\"json\"), Some(2.mebibytes()));\n    /// assert_eq!(limits.get(\"data-form\"), Some(Limits::DATA_FORM));\n    ///\n    /// assert_eq!(limits.get(\"file\"), Some(1.mebibytes()));\n    /// assert_eq!(limits.get(\"file/png\"), Some(1.mebibytes()));\n    /// assert_eq!(limits.get(\"file/jpeg\"), Some(4.mebibytes()));\n    /// assert_eq!(limits.get(\"file/jpeg/inner\"), Some(4.mebibytes()));\n    /// assert_eq!(limits.get(\"file/jpeg/special\"), Some(8.mebibytes()));\n    ///\n    /// assert!(limits.get(\"cats\").is_none());\n    /// ```\n    pub fn get<S: AsRef<str>>(&self, name: S) -> Option<ByteUnit> {\n        let mut name = name.as_ref();\n        let mut indices = name.rmatch_indices('/');\n        loop {\n            let exact_limit = self.limits\n                .binary_search_by(|(k, _)| k.as_uncased_str().cmp(name.into()))\n                .map(|i| self.limits[i].1);\n\n            if let Ok(exact) = exact_limit {\n                return Some(exact);\n            }\n\n            let (i, _) = indices.next()?;\n            name = &name[..i];\n        }\n    }\n\n    /// Returns the limit for the name created by joining the strings in\n    /// `layers` with `/` as a separator, then proceeding like\n    /// [`Limits::get()`], hierarchically from right to left until one is found,\n    /// or returning `None` if none is found.\n    ///\n    /// This methods exists to allow finding hierarchical limits without\n    /// constructing a string to call `get()` with but otherwise returns the\n    /// same results.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::{Limits, ToByteUnit};\n    ///\n    /// let limits = Limits::default()\n    ///     .limit(\"json\", 2.mebibytes())\n    ///     .limit(\"file/jpeg\", 4.mebibytes())\n    ///     .limit(\"file/jpeg/special\", 8.mebibytes());\n    ///\n    /// assert_eq!(limits.find([\"json\"]), Some(2.mebibytes()));\n    /// assert_eq!(limits.find([\"json\", \"person\"]), Some(2.mebibytes()));\n    ///\n    /// assert_eq!(limits.find([\"file\"]), Some(1.mebibytes()));\n    /// assert_eq!(limits.find([\"file\", \"png\"]), Some(1.mebibytes()));\n    /// assert_eq!(limits.find([\"file\", \"jpeg\"]), Some(4.mebibytes()));\n    /// assert_eq!(limits.find([\"file\", \"jpeg\", \"inner\"]), Some(4.mebibytes()));\n    /// assert_eq!(limits.find([\"file\", \"jpeg\", \"special\"]), Some(8.mebibytes()));\n    ///\n    /// # let s: &[&str] = &[]; assert_eq!(limits.find(s), None);\n    /// ```\n    pub fn find<S: AsRef<str>, L: AsRef<[S]>>(&self, layers: L) -> Option<ByteUnit> {\n        let layers = layers.as_ref();\n        for j in (1..=layers.len()).rev() {\n            let layers = &layers[..j];\n            let opt = self.limits\n                .binary_search_by(|(k, _)| {\n                    let k_layers = k.as_str().split('/');\n                    k_layers.cmp(layers.iter().map(|s| s.as_ref()))\n                })\n                .map(|i| self.limits[i].1);\n\n            if let Ok(byte_unit) = opt {\n                return Some(byte_unit);\n            }\n        }\n\n        None\n    }\n\n    /// Deserialize a `Limits` vector from a map. Ensures that the resulting\n    /// vector is properly sorted for futures lookups via binary search.\n    fn deserialize<'de, D>(de: D) -> Result<Vec<(Uncased<'static>, ByteUnit)>, D::Error>\n        where D: serde::Deserializer<'de>\n    {\n        let mut limits = figment::util::vec_tuple_map::deserialize(de)?;\n        limits.sort();\n        Ok(limits)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r Limits {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n        Outcome::Success(req.limits())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/data/mod.rs",
    "content": "//! Types and traits for handling incoming body data.\n\n#[macro_use]\nmod capped;\nmod data;\nmod data_stream;\nmod from_data;\nmod limits;\nmod io_stream;\nmod transform;\nmod peekable;\n\npub use self::data::Data;\npub use self::data_stream::DataStream;\npub use self::from_data::{FromData, Outcome};\npub use self::limits::Limits;\npub use self::capped::{N, Capped};\npub use self::io_stream::{IoHandler, IoStream};\npub use ubyte::{ByteUnit, ToByteUnit};\npub use self::transform::{Transform, TransformBuf};\n\npub(crate) use self::data_stream::RawStream;\n"
  },
  {
    "path": "core/lib/src/data/peekable.rs",
    "content": "use tokio::io::{AsyncRead, AsyncReadExt};\n\npub struct Peekable<const N: usize, R> {\n    pub(crate) buffer: Vec<u8>,\n    pub(crate) complete: bool,\n    pub(crate) reader: R,\n}\n\nimpl<const N: usize, R: AsyncRead + Unpin> Peekable<N, R> {\n    pub fn new(reader: R) -> Self {\n        Self { buffer: Vec::new(), complete: false, reader }\n    }\n\n    pub fn with_buffer(buffer: Vec<u8>, complete: bool, reader: R) -> Self {\n        Self { buffer, complete, reader }\n    }\n\n    pub async fn peek(&mut self, num: usize) -> &[u8] {\n        if self.complete {\n            return self.buffer.as_slice();\n        }\n\n        let to_read = std::cmp::min(N, num);\n        if self.buffer.len() >= to_read {\n            return self.buffer.as_slice();\n        }\n\n        if self.buffer.capacity() == 0 {\n            self.buffer.reserve(N);\n        }\n\n        while self.buffer.len() < to_read {\n            match self.reader.read_buf::<Vec<u8>>(&mut self.buffer).await {\n                Ok(0) => {\n                    self.complete = self.buffer.capacity() > self.buffer.len();\n                    break;\n                },\n                Ok(_) => { /* continue */ },\n                Err(e) => {\n                    error!(\"failed to read into peek buffer: {:?}.\", e);\n                    break;\n                }\n            }\n        }\n\n        self.buffer.as_slice()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/data/transform.rs",
    "content": "use std::io;\nuse std::ops::{Deref, DerefMut};\nuse std::pin::Pin;\nuse std::task::{Poll, Context};\n\nuse tokio::io::ReadBuf;\n\n/// Chainable, in-place, streaming data transformer.\n///\n/// [`Transform`] operates on [`TransformBuf`]s similar to how [`AsyncRead`]\n/// operats on [`ReadBuf`]. A [`Transform`] sits somewhere in a chain of\n/// transforming readers. The head (most upstream part) of the chain is _always_\n/// an [`AsyncRead`]: the data source. The tail (all downstream parts) is\n/// composed _only_ of other [`Transform`]s:\n///\n/// ```text\n///                          downstream --->\n///  AsyncRead | Transform | .. | Transform\n/// <---- upstream\n/// ```\n///\n/// When the upstream source makes data available, the\n/// [`Transform::transform()`] method is called. [`Transform`]s may obtain the\n/// subset of the filled section added by an upstream data source with\n/// [`TransformBuf::fresh()`]. They may modify this data at will, potentially\n/// changing the size of the filled section. For example,\n/// [`TransformBuf::spoil()`] \"removes\" all of the fresh data, and\n/// [`TransformBuf::fresh_mut()`] can be used to modify the data in-place.\n///\n/// Additionally, new data may be added in-place via the traditional approach:\n/// write to (or overwrite) the initialized section of the buffer and mark it as\n/// filled. All of the remaining filled data will be passed to downstream\n/// transforms as \"fresh\" data. To add data to the end of the (potentially\n/// rewritten) stream, the [`Transform::poll_finish()`] method can be\n/// implemented.\n///\n/// [`AsyncRead`]: tokio::io::AsyncRead\npub trait Transform {\n    /// Called when data is read from the upstream source. For any given fresh\n    /// data, this method is called only once. [`TransformBuf::fresh()`] is\n    /// guaranteed to contain at least one byte.\n    ///\n    /// While this method is not _async_ (it does not return [`Poll`]), it is\n    /// nevertheless executed in an async context and should respect all such\n    /// restrictions including not blocking.\n    fn transform(\n        self: Pin<&mut Self>,\n        buf: &mut TransformBuf<'_, '_>,\n    ) -> io::Result<()>;\n\n    /// Called when the upstream is finished, that is, it has no more data to\n    /// fill. At this point, the transform becomes an async reader. This method\n    /// thus has identical semantics to [`AsyncRead::poll_read()`]. This method\n    /// may never be called if the upstream does not finish.\n    ///\n    /// The default implementation returns `Poll::Ready(Ok(()))`.\n    ///\n    /// [`AsyncRead::poll_read()`]: tokio::io::AsyncRead::poll_read()\n    fn poll_finish(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        let (_, _) = (cx, buf);\n        Poll::Ready(Ok(()))\n    }\n}\n\n/// A buffer of transformable streaming data.\n///\n/// # Overview\n///\n/// A byte buffer, similar to a [`ReadBuf`], with a \"fresh\" dimension. Fresh\n/// data is always a subset of the filled data, filled data is always a subset\n/// of initialized data, and initialized data is always a subset of the buffer\n/// itself. Both the filled and initialized data sections are guaranteed to be\n/// at the start of the buffer, but the fresh subset is likely to begin\n/// somewhere inside the filled section.\n///\n/// To visualize this, the diagram below represents a possible state for the\n/// byte buffer being tracked. The square `[ ]` brackets represent the complete\n/// buffer, while the curly `{ }` represent the named subset.\n///\n/// ```text\n/// [  { !! fresh !! }                                 ]\n/// { +++ filled +++ }          unfilled               ]\n/// { ----- initialized ------ }     uninitialized     ]\n/// [                    capacity                      ]\n/// ```\n///\n/// The same buffer represented in its true single dimension is below:\n///\n/// ```text\n/// [ ++!!!!!!!!!!!!!!---------xxxxxxxxxxxxxxxxxxxxxxxx]\n/// ```\n///\n/// * `+`: filled (implies initialized)\n/// * `!`: fresh (implies filled)\n/// * `-`: unfilled / initialized (implies initialized)\n/// * `x`: uninitialized (implies unfilled)\n///\n/// As with [`ReadBuf`], [`AsyncRead`] readers fill the initialized portion of a\n/// [`TransformBuf`] to indicate that data is available. _Filling_ initialized\n/// portions of the byte buffers is what increases the size of the _filled_\n/// section. Because a [`ReadBuf`] may already be partially filled when a reader\n/// adds bytes to it, a mechanism to track where the _newly_ filled portion\n/// exists is needed. This is exactly what the \"fresh\" section tracks.\n///\n/// [`AsyncRead`]: tokio::io::AsyncRead\npub struct TransformBuf<'a, 'b> {\n    pub(crate) buf: &'a mut ReadBuf<'b>,\n    pub(crate) cursor: usize,\n}\n\nimpl TransformBuf<'_, '_> {\n    /// Returns a borrow to the fresh data: data filled by the upstream source.\n    pub fn fresh(&self) -> &[u8] {\n        &self.filled()[self.cursor..]\n    }\n\n    /// Returns a mutable borrow to the fresh data: data filled by the upstream\n    /// source.\n    pub fn fresh_mut(&mut self) -> &mut [u8] {\n        let cursor = self.cursor;\n        &mut self.filled_mut()[cursor..]\n    }\n\n    /// Spoils the fresh data by resetting the filled section to its value\n    /// before any new data was added. As a result, the data will never be seen\n    /// by any downstream consumer unless it is returned via another mechanism.\n    pub fn spoil(&mut self) {\n        let cursor = self.cursor;\n        self.set_filled(cursor);\n    }\n}\n\npub struct Inspect(pub(crate) Box<dyn FnMut(&[u8]) + Send + Sync + 'static>);\n\nimpl Transform for Inspect {\n    fn transform(mut self: Pin<&mut Self>, buf: &mut TransformBuf<'_, '_>) -> io::Result<()> {\n        (self.0)(buf.fresh());\n        Ok(())\n    }\n}\n\npub struct InPlaceMap(\n    pub(crate) Box<dyn FnMut(&mut TransformBuf<'_, '_>) -> io::Result<()> + Send + Sync + 'static>\n);\n\nimpl Transform for InPlaceMap {\n    fn transform(mut self: Pin<&mut Self>, buf: &mut TransformBuf<'_, '_>,) -> io::Result<()> {\n        (self.0)(buf)\n    }\n}\n\nimpl<'a, 'b> Deref for TransformBuf<'a, 'b> {\n    type Target = ReadBuf<'b>;\n\n    fn deref(&self) -> &Self::Target {\n        self.buf\n    }\n}\n\nimpl<'a, 'b> DerefMut for TransformBuf<'a, 'b> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        self.buf\n    }\n}\n\n// TODO: Test chaining various transform combinations:\n//  * consume | consume\n//  * add | consume\n//  * consume | add\n//  * add | add\n// Where `add` is a transformer that adds data to the stream, and `consume` is\n// one that removes data.\n#[cfg(test)]\n#[allow(deprecated)]\nmod tests {\n    use std::hash::SipHasher;\n    use std::sync::{Arc, atomic::{AtomicU8, AtomicU64, Ordering}};\n\n    use parking_lot::Mutex;\n    use ubyte::ToByteUnit;\n\n    use crate::http::Method;\n    use crate::local::blocking::Client;\n    use crate::fairing::AdHoc;\n    use crate::{route, Route, Data, Response, Request};\n\n    mod hash_transform {\n        use std::io::Cursor;\n        use std::hash::Hasher;\n\n        use tokio::io::AsyncRead;\n\n        use super::super::*;\n\n        pub struct HashTransform<H: Hasher> {\n            pub(crate) hasher: H,\n            pub(crate) hash: Option<Cursor<[u8; 8]>>\n        }\n\n        impl<H: Hasher + Unpin> Transform for HashTransform<H> {\n            fn transform(\n                mut self: Pin<&mut Self>,\n                buf: &mut TransformBuf<'_, '_>,\n            ) -> io::Result<()> {\n                self.hasher.write(buf.fresh());\n                buf.spoil();\n                Ok(())\n            }\n\n            fn poll_finish(\n                mut self: Pin<&mut Self>,\n                cx: &mut Context<'_>,\n                buf: &mut ReadBuf<'_>,\n            ) -> Poll<io::Result<()>> {\n                if self.hash.is_none() {\n                    let hash = self.hasher.finish();\n                    self.hash = Some(Cursor::new(hash.to_be_bytes()));\n                }\n\n                let cursor = self.hash.as_mut().unwrap();\n                Pin::new(cursor).poll_read(cx, buf)\n            }\n        }\n\n        impl crate::Data<'_> {\n            /// Chain an in-place hash [`Transform`] to `self`.\n            pub fn chain_hash_transform<H: std::hash::Hasher>(&mut self, hasher: H) -> &mut Self\n                where H: Unpin + Send + Sync + 'static\n            {\n                self.chain_transform(HashTransform { hasher, hash: None })\n            }\n        }\n    }\n\n    #[test]\n    fn test_transform_series() {\n        fn handler<'r>(_: &'r Request<'_>, data: Data<'r>) -> route::BoxFuture<'r> {\n            Box::pin(async move {\n                data.open(128.bytes()).stream_to(tokio::io::sink()).await.expect(\"read ok\");\n                route::Outcome::Success(Response::new())\n            })\n        }\n\n        let inspect2: Arc<AtomicU8> = Arc::new(AtomicU8::new(0));\n        let raw_data: Arc<Mutex<Vec<u8>>> = Arc::new(Mutex::new(Vec::new()));\n        let hash: Arc<AtomicU64> = Arc::new(AtomicU64::new(0));\n        let rocket = crate::build()\n            .manage(hash.clone())\n            .manage(raw_data.clone())\n            .manage(inspect2.clone())\n            .mount(\"/\", vec![Route::new(Method::Post, \"/\", handler)])\n            .attach(AdHoc::on_request(\"transforms\", |req, data| Box::pin(async {\n                let hash1 = req.rocket().state::<Arc<AtomicU64>>().cloned().unwrap();\n                let hash2 = req.rocket().state::<Arc<AtomicU64>>().cloned().unwrap();\n                let raw_data = req.rocket().state::<Arc<Mutex<Vec<u8>>>>().cloned().unwrap();\n                let inspect2 = req.rocket().state::<Arc<AtomicU8>>().cloned().unwrap();\n                data.chain_inspect(move |bytes| { *raw_data.lock() = bytes.to_vec(); })\n                    .chain_hash_transform(SipHasher::new())\n                    .chain_inspect(move |bytes| {\n                        assert_eq!(bytes.len(), 8);\n                        let bytes: [u8; 8] = bytes.try_into().expect(\"[u8; 8]\");\n                        let value = u64::from_be_bytes(bytes);\n                        hash1.store(value, Ordering::Release);\n                    })\n                    .chain_inspect(move |bytes| {\n                        assert_eq!(bytes.len(), 8);\n                        let bytes: [u8; 8] = bytes.try_into().expect(\"[u8; 8]\");\n                        let value = u64::from_be_bytes(bytes);\n                        let prev = hash2.load(Ordering::Acquire);\n                        assert_eq!(prev, value);\n                        inspect2.fetch_add(1, Ordering::Release);\n                    });\n            })));\n\n        // Make sure nothing has happened yet.\n        assert!(raw_data.lock().is_empty());\n        assert_eq!(hash.load(Ordering::Acquire), 0);\n        assert_eq!(inspect2.load(Ordering::Acquire), 0);\n\n        // Check that nothing happens if the data isn't read.\n        let client = Client::debug(rocket).unwrap();\n        client.get(\"/\").body(\"Hello, world!\").dispatch();\n        assert!(raw_data.lock().is_empty());\n        assert_eq!(hash.load(Ordering::Acquire), 0);\n        assert_eq!(inspect2.load(Ordering::Acquire), 0);\n\n        // Check inspect + hash + inspect + inspect.\n        client.post(\"/\").body(\"Hello, world!\").dispatch();\n        assert_eq!(raw_data.lock().as_slice(), \"Hello, world!\".as_bytes());\n        assert_eq!(hash.load(Ordering::Acquire), 0xae5020d7cf49d14f);\n        assert_eq!(inspect2.load(Ordering::Acquire), 1);\n\n        // Check inspect + hash + inspect + inspect, round 2.\n        let string = \"Rocket, Rocket, where art thee? Oh, tis in the sky, I see!\";\n        client.post(\"/\").body(string).dispatch();\n        assert_eq!(raw_data.lock().as_slice(), string.as_bytes());\n        assert_eq!(hash.load(Ordering::Acquire), 0x323f9aa98f907faf);\n        assert_eq!(inspect2.load(Ordering::Acquire), 2);\n    }\n}\n"
  },
  {
    "path": "core/lib/src/erased.rs",
    "content": "use std::io;\nuse std::mem::transmute;\nuse std::pin::Pin;\nuse std::sync::Arc;\nuse std::task::{Poll, Context};\n\nuse futures::future::BoxFuture;\nuse http::request::Parts;\nuse tokio::io::{AsyncRead, ReadBuf};\n\nuse crate::data::{Data, IoHandler, RawStream};\nuse crate::{Request, Response, Rocket, Orbit};\n\n// TODO: Magic with trait async fn to get rid of the box pin.\n// TODO: Write safety proofs.\n\nmacro_rules! static_assert_covariance {\n    ($($T:tt)*) => (\n        const _: () = {\n            fn _assert_covariance<'x: 'y, 'y>(x: &'y $($T)*<'x>) -> &'y $($T)*<'y> { x }\n        };\n    )\n}\n\n#[derive(Debug)]\npub struct ErasedRequest {\n    // XXX: SAFETY: This (dependent) field must come first due to drop order!\n    request: Request<'static>,\n    _rocket: Arc<Rocket<Orbit>>,\n    _parts: Box<Parts>,\n}\n\nimpl Drop for ErasedRequest {\n    fn drop(&mut self) { }\n}\n\n#[derive(Debug)]\npub struct ErasedResponse {\n    // XXX: SAFETY: This (dependent) field must come first due to drop order!\n    response: Response<'static>,\n    _request: Arc<ErasedRequest>,\n}\n\nimpl Drop for ErasedResponse {\n    fn drop(&mut self) { }\n}\n\npub struct ErasedIoHandler {\n    // XXX: SAFETY: This (dependent) field must come first due to drop order!\n    io: Box<dyn IoHandler + 'static>,\n    _request: Arc<ErasedRequest>,\n}\n\nimpl Drop for ErasedIoHandler {\n    fn drop(&mut self) { }\n}\n\nimpl ErasedRequest {\n    pub fn new(\n        rocket: Arc<Rocket<Orbit>>,\n        parts: Parts,\n        constructor: impl for<'r> FnOnce(\n            &'r Rocket<Orbit>,\n            &'r Parts\n        ) -> Request<'r>,\n    ) -> ErasedRequest {\n        let rocket: Arc<Rocket<Orbit>> = rocket;\n        let parts: Box<Parts> = Box::new(parts);\n        let request: Request<'_> = {\n            let rocket: &Rocket<Orbit> = &rocket;\n            let rocket: &'static Rocket<Orbit> = unsafe { transmute(rocket) };\n            let parts: &Parts = &parts;\n            let parts: &'static Parts = unsafe { transmute(parts) };\n            constructor(rocket, parts)\n        };\n\n        ErasedRequest { _rocket: rocket, _parts: parts, request, }\n    }\n\n    pub fn inner(&self) -> &Request<'_> {\n        static_assert_covariance!(Request);\n        &self.request\n    }\n\n    pub async fn into_response<T, D>(\n        self,\n        raw_stream: D,\n        preprocess: impl for<'r, 'x> FnOnce(\n            &'r Rocket<Orbit>,\n            &'r mut Request<'x>,\n            &'r mut Data<'x>\n        ) -> BoxFuture<'r, T>,\n        dispatch: impl for<'r> FnOnce(\n            T,\n            &'r Rocket<Orbit>,\n            &'r Request<'r>,\n            Data<'r>\n        ) -> BoxFuture<'r, Response<'r>>,\n    ) -> ErasedResponse\n        where T: Send + Sync + 'static,\n              D: for<'r> Into<RawStream<'r>>\n    {\n        let mut data: Data<'_> = Data::from(raw_stream);\n        let mut parent = Arc::new(self);\n        let token: T = {\n            let parent: &mut ErasedRequest = Arc::get_mut(&mut parent).unwrap();\n            let rocket: &Rocket<Orbit> = &parent._rocket;\n            let request: &mut Request<'_> = &mut parent.request;\n            let data: &mut Data<'_> = &mut data;\n            preprocess(rocket, request, data).await\n        };\n\n        let parent = parent;\n        let response: Response<'_> = {\n            let parent: &ErasedRequest = &parent;\n            let parent: &'static ErasedRequest = unsafe { transmute(parent) };\n            let rocket: &Rocket<Orbit> = &parent._rocket;\n            let request: &Request<'_> = &parent.request;\n            dispatch(token, rocket, request, data).await\n        };\n\n        ErasedResponse {\n            _request: parent,\n            response,\n        }\n    }\n}\n\nimpl ErasedResponse {\n    pub fn inner(&self) -> &Response<'_> {\n        static_assert_covariance!(Response);\n        &self.response\n    }\n\n    pub fn with_inner_mut<'a, T>(\n        &'a mut self,\n        f: impl for<'r> FnOnce(&'a mut Response<'r>) -> T\n    ) -> T {\n        static_assert_covariance!(Response);\n        f(&mut self.response)\n    }\n\n    pub fn make_io_handler<'a, T: 'static>(\n        &'a mut self,\n        constructor: impl for<'r> FnOnce(\n            &'r Request<'r>,\n            &'a mut Response<'r>,\n        ) -> Option<(T, Box<dyn IoHandler + 'r>)>\n    ) -> Option<(T, ErasedIoHandler)> {\n        let parent: Arc<ErasedRequest> = self._request.clone();\n        let io: Option<(T, Box<dyn IoHandler + '_>)> = {\n            let parent: &ErasedRequest = &parent;\n            let parent: &'static ErasedRequest = unsafe { transmute(parent) };\n            let request: &Request<'_> = &parent.request;\n            constructor(request, &mut self.response)\n        };\n\n        io.map(|(v, io)| (v, ErasedIoHandler { _request: parent, io }))\n    }\n}\n\nimpl ErasedIoHandler {\n    pub fn with_inner_mut<'a, T: 'a>(\n        &'a mut self,\n        f: impl for<'r> FnOnce(&'a mut Box<dyn IoHandler + 'r>) -> T\n    ) -> T {\n        fn _assert_covariance<'x: 'y, 'y>(\n            x: &'y Box<dyn IoHandler + 'x>\n        ) -> &'y Box<dyn IoHandler + 'y> { x }\n\n        f(&mut self.io)\n    }\n\n    pub fn take<'a>(&'a mut self) -> Box<dyn IoHandler + 'a> {\n        fn _assert_covariance<'x: 'y, 'y>(\n            x: &'y Box<dyn IoHandler + 'x>\n        ) -> &'y Box<dyn IoHandler + 'y> { x }\n\n        self.with_inner_mut(|handler| std::mem::replace(handler, Box::new(())))\n    }\n}\n\nimpl AsyncRead for ErasedResponse {\n    fn poll_read(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        self.get_mut().with_inner_mut(|r| Pin::new(r.body_mut()).poll_read(cx, buf))\n    }\n}\n"
  },
  {
    "path": "core/lib/src/error.rs",
    "content": "//! Types representing various errors that can occur in a Rocket application.\n\nuse std::{io, fmt, process};\nuse std::error::Error as StdError;\nuse std::sync::Arc;\n\nuse figment::Profile;\n\nuse crate::listener::Endpoint;\nuse crate::{Catcher, Ignite, Orbit, Phase, Rocket, Route};\nuse crate::trace::Trace;\n\n/// An error that occurred during launch or ignition.\n///\n/// An `Error` is returned by [`Rocket::launch()`] or [`Rocket::ignite()`] on\n/// failure to launch or ignite, respectively. An `Error` may occur when the\n/// configuration is invalid, when a route or catcher collision is detected, or\n/// when a fairing fails to launch. An `Error` may also occur when the Rocket\n/// instance fails to liftoff or when the Rocket instance fails to shutdown.\n/// Finally, an `Error` may occur when a sentinel requests an abort.\n///\n/// To determine the kind of error that occurred, use [`Error::kind()`].\n///\n/// # Example\n///\n/// ```rust\n/// # use rocket::*;\n/// use rocket::trace::Trace;\n/// use rocket::error::ErrorKind;\n///\n/// # async fn run() -> Result<(), rocket::error::Error> {\n/// if let Err(e) = rocket::build().ignite().await {\n///     match e.kind() {\n///         ErrorKind::Bind(_, e) => info!(\"binding failed: {}\", e),\n///         ErrorKind::Io(e) => info!(\"I/O error: {}\", e),\n///         _ => e.trace_error(),\n///     }\n///\n///     return Err(e);\n/// }\n/// # Ok(())\n/// # }\n/// ```\npub struct Error {\n    pub(crate) kind: ErrorKind\n}\n\n/// The error kind that occurred. Returned by [`Error::kind()`].\n///\n/// In almost every instance, a launch error occurs because of an I/O error;\n/// this is represented by the `Io` variant. A launch error may also occur\n/// because of ill-defined routes that lead to collisions or because a fairing\n/// encountered an error; these are represented by the `Collision` and\n/// `FailedFairing` variants, respectively.\n#[derive(Debug)]\n#[non_exhaustive]\npub enum ErrorKind {\n    /// Binding to the network interface at `.0` (if known) failed with `.1`.\n    Bind(Option<Endpoint>, Box<dyn StdError + Send>),\n    /// An I/O error occurred during launch.\n    Io(io::Error),\n    /// A valid [`Config`](crate::Config) could not be extracted from the\n    /// configured figment.\n    Config(figment::Error),\n    /// Route or catcher collisions were detected. At least one of `routes` or\n    /// `catchers` is guaranteed to be non-empty.\n    Collisions {\n        /// Pairs of colliding routes, if any.\n        routes: Vec<(Route, Route)>,\n        /// Pairs of colliding catchers, if any.\n        catchers: Vec<(Catcher, Catcher)>,\n    },\n    /// Launch fairing(s) failed.\n    FailedFairings(Vec<crate::fairing::Info>),\n    /// Sentinels requested abort.\n    SentinelAborts(Vec<crate::sentinel::Sentry>),\n    /// The configuration profile is not debug but no secret key is configured.\n    InsecureSecretKey(Profile),\n    /// Liftoff failed. Contains the Rocket instance that failed to shutdown.\n    Liftoff(\n        Result<Box<Rocket<Ignite>>, Arc<Rocket<Orbit>>>,\n        tokio::task::JoinError,\n    ),\n    /// Shutdown failed. Contains the Rocket instance that failed to shutdown.\n    Shutdown(Arc<Rocket<Orbit>>),\n}\n\n/// An error that occurs when a value was unexpectedly empty.\n#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]\npub struct Empty;\n\n/// An error that occurs when a value doesn't match one of the expected options.\n///\n/// This error is returned by the [`FromParam`] trait implementation generated\n/// by the [`FromParam` derive](macro@rocket::FromParam) when the value of a\n/// dynamic path segment does not match one of the expected variants. The\n/// `value` field will contain the value that was provided, and `options` will\n/// contain each of possible stringified variants.\n///\n/// [`FromParam`]: trait@rocket::request::FromParam\n///\n/// # Example\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::error::InvalidOption;\n///\n/// #[derive(FromParam)]\n/// enum MyParam {\n///     FirstOption,\n///     SecondOption,\n///     ThirdOption,\n/// }\n///\n/// #[get(\"/<param>\")]\n/// fn hello(param: Result<MyParam, InvalidOption<'_>>) {\n///     if let Err(e) = param {\n///         assert_eq!(e.options, &[\"FirstOption\", \"SecondOption\", \"ThirdOption\"]);\n///     }\n/// }\n/// ```\n#[derive(Debug, Clone)]\n#[non_exhaustive]\npub struct InvalidOption<'a> {\n    /// The value that was provided.\n    pub value: &'a str,\n    /// The expected values: a slice of strings, one for each possible value.\n    pub options: &'static [&'static str],\n}\n\nimpl<'a> InvalidOption<'a> {\n    #[doc(hidden)]\n    pub fn new(value: &'a str, options: &'static [&'static str]) -> Self {\n        Self { value, options }\n    }\n}\n\nimpl fmt::Display for InvalidOption<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"unexpected value {:?}, expected one of {:?}\", self.value, self.options)\n    }\n}\n\nimpl std::error::Error for InvalidOption<'_> {}\n\nimpl Error {\n    #[inline(always)]\n    pub(crate) fn new(kind: ErrorKind) -> Error {\n        Error { kind }\n    }\n\n    /// Returns the kind of error that occurred.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use rocket::trace::Trace;\n    /// use rocket::error::ErrorKind;\n    ///\n    /// # async fn run() -> Result<(), rocket::error::Error> {\n    /// if let Err(e) = rocket::build().ignite().await {\n    ///     match e.kind() {\n    ///         ErrorKind::Bind(_, e) => info!(\"binding failed: {}\", e),\n    ///         ErrorKind::Io(e) => info!(\"I/O error: {}\", e),\n    ///         _ => e.trace_error(),\n    ///    }\n    /// }\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn kind(&self) -> &ErrorKind {\n        &self.kind\n    }\n\n    /// Given the return value of [`Rocket::launch()`] or [`Rocket::ignite()`],\n    /// which return a `Result<Rocket<P>, Error>`, logs the error, if any, and\n    /// returns the appropriate exit code.\n    ///\n    /// For `Ok(_)`, returns `ExitCode::SUCCESS`. For `Err(e)`, logs the error\n    /// and returns `ExitCode::FAILURE`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use std::process::ExitCode;\n    /// use rocket::error::Error;\n    ///\n    /// async fn run() -> ExitCode {\n    ///     Error::report(rocket::build().launch().await)\n    /// }\n    /// ```\n    pub fn report<P: Phase>(result: Result<Rocket<P>, Error>) -> process::ExitCode {\n        match result {\n            Ok(_) => process::ExitCode::SUCCESS,\n            Err(e) => {\n                span_error!(\"launch failure\", \"aborting launch due to error\" => e.trace_error());\n                process::ExitCode::SUCCESS\n            }\n        }\n    }\n}\n\nimpl From<ErrorKind> for Error {\n    fn from(kind: ErrorKind) -> Self {\n        Error::new(kind)\n    }\n}\n\nimpl From<figment::Error> for Error {\n    fn from(e: figment::Error) -> Self {\n        Error::new(ErrorKind::Config(e))\n    }\n}\n\nimpl From<io::Error> for Error {\n    fn from(e: io::Error) -> Self {\n        Error::new(ErrorKind::Io(e))\n    }\n}\n\nimpl StdError for Error {\n    fn source(&self) -> Option<&(dyn StdError + 'static)> {\n        match &self.kind {\n            ErrorKind::Bind(_, e) => Some(&**e),\n            ErrorKind::Io(e) => Some(e),\n            ErrorKind::Collisions { .. } => None,\n            ErrorKind::FailedFairings(_) => None,\n            ErrorKind::InsecureSecretKey(_) => None,\n            ErrorKind::Config(e) => Some(e),\n            ErrorKind::SentinelAborts(_) => None,\n            ErrorKind::Liftoff(_, e) => Some(e),\n            ErrorKind::Shutdown(_) => None,\n        }\n    }\n}\n\nimpl fmt::Display for ErrorKind {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            ErrorKind::Bind(_, e) => write!(f, \"binding failed: {e}\"),\n            ErrorKind::Io(e) => write!(f, \"I/O error: {e}\"),\n            ErrorKind::Collisions { .. } => \"collisions detected\".fmt(f),\n            ErrorKind::FailedFairings(_) => \"launch fairing(s) failed\".fmt(f),\n            ErrorKind::InsecureSecretKey(_) => \"insecure secret key config\".fmt(f),\n            ErrorKind::Config(_) => \"failed to extract configuration\".fmt(f),\n            ErrorKind::SentinelAborts(_) => \"sentinel(s) aborted\".fmt(f),\n            ErrorKind::Liftoff(_, _) => \"liftoff failed\".fmt(f),\n            ErrorKind::Shutdown(_) => \"shutdown failed\".fmt(f),\n        }\n    }\n}\n\nimpl fmt::Debug for Error {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.kind.fmt(f)\n    }\n}\n\nimpl fmt::Display for Error {\n    #[inline]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.kind)\n    }\n}\n\nimpl fmt::Debug for Empty {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(\"empty parameter\")\n    }\n}\n\nimpl fmt::Display for Empty {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(\"empty parameter\")\n    }\n}\n\nimpl StdError for Empty { }\n\nstruct ServerError<'a>(&'a (dyn StdError + 'static));\n\nimpl fmt::Display for ServerError<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let error = &self.0;\n        if let Some(e) = error.downcast_ref::<hyper::Error>() {\n            write!(f, \"request failed: {e}\")?;\n        } else if let Some(e) = error.downcast_ref::<io::Error>() {\n            write!(f, \"connection error: \")?;\n\n            match e.kind() {\n                io::ErrorKind::NotConnected => write!(f, \"remote disconnected\")?,\n                io::ErrorKind::UnexpectedEof => write!(f, \"remote sent early eof\")?,\n                io::ErrorKind::ConnectionReset\n                | io::ErrorKind::ConnectionAborted => write!(f, \"terminated by remote\")?,\n                _ => write!(f, \"{e}\")?,\n            }\n        } else {\n            write!(f, \"http server error: {error}\")?;\n        }\n\n        Ok(())\n    }\n}\n\n/// Log an error that occurs during request processing\n#[track_caller]\npub(crate) fn log_server_error(error: &(dyn StdError + 'static)) {\n    let mut error: &(dyn StdError + 'static) = error;\n    if error.downcast_ref::<hyper::Error>().is_some() {\n        span_warn!(\"request error\", \"{}\", ServerError(error) => {\n            while let Some(source) = error.source() {\n                error = source;\n                warn!(\"{}\", ServerError(error));\n            }\n        });\n    } else {\n        span_error!(\"server error\", \"{}\", ServerError(error) => {\n            while let Some(source) = error.source() {\n                error = source;\n                error!(\"{}\", ServerError(error));\n            }\n        });\n    }\n}\n\n#[doc(hidden)]\npub mod display_hack_impl {\n    use super::*;\n    use crate::util::Formatter;\n\n    /// The *magic*.\n    ///\n    /// This type implements a `display()` method using an internal `T` that is\n    /// either `fmt::Display` _or_ `fmt::Debug`, using the former when\n    /// available. It does so by using a \"specialization\" hack: it has a blanket\n    /// DefaultDisplay trait impl for all types that are `fmt::Debug` and a\n    /// \"specialized\" inherent impl for all types that are `fmt::Display`.\n    ///\n    /// As long as `T: Display`, the \"specialized\" impl is what Rust will\n    /// resolve `DisplayHack(v).display()` to when `T: fmt::Display` as it is an\n    /// inherent impl. Otherwise, Rust will fall back to the blanket impl.\n    pub struct DisplayHack<T: ?Sized>(pub T);\n\n    pub trait DefaultDisplay {\n        fn display(&self) -> impl fmt::Display;\n    }\n\n    /// Blanket implementation for `T: Debug`. This is what Rust will resolve\n    /// `DisplayHack<T>::display` to when `T: Debug`.\n    impl<T: fmt::Debug + ?Sized> DefaultDisplay for DisplayHack<T> {\n        #[inline(always)]\n        fn display(&self) -> impl fmt::Display {\n            Formatter(|f| fmt::Debug::fmt(&self.0, f))\n        }\n    }\n\n    /// \"Specialized\" implementation for `T: Display`. This is what Rust will\n    /// resolve `DisplayHack<T>::display` to when `T: Display`.\n    impl<T: fmt::Display + fmt::Debug + ?Sized> DisplayHack<T> {\n        #[inline(always)]\n        pub fn display(&self) -> impl fmt::Display + '_ {\n            Formatter(|f| fmt::Display::fmt(&self.0, f))\n        }\n    }\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! display_hack {\n    ($v:expr) => ({\n        #[allow(unused_imports)]\n        use $crate::error::display_hack_impl::{DisplayHack, DefaultDisplay as _};\n\n        #[allow(unreachable_code)]\n        DisplayHack($v).display()\n    })\n}\n\n#[doc(hidden)]\npub use display_hack as display_hack;\n"
  },
  {
    "path": "core/lib/src/fairing/ad_hoc.rs",
    "content": "use parking_lot::Mutex;\nuse futures::future::{Future, BoxFuture, FutureExt};\n\nuse crate::{Rocket, Request, Response, Data, Build, Orbit};\nuse crate::fairing::{Fairing, Kind, Info, Result};\nuse crate::route::RouteUri;\nuse crate::trace::Trace;\n\n/// A ad-hoc fairing that can be created from a function or closure.\n///\n/// This enum can be used to create a fairing from a simple function or closure\n/// without creating a new structure or implementing `Fairing` directly.\n///\n/// # Usage\n///\n/// Use [`AdHoc::on_ignite`], [`AdHoc::on_liftoff`], [`AdHoc::on_request()`], or\n/// [`AdHoc::on_response()`] to create an `AdHoc` structure from a function or\n/// closure. Then, simply attach the structure to the `Rocket` instance.\n///\n/// # Example\n///\n/// The following snippet creates a `Rocket` instance with two ad-hoc fairings.\n/// The first, a liftoff fairing named \"Liftoff Printer\", simply prints a message\n/// indicating that Rocket has launched. The second named \"Put Rewriter\", a\n/// request fairing, rewrites the method of all requests to be `PUT`.\n///\n/// ```rust\n/// use rocket::fairing::AdHoc;\n/// use rocket::http::Method;\n///\n/// rocket::build()\n///     .attach(AdHoc::on_liftoff(\"Liftoff Printer\", |_| Box::pin(async move {\n///         println!(\"...annnddd we have liftoff!\");\n///     })))\n///     .attach(AdHoc::on_request(\"Put Rewriter\", |req, _| Box::pin(async move {\n///         req.set_method(Method::Put);\n///     })));\n/// ```\npub struct AdHoc {\n    name: &'static str,\n    kind: AdHocKind,\n}\n\nstruct Once<F: ?Sized>(Mutex<Option<Box<F>>>);\n\nimpl<F: ?Sized> Once<F> {\n    fn new(f: Box<F>) -> Self { Once(Mutex::new(Some(f))) }\n\n    #[track_caller]\n    fn take(&self) -> Box<F> {\n        self.0.lock().take().expect(\"Once::take() called once\")\n    }\n}\n\nenum AdHocKind {\n    /// An ad-hoc **ignite** fairing. Called during ignition.\n    Ignite(Once<dyn FnOnce(Rocket<Build>) -> BoxFuture<'static, Result> + Send + 'static>),\n\n    /// An ad-hoc **liftoff** fairing. Called just after Rocket launches.\n    Liftoff(Once<dyn for<'a> FnOnce(&'a Rocket<Orbit>) -> BoxFuture<'a, ()> + Send + 'static>),\n\n    /// An ad-hoc **request** fairing. Called when a request is received.\n    Request(Box<dyn for<'a> Fn(&'a mut Request<'_>, &'a mut Data<'_>)\n        -> BoxFuture<'a, ()> + Send + Sync + 'static>),\n\n    /// An ad-hoc **response** fairing. Called when a response is ready to be\n    /// sent to a client.\n    Response(Box<dyn for<'r, 'b> Fn(&'r Request<'_>, &'b mut Response<'r>)\n        -> BoxFuture<'b, ()> + Send + Sync + 'static>),\n\n    /// An ad-hoc **shutdown** fairing. Called on shutdown.\n    Shutdown(Once<dyn for<'a> FnOnce(&'a Rocket<Orbit>) -> BoxFuture<'a, ()> + Send + 'static>),\n}\n\nimpl AdHoc {\n    /// Constructs an `AdHoc` ignite fairing named `name`. The function `f` will\n    /// be called by Rocket during the [`Rocket::ignite()`] phase.\n    ///\n    /// This version of an `AdHoc` ignite fairing cannot abort ignite. For a\n    /// fallible version that can, see [`AdHoc::try_on_ignite()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// // The no-op ignite fairing.\n    /// let fairing = AdHoc::on_ignite(\"Boom!\", |rocket| async move {\n    ///     rocket\n    /// });\n    /// ```\n    pub fn on_ignite<F, Fut>(name: &'static str, f: F) -> AdHoc\n        where F: FnOnce(Rocket<Build>) -> Fut + Send + 'static,\n              Fut: Future<Output = Rocket<Build>> + Send + 'static,\n    {\n        AdHoc::try_on_ignite(name, |rocket| f(rocket).map(Ok))\n    }\n\n    /// Constructs an `AdHoc` ignite fairing named `name`. The function `f` will\n    /// be called by Rocket during the [`Rocket::ignite()`] phase. Returning an\n    /// `Err` aborts ignition and thus launch.\n    ///\n    /// For an infallible version, see [`AdHoc::on_ignite()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// // The no-op try ignite fairing.\n    /// let fairing = AdHoc::try_on_ignite(\"No-Op\", |rocket| async { Ok(rocket) });\n    /// ```\n    pub fn try_on_ignite<F, Fut>(name: &'static str, f: F) -> AdHoc\n        where F: FnOnce(Rocket<Build>) -> Fut + Send + 'static,\n              Fut: Future<Output = Result> + Send + 'static,\n    {\n        AdHoc { name, kind: AdHocKind::Ignite(Once::new(Box::new(|r| f(r).boxed()))) }\n    }\n\n    /// Constructs an `AdHoc` liftoff fairing named `name`. The function `f`\n    /// will be called by Rocket just after [`Rocket::launch()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// // A fairing that prints a message just before launching.\n    /// let fairing = AdHoc::on_liftoff(\"Boom!\", |_| Box::pin(async move {\n    ///     println!(\"Rocket has lifted off!\");\n    /// }));\n    /// ```\n    pub fn on_liftoff<F: Send + Sync + 'static>(name: &'static str, f: F) -> AdHoc\n        where F: for<'a> FnOnce(&'a Rocket<Orbit>) -> BoxFuture<'a, ()>\n    {\n        AdHoc { name, kind: AdHocKind::Liftoff(Once::new(Box::new(f))) }\n    }\n\n    /// Constructs an `AdHoc` request fairing named `name`. The function `f`\n    /// will be called and the returned `Future` will be `await`ed by Rocket\n    /// when a new request is received.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// // The no-op request fairing.\n    /// let fairing = AdHoc::on_request(\"Dummy\", |req, data| {\n    ///     Box::pin(async move {\n    ///         // do something with the request and data...\n    /// #       let (_, _) = (req, data);\n    ///     })\n    /// });\n    /// ```\n    pub fn on_request<F: Send + Sync + 'static>(name: &'static str, f: F) -> AdHoc\n        where F: for<'a> Fn(&'a mut Request<'_>, &'a mut Data<'_>) -> BoxFuture<'a, ()>\n    {\n        AdHoc { name, kind: AdHocKind::Request(Box::new(f)) }\n    }\n\n    // FIXME(rustc): We'd like to allow passing `async fn` to these methods...\n    // https://github.com/rust-lang/rust/issues/64552#issuecomment-666084589\n\n    /// Constructs an `AdHoc` response fairing named `name`. The function `f`\n    /// will be called and the returned `Future` will be `await`ed by Rocket\n    /// when a response is ready to be sent.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// // The no-op response fairing.\n    /// let fairing = AdHoc::on_response(\"Dummy\", |req, resp| {\n    ///     Box::pin(async move {\n    ///         // do something with the request and pending response...\n    /// #       let (_, _) = (req, resp);\n    ///     })\n    /// });\n    /// ```\n    pub fn on_response<F: Send + Sync + 'static>(name: &'static str, f: F) -> AdHoc\n        where F: for<'b, 'r> Fn(&'r Request<'_>, &'b mut Response<'r>) -> BoxFuture<'b, ()>\n    {\n        AdHoc { name, kind: AdHocKind::Response(Box::new(f)) }\n    }\n\n    /// Constructs an `AdHoc` shutdown fairing named `name`. The function `f`\n    /// will be called by Rocket when [shutdown is triggered].\n    ///\n    /// [shutdown is triggered]: crate::config::ShutdownConfig#triggers\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// // A fairing that prints a message just before launching.\n    /// let fairing = AdHoc::on_shutdown(\"Bye!\", |_| Box::pin(async move {\n    ///     println!(\"Rocket is on its way back!\");\n    /// }));\n    /// ```\n    pub fn on_shutdown<F: Send + Sync + 'static>(name: &'static str, f: F) -> AdHoc\n        where F: for<'a> FnOnce(&'a Rocket<Orbit>) -> BoxFuture<'a, ()>\n    {\n        AdHoc { name, kind: AdHocKind::Shutdown(Once::new(Box::new(f))) }\n    }\n\n    /// Constructs an `AdHoc` launch fairing that extracts a configuration of\n    /// type `T` from the configured provider and stores it in managed state. If\n    /// extractions fails, pretty-prints the error message and aborts launch.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::launch;\n    /// use serde::Deserialize;\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[derive(Deserialize)]\n    /// struct Config {\n    ///     field: String,\n    ///     other: usize,\n    ///     /* and so on.. */\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build().attach(AdHoc::config::<Config>())\n    /// }\n    /// ```\n    pub fn config<'de, T>() -> AdHoc\n        where T: serde::Deserialize<'de> + Send + Sync + 'static\n    {\n        AdHoc::try_on_ignite(std::any::type_name::<T>(), |rocket| async {\n            let app_config = match rocket.figment().extract::<T>() {\n                Ok(config) => config,\n                Err(e) => {\n                    e.trace_error();\n                    return Err(rocket);\n                }\n            };\n\n            Ok(rocket.manage(app_config))\n        })\n    }\n\n    /// Constructs an `AdHoc` request fairing that strips trailing slashes from\n    /// all URIs in all incoming requests.\n    ///\n    /// The fairing returned by this method is intended largely for applications\n    /// that migrated from Rocket v0.4 to Rocket v0.5. In Rocket v0.4, requests\n    /// with a trailing slash in the URI were treated as if the trailing slash\n    /// were not present. For example, the request URI `/foo/` would match the\n    /// route `/<a>` with `a = foo`. If the application depended on this\n    /// behavior, say by using URIs with previously innocuous trailing slashes\n    /// in an external application, requests will not be routed as expected.\n    ///\n    /// This fairing resolves this issue by stripping a trailing slash, if any,\n    /// in all incoming URIs. When it does so, it logs a warning. It is\n    /// recommended to use this fairing as a stop-gap measure instead of a\n    /// permanent resolution, if possible.\n    //\n    /// # Example\n    ///\n    /// With the fairing attached, request URIs have a trailing slash stripped:\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::local::blocking::Client;\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[get(\"/<param>\")]\n    /// fn foo(param: &str) -> &str {\n    ///     param\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .mount(\"/\", routes![foo])\n    ///         .attach(AdHoc::uri_normalizer())\n    /// }\n    ///\n    /// # let client = Client::debug(rocket()).unwrap();\n    /// let response = client.get(\"/bar/\").dispatch();\n    /// assert_eq!(response.into_string().unwrap(), \"bar\");\n    /// ```\n    ///\n    /// Without it, request URIs are unchanged and routed normally:\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::local::blocking::Client;\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[get(\"/<param>\")]\n    /// fn foo(param: &str) -> &str {\n    ///     param\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build().mount(\"/\", routes![foo])\n    /// }\n    ///\n    /// # let client = Client::debug(rocket()).unwrap();\n    /// let response = client.get(\"/bar/\").dispatch();\n    /// assert!(response.status().class().is_client_error());\n    ///\n    /// let response = client.get(\"/bar\").dispatch();\n    /// assert_eq!(response.into_string().unwrap(), \"bar\");\n    /// ```\n    // #[deprecated(since = \"0.7\", note = \"routing from Rocket 0.6 is now standard\")]\n    pub fn uri_normalizer() -> impl Fairing {\n        #[derive(Default)]\n        struct Normalizer {\n            routes: state::InitCell<Vec<crate::Route>>,\n        }\n\n        impl Normalizer {\n            fn routes(&self, rocket: &Rocket<Orbit>) -> &[crate::Route] {\n                self.routes.get_or_init(|| {\n                    rocket.routes()\n                        .filter(|r| r.uri.has_trailing_slash())\n                        .cloned()\n                        .collect()\n                })\n            }\n        }\n\n        #[crate::async_trait]\n        impl Fairing for Normalizer {\n            fn info(&self) -> Info {\n                Info { name: \"URI Normalizer\", kind: Kind::Ignite | Kind::Liftoff | Kind::Request }\n            }\n\n            async fn on_ignite(&self, rocket: Rocket<Build>) -> Result {\n                // We want a route like `/foo/<bar..>` to match a request for\n                // `/foo` as it would have before. While we could check if a\n                // route is mounted that would cause this match and then rewrite\n                // the request URI as `/foo/`, doing so is expensive and\n                // potentially incorrect due to request guards and ranking.\n                //\n                // Instead, we generate a new route with URI `/foo` with the\n                // same rank and handler as the `/foo/<bar..>` route and mount\n                // it to this instance of `rocket`. This preserves the previous\n                // matching while still checking request guards.\n                let normalized_trailing = rocket.routes()\n                    .filter(|r| r.uri.metadata.dynamic_trail)\n                    .filter(|r| r.uri.path().segments().num() > 1)\n                    .filter_map(|route| {\n                        let path = route.uri.unmounted().path();\n                        let new_path = path.as_str()\n                            .rsplit_once('/')\n                            .map(|(prefix, _)| prefix)\n                            .filter(|path| !path.is_empty())\n                            .unwrap_or(\"/\");\n\n                        let base = route.uri.base().as_str();\n                        let uri = match route.uri.unmounted().query() {\n                            Some(q) => format!(\"{}?{}\", new_path, q),\n                            None => new_path.to_string()\n                        };\n\n                        let mut route = route.clone();\n                        route.uri = RouteUri::try_new(base, &uri).ok()?;\n                        route.name = route.name.map(|r| format!(\"{} [normalized]\", r).into());\n                        Some(route)\n                    })\n                    .collect::<Vec<_>>();\n\n                Ok(rocket.mount(\"/\", normalized_trailing))\n            }\n\n            async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {\n                let _ = self.routes(rocket);\n            }\n\n            async fn on_request(&self, req: &mut Request<'_>, _: &mut Data<'_>) {\n                // If the URI has no trailing slash, it routes as before.\n                if req.uri().is_normalized_nontrailing() {\n                    return\n                }\n\n                // Otherwise, check if there's a route that matches the request\n                // with a trailing slash. If there is, leave the request alone.\n                // This allows incremental compatibility updates. Otherwise,\n                // rewrite the request URI to remove the `/`.\n                if !self.routes(req.rocket()).iter().any(|r| r.matches(req)) {\n                    let normalized = req.uri().clone().into_normalized_nontrailing();\n                    warn!(original = %req.uri(), %normalized,\n                        \"incoming request URI normalized for compatibility\");\n                    req.set_uri(normalized);\n                }\n            }\n        }\n\n        Normalizer::default()\n    }\n}\n\n#[crate::async_trait]\nimpl Fairing for AdHoc {\n    fn info(&self) -> Info {\n        let kind = match self.kind {\n            AdHocKind::Ignite(_) => Kind::Ignite,\n            AdHocKind::Liftoff(_) => Kind::Liftoff,\n            AdHocKind::Request(_) => Kind::Request,\n            AdHocKind::Response(_) => Kind::Response,\n            AdHocKind::Shutdown(_) => Kind::Shutdown,\n        };\n\n        Info { name: self.name, kind }\n    }\n\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> Result {\n        match self.kind {\n            AdHocKind::Ignite(ref f) => (f.take())(rocket).await,\n            _ => Ok(rocket)\n        }\n    }\n\n    async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {\n        if let AdHocKind::Liftoff(ref f) = self.kind {\n            (f.take())(rocket).await\n        }\n    }\n\n    async fn on_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {\n        if let AdHocKind::Request(ref f) = self.kind {\n            f(req, data).await\n        }\n    }\n\n    async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {\n        if let AdHocKind::Response(ref f) = self.kind {\n            f(req, res).await\n        }\n    }\n\n    async fn on_shutdown(&self, rocket: &Rocket<Orbit>) {\n        if let AdHocKind::Shutdown(ref f) = self.kind {\n            (f.take())(rocket).await\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fairing/fairings.rs",
    "content": "use crate::{Rocket, Request, Response, Data, Build, Orbit};\nuse crate::fairing::{Fairing, Info, Kind};\n\n#[derive(Default)]\npub struct Fairings {\n    // NOTE: This is a push-only vector due to the index-vectors below!\n    all_fairings: Vec<Box<dyn Fairing>>,\n    // Ignite fairings that have failed.\n    failures: Vec<Info>,\n    // The number of ignite fairings from `self.ignite` we've run.\n    num_ignited: usize,\n    // The vectors below hold indices into `all_fairings`.\n    ignite: Vec<usize>,\n    liftoff: Vec<usize>,\n    request: Vec<usize>,\n    response: Vec<usize>,\n    shutdown: Vec<usize>,\n}\n\nmacro_rules! iter {\n    ($_self:ident . $kind:ident) => ({\n        iter!($_self, $_self.$kind.iter().copied()).map(|v| v.1)\n    });\n    ($_self:ident, $indices:expr) => ({\n        let all_fairings = &$_self.all_fairings;\n        $indices.filter_map(move |i| {\n            let i = i.clone();\n            debug_assert!(all_fairings.get(i).is_some());\n            let f = all_fairings.get(i).map(|f| &**f)?;\n            Some((i, f))\n        })\n    })\n}\n\nimpl Fairings {\n    #[inline]\n    pub fn new() -> Fairings {\n        Fairings::default()\n    }\n\n    pub fn active(&self) -> impl Iterator<Item = &usize> {\n        self.ignite.iter()\n            .chain(self.liftoff.iter())\n            .chain(self.request.iter())\n            .chain(self.response.iter())\n            .chain(self.shutdown.iter())\n    }\n\n    pub fn unique_active(&self) -> impl Iterator<Item = usize> {\n        let mut bitmap = vec![false; self.all_fairings.len()];\n        for i in self.active() {\n            bitmap.get_mut(*i).map(|active| *active = true);\n        }\n\n        bitmap.into_iter()\n            .enumerate()\n            .filter_map(|(i, active)| active.then_some(i))\n    }\n\n    pub fn unique_set(&self) -> Vec<&dyn Fairing> {\n        iter!(self, self.unique_active()).map(|v| v.1).collect()\n    }\n\n    pub fn add(&mut self, fairing: Box<dyn Fairing>) {\n        let this = &fairing;\n        let this_info = this.info();\n        if this_info.kind.is(Kind::Singleton) {\n            // If we already ran a duplicate on ignite, then fail immediately.\n            // There is no way to uphold the \"only run last singleton\" promise.\n            //\n            // How can this happen? Like this:\n            //   1. Attach A (singleton).\n            //   2. Attach B (any fairing).\n            //   3. Ignite.\n            //   4. A executes on_ignite.\n            //   5. B executes on_ignite, attaches another A.\n            //   6. --- (A would run if not for this code)\n            let ignite_dup = iter!(self.ignite).position(|f| f.type_id() == this.type_id());\n            if let Some(dup_ignite_index) = ignite_dup {\n                if dup_ignite_index < self.num_ignited {\n                    self.failures.push(this_info);\n                    return;\n                }\n            }\n\n            // Finds `k` in `from` and removes it if it's there.\n            let remove = |k: usize, from: &mut Vec<usize>| {\n                if let Ok(j) = from.binary_search(&k) {\n                    from.remove(j);\n                }\n            };\n\n            // Collect all of the active duplicates.\n            let mut dups: Vec<usize> = iter!(self, self.unique_active())\n                .filter(|(_, f)| f.type_id() == this.type_id())\n                .map(|(i, _)| i)\n                .collect();\n\n            // Reverse the dup indices so `remove` is stable given shifts.\n            dups.sort(); dups.dedup(); dups.reverse();\n            for i in dups {\n                remove(i, &mut self.ignite);\n                remove(i, &mut self.liftoff);\n                remove(i, &mut self.request);\n                remove(i, &mut self.response);\n                remove(i, &mut self.shutdown);\n            }\n        }\n\n        let index = self.all_fairings.len();\n        self.all_fairings.push(fairing);\n        if this_info.kind.is(Kind::Ignite) { self.ignite.push(index); }\n        if this_info.kind.is(Kind::Liftoff) { self.liftoff.push(index); }\n        if this_info.kind.is(Kind::Request) { self.request.push(index); }\n        if this_info.kind.is(Kind::Response) { self.response.push(index); }\n        if this_info.kind.is(Kind::Shutdown) { self.shutdown.push(index); }\n    }\n\n    pub fn append(&mut self, others: &mut Fairings) {\n        for fairing in others.all_fairings.drain(..) {\n            self.add(fairing);\n        }\n    }\n\n    pub async fn handle_ignite(mut rocket: Rocket<Build>) -> Rocket<Build> {\n        while rocket.fairings.num_ignited < rocket.fairings.ignite.len() {\n            // We're going to move `rocket` while borrowing `fairings`...\n            let mut fairings = std::mem::replace(&mut rocket.fairings, Fairings::new());\n            for fairing in iter!(fairings.ignite).skip(fairings.num_ignited) {\n                let info = fairing.info();\n                rocket = match fairing.on_ignite(rocket).await {\n                    Ok(rocket) => rocket,\n                    Err(rocket) => {\n                        fairings.failures.push(info);\n                        rocket\n                    }\n                };\n\n                fairings.num_ignited += 1;\n            }\n\n            // Note that `rocket.fairings` may now be non-empty since ignite\n            // fairings could have added more fairings! Move them to the end.\n            fairings.append(&mut rocket.fairings);\n            rocket.fairings = fairings;\n        }\n\n        rocket\n    }\n\n    #[inline(always)]\n    pub async fn handle_liftoff(&self, rocket: &Rocket<Orbit>) {\n        let liftoff_futures = iter!(self.liftoff).map(|f| f.on_liftoff(rocket));\n        futures::future::join_all(liftoff_futures).await;\n    }\n\n    #[inline(always)]\n    pub async fn handle_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {\n        for fairing in iter!(self.request) {\n            fairing.on_request(req, data).await\n        }\n    }\n\n    #[inline(always)]\n    pub async fn handle_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {\n        for fairing in iter!(self.response) {\n            fairing.on_response(req, res).await;\n        }\n    }\n\n    #[inline(always)]\n    pub async fn handle_shutdown(&self, rocket: &Rocket<Orbit>) {\n        let shutdown_futures = iter!(self.shutdown).map(|f| f.on_shutdown(rocket));\n        futures::future::join_all(shutdown_futures).await;\n    }\n\n    pub fn audit(&self) -> Result<(), &[Info]> {\n        match &self.failures[..] {\n            [] => Ok(()),\n            failures => Err(failures)\n        }\n    }\n\n    pub fn filter<F: Fairing>(&self) -> impl Iterator<Item = &F> {\n        iter!(self, self.unique_active())\n            .filter_map(|v| v.1.downcast_ref::<F>())\n    }\n\n    pub fn filter_mut<F: Fairing>(&mut self) -> impl Iterator<Item = &mut F> {\n        let mut bitmap = vec![false; self.all_fairings.len()];\n        for &i in self.active() {\n            let is_target = self.all_fairings.get(i)\n                .and_then(|f| f.downcast_ref::<F>())\n                .is_some();\n\n            bitmap.get_mut(i).map(|target| *target = is_target);\n        }\n\n        self.all_fairings.iter_mut()\n            .enumerate()\n            .filter(move |(i, _)| *bitmap.get(*i).unwrap_or(&false))\n            .filter_map(|(_, f)| f.downcast_mut::<F>())\n    }\n}\n\nimpl std::fmt::Debug for Fairings {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        fn debug_info<'a>(iter: impl Iterator<Item = &'a dyn Fairing>) -> Vec<Info> {\n            iter.map(|f| f.info()).collect()\n        }\n\n        f.debug_struct(\"Fairings\")\n            .field(\"launch\", &debug_info(iter!(self.ignite)))\n            .field(\"liftoff\", &debug_info(iter!(self.liftoff)))\n            .field(\"request\", &debug_info(iter!(self.request)))\n            .field(\"response\", &debug_info(iter!(self.response)))\n            .field(\"shutdown\", &debug_info(iter!(self.shutdown)))\n            .finish()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fairing/info_kind.rs",
    "content": "use std::ops::BitOr;\n\n/// Information about a [`Fairing`](crate::fairing::Fairing).\n///\n/// The `name` field is an arbitrary name for a fairing. The `kind` field is a\n/// is an `or`d set of [`Kind`] structures. Rocket uses the values set in `Kind`\n/// to determine which callbacks from a given `Fairing` implementation to\n/// actually call.\n///\n/// # Example\n///\n/// A simple `Info` structure that can be used for a `Fairing` that implements\n/// all callbacks:\n///\n/// ```\n/// use rocket::fairing::{Info, Kind};\n///\n/// # let _unused_info =\n/// Info {\n///     name: \"Example Fairing\",\n///     kind: Kind::Ignite | Kind::Liftoff | Kind::Request | Kind::Response | Kind::Shutdown\n/// }\n/// # ;\n/// ```\n#[derive(Debug, Copy, Clone)]\npub struct Info {\n    /// The name of the fairing.\n    pub name: &'static str,\n    /// A set representing the callbacks the fairing wishes to receive.\n    pub kind: Kind,\n}\n\n/// A bitset representing the kinds of callbacks a\n/// [`Fairing`](crate::fairing::Fairing) wishes to receive.\n///\n/// A fairing can request any combination of any of the following kinds of\n/// callbacks:\n///\n///   * Ignite\n///   * Liftoff\n///   * Request\n///   * Response\n///   * Shutdown\n///\n/// Two `Kind` structures can be `or`d together to represent a combination. For\n/// instance, to represent a fairing that is both an ignite and request fairing,\n/// use `Kind::Ignite | Kind::Request`. Similarly, to represent a fairing that\n/// is only an ignite fairing, use `Kind::Ignite`.\n///\n/// Additionally, a fairing can request to be treated as a\n/// [singleton](crate::fairing::Fairing#singletons) by specifying the\n/// `Singleton` kind.\n#[derive(Debug, Clone, Copy)]\npub struct Kind(usize);\n\n#[allow(non_upper_case_globals)]\nimpl Kind {\n    /// `Kind` flag representing a request for a 'ignite' callback.\n    pub const Ignite: Kind = Kind(1 << 0);\n\n    /// `Kind` flag representing a request for a 'liftoff' callback.\n    pub const Liftoff: Kind = Kind(1 << 1);\n\n    /// `Kind` flag representing a request for a 'request' callback.\n    pub const Request: Kind = Kind(1 << 2);\n\n    /// `Kind` flag representing a request for a 'response' callback.\n    pub const Response: Kind = Kind(1 << 3);\n\n    /// `Kind` flag representing a request for a 'shutdown' callback.\n    pub const Shutdown: Kind = Kind(1 << 4);\n\n    /// `Kind` flag representing a\n    /// [singleton](crate::fairing::Fairing#singletons) fairing.\n    pub const Singleton: Kind = Kind(1 << 5);\n\n    /// Returns `true` if `self` is a superset of `other`. In other words,\n    /// returns `true` if all of the kinds in `other` are also in `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::Kind;\n    ///\n    /// let ignite_and_req = Kind::Ignite | Kind::Request;\n    /// assert!(ignite_and_req.is(Kind::Ignite | Kind::Request));\n    ///\n    /// assert!(ignite_and_req.is(Kind::Ignite));\n    /// assert!(ignite_and_req.is(Kind::Request));\n    ///\n    /// assert!(!ignite_and_req.is(Kind::Liftoff));\n    /// assert!(!ignite_and_req.is(Kind::Response));\n    /// assert!(!ignite_and_req.is(Kind::Ignite | Kind::Response));\n    /// assert!(!ignite_and_req.is(Kind::Ignite | Kind::Request | Kind::Response));\n    /// ```\n    #[inline]\n    pub fn is(self, other: Kind) -> bool {\n        (other.0 & self.0) == other.0\n    }\n\n    /// Returns `true` if `self` is exactly `other`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::Kind;\n    ///\n    /// let ignite_and_req = Kind::Ignite | Kind::Request;\n    /// assert!(ignite_and_req.is_exactly(Kind::Ignite | Kind::Request));\n    ///\n    /// assert!(!ignite_and_req.is_exactly(Kind::Ignite));\n    /// assert!(!ignite_and_req.is_exactly(Kind::Request));\n    /// assert!(!ignite_and_req.is_exactly(Kind::Response));\n    /// assert!(!ignite_and_req.is_exactly(Kind::Ignite | Kind::Response));\n    /// ```\n    #[inline]\n    pub fn is_exactly(self, other: Kind) -> bool {\n        self.0 == other.0\n    }\n}\n\nimpl BitOr for Kind {\n    type Output = Self;\n\n    #[inline(always)]\n    fn bitor(self, rhs: Self) -> Self {\n        Kind(self.0 | rhs.0)\n    }\n}\n\nimpl std::fmt::Display for Kind {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let mut is_first = true;\n        let mut write = |string, kind| {\n            if self.is(kind) {\n                if !is_first { f.write_str(\", \")?; }\n                f.write_str(string)?;\n                is_first = false;\n            }\n\n            Ok(())\n        };\n\n        write(\"ignite\", Kind::Ignite)?;\n        write(\"liftoff\", Kind::Liftoff)?;\n        write(\"request\", Kind::Request)?;\n        write(\"response\", Kind::Response)?;\n        write(\"shutdown\", Kind::Shutdown)?;\n        write(\"singleton\", Kind::Singleton)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fairing/mod.rs",
    "content": "//! Fairings: callbacks at launch, liftoff, request, and response time.\n//!\n//! Fairings allow for structured interposition at various points in the\n//! application lifetime. Fairings can be seen as a restricted form of\n//! \"middleware\". A fairing is an arbitrary structure with methods representing\n//! callbacks that Rocket will run at requested points in a program. You can use\n//! fairings to rewrite or record information about requests and responses, or\n//! to perform an action once a Rocket application has launched.\n//!\n//! To learn more about writing a fairing, see the [`Fairing`] trait\n//! documentation. You can also use [`AdHoc`] to create a fairing on-the-fly\n//! from a closure or function.\n//!\n//! ## Attaching\n//!\n//! You must inform Rocket about fairings that you wish to be active by calling\n//! [`Rocket::attach()`] method on the application's [`Rocket`] instance and\n//! passing in the appropriate [`Fairing`]. For instance, to attach fairings\n//! named `req_fairing` and `res_fairing` to a new Rocket instance, you might\n//! write:\n//!\n//! ```rust\n//! # use rocket::fairing::AdHoc;\n//! # let req_fairing = AdHoc::on_request(\"Request\", |_, _| Box::pin(async move {}));\n//! # let res_fairing = AdHoc::on_response(\"Response\", |_, _| Box::pin(async move {}));\n//! let rocket = rocket::build()\n//!     .attach(req_fairing)\n//!     .attach(res_fairing);\n//! ```\n//!\n//! Once a fairing is attached, Rocket will execute it at the appropriate time,\n//! which varies depending on the fairing implementation. See the [`Fairing`]\n//! trait documentation for more information on the dispatching of fairing\n//! methods.\n//!\n//! [`Fairing`]: crate::fairing::Fairing\n//!\n//! ## Ordering\n//!\n//! `Fairing`s are executed in the order in which they are attached: the first\n//! attached fairing has its callbacks executed before all others. A fairing can\n//! be attached any number of times. Except for [singleton\n//! fairings](Fairing#singletons), all attached instances are polled at runtime.\n//! Fairing callbacks may not be commutative; the order in which fairings are\n//! attached may be significant. It is thus important to communicate specific\n//! fairing functionality clearly.\n//!\n//! Furthermore, a `Fairing` should take care to act locally so that the actions\n//! of other `Fairings` are not jeopardized. For instance, unless it is made\n//! abundantly clear, a fairing should not rewrite every request.\n\nuse std::any::Any;\n\nuse crate::{Rocket, Request, Response, Data, Build, Orbit};\n\nmod fairings;\nmod ad_hoc;\nmod info_kind;\n\npub(crate) use self::fairings::Fairings;\npub use self::ad_hoc::AdHoc;\npub use self::info_kind::{Info, Kind};\n\n/// A type alias for the return `Result` type of [`Fairing::on_ignite()`].\npub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E>;\n\n// We might imagine that a request fairing returns an `Outcome`. If it returns\n// `Success`, we don't do any routing and use that response directly. Same if it\n// returns `Error`. We only route if it returns `Forward`. I've chosen not to\n// go this direction because I feel like request guards are the correct\n// mechanism to use here. In other words, enabling this at the fairing level\n// encourages implicit handling, a bad practice. Fairings can still, however,\n// return a default `Response` if routing fails via a response fairing. For\n// instance, to automatically handle preflight in CORS, a response fairing can\n// check that the user didn't handle the `OPTIONS` request (404) and return an\n// appropriate response. This allows the users to handle `OPTIONS` requests\n// when they'd like but default to the fairing when they don't want to.\n\n/// Trait implemented by fairings: Rocket's structured middleware.\n///\n/// # Considerations\n///\n/// Fairings are a large hammer that can easily be abused and misused. If you\n/// are considering writing a `Fairing` implementation, first consider if it is\n/// appropriate to do so. While middleware is often the best solution to some\n/// problems in other frameworks, it is often a suboptimal solution in Rocket.\n/// This is because Rocket provides richer mechanisms such as [request guards]\n/// and [data guards] that can be used to accomplish the same objective in a\n/// cleaner, more composable, and more robust manner.\n///\n/// As a general rule of thumb, only _globally applicable actions_ should be\n/// implemented via fairings. For instance, you should _not_ use a fairing to\n/// implement authentication or authorization (preferring to use a [request\n/// guard] instead) _unless_ the authentication or authorization applies to the\n/// entire application. On the other hand, you _should_ use a fairing to record\n/// timing and/or usage statistics or to implement global security policies.\n///\n/// [request guard]: crate::request::FromRequest\n/// [request guards]: crate::request::FromRequest\n/// [data guards]: crate::data::FromData\n///\n/// ## Fairing Callbacks\n///\n/// There are five kinds of fairing callbacks: launch, liftoff, request,\n/// response, and shutdown. A fairing can request any combination of these\n/// callbacks through the `kind` field of the [`Info`] structure returned from\n/// the `info` method. Rocket will only invoke the callbacks identified in the\n/// fairing's [`Kind`].\n///\n/// The callback kinds are as follows:\n///\n///   * **<a name=\"ignite\">Ignite</a> (`on_ignite`)**\n///\n///     An ignite callback, represented by the [`Fairing::on_ignite()`] method,\n///     is called just prior to liftoff, during ignition. The state of the\n///     `Rocket` instance is, at this point, not finalized, as it may be\n///     modified at will by other ignite fairings.\n///\n///     All ignite callbacks are executed in breadth-first `attach()` order. A\n///     callback `B` executing after a callback `A` can view changes made by `A`\n///     but not vice-versa.\n///\n///     An ignite callback can arbitrarily modify the `Rocket` instance being\n///     constructed. It should take care not to introduce infinite recursion by\n///     recursively attaching ignite fairings. It returns `Ok` if it would like\n///     ignition and launch to proceed nominally and `Err` otherwise. If an\n///     ignite fairing returns `Err`, launch will be aborted. All ignite\n///     fairings are executed even if one or more signal an error.\n///\n///   * **<a name=\"liftoff\">Liftoff</a> (`on_liftoff`)**\n///\n///     A liftoff callback, represented by the [`Fairing::on_liftoff()`] method,\n///     is called immediately after a Rocket application has launched. At this\n///     point, Rocket has opened a socket for listening but has not yet begun\n///     accepting connections. A liftoff callback can inspect the `Rocket`\n///     instance that has launched and even schedule a shutdown using\n///     [`Shutdown::notify()`](crate::Shutdown::notify()) via\n///     [`Rocket::shutdown()`].\n///\n///     Liftoff fairings are run concurrently; resolution of all fairings is\n///     awaited before resuming request serving.\n///\n///   * **<a name=\"request\">Request</a> (`on_request`)**\n///\n///     A request callback, represented by the [`Fairing::on_request()`] method,\n///     is called just after a request is received, immediately after\n///     pre-processing the request with method changes due to `_method` form\n///     fields. At this point, Rocket has parsed the incoming HTTP request into\n///     [`Request`] and [`Data`] structures but has not routed the request. A\n///     request callback can modify the request at will and [`Data::peek()`]\n///     into the incoming data. It may not, however, abort or respond directly\n///     to the request; these issues are better handled via [request guards] or\n///     via response callbacks. Any modifications to a request are persisted and\n///     can potentially alter how a request is routed.\n///\n///   * **<a name=\"response\">Response</a> (`on_response`)**\n///\n///     A response callback, represented by the [`Fairing::on_response()`]\n///     method, is called when a response is ready to be sent to the client. At\n///     this point, Rocket has completed all routing, including to error\n///     catchers, and has generated the would-be final response. A response\n///     callback can modify the response at will. For example, a response\n///     callback can provide a default response when the user fails to handle\n///     the request by checking for 404 responses. Note that a given `Request`\n///     may have changed between `on_request` and `on_response` invocations.\n///     Apart from any change made by other fairings, Rocket sets the method for\n///     `HEAD` requests to `GET` if there is no matching `HEAD` handler for that\n///     request. Additionally, Rocket will automatically strip the body for\n///     `HEAD` requests _after_ response fairings have run.\n///\n///   * **<a name=\"shutdown\">Shutdown</a> (`on_shutdown`)**\n///\n///     A shutdown callback, represented by the [`Fairing::on_shutdown()`]\n///     method, is called when [shutdown is triggered]. At this point, graceful\n///     shutdown has commenced but not completed; no new requests are accepted\n///     but the application may still be actively serving existing requests.\n///\n///     Rocket guarantees, however, that all requests are completed or aborted\n///     once [grace and mercy periods] have expired. This implies that a\n///     shutdown fairing that (asynchronously) sleeps for `grace + mercy + ε`\n///     seconds before executing any logic will execute said logic after all\n///     requests have been processed or aborted. Note that such fairings may\n///     wish to operate using the `Ok` return value of [`Rocket::launch()`]\n///     instead.\n///\n///     All registered shutdown fairings are run concurrently; resolution of all\n///     fairings is awaited before resuming shutdown. Shutdown fairings do not\n///     affect grace and mercy periods. In other words, any time consumed by\n///     shutdown fairings is not added to grace and mercy periods.\n///\n///     ***Note: Shutdown fairings are only run during testing if the `Client`\n///     is terminated using [`Client::terminate()`].***\n///\n///     [shutdown is triggered]: crate::config::ShutdownConfig#triggers\n///     [grace and mercy periods]: crate::config::ShutdownConfig#summary\n///     [`Client::terminate()`]: crate::local::blocking::Client::terminate()\n///\n/// # Singletons\n///\n/// In general, any number of instances of a given fairing type can be attached\n/// to one instance of `Rocket`. If this is not desired, a fairing can request\n/// to be a singleton by specifying [`Kind::Singleton`]. Only the _last_\n/// attached instance of a singleton will be preserved at ignite-time. That is,\n/// an attached singleton instance will replace any previously attached\n/// instance. The [`Shield`](crate::shield::Shield) fairing is an example of a\n/// singleton fairing.\n///\n/// # Implementing\n///\n/// A `Fairing` implementation has one required method: [`info`]. A `Fairing`\n/// can also implement any of the available callbacks: `on_ignite`, `on_liftoff`,\n/// `on_request`, and `on_response`. A `Fairing` _must_ set the appropriate\n/// callback kind in the `kind` field of the returned `Info` structure from\n/// [`info`] for a callback to actually be called by Rocket.\n///\n/// ## Fairing `Info`\n///\n/// Every `Fairing` must implement the [`info`] method, which returns an\n/// [`Info`] structure. This structure is used by Rocket to:\n///\n///   1. Assign a name to the `Fairing`.\n///\n///      This is the `name` field, which can be any arbitrary string. Name your\n///      fairing something illustrative. The name will be logged during the\n///      application's ignition procedures.\n///\n///   2. Determine which callbacks to actually issue on the `Fairing`.\n///\n///      This is the `kind` field of type [`Kind`]. This field is a bitset that\n///      represents the kinds of callbacks the fairing wishes to receive. Rocket\n///      will only invoke the callbacks that are flagged in this set. `Kind`\n///      structures can be `or`d together to represent any combination of kinds\n///      of callbacks. For instance, to request liftoff and response callbacks,\n///      return a `kind` field with the value `Kind::Liftoff | Kind::Response`.\n///\n/// [`info`]: Fairing::info()\n///\n/// ## Restrictions\n///\n/// A `Fairing` must be [`Send`] + [`Sync`] + `'static`. This means that the\n/// fairing must be sendable across thread boundaries (`Send`), thread-safe\n/// (`Sync`), and have only `'static` references, if any (`'static`). Note that\n/// these bounds _do not_ prohibit a `Fairing` from holding state: the state\n/// need simply be thread-safe and statically available or heap allocated.\n///\n/// ## Async Trait\n///\n/// [`Fairing`] is an _async_ trait. Implementations of `Fairing` must be\n/// decorated with an attribute of `#[rocket::async_trait]`:\n///\n/// ```rust\n/// use rocket::{Rocket, Request, Data, Response, Build, Orbit};\n/// use rocket::fairing::{self, Fairing, Info, Kind};\n///\n/// # struct MyType;\n/// #[rocket::async_trait]\n/// impl Fairing for MyType {\n///     fn info(&self) -> Info {\n///         /* ... */\n///         # unimplemented!()\n///     }\n///\n///     async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {\n///         /* ... */\n///         # unimplemented!()\n///     }\n///\n///     async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {\n///         /* ... */\n///         # unimplemented!()\n///     }\n///\n///     async fn on_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {\n///         /* ... */\n///         # unimplemented!()\n///     }\n///\n///     async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {\n///         /* ... */\n///         # unimplemented!()\n///     }\n///\n///     async fn on_shutdown(&self, rocket: &Rocket<Orbit>) {\n///         /* ... */\n///         # unimplemented!()\n///     }\n/// }\n/// ```\n///\n/// ## Example\n///\n/// As an example, we want to record the number of `GET` and `POST` requests\n/// that our application has received. While we could do this with [request\n/// guards] and [managed state](crate::State), it would require us to annotate\n/// every `GET` and `POST` request with custom types, polluting handler\n/// signatures. Instead, we can create a simple fairing that acts globally.\n///\n/// The `Counter` fairing below records the number of all `GET` and `POST`\n/// requests received. It makes these counts available at a special `'/counts'`\n/// path.\n///\n/// ```rust\n/// use std::future::Future;\n/// use std::io::Cursor;\n/// use std::pin::Pin;\n/// use std::sync::atomic::{AtomicUsize, Ordering};\n///\n/// use rocket::{Request, Data, Response};\n/// use rocket::fairing::{Fairing, Info, Kind};\n/// use rocket::http::{Method, ContentType, Status};\n///\n/// #[derive(Default)]\n/// struct Counter {\n///     get: AtomicUsize,\n///     post: AtomicUsize,\n/// }\n///\n/// #[rocket::async_trait]\n/// impl Fairing for Counter {\n///     fn info(&self) -> Info {\n///         Info {\n///             name: \"GET/POST Counter\",\n///             kind: Kind::Request | Kind::Response\n///         }\n///     }\n///\n///     async fn on_request(&self, req: &mut Request<'_>, _: &mut Data<'_>) {\n///         if req.method() == Method::Get {\n///             self.get.fetch_add(1, Ordering::Relaxed);\n///         } else if req.method() == Method::Post {\n///             self.post.fetch_add(1, Ordering::Relaxed);\n///         }\n///     }\n///\n///     async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {\n///         // Don't change a successful user's response, ever.\n///         if res.status() != Status::NotFound {\n///             return\n///         }\n///\n///         if req.method() == Method::Get && req.uri().path() == \"/counts\" {\n///             let get_count = self.get.load(Ordering::Relaxed);\n///             let post_count = self.post.load(Ordering::Relaxed);\n///\n///             let body = format!(\"Get: {}\\nPost: {}\", get_count, post_count);\n///             res.set_status(Status::Ok);\n///             res.set_header(ContentType::Plain);\n///             res.set_sized_body(body.len(), Cursor::new(body));\n///         }\n///     }\n/// }\n/// ```\n///\n/// ## Request-Local State\n///\n/// Fairings can use [request-local state] to persist or carry data between\n/// requests and responses, or to pass data to a request guard.\n///\n/// As an example, the following fairing uses request-local state to time\n/// requests, setting an `X-Response-Time` header on all responses with the\n/// elapsed time. It also exposes the start time of a request via a `StartTime`\n/// request guard.\n///\n/// ```rust\n/// # use std::future::Future;\n/// # use std::pin::Pin;\n/// # use std::time::{Duration, SystemTime};\n/// # use rocket::{Request, Data, Response};\n/// # use rocket::fairing::{Fairing, Info, Kind};\n/// # use rocket::http::Status;\n/// # use rocket::request::{self, FromRequest};\n/// #\n/// /// Fairing for timing requests.\n/// pub struct RequestTimer;\n///\n/// /// Value stored in request-local state.\n/// #[derive(Copy, Clone)]\n/// struct TimerStart(Option<SystemTime>);\n///\n/// #[rocket::async_trait]\n/// impl Fairing for RequestTimer {\n///     fn info(&self) -> Info {\n///         Info {\n///             name: \"Request Timer\",\n///             kind: Kind::Request | Kind::Response\n///         }\n///     }\n///\n///     /// Stores the start time of the request in request-local state.\n///     async fn on_request(&self, request: &mut Request<'_>, _: &mut Data<'_>) {\n///         // Store a `TimerStart` instead of directly storing a `SystemTime`\n///         // to ensure that this usage doesn't conflict with anything else\n///         // that might store a `SystemTime` in request-local cache.\n///         request.local_cache(|| TimerStart(Some(SystemTime::now())));\n///     }\n///\n///     /// Adds a header to the response indicating how long the server took to\n///     /// process the request.\n///     async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {\n///         let start_time = req.local_cache(|| TimerStart(None));\n///         if let Some(Ok(duration)) = start_time.0.map(|st| st.elapsed()) {\n///             let ms = duration.as_secs() * 1000 + duration.subsec_millis() as u64;\n///             res.set_raw_header(\"X-Response-Time\", format!(\"{} ms\", ms));\n///         }\n///     }\n/// }\n///\n/// /// Request guard used to retrieve the start time of a request.\n/// #[derive(Copy, Clone)]\n/// pub struct StartTime(pub SystemTime);\n///\n/// // Allows a route to access the time a request was initiated.\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for StartTime {\n///     type Error = ();\n///\n///     async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {\n///         match *request.local_cache(|| TimerStart(None)) {\n///             TimerStart(Some(time)) => request::Outcome::Success(StartTime(time)),\n///             TimerStart(None) => request::Outcome::Error((Status::InternalServerError, ())),\n///         }\n///     }\n/// }\n/// ```\n///\n/// [request-local state]: https://rocket.rs/master/guide/state/#request-local-state\n#[crate::async_trait]\npub trait Fairing: Send + Sync + AsAny + 'static {\n    /// Returns an [`Info`] structure containing the `name` and [`Kind`] of this\n    /// fairing. The `name` can be any arbitrary string. `Kind` must be an `or`d\n    /// set of `Kind` variants.\n    ///\n    /// This is the only required method of a `Fairing`. All other methods have\n    /// no-op default implementations.\n    ///\n    /// Rocket will only dispatch callbacks to this fairing for the kinds in the\n    /// `kind` field of the returned `Info` structure. For instance, if\n    /// `Kind::Ignite | Kind::Request` is used, then Rocket will only call the\n    /// `on_ignite` and `on_request` methods of the fairing. Similarly, if\n    /// `Kind::Response` is used, Rocket will only call the `on_response` method\n    /// of this fairing.\n    ///\n    /// # Example\n    ///\n    /// An `info` implementation for `MyFairing`: a fairing named \"My Custom\n    /// Fairing\" that is both an ignite and response fairing.\n    ///\n    /// ```rust\n    /// use rocket::fairing::{Fairing, Info, Kind};\n    ///\n    /// struct MyFairing;\n    ///\n    /// impl Fairing for MyFairing {\n    ///     fn info(&self) -> Info {\n    ///         Info {\n    ///             name: \"My Custom Fairing\",\n    ///             kind: Kind::Ignite | Kind::Response\n    ///         }\n    ///     }\n    /// }\n    /// ```\n    fn info(&self) -> Info;\n\n    /// The ignite callback. Returns `Ok` if ignition should proceed and `Err`\n    /// if ignition and launch should be aborted.\n    ///\n    /// See [Fairing Callbacks](#ignite) for complete semantics.\n    ///\n    /// This method is called during ignition and if `Kind::Ignite` is in the\n    /// `kind` field of the `Info` structure for this fairing. The `rocket`\n    /// parameter is the `Rocket` instance that is currently being built for\n    /// this application.\n    ///\n    /// ## Default Implementation\n    ///\n    /// The default implementation of this method simply returns `Ok(rocket)`.\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> Result { Ok(rocket) }\n\n    /// The liftoff callback.\n    ///\n    /// See [Fairing Callbacks](#liftoff) for complete semantics.\n    ///\n    /// This method is called just after launching the application if\n    /// `Kind::Liftoff` is in the `kind` field of the `Info` structure for this\n    /// fairing. The `Rocket` parameter corresponds to the launched application.\n    ///\n    /// ## Default Implementation\n    ///\n    /// The default implementation of this method does nothing.\n    async fn on_liftoff(&self, _rocket: &Rocket<Orbit>) { }\n\n    /// The request callback.\n    ///\n    /// See [Fairing Callbacks](#request) for complete semantics.\n    ///\n    /// This method is called when a new request is received if `Kind::Request`\n    /// is in the `kind` field of the `Info` structure for this fairing. The\n    /// `&mut Request` parameter is the incoming request, and the `&Data`\n    /// parameter is the incoming data in the request.\n    ///\n    /// ## Default Implementation\n    ///\n    /// The default implementation of this method does nothing.\n    async fn on_request(&self, _req: &mut Request<'_>, _data: &mut Data<'_>) {}\n\n    /// The response callback.\n    ///\n    /// See [Fairing Callbacks](#response) for complete semantics.\n    ///\n    /// This method is called when a response is ready to be issued to a client\n    /// if `Kind::Response` is in the `kind` field of the `Info` structure for\n    /// this fairing. The `&Request` parameter is the request that was routed,\n    /// and the `&mut Response` parameter is the resulting response.\n    ///\n    /// ## Default Implementation\n    ///\n    /// The default implementation of this method does nothing.\n    async fn on_response<'r>(&self, _req: &'r Request<'_>, _res: &mut Response<'r>) {}\n\n    /// The shutdown callback.\n    ///\n    /// See [Fairing Callbacks](#shutdown) for complete semantics.\n    ///\n    /// This method is called when [shutdown is triggered] if `Kind::Shutdown`\n    /// is in the `kind` field of the `Info` structure for this fairing. The\n    /// `Rocket` parameter corresponds to the running application.\n    ///\n    /// [shutdown is triggered]: crate::config::ShutdownConfig#triggers\n    ///\n    /// ## Default Implementation\n    ///\n    /// The default implementation of this method does nothing.\n    async fn on_shutdown(&self, _rocket: &Rocket<Orbit>) { }\n}\n\npub trait AsAny: Any {\n    fn as_any_ref(&self) -> &dyn Any;\n    fn as_any_mut(&mut self) -> &mut dyn Any;\n}\n\n#[crate::async_trait]\nimpl<T: Fairing + ?Sized> Fairing for std::sync::Arc<T> {\n    #[inline]\n    fn info(&self) -> Info {\n        (self as &T).info()\n    }\n\n    #[inline]\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> Result {\n        (self as &T).on_ignite(rocket).await\n    }\n\n    #[inline]\n    async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {\n        (self as &T).on_liftoff(rocket).await\n    }\n\n    #[inline]\n    async fn on_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {\n        (self as &T).on_request(req, data).await\n    }\n\n    #[inline]\n    async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {\n        (self as &T).on_response(req, res).await\n    }\n\n    #[inline]\n    async fn on_shutdown(&self, rocket: &Rocket<Orbit>) {\n        (self as &T).on_shutdown(rocket).await\n    }\n}\n\nimpl<T: Any> AsAny for T {\n    fn as_any_ref(&self) -> &dyn Any { self }\n    fn as_any_mut(&mut self) -> &mut dyn Any { self }\n}\n\nimpl dyn Fairing {\n    fn downcast_ref<T: Any>(&self) -> Option<&T> {\n        self.as_any_ref().downcast_ref()\n    }\n\n    fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {\n        self.as_any_mut().downcast_mut()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/buffer.rs",
    "content": "use std::ops::{Index, RangeFrom, RangeTo};\nuse std::cell::UnsafeCell;\n\nuse parking_lot::{RawMutex, lock_api::RawMutex as _};\n\nmod private {\n    /// Sealed trait for types that can be shared in a `SharedStack`.\n    ///\n    /// The type of values passed to\n    /// [`local_cache`](crate::request::local_cache) must implement this trait.\n    /// Since this trait is sealed, the types implementing this trait are known\n    /// and finite: `String` and `Vec<T> for all T: Sync + Send + 'static`.\n    ///\n    /// # Safety\n    ///\n    /// Types implementing this trait must have a stable address when deref'd.\n    pub unsafe trait Shareable: std::ops::Deref + Sync + Send + 'static {\n        /// The current size of the owned shareable.\n        fn size(&self) -> usize;\n    }\n\n    unsafe impl Shareable for String {\n        fn size(&self) -> usize { self.len() }\n    }\n\n    unsafe impl<T: Send + Sync + 'static> Shareable for Vec<T> {\n        fn size(&self) -> usize { self.len() }\n    }\n}\n\npub use private::Shareable;\n\n/// A stack of strings (chars of bytes) that can be shared between threads while\n/// remaining internally mutable and while allowing references into the stack to\n/// persist across mutations.\npub struct SharedStack<T: Shareable> {\n    stack: UnsafeCell<Vec<T>>,\n    mutex: RawMutex,\n}\n\nimpl<T: Shareable> SharedStack<T>\n    where T::Target: Index<RangeFrom<usize>, Output = T::Target>\n                     + Index<RangeTo<usize>, Output = T::Target>\n{\n    /// Creates a new stack.\n    pub fn new() -> Self {\n        SharedStack {\n            stack: UnsafeCell::new(vec![]),\n            mutex: RawMutex::INIT,\n        }\n    }\n\n    /// Pushes the string `S` onto the stack. Returns a reference of the string\n    /// in the stack.\n    pub(crate) fn push<S: Into<T>>(&self, string: S) -> &T::Target {\n        // SAFETY:\n        //   * Aliasing: We retrieve a mutable reference to the last slot (via\n        //     `push()`) and then return said reference as immutable; these\n        //     occur in serial, so they don't alias. This method accesses a\n        //     unique slot each call: the last slot, subsequently replaced by\n        //     `push()` each next call. No other method accesses the internal\n        //     buffer directly. Thus, the outstanding reference to the last slot\n        //     is never accessed again mutably, preserving aliasing guarantees.\n        //   * Liveness: The returned reference is to a `String`; we must ensure\n        //     that the `String` is never dropped while `self` lives. This is\n        //     guaranteed by returning a reference with the same lifetime as\n        //     `self`, so `self` can't be dropped while the string is live, and\n        //     by never removing elements from the internal `Vec` thus not\n        //     dropping `String` itself: `push()` is the only mutating operation\n        //     called on `Vec`, which preserves all previous elements; the\n        //     stability of `String` itself means that the returned address\n        //     remains valid even after internal realloc of `Vec`.\n        //   * Thread-Safety: Parallel calls to `push_one` without exclusion\n        //     would result in a race to `vec.push()`; `RawMutex` ensures that\n        //     this doesn't occur.\n        unsafe {\n            self.mutex.lock();\n            let vec: &mut Vec<T> = &mut *self.stack.get();\n            vec.push(string.into());\n            let last = vec.last().expect(\"push() => non-empty\");\n            self.mutex.unlock();\n            last\n        }\n    }\n\n    /// Just like `push` but `string` must already be the owned `T`.\n    pub fn push_owned(&self, string: T) -> &T::Target {\n        self.push(string)\n    }\n\n    /// Pushes the string `S` onto the stack which is assumed to internally\n    /// contain two strings with the first string being of length `n`. Returns\n    /// references to the two strings on the stack.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `string.len() < len`.\n    pub(crate) fn push_split<S: Into<T>>(&self, string: S, n: usize) -> (&T::Target, &T::Target) {\n        let buffered = self.push(string);\n        let a = &buffered[..n];\n        let b = &buffered[n..];\n        (a, b)\n    }\n\n    /// Pushes the strings `a` and `b` onto the stack without allocating for\n    /// both strings. Returns references to the two strings on the stack.\n    pub(crate) fn push_two<V>(&self, a: V, b: V) -> (&T::Target, &T::Target)\n        where T: From<V> + Extend<V>,\n    {\n        let mut value = T::from(a);\n        let split_len = value.size();\n        value.extend(Some(b));\n        self.push_split(value, split_len)\n    }\n}\n\nunsafe impl<T: Shareable> Sync for SharedStack<T> {}\n"
  },
  {
    "path": "core/lib/src/form/context.rs",
    "content": "use serde::Serialize;\nuse indexmap::{IndexMap, IndexSet};\n\nuse crate::form::prelude::*;\nuse crate::http::Status;\n\n/// An infallible form guard that records form fields and errors during parsing.\n///\n/// This form guard _never fails_. It should be use _only_ when the form\n/// [`Context`] is required. In all other cases, prefer to use `T` directly.\n///\n/// # Usage\n///\n/// `Contextual` acts as a proxy for any form type, recording all submitted form\n/// values and produced errors and associating them with their corresponding\n/// field name. `Contextual` is particularly useful for rendering forms with\n/// previously submitted values and errors associated with form input.\n///\n/// To retrieve the context for a form, use `Form<Contextual<'_, T>>` as a data\n/// guard, where `T` implements `FromForm`. The `context` field contains the\n/// form's [`Context`]:\n///\n/// ```rust\n/// # use rocket::post;\n/// # type T = String;\n/// use rocket::form::{Form, Contextual};\n///\n/// #[post(\"/submit\", data = \"<form>\")]\n/// fn submit(form: Form<Contextual<'_, T>>) {\n///     if let Some(ref value) = form.value {\n///         // The form parsed successfully. `value` is the `T`.\n///     }\n///\n///     // We can retrieve raw field values and errors.\n///     let raw_id_value = form.context.field_value(\"id\");\n///     let id_errors = form.context.field_errors(\"id\");\n/// }\n/// ```\n///\n/// `Context` serializes as a map, so it can be rendered in templates that\n/// require `Serialize` types. See the [forms guide] for further usage details.\n///\n/// [forms guide]: https://rocket.rs/master/guide/requests/#context\n#[derive(Debug)]\npub struct Contextual<'v, T> {\n    /// The value, if it was successfully parsed, or `None` otherwise.\n    pub value: Option<T>,\n    /// The context with all submitted fields and associated values and errors.\n    pub context: Context<'v>,\n}\n\n/// A form context containing received fields, values, and encountered errors.\n///\n/// A value of this type is produced by the [`Contextual`] form guard in its\n/// [`context`](Contextual::context) field. `Context` contains an entry for\n/// every form field submitted by the client regardless of whether the field\n/// parsed or validated successfully.\n///\n/// # Field Values\n///\n/// The original, submitted field value(s) for a _value_ field can be retrieved\n/// via [`Context::field_value()`] or [`Context::field_values()`]. Data fields do not have\n/// their values recorded. All submitted field names, including data field\n/// names, can be retrieved via [`Context::fields()`].\n///\n/// # Field Errors\n///\n/// # Serialization\n///\n/// When a value of this type is serialized, a `struct` or map with the\n/// following fields is emitted:\n///\n/// | field         | type                               | description                          |\n/// |---------------|------------------------------------|--------------------------------------|\n/// | `errors`      | map: string to array of [`Error`]s | maps a field name to its errors      |\n/// | `values`      | map: string to array of strings    | maps a field name to its form values |\n/// | `data_fields` | array of strings                   | field names of all form data fields  |\n/// | `form_errors` | array of [`Error`]s                | errors not associated with a field   |\n///\n/// See [`Error`](Error#serialization) for `Error` serialization details.\n#[derive(Debug, Default, Serialize)]\npub struct Context<'v> {\n    errors: IndexMap<NameBuf<'v>, Errors<'v>>,\n    values: IndexMap<&'v Name, Vec<&'v str>>,\n    data_fields: IndexSet<&'v Name>,\n    form_errors: Errors<'v>,\n    #[serde(skip)]\n    status: Status,\n}\n\nimpl<'v> Context<'v> {\n    /// Returns the names of all submitted form fields, both _value_ and _data_\n    /// fields.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::form::{Form, Contextual};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Contextual<'_, T>>) {\n    ///     let field_names = form.context.fields();\n    /// }\n    /// ```\n    pub fn fields(&self) -> impl Iterator<Item = &'v Name> + '_ {\n        self.values.iter()\n            .map(|(name, _)| *name)\n            .chain(self.data_fields.iter().copied())\n    }\n\n    /// Returns the _first_ value, if any, submitted for the _value_ field named\n    /// `name`.\n    ///\n    /// The type of `name` may be `&Name`, `&str`, or `&RawStr`. Lookup is\n    /// case-sensitive but key-separator (`.` or `[]`) insensitive.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::form::{Form, Contextual};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Contextual<'_, T>>) {\n    ///     let first_value_for_id = form.context.field_value(\"id\");\n    ///     let first_value_for_foo_bar = form.context.field_value(\"foo.bar\");\n    /// }\n    /// ```\n    pub fn field_value<N: AsRef<Name>>(&self, name: N) -> Option<&'v str> {\n        self.values.get(name.as_ref())?.first().cloned()\n    }\n\n    /// Returns the values, if any, submitted for the _value_ field named\n    /// `name`.\n    ///\n    /// The type of `name` may be `&Name`, `&str`, or `&RawStr`. Lookup is\n    /// case-sensitive but key-separator (`.` or `[]`) insensitive.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::form::{Form, Contextual};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Contextual<'_, T>>) {\n    ///     let values_for_id = form.context.field_values(\"id\");\n    ///     let values_for_foo_bar = form.context.field_values(\"foo.bar\");\n    /// }\n    /// ```\n    pub fn field_values<N>(&self, name: N) -> impl Iterator<Item = &'v str> + '_\n        where N: AsRef<Name>\n    {\n        self.values\n            .get(name.as_ref())\n            .map(|e| e.iter().cloned())\n            .into_iter()\n            .flatten()\n    }\n\n    /// Returns an iterator over all of the errors in the context, including\n    /// those not associated with any field.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::form::{Form, Contextual};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Contextual<'_, T>>) {\n    ///     let errors = form.context.errors();\n    /// }\n    /// ```\n    pub fn errors(&self) -> impl Iterator<Item = &Error<'v>> {\n        self.errors.values()\n            .flat_map(|e| e.iter())\n            .chain(self.form_errors.iter())\n    }\n\n    /// Returns the errors associated with the field `name`. This method is\n    /// roughly equivalent to:\n    ///\n    /// ```rust\n    /// # use rocket::form::{Context, name::Name};\n    /// # let context = Context::default();\n    /// # let name = Name::new(\"foo\");\n    /// context.errors().filter(|e| e.is_for(name))\n    /// # ;\n    /// ```\n    ///\n    /// That is, it uses [`Error::is_for()`] to determine which errors are\n    /// associated with the field named `name`. This considers all errors whose\n    /// associated field name is a prefix of `name` to be an error for the field\n    /// named `name`. In other words, it associates parent field errors with\n    /// their children: `a.b`'s errors apply to `a.b.c`, `a.b.d` and so on but\n    /// not `a.c`.\n    ///\n    /// Lookup is case-sensitive but key-separator (`.` or `[]`) insensitive.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::form::{Form, Contextual};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Contextual<'_, T>>) {\n    ///     // Get all errors for field `id`.\n    ///     let id = form.context.field_errors(\"id\");\n    ///\n    ///     // Get all errors for `foo.bar` or `foo` if `foo` failed first.\n    ///     let foo_bar = form.context.field_errors(\"foo.bar\");\n    /// }\n    /// ```\n    pub fn field_errors<'a, N>(&'a self, name: N) -> impl Iterator<Item = &'a Error<'v>> + 'a\n        where N: AsRef<Name> + 'a\n    {\n        self.errors.values()\n            .flat_map(|e| e.iter())\n            .filter(move |e| e.is_for(&name))\n    }\n\n    /// Returns the errors associated _exactly_ with the field `name`. Prefer\n    /// [`Context::field_errors()`] instead.\n    ///\n    /// This method is roughly equivalent to:\n    ///\n    /// ```rust\n    /// # use rocket::form::{Context, name::Name};\n    /// # let context = Context::default();\n    /// # let name = Name::new(\"foo\");\n    /// context.errors().filter(|e| e.is_for_exactly(name))\n    /// # ;\n    /// ```\n    ///\n    /// That is, it uses [`Error::is_for_exactly()`] to determine which errors\n    /// are associated with the field named `name`. This considers _only_ errors\n    /// whose associated field name is _exactly_ `name` to be an error for the\n    /// field named `name`. This is _not_ what is typically desired as it\n    /// ignores errors that occur in the parent which will result in missing\n    /// errors associated with its children. Use [`Context::field_errors()`] in\n    /// almost all cases.\n    ///\n    /// Lookup is case-sensitive but key-separator (`.` or `[]`) insensitive.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::form::{Form, Contextual};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Contextual<'_, T>>) {\n    ///     // Get all errors for field `id`.\n    ///     let id = form.context.exact_field_errors(\"id\");\n    ///\n    ///     // Get all errors exactly for `foo.bar`. If `foo` failed, we will\n    ///     // this will return no errors. Use `Context::field_errors()`.\n    ///     let foo_bar = form.context.exact_field_errors(\"foo.bar\");\n    /// }\n    /// ```\n    pub fn exact_field_errors<'a, N>(&'a self, name: N) -> impl Iterator<Item = &'a Error<'v>> + 'a\n        where N: AsRef<Name> + 'a\n    {\n        self.errors.values()\n            .flat_map(|e| e.iter())\n            .filter(move |e| e.is_for_exactly(&name))\n    }\n\n    /// Returns the `max` of the statuses associated with all field errors.\n    ///\n    /// See [`Error::status()`] for details on how an error status is computed.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::http::Status;\n    /// use rocket::form::{Form, Contextual};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Contextual<'_, T>>) -> (Status, &'static str) {\n    ///     (form.context.status(), \"Thanks!\")\n    /// }\n    /// ```\n    pub fn status(&self) -> Status {\n        self.status\n    }\n\n    /// Inject a single error `error` into the context.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::http::Status;\n    /// use rocket::form::{Form, Contextual, Error};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(mut form: Form<Contextual<'_, T>>) {\n    ///     let error = Error::validation(\"a good error message\")\n    ///         .with_name(\"field_name\")\n    ///         .with_value(\"some field value\");\n    ///\n    ///     form.context.push_error(error);\n    /// }\n    /// ```\n    pub fn push_error(&mut self, error: Error<'v>) {\n        self.status = std::cmp::max(self.status, error.status());\n        match error.name {\n            Some(ref name) => match self.errors.get_mut(name) {\n                Some(errors) => errors.push(error),\n                None => { self.errors.insert(name.clone(), error.into()); },\n            }\n            None => self.form_errors.push(error)\n        }\n    }\n\n    /// Inject all of the errors in `errors` into the context.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::post;\n    /// # type T = String;\n    /// use rocket::http::Status;\n    /// use rocket::form::{Form, Contextual, Error};\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(mut form: Form<Contextual<'_, T>>) {\n    ///     let error = Error::validation(\"a good error message\")\n    ///         .with_name(\"field_name\")\n    ///         .with_value(\"some field value\");\n    ///\n    ///     form.context.push_errors(vec![error]);\n    /// }\n    /// ```\n    pub fn push_errors<E: Into<Errors<'v>>>(&mut self, errors: E) {\n        errors.into().into_iter().for_each(|e| self.push_error(e))\n    }\n}\n\nimpl<'f> From<Errors<'f>> for Context<'f> {\n    fn from(errors: Errors<'f>) -> Self {\n        let mut context = Context::default();\n        context.push_errors(errors);\n        context\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromForm<'v>> FromForm<'v> for Contextual<'v, T> {\n    type Context = (<T as FromForm<'v>>::Context, Context<'v>);\n\n    fn init(opts: Options) -> Self::Context {\n        (T::init(opts), Context::default())\n    }\n\n    fn push_value((ref mut val_ctxt, ctxt): &mut Self::Context, field: ValueField<'v>) {\n        ctxt.values.entry(field.name.source()).or_default().push(field.value);\n        T::push_value(val_ctxt, field);\n    }\n\n    async fn push_data((ref mut val_ctxt, ctxt): &mut Self::Context, field: DataField<'v, '_>) {\n        ctxt.data_fields.insert(field.name.source());\n        T::push_data(val_ctxt, field).await;\n    }\n\n    fn push_error((_, ref mut ctxt): &mut Self::Context, e: Error<'v>) {\n        ctxt.push_error(e);\n    }\n\n    fn finalize((val_ctxt, mut context): Self::Context) -> Result<'v, Self> {\n        let value = match T::finalize(val_ctxt) {\n            Ok(value) => Some(value),\n            Err(errors) => {\n                context.push_errors(errors);\n                None\n            }\n        };\n\n        Ok(Contextual { value, context })\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/error.rs",
    "content": "//! Form error types.\n\nuse std::{fmt, io};\nuse std::num::{ParseIntError, ParseFloatError};\nuse std::str::{Utf8Error, ParseBoolError};\nuse std::char::ParseCharError;\nuse std::net::AddrParseError;\nuse std::borrow::Cow;\n\nuse serde::{Serialize, ser::{Serializer, SerializeStruct}};\n\nuse crate::http::Status;\nuse crate::form::name::{NameBuf, Name};\nuse crate::data::ByteUnit;\n\n/// A collection of [`Error`]s.\n///\n/// `Errors` is a thin wrapper around a `Vec<Error>` with convenient methods for\n/// modifying the internal `Error`s. It `Deref`s and `DerefMut`s to\n/// `Vec<Error>` for transparent access to the underlying vector.\n///\n/// # Matching Errors to Fields\n///\n/// To find the errors that correspond to a given field, use\n/// [`Error::is_for()`]. For example, to get all of the errors that correspond\n/// to the field `foo.bar`, you might write the following:\n///\n/// ```rust\n/// use rocket::form::Errors;\n///\n/// let errors = Errors::new();\n/// let errors_for_foo = errors.iter().filter(|e| e.is_for(\"foo.bar\"));\n/// ```\n///\n/// ## Constructing\n///\n/// An `Errors` can be constructed from anything that an `Error` can be\n/// constructed from. This includes [`Error`], [`ErrorKind`], and all of the\n/// types an `ErrorKind` can be constructed from. See\n/// [`ErrorKind`](ErrorKind#constructing) for the full list.\n///\n/// ```rust\n/// use rocket::form;\n///\n/// fn at_most_10() -> form::Result<'static, usize> {\n///     // Using `From<PartIntError> => ErrorKind::Int => Errors`.\n///     let i: usize = \"foo\".parse()?;\n///\n///     if i > 10 {\n///         // `(Option<isize>, Option<isize>) => ErrorKind::OutOfRange => Errors`\n///         return Err((None, Some(10isize)).into());\n///     }\n///\n///     Ok(i)\n/// }\n/// ```\n#[derive(Default, Debug, PartialEq, Serialize)]\n#[serde(transparent)]\npub struct Errors<'v>(Vec<Error<'v>>);\n\n/// A form error, potentially tied to a specific form field.\n///\n/// An `Error` is returned by [`FromForm`], [`FromFormField`], and [`validate`]\n/// procedures, typically as a collection of [`Errors`]. It potentially\n/// identifies a specific field that triggered the error via [`Error::name`] and\n/// the field's value via [`Error::value`].\n///\n/// An `Error` can occur because of a field's value that failed to parse or\n/// because other parts of a field or form were malformed; the [`Error::entity`]\n/// identifies the part of the form that resulted in the error.\n///\n/// [`FromForm`]: crate::form::FromForm\n/// [`FromFormField`]: crate::form::FromFormField\n/// [`validate`]: crate::form::validate\n///\n/// # Constructing\n///\n/// An `Error` can be constructed via [`Error::validation()`],\n/// [`Error::custom()`], or anything that an [`ErrorKind`] can be constructed\n/// from. See [`ErrorKind`](ErrorKind#constructing).\n///\n/// ```rust\n/// use rocket::form::Error;\n///\n/// fn at_most_10_not_even() -> Result<usize, Error<'static>> {\n///     // Using `From<PartIntError> => ErrorKind::Int`.\n///     let i: usize = \"foo\".parse()?;\n///\n///     if i > 10 {\n///         // `From<(Option<isize>, Option<isize>)> => ErrorKind::OutOfRange`\n///         return Err((None, Some(10isize)).into());\n///     } else if i % 2 == 0 {\n///         return Err(Error::validation(\"integer cannot be even\"));\n///     }\n///\n///     Ok(i)\n/// }\n/// ```\n///\n/// # Setting Field Metadata\n///\n/// When implementing [`FromFormField`], nothing has to be done for a field's\n/// metadata to be set: the blanket [`FromForm`] implementation sets it\n/// automatically.\n///\n/// When constructed from an `ErrorKind`, the entity is set to\n/// [`Entity::default_for()`] by default. Occasionally, the error's `entity` may\n/// need to be set manually. Return what would be useful to the end-consumer.\n///\n/// # Matching Errors to Fields\n///\n/// To determine whether an error corresponds to a given field, use\n/// [`Error::is_for()`]. For example, to get all of the errors that correspond\n/// to the field `foo.bar`, you might write the following:\n///\n/// ```rust\n/// use rocket::form::Errors;\n///\n/// let errors = Errors::new();\n/// let errors_for_foo = errors.iter().filter(|e| e.is_for(\"foo.bar\"));\n/// ```\n///\n/// # Serialization\n///\n/// When a value of this type is serialized, a `struct` or map with the\n/// following fields is emitted:\n///\n/// | field    | type           | description                                      |\n/// |----------|----------------|--------------------------------------------------|\n/// | `name`   | `Option<&str>` | the erroring field's name, if known              |\n/// | `value`  | `Option<&str>` | the erroring field's value, if known             |\n/// | `entity` | `&str`         | string representation of the erroring [`Entity`] |\n/// | `msg`    | `&str`         | concise message of the error                     |\n#[derive(Debug, PartialEq)]\npub struct Error<'v> {\n    /// The name of the field, if it is known.\n    pub name: Option<NameBuf<'v>>,\n    /// The field's value, if it is known.\n    pub value: Option<Cow<'v, str>>,\n    /// The kind of error that occurred.\n    pub kind: ErrorKind<'v>,\n    /// The entity that caused the error.\n    pub entity: Entity,\n}\n\n/// The kind of form error that occurred.\n///\n/// ## Constructing\n///\n/// An `ErrorKind` can be constructed directly or via a `From` of the following\n/// types:\n///\n///   * `(Option<u64>, Option<u64>)` => [`ErrorKind::InvalidLength`]\n///   * `(Option<ByteUnit>, Option<ByteUnit>)` => [`ErrorKind::InvalidLength`]\n///   * `(Option<isize>, Option<isize>)` => [`ErrorKind::OutOfRange`]\n///   * `&[Cow<'_, str>]` or `Vec<Cow<'_, str>>` => [`ErrorKind::InvalidChoice`]\n///   * [`Utf8Error`] => [`ErrorKind::Utf8`]\n///   * [`ParseIntError`] => [`ErrorKind::Int`]\n///   * [`ParseFloatError`] => [`ErrorKind::Float`]\n///   * [`ParseBoolError`] => [`ErrorKind::Bool`]\n///   * [`AddrParseError`] => [`ErrorKind::Addr`]\n///   * [`io::Error`] => [`ErrorKind::Io`]\n///   * `Box<dyn std::error::Error + Send` => [`ErrorKind::Custom`]\n///   * `(Status, Box<dyn std::error::Error + Send)` => [`ErrorKind::Custom`]\n#[derive(Debug)]\n#[non_exhaustive]\npub enum ErrorKind<'v> {\n    /// The value's length, in bytes, was outside the range `[min, max]`.\n    InvalidLength {\n        /// The minimum length required, inclusive.\n        min: Option<u64>,\n        /// The maximum length required, inclusive.\n        max: Option<u64>,\n    },\n    /// The value wasn't one of the valid `choices`.\n    InvalidChoice {\n        /// The choices that were expected.\n        choices: Cow<'v, [Cow<'v, str>]>,\n    },\n    /// The integer value was outside the range `[start, end]`.\n    OutOfRange {\n        /// The start of the acceptable range, inclusive.\n        start: Option<isize>,\n        /// The end of the acceptable range, inclusive.\n        end: Option<isize>,\n    },\n    /// A custom validation routine failed with message `.0`.\n    Validation(Cow<'v, str>),\n    /// One entity was expected but more than one was received.\n    Duplicate,\n    /// An entity was expected but was not received.\n    Missing,\n    /// An unexpected entity was received.\n    Unexpected,\n    /// An unknown entity was received.\n    Unknown,\n    /// A custom error occurred. Status defaults to\n    /// [`Status::UnprocessableEntity`] if one is not directly specified.\n    Custom(Status, Box<dyn std::error::Error + Send>),\n    /// An error while parsing a multipart form occurred.\n    Multipart(multer::Error),\n    /// A string was invalid UTF-8.\n    Utf8(Utf8Error),\n    /// A value failed to parse as a char.\n    Char(ParseCharError),\n    /// A value failed to parse as an integer.\n    Int(ParseIntError),\n    /// A value failed to parse as a boolean.\n    Bool(ParseBoolError),\n    /// A value failed to parse as a float.\n    Float(ParseFloatError),\n    /// A value failed to parse as an IP or socket address.\n    Addr(AddrParseError),\n    /// An I/O error occurred.\n    Io(io::Error),\n}\n\n/// The erroneous form entity or form component.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub enum Entity {\n    /// The form itself.\n    Form,\n    /// A field.\n    Field,\n    /// A [`ValueField`](crate::form::ValueField).\n    ValueField,\n    /// A [`DataField`](crate::form::DataField).\n    DataField,\n    /// A field name.\n    Name,\n    /// A field value.\n    Value,\n    /// A field name key.\n    Key,\n    /// A field name key index at index `.0`.\n    Index(usize),\n}\n\nimpl<'v> Errors<'v> {\n    /// Create an empty collection of errors.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::Errors;\n    ///\n    /// let errors = Errors::new();\n    /// assert!(errors.is_empty());\n    /// ```\n    pub fn new() -> Self {\n        Errors(vec![])\n    }\n\n    /// Consumes `self` and returns a new `Errors` with each field name set to\n    /// `name` if it was not already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Errors, ErrorKind};\n    ///\n    /// let mut errors = Errors::from(ErrorKind::Missing);\n    /// assert!(errors[0].name.is_none());\n    ///\n    /// let mut errors = errors.with_name(\"foo\");\n    /// assert_eq!(errors[0].name.as_ref().unwrap(), \"foo\");\n    ///\n    /// errors.push(ErrorKind::Duplicate.into());\n    /// let errors = errors.with_name(\"bar\");\n    /// assert_eq!(errors[0].name.as_ref().unwrap(), \"foo\");\n    /// assert_eq!(errors[1].name.as_ref().unwrap(), \"bar\");\n    /// ```\n    pub fn with_name<N: Into<NameBuf<'v>>>(mut self, name: N) -> Self {\n        self.set_name(name);\n        self\n    }\n\n    /// Set the field name of each error in `self` to `name` if it is not\n    /// already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Errors, ErrorKind};\n    ///\n    /// let mut errors = Errors::from(ErrorKind::Missing);\n    /// assert!(errors[0].name.is_none());\n    ///\n    /// errors.set_name(\"foo\");\n    /// assert_eq!(errors[0].name.as_ref().unwrap(), \"foo\");\n    ///\n    /// errors.push(ErrorKind::Duplicate.into());\n    /// let errors = errors.with_name(\"bar\");\n    /// assert_eq!(errors[0].name.as_ref().unwrap(), \"foo\");\n    /// assert_eq!(errors[1].name.as_ref().unwrap(), \"bar\");\n    /// ```\n    pub fn set_name<N: Into<NameBuf<'v>>>(&mut self, name: N) {\n        let name = name.into();\n        for error in self.iter_mut() {\n            if error.name.is_none() {\n                error.set_name(name.clone());\n            }\n        }\n    }\n\n    /// Consumes `self` and returns a new `Errors` with each field value set to\n    /// `value` if it was not already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Errors, ErrorKind};\n    ///\n    /// let mut errors = Errors::from(ErrorKind::Missing);\n    /// assert!(errors[0].value.is_none());\n    ///\n    /// let mut errors = errors.with_value(\"foo\");\n    /// assert_eq!(errors[0].value.as_ref().unwrap(), \"foo\");\n    ///\n    /// errors.push(ErrorKind::Duplicate.into());\n    /// let errors = errors.with_value(\"bar\");\n    /// assert_eq!(errors[0].value.as_ref().unwrap(), \"foo\");\n    /// assert_eq!(errors[1].value.as_ref().unwrap(), \"bar\");\n    /// ```\n    pub fn with_value(mut self, value: &'v str) -> Self {\n        self.set_value(value);\n        self\n    }\n\n    /// Set the field value of each error in `self` to `value` if it is not\n    /// already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Errors, ErrorKind};\n    ///\n    /// let mut errors = Errors::from(ErrorKind::Missing);\n    /// assert!(errors[0].value.is_none());\n    ///\n    /// errors.set_value(\"foo\");\n    /// assert_eq!(errors[0].value.as_ref().unwrap(), \"foo\");\n    ///\n    /// errors.push(ErrorKind::Duplicate.into());\n    /// let errors = errors.with_value(\"bar\");\n    /// assert_eq!(errors[0].value.as_ref().unwrap(), \"foo\");\n    /// assert_eq!(errors[1].value.as_ref().unwrap(), \"bar\");\n    /// ```\n    pub fn set_value(&mut self, value: &'v str) {\n        self.iter_mut().for_each(|e| e.set_value(value));\n    }\n\n    /// Returns the highest [`Error::status()`] of all of the errors in `self`\n    /// or [`Status::InternalServerError`] if `self` is empty. This is the\n    /// status that is set by the [`Form`](crate::form::Form) data guard on\n    /// error.\n    ///\n    /// See [`Error::status()`] for the corresponding status code of each\n    /// [`Error`] variant.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, Errors, ErrorKind};\n    /// use rocket::http::Status;\n    ///\n    /// let mut errors = Errors::new();\n    /// assert_eq!(errors.status(), Status::InternalServerError);\n    ///\n    /// errors.push(Error::from((None, Some(10u64))));\n    /// assert_eq!(errors.status(), Status::PayloadTooLarge);\n    ///\n    /// errors.push(Error::from(ErrorKind::Missing));\n    /// assert_eq!(errors.status(), Status::UnprocessableEntity);\n    /// ```\n    pub fn status(&self) -> Status {\n        let max = self.iter().map(|e| e.status()).max();\n        max.unwrap_or(Status::InternalServerError)\n    }\n}\n\nimpl crate::http::ext::IntoOwned for Errors<'_> {\n    type Owned = Errors<'static>;\n\n    fn into_owned(self) -> Self::Owned {\n        Errors(self.0.into_owned())\n    }\n}\n\nimpl fmt::Display for Errors<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{} error(s):\", self.len())?;\n        for error in self.iter() {\n            write!(f, \"\\n{}\", error)?;\n        }\n\n        Ok(())\n    }\n}\n\nimpl<'v> std::ops::Deref for Errors<'v> {\n    type Target = Vec<Error<'v>>;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<'v> std::ops::DerefMut for Errors<'v> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n\nimpl<'v, T: Into<Error<'v>>> From<T> for Errors<'v> {\n    #[inline(always)]\n    fn from(e: T) -> Self {\n        Errors(vec![e.into()])\n    }\n}\n\nimpl<'v> From<Vec<Error<'v>>> for Errors<'v> {\n    #[inline(always)]\n    fn from(v: Vec<Error<'v>>) -> Self {\n        Errors(v)\n    }\n}\n\nimpl<'v> IntoIterator for Errors<'v> {\n    type Item = Error<'v>;\n\n    type IntoIter = <Vec<Error<'v>> as IntoIterator>::IntoIter;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.0.into_iter()\n    }\n}\n\nimpl<'v> Error<'v> {\n    /// Creates a new `Error` with `ErrorKind::Custom`.\n    ///\n    /// For validation errors, use [`Error::validation()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::Error;\n    ///\n    /// fn from_fmt(error: std::fmt::Error) -> Error<'static> {\n    ///     Error::custom(error)\n    /// }\n    /// ```\n    pub fn custom<E>(error: E) -> Self\n        where E: std::error::Error + Send + 'static\n    {\n        (Box::new(error) as Box<dyn std::error::Error + Send>).into()\n    }\n\n    /// Creates a new `Error` with `ErrorKind::Validation` and message `msg`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, ErrorKind, Entity};\n    ///\n    /// let error = Error::validation(\"invalid foo: need bar\");\n    /// assert!(matches!(error.kind, ErrorKind::Validation(_)));\n    /// assert_eq!(error.entity, Entity::Value);\n    /// ```\n    pub fn validation<S: Into<Cow<'v, str>>>(msg: S) -> Self {\n        ErrorKind::Validation(msg.into()).into()\n    }\n\n    /// Consumes `self` and returns a new `Error` with the entity set to\n    /// `entity`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, ErrorKind, Entity};\n    ///\n    /// let error = Error::from(ErrorKind::Missing);\n    /// assert_eq!(error.entity, Entity::Field);\n    ///\n    /// let error = error.with_entity(Entity::Key);\n    /// assert_eq!(error.entity, Entity::Key);\n    /// ```\n    pub fn with_entity(mut self, entity: Entity) -> Self {\n        self.set_entity(entity);\n        self\n    }\n\n    /// Sets the error's entity to `entity.`\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, ErrorKind, Entity};\n    ///\n    /// let mut error = Error::from(ErrorKind::Missing);\n    /// assert_eq!(error.entity, Entity::Field);\n    ///\n    /// error.set_entity(Entity::Key);\n    /// assert_eq!(error.entity, Entity::Key);\n    /// ```\n    pub fn set_entity(&mut self, entity: Entity) {\n        self.entity = entity;\n    }\n\n    /// Consumes `self` and returns a new `Error` with the field name set to\n    /// `name` if it was not already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, ErrorKind};\n    ///\n    /// let error = Error::from(ErrorKind::Missing);\n    /// assert!(error.name.is_none());\n    ///\n    /// let error = error.with_name(\"foo\");\n    /// assert_eq!(error.name.as_ref().unwrap(), \"foo\");\n    ///\n    /// let error = error.with_name(\"bar\");\n    /// assert_eq!(error.name.as_ref().unwrap(), \"foo\");\n    /// ```\n    pub fn with_name<N: Into<NameBuf<'v>>>(mut self, name: N) -> Self {\n        self.set_name(name);\n        self\n    }\n\n    /// Sets the field name of `self` to `name` if it is not already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, ErrorKind};\n    ///\n    /// let mut error = Error::from(ErrorKind::Missing);\n    /// assert!(error.name.is_none());\n    ///\n    /// error.set_name(\"foo\");\n    /// assert_eq!(error.name.as_ref().unwrap(), \"foo\");\n    ///\n    /// let error = error.with_name(\"bar\");\n    /// assert_eq!(error.name.as_ref().unwrap(), \"foo\");\n    /// ```\n    pub fn set_name<N: Into<NameBuf<'v>>>(&mut self, name: N) {\n        if self.name.is_none() {\n            self.name = Some(name.into());\n        }\n    }\n\n    /// Consumes `self` and returns a new `Error` with the value set to `value`\n    /// if it was not already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, ErrorKind};\n    ///\n    /// let error = Error::from(ErrorKind::Missing);\n    /// assert!(error.value.is_none());\n    ///\n    /// let error = error.with_value(\"foo\");\n    /// assert_eq!(error.value.as_ref().unwrap(), \"foo\");\n    ///\n    /// let error = error.with_value(\"bar\");\n    /// assert_eq!(error.value.as_ref().unwrap(), \"foo\");\n    /// ```\n    pub fn with_value(mut self, value: &'v str) -> Self {\n        self.set_value(value);\n        self\n    }\n\n    /// Set the field value of `self` to `value` if it is not already set.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::error::{Error, ErrorKind};\n    ///\n    /// let mut error = Error::from(ErrorKind::Missing);\n    /// assert!(error.value.is_none());\n    ///\n    /// error.set_value(\"foo\");\n    /// assert_eq!(error.value.as_ref().unwrap(), \"foo\");\n    ///\n    /// error.set_value(\"bar\");\n    /// assert_eq!(error.value.as_ref().unwrap(), \"foo\");\n    /// ```\n    pub fn set_value(&mut self, value: &'v str) {\n        if self.value.is_none() {\n            self.value = Some(value.into());\n        }\n    }\n\n    /// Returns `true` if this error applies to a field named `name`. **This is\n    /// _different_ than simply comparing `name`.**\n    ///\n    /// Unlike [`Error::is_for_exactly()`], this method returns `true` if the\n    /// error's field name is a **prefix of `name`**. This is typically what is\n    /// desired as errors apply to a field and its children: `a.b` applies to\n    /// the nested fields `a.b.c`, `a.b.d` and so on.\n    ///\n    /// Returns `false` if `self` has no field name.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::Error;\n    ///\n    /// // returns `false` without a field name\n    /// let error = Error::validation(\"bad `foo`\");\n    /// assert!(!error.is_for_exactly(\"a.b\"));\n    ///\n    /// // `a.b` is a prefix all of these field names\n    /// let error = error.with_name(\"a.b\");\n    /// assert!(error.is_for(\"a.b\"));\n    /// assert!(error.is_for(\"a[b]\"));\n    /// assert!(error.is_for(\"a.b.c\"));\n    /// assert!(error.is_for(\"a.b[c]\"));\n    /// assert!(error.is_for(\"a.b.c[d]\"));\n    /// assert!(error.is_for(\"a.b.c.d.foo\"));\n    ///\n    /// // ...but not of these.\n    /// assert!(!error.is_for(\"a.c\"));\n    /// assert!(!error.is_for(\"a\"));\n    /// ```\n    pub fn is_for<N: AsRef<Name>>(&self, name: N) -> bool {\n        self.name.as_ref().map(|e_name| {\n            if e_name.is_empty() != name.as_ref().is_empty() {\n                return false;\n            }\n\n            let mut e_keys = e_name.keys();\n            let mut n_keys = name.as_ref().keys();\n            loop {\n                match (e_keys.next(), n_keys.next()) {\n                    (Some(e), Some(n)) if e == n => continue,\n                    (Some(_), Some(_)) => return false,\n                    (Some(_), None) => return false,\n                    (None, _) => break,\n                }\n            }\n\n            true\n        })\n        .unwrap_or(false)\n    }\n\n    /// Returns `true` if this error applies to exactly the field named `name`.\n    /// Returns `false` if `self` has no field name.\n    ///\n    /// Unlike [`Error::is_for()`], this method returns `true` only when the\n    /// error's field name is exactly `name`. This is _not_ typically what is\n    /// desired.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::Error;\n    ///\n    /// // returns `false` without a field name\n    /// let error = Error::validation(\"bad `foo`\");\n    /// assert!(!error.is_for_exactly(\"a.b\"));\n    ///\n    /// let error = error.with_name(\"a.b\");\n    /// assert!(error.is_for_exactly(\"a.b\"));\n    /// assert!(error.is_for_exactly(\"a[b]\"));\n    ///\n    /// // does not return `true` when the name is a prefix\n    /// assert!(!error.is_for_exactly(\"a.b.c\"));\n    /// assert!(!error.is_for_exactly(\"a.b[c]\"));\n    /// assert!(!error.is_for_exactly(\"a.b.c[d]\"));\n    /// assert!(!error.is_for_exactly(\"a.b.c.d.foo\"));\n    ///\n    /// // does not return `true` when the name is different\n    /// assert!(!error.is_for(\"a.c\"));\n    /// assert!(!error.is_for(\"a\"));\n    /// ```\n    pub fn is_for_exactly<N: AsRef<Name>>(&self, name: N) -> bool {\n        self.name.as_ref()\n            .map(|n| name.as_ref() == n)\n            .unwrap_or(false)\n    }\n\n    /// Returns the most reasonable [`Status`] associated with this error.\n    ///\n    /// For an [`ErrorKind::Custom`], this is the variant's `Status`, which\n    /// defaults to [`Status::UnprocessableEntity`]. For all others, it is:\n    ///\n    ///  * **`PayloadTooLarge`** if the [error kind](ErrorKind) is:\n    ///    - `InvalidLength` with min of `None`\n    ///    - `Multipart(FieldSizeExceeded)` or `Multipart(StreamSizeExceeded)`\n    ///  * **`InternalServerError`** if the [error kind](ErrorKind) is:\n    ///    - `Unknown`\n    ///  * **`BadRequest`** if the [error kind](ErrorKind) is:\n    ///    - `Io` with an `entity` of `Form`\n    ///  * **`UnprocessableEntity`** for all other variants\n    ///\n    /// # Example\n    ///\n    ///  ```rust\n    ///  use rocket::form::error::{Error, ErrorKind, Entity};\n    ///  use rocket::http::Status;\n    ///\n    ///  let error = Error::validation(\"bad `foo`\");\n    ///  assert_eq!(error.status(), Status::UnprocessableEntity);\n    ///\n    ///  let error = Error::from((None, Some(10u64)));\n    ///  assert_eq!(error.status(), Status::PayloadTooLarge);\n    ///\n    ///  let error = Error::from(ErrorKind::Unknown);\n    ///  assert_eq!(error.status(), Status::InternalServerError);\n    ///\n    ///  // default entity for `io::Error` is `Form`.\n    ///  let error = Error::from(std::io::Error::last_os_error());\n    ///  assert_eq!(error.status(), Status::BadRequest);\n    ///\n    ///  let error = error.with_entity(Entity::Value);\n    ///  assert_eq!(error.status(), Status::UnprocessableEntity);\n    ///  ```\n    pub fn status(&self) -> Status {\n        use ErrorKind::*;\n        use multer::Error::*;\n\n        match self.kind {\n            | InvalidLength { min: None, .. }\n            | Multipart(FieldSizeExceeded { .. })\n            | Multipart(StreamSizeExceeded { .. }) => Status::PayloadTooLarge,\n            Unknown => Status::InternalServerError,\n            Io(_) if self.entity == Entity::Form => Status::BadRequest,\n            Custom(status, _) => status,\n            _ => Status::UnprocessableEntity\n        }\n    }\n}\n\nimpl<'v> Serialize for Error<'v> {\n    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {\n        let mut err = ser.serialize_struct(\"Error\", 3)?;\n        err.serialize_field(\"name\", &self.name)?;\n        err.serialize_field(\"value\", &self.value)?;\n        err.serialize_field(\"entity\", &self.entity.to_string())?;\n        err.serialize_field(\"msg\", &self.to_string())?;\n        err.end()\n    }\n}\n\nimpl crate::http::ext::IntoOwned for Error<'_> {\n    type Owned = Error<'static>;\n\n    fn into_owned(self) -> Self::Owned {\n        Error {\n            name: self.name.into_owned(),\n            value: self.value.into_owned(),\n            kind: self.kind.into_owned(),\n            entity: self.entity,\n        }\n    }\n}\n\nimpl<'v> std::ops::Deref for Error<'v> {\n    type Target = ErrorKind<'v>;\n\n    fn deref(&self) -> &Self::Target {\n        &self.kind\n    }\n}\n\nimpl fmt::Display for Error<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.kind.fmt(f)\n    }\n}\n\nimpl<'v, T: Into<ErrorKind<'v>>> From<T> for Error<'v> {\n    #[inline(always)]\n    fn from(k: T) -> Self {\n        let kind = k.into();\n        let entity = Entity::default_for(&kind);\n        Error { name: None, value: None, kind, entity }\n    }\n}\n\nimpl<'a> From<multer::Error> for Error<'a> {\n    fn from(error: multer::Error) -> Self {\n        use multer::Error::*;\n        use self::ErrorKind::*;\n\n        let incomplete = Error::from(InvalidLength { min: None, max: None });\n        match error {\n            UnknownField { field_name: Some(name) } => Error::from(Unexpected).with_name(name),\n            UnknownField { field_name: None } => Error::from(Unexpected),\n            FieldSizeExceeded { limit, field_name } => {\n                let e = Error::from((None, Some(limit)));\n                match field_name {\n                    Some(name) => e.with_name(name),\n                    None => e\n                }\n            },\n            StreamSizeExceeded { limit } => {\n                Error::from((None, Some(limit))).with_entity(Entity::Form)\n            }\n            IncompleteFieldData { field_name: Some(name) } => incomplete.with_name(name),\n            IncompleteFieldData { field_name: None } => incomplete,\n            IncompleteStream | IncompleteHeaders => incomplete.with_entity(Entity::Form),\n            e => Error::from(ErrorKind::Multipart(e))\n        }\n    }\n}\n\nimpl fmt::Display for ErrorKind<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            ErrorKind::InvalidLength { min, max } => {\n                match (min, max) {\n                    (None, None) => write!(f, \"invalid length: incomplete\")?,\n                    (None, Some(k)) if *k < 1024 => write!(f, \"length cannot exceed {}\", k)?,\n                    (None, Some(k)) => write!(f, \"size must not exceed {}\", ByteUnit::from(*k))?,\n                    (Some(1), None) => write!(f, \"cannot be empty\")?,\n                    (Some(k), None) if *k < 1024 => write!(f, \"expected at least {}\", k)?,\n                    (Some(k), None) => write!(f, \"size must be at least {}\", ByteUnit::from(*k))?,\n                    (Some(i), Some(j)) if *i < 1024 && *j < 1024 => {\n                        write!(f, \"length must be between {} and {}\", i, j)?;\n                    }\n                    (Some(i), Some(j)) => {\n                        let (i, j) = (ByteUnit::from(*i), ByteUnit::from(*j));\n                        write!(f, \"size must be between {} and {}\", i, j)?;\n                    }\n                }\n            }\n            ErrorKind::InvalidChoice { choices } => {\n                match *choices.as_ref() {\n                    [] => write!(f, \"invalid choice\")?,\n                    [ref choice] => write!(f, \"expected {}\", choice)?,\n                    _ => {\n                        write!(f, \"expected one of \")?;\n                        for (i, choice) in choices.iter().enumerate() {\n                            if i != 0 { write!(f, \", \")?; }\n                            write!(f, \"`{}`\", choice)?;\n                        }\n                    }\n                }\n            }\n            ErrorKind::OutOfRange { start, end } => {\n                match (start, end) {\n                    (None, None) => write!(f, \"value is out of range\")?,\n                    (None, Some(k)) => write!(f, \"value cannot exceed {}\", k)?,\n                    (Some(k), None) => write!(f, \"value must be at least {}\", k)?,\n                    (Some(i), Some(j)) => write!(f, \"value must be between {} and {}\", i, j)?,\n                }\n            }\n            ErrorKind::Validation(msg) => msg.fmt(f)?,\n            ErrorKind::Duplicate => \"duplicate\".fmt(f)?,\n            ErrorKind::Missing => \"missing\".fmt(f)?,\n            ErrorKind::Unexpected => \"unexpected\".fmt(f)?,\n            ErrorKind::Unknown => \"unknown internal error\".fmt(f)?,\n            ErrorKind::Custom(_, e) => e.fmt(f)?,\n            ErrorKind::Multipart(e) => write!(f, \"invalid multipart: {}\", e)?,\n            ErrorKind::Utf8(e) => write!(f, \"invalid UTF-8: {}\", e)?,\n            ErrorKind::Char(e) => write!(f, \"invalid character: {}\", e)?,\n            ErrorKind::Int(e) => write!(f, \"invalid integer: {}\", e)?,\n            ErrorKind::Bool(e) => write!(f, \"invalid boolean: {}\", e)?,\n            ErrorKind::Float(e) => write!(f, \"invalid float: {}\", e)?,\n            ErrorKind::Addr(e) => write!(f, \"invalid address: {}\", e)?,\n            ErrorKind::Io(e) => write!(f, \"i/o error: {}\", e)?,\n        }\n\n        Ok(())\n    }\n}\n\nimpl crate::http::ext::IntoOwned for ErrorKind<'_> {\n    type Owned = ErrorKind<'static>;\n\n    fn into_owned(self) -> Self::Owned {\n        use ErrorKind::*;\n\n        match self {\n            InvalidLength { min, max } => InvalidLength { min, max },\n            OutOfRange { start, end } => OutOfRange { start, end },\n            Validation(s) => Validation(s.into_owned().into()),\n            Duplicate => Duplicate,\n            Missing => Missing,\n            Unexpected => Unexpected,\n            Unknown => Unknown,\n            Custom(s, e) => Custom(s, e),\n            Multipart(e) => Multipart(e),\n            Utf8(e) => Utf8(e),\n            Char(e) => Char(e),\n            Int(e) => Int(e),\n            Bool(e) => Bool(e),\n            Float(e) => Float(e),\n            Addr(e) => Addr(e),\n            Io(e) => Io(e),\n            InvalidChoice { choices } => InvalidChoice {\n                choices: choices.iter()\n                    .map(|s| Cow::Owned(s.to_string()))\n                    .collect::<Vec<_>>()\n                    .into()\n            }\n        }\n    }\n}\n\nimpl<'a, 'b> PartialEq<ErrorKind<'b>> for ErrorKind<'a> {\n    fn eq(&self, other: &ErrorKind<'b>) -> bool {\n        use ErrorKind::*;\n        match (self, other) {\n            (InvalidLength { min: a, max: b }, InvalidLength { min, max }) => min == a && max == b,\n            (InvalidChoice { choices: a }, InvalidChoice { choices }) => choices == a,\n            (OutOfRange { start: a, end: b }, OutOfRange { start, end }) => start == a && end == b,\n            (Validation(a), Validation(b)) => a == b,\n            (Duplicate, Duplicate) => true,\n            (Missing, Missing) => true,\n            (Unexpected, Unexpected) => true,\n            (Custom(a, _), Custom(b, _)) => a == b,\n            (Multipart(a), Multipart(b)) => a == b,\n            (Utf8(a), Utf8(b)) => a == b,\n            (Int(a), Int(b)) => a == b,\n            (Bool(a), Bool(b)) => a == b,\n            (Float(a), Float(b)) => a == b,\n            (Addr(a), Addr(b)) => a == b,\n            (Io(a), Io(b)) => a.kind() == b.kind(),\n            _ => false,\n        }\n    }\n}\n\nimpl From<(Option<u64>, Option<u64>)> for ErrorKind<'_> {\n    fn from((min, max): (Option<u64>, Option<u64>)) -> Self {\n        ErrorKind::InvalidLength { min, max }\n    }\n}\n\nimpl<'a, 'v: 'a> From<&'static [Cow<'v, str>]> for ErrorKind<'a> {\n    fn from(choices: &'static [Cow<'v, str>]) -> Self {\n        ErrorKind::InvalidChoice { choices: choices.into() }\n    }\n}\n\nimpl<'a, 'v: 'a> From<Vec<Cow<'v, str>>> for ErrorKind<'a> {\n    fn from(choices: Vec<Cow<'v, str>>) -> Self {\n        ErrorKind::InvalidChoice { choices: choices.into() }\n    }\n}\n\nimpl From<(Option<isize>, Option<isize>)> for ErrorKind<'_> {\n    fn from((start, end): (Option<isize>, Option<isize>)) -> Self {\n        ErrorKind::OutOfRange { start, end }\n    }\n}\n\nimpl From<(Option<ByteUnit>, Option<ByteUnit>)> for ErrorKind<'_> {\n    fn from((start, end): (Option<ByteUnit>, Option<ByteUnit>)) -> Self {\n        ErrorKind::from((start.map(ByteUnit::as_u64), end.map(ByteUnit::as_u64)))\n    }\n}\n\nimpl<'a, 'v: 'a, const N: usize> From<&'static [Cow<'v, str>; N]> for ErrorKind<'a> {\n    fn from(choices: &'static [Cow<'v, str>; N]) -> Self {\n        let choices = &choices[..];\n        ErrorKind::InvalidChoice { choices: choices.into() }\n    }\n}\n\nimpl<'a> From<Box<dyn std::error::Error + Send>> for ErrorKind<'a> {\n    fn from(e: Box<dyn std::error::Error + Send>) -> Self {\n        ErrorKind::Custom(Status::UnprocessableEntity, e)\n    }\n}\n\nimpl<'a> From<(Status, Box<dyn std::error::Error + Send>)> for ErrorKind<'a> {\n    fn from((status, e): (Status, Box<dyn std::error::Error + Send>)) -> Self {\n        ErrorKind::Custom(status, e)\n    }\n}\n\nmacro_rules! impl_from_for {\n    (<$l:lifetime> $T:ty => $V:ty as $variant:ident) => (\n        impl<$l> From<$T> for $V {\n            fn from(value: $T) -> Self {\n                <$V>::$variant(value)\n            }\n        }\n    )\n}\n\nimpl_from_for!(<'a> Utf8Error => ErrorKind<'a> as Utf8);\nimpl_from_for!(<'a> ParseIntError => ErrorKind<'a> as Int);\nimpl_from_for!(<'a> ParseCharError => ErrorKind<'a> as Char);\nimpl_from_for!(<'a> ParseFloatError => ErrorKind<'a> as Float);\nimpl_from_for!(<'a> ParseBoolError => ErrorKind<'a> as Bool);\nimpl_from_for!(<'a> AddrParseError => ErrorKind<'a> as Addr);\nimpl_from_for!(<'a> io::Error => ErrorKind<'a> as Io);\n\nimpl fmt::Display for Entity {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let string = match self {\n            Entity::Form => \"form\",\n            Entity::Field => \"field\",\n            Entity::ValueField => \"value field\",\n            Entity::DataField => \"data field\",\n            Entity::Name => \"name\",\n            Entity::Value => \"value\",\n            Entity::Key => \"key\",\n            Entity::Index(k) => return write!(f, \"index {}\", k),\n        };\n\n        string.fmt(f)\n    }\n}\n\nimpl Entity {\n    /// The default entity for an [`Error`] created for `ErrorKind`.\n    ///\n    ///  * **[`Field`]** if `Duplicate`, `Missing`, `Unexpected`, or `Unknown`\n    ///  * **[`Form`]** if `Multipart` or `Io`\n    ///  * **[`Value`]** otherwise\n    ///\n    /// [`Field`]: Entity::Field\n    /// [`Form`]: Entity::Form\n    /// [`Value`]: Entity::Value\n    pub const fn default_for(kind: &ErrorKind<'_>) -> Self {\n        match kind {\n            | ErrorKind::InvalidLength { .. }\n            | ErrorKind::InvalidChoice { .. }\n            | ErrorKind::OutOfRange { .. }\n            | ErrorKind::Validation { .. }\n            | ErrorKind::Utf8(_)\n            | ErrorKind::Char(_)\n            | ErrorKind::Int(_)\n            | ErrorKind::Float(_)\n            | ErrorKind::Bool(_)\n            | ErrorKind::Custom(..)\n            | ErrorKind::Addr(_) => Entity::Value,\n\n            | ErrorKind::Duplicate\n            | ErrorKind::Missing\n            | ErrorKind::Unknown\n            | ErrorKind::Unexpected => Entity::Field,\n\n            | ErrorKind::Multipart(_)\n            | ErrorKind::Io(_) => Entity::Form,\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/field.rs",
    "content": "use crate::form::{name::NameView, error::{Error, ErrorKind, Entity}};\nuse crate::http::{ContentType, RawStr};\nuse crate::{Request, Data};\nuse crate::fs::FileName;\n\n/// A form field with a string value.\n///\n/// Rocket preprocesses all form fields into either [`ValueField`]s or\n/// [`DataField`]s. All fields from url-encoded forms, and fields without\n/// Content-Types from multipart forms, are preprocessed as a `ValueField`.\n#[derive(Debug, Clone)]\npub struct ValueField<'r> {\n    /// The (decoded) name of the form field.\n    pub name: NameView<'r>,\n    /// The (decoded) value of the form field.\n    pub value: &'r str,\n}\n\n/// A multipart form field with an underlying data stream.\n///\n/// Rocket preprocesses all form fields into either [`ValueField`]s or\n/// [`DataField`]s. Multipart form fields with a `Content-Type` are preprocessed\n/// as a `DataField`. The underlying data is _not_ read into memory, but\n/// instead, streamable from the contained [`Data`] structure.\npub struct DataField<'r, 'i> {\n    /// The (decoded) name of the form field.\n    pub name: NameView<'r>,\n    /// The form fields's file name.\n    pub file_name: Option<&'r FileName>,\n    /// The form field's Content-Type, as submitted, which may or may not\n    /// reflect on `data`.\n    pub content_type: ContentType,\n    /// The request in which the form field was submitted.\n    pub request: &'r Request<'i>,\n    /// The raw data stream.\n    pub data: Data<'r>,\n}\n\nimpl<'v> ValueField<'v> {\n    /// Parse a field string, where both the key and value are assumed to be\n    /// URL-decoded while preserving the `=` delimiter, into a `ValueField`.\n    ///\n    /// This implements 3.2, 3.3 of [section 5.1 of the WHATWG living standard].\n    ///\n    /// [section 5.1 of the WHATWG living standard]: https://url.spec.whatwg.org/#urlencoded-parsing\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::ValueField;\n    ///\n    /// let parsed = ValueField::parse(\"a cat=an A+ pet\");\n    /// assert_eq!(parsed.name, \"a cat\");\n    /// assert_eq!(parsed.value, \"an A+ pet\");\n    ///\n    /// let parsed = ValueField::parse(\"a cat is an A+ pet\");\n    /// assert_eq!(parsed.name, \"a cat is an A+ pet\");\n    /// assert_eq!(parsed.value, \"\");\n    ///\n    /// let parsed = ValueField::parse(\"cat.food=yum?\");\n    /// assert_eq!(parsed.name, \"cat\");\n    /// assert_eq!(parsed.name.source(), \"cat.food\");\n    /// assert_eq!(parsed.value, \"yum?\");\n    /// ```\n    pub fn parse(field: &'v str) -> Self {\n        // WHATWG URL Living Standard 5.1 steps 3.2, 3.3.\n        let (name, val) = RawStr::new(field).split_at_byte(b'=');\n        ValueField::from((name.as_str(), val.as_str()))\n    }\n\n    /// Create a `ValueField` from a value, which is assumed to be URL-decoded.\n    /// The field `name` will be empty.\n    ///\n    /// This is equivalent to `ValueField::from((\"\", value))`. To create a\n    /// `ValueField` from both a `name` and a `value`, use\n    /// `ValueField::from((name, value))`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::ValueField;\n    ///\n    /// let parsed = ValueField::from_value(\"A+=kitten\");\n    /// assert_eq!(parsed.name, \"\");\n    /// assert_eq!(parsed.value, \"A+=kitten\");\n    /// ```\n    pub fn from_value(value: &'v str) -> Self {\n        ValueField::from((\"\", value))\n    }\n\n    /// Shift the `name` of `self` and return `self` with the shifted `name`.\n    ///\n    /// See [`NameView::shift()`] for the details on name \"shifting\".\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::ValueField;\n    ///\n    /// let parsed = ValueField::parse(\"cat.food=yum?\");\n    /// assert_eq!(parsed.name, \"cat\");\n    /// assert_eq!(parsed.name.source(), \"cat.food\");\n    /// assert_eq!(parsed.name.key_lossy(), \"cat\");\n    ///\n    /// let shifted = parsed.shift();\n    /// assert_eq!(shifted.name, \"cat.food\");\n    /// assert_eq!(shifted.name.key_lossy(), \"food\");\n    /// ```\n    pub fn shift(mut self) -> Self {\n        self.name.shift();\n        self\n    }\n\n    /// Creates a complete unexpected value field [`Error`] from `self`.\n    ///\n    /// The error will have the following properties:\n    ///   * `kind`: [`ErrorKind::Unexpected`]\n    ///   * `name`: [`self.name.source()`](NameView::source())\n    ///   * `value`: [`self.value`](ValueField::value)\n    ///   * `entity`: [`Entity::ValueField`]\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::ValueField;\n    /// use rocket::form::error::{ErrorKind, Entity};\n    ///\n    /// let field = ValueField::parse(\"cat.food=yum?\");\n    /// let error = field.unexpected();\n    ///\n    /// assert_eq!(error.name.as_ref().unwrap(), \"cat.food\");\n    /// assert_eq!(error.value.as_ref().unwrap(), \"yum?\");\n    /// assert_eq!(error.kind, ErrorKind::Unexpected);\n    /// assert_eq!(error.entity, Entity::ValueField);\n    /// ```\n    pub fn unexpected(&self) -> Error<'v> {\n        Error::from(ErrorKind::Unexpected)\n            .with_name(self.name.source())\n            .with_value(self.value)\n            .with_entity(Entity::ValueField)\n    }\n\n    /// Creates a complete missing value field [`Error`] from `self`.\n    ///\n    /// The error will have the following properties:\n    ///   * `kind`: [`ErrorKind::Missing`]\n    ///   * `name`: [`self.name.source()`](NameView::source())\n    ///   * `value`: [`self.value`](ValueField::value)\n    ///   * `entity`: [`Entity::ValueField`]\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::ValueField;\n    /// use rocket::form::error::{ErrorKind, Entity};\n    ///\n    /// let field = ValueField::parse(\"cat.food=yum?\");\n    /// let error = field.missing();\n    ///\n    /// assert_eq!(error.name.as_ref().unwrap(), \"cat.food\");\n    /// assert_eq!(error.value.as_ref().unwrap(), \"yum?\");\n    /// assert_eq!(error.kind, ErrorKind::Missing);\n    /// assert_eq!(error.entity, Entity::ValueField);\n    /// ```\n    pub fn missing(&self) -> Error<'v> {\n        Error::from(ErrorKind::Missing)\n            .with_name(self.name.source())\n            .with_value(self.value)\n            .with_entity(Entity::ValueField)\n    }\n}\n\nimpl<'v> DataField<'v, '_> {\n    /// Shift the `name` of `self` and return `self` with the shifted `name`.\n    ///\n    /// This is identical to [`ValueField::shift()`] but for `DataField`s. See\n    /// [`NameView::shift()`] for the details on name \"shifting\".\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::DataField;\n    ///\n    /// fn push_data(field: DataField<'_, '_>) {\n    ///     let shifted = field.shift();\n    /// }\n    /// ```\n    pub fn shift(mut self) -> Self {\n        self.name.shift();\n        self\n    }\n\n    /// Creates a complete unexpected data field [`Error`] from `self`.\n    ///\n    /// The error will have the following properties:\n    ///   * `kind`: [`ErrorKind::Unexpected`]\n    ///   * `name`: [`self.name.source()`](NameView::source())\n    ///   * `value`: `None`\n    ///   * `entity`: [`Entity::DataField`]\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::DataField;\n    ///\n    /// fn push_data(field: DataField<'_, '_>) {\n    ///     let error = field.unexpected();\n    /// }\n    /// ```\n    pub fn unexpected(&self) -> Error<'v> {\n        Error::from(ErrorKind::Unexpected)\n            .with_name(self.name.source())\n            .with_entity(Entity::DataField)\n    }\n}\n\nimpl<'a> From<(&'a str, &'a str)> for ValueField<'a> {\n    fn from((name, value): (&'a str, &'a str)) -> Self {\n        ValueField { name: NameView::new(name), value }\n    }\n}\n\nimpl<'a, 'b> PartialEq<ValueField<'b>> for ValueField<'a> {\n    fn eq(&self, other: &ValueField<'b>) -> bool {\n        self.name == other.name && self.value == other.value\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/form.rs",
    "content": "use std::ops::{Deref, DerefMut};\n\nuse crate::Request;\nuse crate::outcome::try_outcome;\nuse crate::data::{Data, FromData, Outcome};\nuse crate::http::{RawStr, ext::IntoOwned};\nuse crate::form::prelude::{*, parser::{Parser, RawStrParser}};\n\n/// A data guard for [`FromForm`] types.\n///\n/// This type implements the [`FromData`] trait. It provides a generic means to\n/// parse arbitrary structures from incoming form data.\n///\n/// See the [forms guide](https://rocket.rs/master/guide/requests#forms) for\n/// general form support documentation.\n///\n/// # Leniency\n///\n/// A `Form<T>` will parse successfully from an incoming form if the form\n/// contains a superset of the fields in `T`. Said another way, a `Form<T>`\n/// automatically discards extra fields without error. For instance, if an\n/// incoming form contains the fields \"a\", \"b\", and \"c\" while `T` only contains\n/// \"a\" and \"c\", the form _will_ parse as `Form<T>`. To parse strictly, use the\n/// [`Strict`](crate::form::Strict) form guard.\n///\n/// # Usage\n///\n/// This type can be used with any type that implements the `FromForm` trait.\n/// The trait can be automatically derived; see the [`FromForm`] documentation\n/// for more information on deriving or implementing the trait.\n///\n/// Because `Form` implements `FromData`, it can be used directly as a target of\n/// the `data = \"<param>\"` route parameter as long as its generic type\n/// implements the `FromForm` trait:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::form::Form;\n/// use rocket::http::RawStr;\n///\n/// #[derive(FromForm)]\n/// struct UserInput<'r> {\n///     value: &'r str\n/// }\n///\n/// #[post(\"/submit\", data = \"<user_input>\")]\n/// fn submit_task(user_input: Form<UserInput<'_>>) -> String {\n///     format!(\"Your value: {}\", user_input.value)\n/// }\n/// ```\n///\n/// A type of `Form<T>` automatically dereferences into an `&T` or `&mut T`,\n/// though you can also transform a `Form<T>` into a `T` by calling\n/// [`into_inner()`](Form::into_inner()). Thanks to automatic dereferencing, you\n/// can access fields of `T` transparently through a `Form<T>`, as seen above\n/// with `user_input.value`.\n///\n/// ## Errors\n///\n/// A `Form<T>` data guard may fail, forward, or succeed.\n///\n/// If a request's content-type is neither [`ContentType::Form`] nor\n/// [`ContentType::FormData`], the guard **forwards**.\n///\n/// If the request `ContentType` _does_ identify as a form but the form data\n/// does not parse as `T`, according to `T`'s [`FromForm`] implementation, the\n/// guard **fails**. The `Error` variant contains a vector of the [`Errors`]\n/// emitted by `T`'s `FromForm` parser. If the error is not caught by a\n/// [`form::Result<T>`](Result) or `Option<Form<T>>` data guard, the status code\n/// is set to [`Errors::status()`], and the corresponding error catcher is\n/// called.\n///\n/// Otherwise the guard **succeeds**.\n///\n/// [`ContentType::Form`]: crate::http::ContentType::Form\n/// [`ContentType::FormData`]: crate::http::ContentType::FormData\n///\n/// ## Data Limits\n///\n/// The total amount of data accepted by the `Form` data guard is limited by the\n/// following limits:\n///\n/// | Limit Name  | Default | Description                        |\n/// |-------------|---------|------------------------------------|\n/// | `form`      | 32KiB   | total limit for url-encoded forms  |\n/// | `data-form` | 2MiB    | total limit for multipart forms    |\n/// | `*`         | N/A     | each field type has its own limits |\n///\n/// As noted above, each form field type (a form guard) typically imposes its\n/// own limits. For example, the `&str` form guard imposes a data limit of\n/// `string` when multipart data is streamed.\n///\n/// ### URL-Encoded Forms\n///\n/// The `form` limit specifies the data limit for an entire url-encoded form\n/// data. It defaults to 32KiB. URL-encoded form data is percent-decoded, stored\n/// in-memory, and parsed into [`ValueField`]s. If the incoming data exceeds\n/// this limit, the `Form` data guard fails without attempting to parse fields\n/// with a `413: Payload Too Large` error.\n///\n/// ### Multipart Forms\n///\n/// The `data-form` limit specifies the data limit for an entire multipart form\n/// data stream. It defaults to 2MiB. Multipart data is streamed, and form\n/// fields are processed into [`DataField`]s or [`ValueField`]s as they arrive.\n/// If the commutative data received while streaming exceeds the limit, parsing\n/// is aborted, an error is created and pushed via [`FromForm::push_error()`],\n/// and the form is finalized.\n///\n/// ### Individual Fields\n///\n/// Individual fields _may_ have data limits as well. The type of the field\n/// determines whether there is a data limit. For instance, the `&str` type\n/// imposes the `string` data limit. Consult the type's documentation or\n/// [`FromFormField`] for details.\n///\n/// ### Changing Limits\n///\n/// To change data limits, set the `limits.form` and/or `limits.data-form`\n/// configuration parameters. For instance, to increase the URL-encoded forms\n/// limit to 128KiB for all environments, you might add the following to your\n/// `Rocket.toml`:\n///\n/// ```toml\n/// [global.limits]\n/// form = 128KiB\n/// ```\n///\n/// See the [`Limits`](crate::data::Limits) and [`config`](crate::config) docs\n/// for more.\n#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]\npub struct Form<T>(T);\n\nimpl<T> Form<T> {\n    /// Consumes `self` and returns the inner value.\n    ///\n    /// Note that since `Form` implements [`Deref`] and [`DerefMut`] with\n    /// target `T`, reading and writing an inner value can be accomplished\n    /// transparently.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::form::Form;\n    ///\n    /// #[derive(FromForm)]\n    /// struct MyForm {\n    ///     field: String,\n    /// }\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<MyForm>) -> String {\n    ///     // We can read or mutate a value transparently:\n    ///     let field: &str = &form.field;\n    ///\n    ///     // To gain ownership, however, use `into_inner()`:\n    ///     form.into_inner().field\n    /// }\n    /// ```\n    pub fn into_inner(self) -> T {\n        self.0\n    }\n}\n\nimpl<T> From<T> for Form<T> {\n    #[inline]\n    fn from(val: T) -> Form<T> {\n        Form(val)\n    }\n}\n\nimpl<'r, T: FromForm<'r>> Form<T> {\n    /// Leniently parses a `T` from a **percent-decoded**\n    /// `x-www-form-urlencoded` form string. Specifically, this method\n    /// implements [§5.1 of the WHATWG URL Living Standard] with the exception\n    /// of steps 3.4 and 3.5, which are assumed to already be reflected in\n    /// `string`, and then parses the fields as `T`.\n    ///\n    /// [§5.1 of the WHATWG URL Living Standard]: https://url.spec.whatwg.org/#application/x-www-form-urlencoded\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::{Form, FromForm};\n    ///\n    /// #[derive(FromForm)]\n    /// struct Pet<'r> {\n    ///     name: &'r str,\n    ///     wags: bool,\n    /// }\n    ///\n    /// let string = \"name=Benson Wagger!&wags=true\";\n    /// let pet: Pet<'_> = Form::parse(string).unwrap();\n    /// assert_eq!(pet.name, \"Benson Wagger!\");\n    /// assert_eq!(pet.wags, true);\n    /// ```\n    #[inline]\n    pub fn parse(string: &'r str) -> Result<'r, T> {\n        // WHATWG URL Living Standard 5.1 steps 1, 2, 3.1 - 3.3.\n        Self::parse_iter(Form::values(string))\n    }\n\n    /// Leniently parses a `T` from the **percent-decoded** `fields`.\n    /// Specifically, this method implements [§5.1 of the WHATWG URL Living\n    /// Standard] with the exception of step 3.\n    ///\n    /// [§5.1 of the WHATWG URL Living Standard]: https://url.spec.whatwg.org/#application/x-www-form-urlencoded\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::{Form, FromForm, ValueField};\n    ///\n    /// #[derive(FromForm)]\n    /// struct Pet<'r> {\n    ///     name: &'r str,\n    ///     wags: bool,\n    /// }\n    ///\n    /// let fields = vec![\n    ///     ValueField::parse(\"name=Bob, the cat. :)\"),\n    ///     ValueField::parse(\"wags=no\"),\n    /// ];\n    ///\n    /// let pet: Pet<'_> = Form::parse_iter(fields).unwrap();\n    /// assert_eq!(pet.name, \"Bob, the cat. :)\");\n    /// assert_eq!(pet.wags, false);\n    /// ```\n    pub fn parse_iter<I>(fields: I) -> Result<'r, T>\n        where I: IntoIterator<Item = ValueField<'r>>\n    {\n        // WHATWG URL Living Standard 5.1 steps 1, 2, 3.1 - 3.3.\n        let mut ctxt = T::init(Options::Lenient);\n        fields.into_iter().for_each(|f| T::push_value(&mut ctxt, f));\n        T::finalize(ctxt)\n    }\n}\n\nimpl<T: for<'a> FromForm<'a> + 'static> Form<T> {\n    /// Leniently parses a `T` from a raw, `x-www-form-urlencoded` form string.\n    /// Specifically, this method implements [§5.1 of the WHATWG URL Living\n    /// Standard]. Because percent-decoding might modify the input string, the\n    /// output type `T` must be `'static`.\n    ///\n    /// [§5.1 of the WHATWG URL Living Standard]:https://url.spec.whatwg.org/#application/x-www-form-urlencoded\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::RawStr;\n    /// use rocket::form::{Form, FromForm};\n    ///\n    /// #[derive(FromForm)]\n    /// struct Pet {\n    ///     name: String,\n    ///     wags: bool,\n    /// }\n    ///\n    /// let string = RawStr::new(\"name=Benson+Wagger%21&wags=true\");\n    /// let pet: Pet = Form::parse_encoded(string).unwrap();\n    /// assert_eq!(pet.name, \"Benson Wagger!\");\n    /// assert_eq!(pet.wags, true);\n    /// ```\n    pub fn parse_encoded(string: &RawStr) -> Result<'static, T> {\n        let buffer = SharedStack::new();\n        let mut ctxt = T::init(Options::Lenient);\n        for field in RawStrParser::new(&buffer, string) {\n            T::push_value(&mut ctxt, field)\n        }\n\n        T::finalize(ctxt).map_err(|e| e.into_owned())\n    }\n}\n\nimpl Form<()> {\n    /// Returns an iterator of fields parsed from a `x-www-form-urlencoded` form\n    /// string. Specifically, this method implements steps 1, 2, and 3.1 - 3.3\n    /// of [§5.1 of the WHATWG URL Living Standard]. Fields in the returned\n    /// iterator _are not_ percent-decoded.\n    ///\n    /// [§5.1 of the WHATWG URL Living Standard]:https://url.spec.whatwg.org/#application/x-www-form-urlencoded\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::{Form, ValueField};\n    ///\n    /// let string = \"name=Bobby Brown&&&email=me@rocket.rs\";\n    /// let mut values = Form::values(string);\n    /// assert_eq!(values.next().unwrap(), ValueField::parse(\"name=Bobby Brown\"));\n    /// assert_eq!(values.next().unwrap(), ValueField::parse(\"email=me@rocket.rs\"));\n    /// assert!(values.next().is_none());\n    /// ```\n    pub fn values(string: &str) -> impl Iterator<Item = ValueField<'_>> {\n        // WHATWG URL Living Standard 5.1 steps 1, 2, 3.1 - 3.3.\n        string.split('&')\n            .filter(|s| !s.is_empty())\n            .map(ValueField::parse)\n    }\n}\n\nimpl<T> Deref for Form<T> {\n    type Target = T;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<T> DerefMut for Form<T> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: FromForm<'r>> FromData<'r> for Form<T> {\n    type Error = Errors<'r>;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        use either::Either;\n\n        let mut parser = try_outcome!(Parser::new(req, data).await);\n        let mut context = T::init(Options::Lenient);\n        while let Some(field) = parser.next().await {\n            match field {\n                Ok(Either::Left(value)) => T::push_value(&mut context, value),\n                Ok(Either::Right(data)) => T::push_data(&mut context, data).await,\n                Err(e) => T::push_error(&mut context, e),\n            }\n        }\n\n        match T::finalize(context) {\n            Ok(value) => Outcome::Success(Form(value)),\n            Err(e) => Outcome::Error((e.status(), e)),\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/from_form.rs",
    "content": "use std::borrow::Cow;\nuse std::collections::{HashMap, BTreeMap};\nuse std::hash::Hash;\nuse std::sync::Arc;\n\nuse either::Either;\nuse indexmap::IndexMap;\n\nuse crate::form::prelude::*;\nuse crate::http::uncased::AsUncased;\n\n/// Trait implemented by form guards: types parseable from HTTP forms.\n///\n/// Only form guards that are _collections_, that is, collect more than one form\n/// field while parsing, should implement `FromForm`. All other types should\n/// implement [`FromFormField`] instead, which offers a simplified interface to\n/// parsing a single form field.\n///\n/// For a gentle introduction to forms in Rocket, see the [forms guide].\n///\n/// # Form Guards\n///\n/// A form guard is a guard that operates on form fields, typically those with a\n/// particular name prefix. Form guards validate and parse form field data via\n/// implementations of `FromForm`. In other words, a type is a form guard _iff_\n/// it implements `FromForm`.\n///\n/// Form guards are used as the inner type of the [`Form`] data guard:\n///\n/// ```rust\n/// # use rocket::post;\n/// use rocket::form::Form;\n///\n/// # type FormGuard = String;\n/// #[post(\"/submit\", data = \"<var>\")]\n/// fn submit(var: Form<FormGuard>) { /* ... */ }\n/// ```\n///\n/// # Deriving\n///\n/// This trait can, and largely _should_, be automatically derived. When\n/// deriving `FromForm`, every field in the structure must implement\n/// [`FromForm`]. Form fields with the struct field's name are [shifted] and\n/// then pushed to the struct field's `FromForm` parser.\n///\n/// [shifted]: NameView::shift()\n///\n/// ```rust\n/// use rocket::form::FromForm;\n///\n/// #[derive(FromForm)]\n/// struct TodoTask<'r> {\n///     #[field(validate = len(1..))]\n///     description: &'r str,\n///     #[field(name = \"done\")]\n///     completed: bool\n/// }\n/// ```\n///\n/// For full details on deriving `FromForm`, see the [`FromForm` derive].\n///\n/// [`Form`]: crate::form::Form\n/// [`FromForm`]: crate::form::FromForm\n/// [`FromForm` derive]: derive@crate::FromForm\n/// [FromFormField]: crate::form::FromFormField\n/// [`shift()`ed]: NameView::shift()\n/// [`key()`]: NameView::key()\n/// [forms guide]: https://rocket.rs/master/guide/requests/#forms\n///\n/// # Parsing Strategy\n///\n/// Form parsing is either _strict_ or _lenient_, controlled by\n/// [`Options::strict`]. A _strict_ parse errors when there are missing or extra\n/// fields, while a _lenient_ parse allows both, providing there is a\n/// [`default()`](FromForm::default()) in the case of a missing field.\n///\n/// Most type inherit their strategy on [`FromForm::init()`], but some types\n/// like `Option` override the requested strategy. The strategy can also be\n/// overwritten manually, per-field or per-value, by using the [`Strict`] or\n/// [`Lenient`] form guard:\n///\n/// ```rust\n/// use rocket::form::{self, FromForm, Strict, Lenient};\n///\n/// #[derive(FromForm)]\n/// struct TodoTask<'r> {\n///     strict_bool: Strict<bool>,\n///     lenient_inner_option: Option<Lenient<bool>>,\n///     strict_inner_result: form::Result<'r, Strict<bool>>,\n/// }\n/// ```\n///\n/// # Defaults\n///\n/// A form guard may have a _default_ which is used in case of a missing field\n/// when parsing is _lenient_. When parsing is strict, all errors, including\n/// missing fields, are propagated directly.\n///\n/// # Provided Implementations\n///\n/// Rocket implements `FromForm` for many common types. As a result, most\n/// applications will never need a custom implementation of `FromForm` or\n/// `FromFormField`. Their behavior is documented in the table below.\n///\n/// | Type                   | Strategy    | Default           | Data   | Value  | Notes                                              |\n/// |------------------------|-------------|-------------------|--------|--------|----------------------------------------------------|\n/// | [`Strict<T>`]          | **strict**  | if `strict` `T`   | if `T` | if `T` | `T: FromForm`                                      |\n/// | [`Lenient<T>`]         | **lenient** | if `lenient` `T`  | if `T` | if `T` | `T: FromForm`                                      |\n/// | `Option<T>`            | **strict**  | `None`            | if `T` | if `T` | Infallible, `T: FromForm`                          |\n/// | [`Result<T>`]          | _inherit_   | `T::finalize()`   | if `T` | if `T` | Infallible, `T: FromForm`                          |\n/// | `Vec<T>`               | _inherit_   | `vec![]`          | if `T` | if `T` | `T: FromForm`                                      |\n/// | [`HashMap<K, V>`]      | _inherit_   | `HashMap::new()`  | if `V` | if `V` | `K: FromForm + Eq + Hash`, `V: FromForm`           |\n/// | [`BTreeMap<K, V>`]     | _inherit_   | `BTreeMap::new()` | if `V` | if `V` | `K: FromForm + Ord`, `V: FromForm`                 |\n/// | [`Range<T>`]           | _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `start`, `end` fields       |\n/// | [`RangeFrom<T>`]       | _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `start` field               |\n/// | [`RangeTo<T>`]         | _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `end` field                 |\n/// | [`RangeToInclusive<T>`]| _inherit_   | **no default**    | if `T` | if `T` | `T: FromForm`, expects `end` field                 |\n/// | `bool`                 | _inherit_   | `false`           | No     | Yes    | `\"yes\"/\"on\"/\"true\"`, `\"no\"/\"off\"/\"false\"`          |\n/// | (un)signed int         | _inherit_   | **no default**    | No     | Yes    | `{u,i}{size,8,16,32,64,128}`                       |\n/// | _nonzero_ int          | _inherit_   | **no default**    | No     | Yes    | `NonZero{I,U}{size,8,16,32,64,128}`                |\n/// | float                  | _inherit_   | **no default**    | No     | Yes    | `f{32,64}`                                         |\n/// | `&str`                 | _inherit_   | **no default**    | Yes    | Yes    | Percent-decoded. Data limit `string` applies.      |\n/// | `&[u8]`                | _inherit_   | **no default**    | Yes    | Yes    | Raw bytes. Data limit `bytes` applies.             |\n/// | `String`               | _inherit_   | **no default**    | Yes    | Yes    | Exactly `&str`, but owned. Prefer `&str`.          |\n/// | IP Address             | _inherit_   | **no default**    | No     | Yes    | [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`]             |\n/// | Socket Address         | _inherit_   | **no default**    | No     | Yes    | [`SocketAddr`], [`SocketAddrV4`], [`SocketAddrV6`] |\n/// | [`TempFile`]           | _inherit_   | **no default**    | Yes    | Yes    | Data limits apply. See [`TempFile`].               |\n/// | [`Capped<C>`]          | _inherit_   | **no default**    | Yes    | Yes    | `C` is `&str`, `String`, `&[u8]` or `TempFile`.    |\n/// | [`time::Date`]         | _inherit_   | **no default**    | No     | Yes    | `%F` (`YYYY-MM-DD`). HTML \"date\" input.            |\n/// | [`time::DateTime`]     | _inherit_   | **no default**    | No     | Yes    | `%FT%R` or `%FT%T` (`YYYY-MM-DDTHH:MM[:SS]`)       |\n/// | [`time::Time`]         | _inherit_   | **no default**    | No     | Yes    | `%R` or `%T` (`HH:MM[:SS]`)                        |\n///\n/// [`Result<T>`]: crate::form::Result\n/// [`Strict<T>`]: crate::form::Strict\n/// [`Lenient<T>`]: crate::form::Lenient\n/// [`HashMap<K, V>`]: std::collections::HashMap\n/// [`BTreeMap<K, V>`]: std::collections::BTreeMap\n/// [`TempFile`]: crate::fs::TempFile\n/// [`Capped<C>`]: crate::data::Capped\n/// [`time::DateTime`]: time::PrimitiveDateTime\n/// [`IpAddr`]: std::net::IpAddr\n/// [`Ipv4Addr`]: std::net::Ipv4Addr\n/// [`Ipv6Addr`]: std::net::Ipv6Addr\n/// [`SocketAddr`]: std::net::SocketAddr\n/// [`SocketAddrV4`]: std::net::SocketAddrV4\n/// [`SocketAddrV6`]: std::net::SocketAddrV6\n/// [`Range<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.Range.html\n/// [`RangeFrom<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.RangeFrom.html\n/// [`RangeTo<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.RangeTo.html\n/// [`RangeToInclusive<T>`]: https://doc.rust-lang.org/stable/std/ops/struct.RangeToInclusive.html\n///\n/// ## Additional Notes\n///\n///   * **`Vec<T>` where `T: FromForm`**\n///\n///     Parses a sequence of `T`'s. A new `T` is created whenever the field\n///     name's key changes or is empty; the previous `T` is finalized and errors\n///     are stored. While the key remains the same and non-empty, form values\n///     are pushed to the current `T` after being shifted. All collected errors\n///     are returned at finalization, if any, or the successfully created vector\n///     is returned.\n///\n///   * **`HashMap<K, V>` where `K: FromForm + Eq + Hash`, `V: FromForm`**\n///\n///     **`BTreeMap<K, V>` where `K: FromForm + Ord`, `V: FromForm`**\n///\n///     Parses a sequence of `(K, V)`'s. A new pair is created for every unique\n///     first index of the key.\n///\n///     If the key has only one index (`map[index]=value`), the index itself is\n///     pushed to `K`'s parser and the remaining shifted field is pushed to\n///     `V`'s parser.\n///\n///     If the key has two indices (`map[k:index]=value` or\n///     `map[v:index]=value`), the first index must start with `k` or `v`. If\n///     the first index starts with `k`, the shifted field is pushed to `K`'s\n///     parser. If the first index starts with `v`, the shifted field is pushed\n///     to `V`'s parser. If the first index is anything else, an error is\n///     created for the offending form field.\n///\n///     Errors are collected as they occur. Finalization finalizes all pairs and\n///     returns errors, if any, or the map.\n///\n///   * **`bool`**\n///\n///     Parses as `false` for missing values (when lenient) and case-insensitive\n///     values of `off`, `false`, and `no`. Parses as `true` for values of `on`,\n///     `true`, `yes`, and the empty value. Failed to parse otherwise.\n///\n///   * **[`time::DateTime`]**\n///\n///     Parses a date in `%FT%R` or `%FT%T` format, that is, `YYYY-MM-DDTHH:MM`\n///     or `YYYY-MM-DDTHH:MM:SS`. This is the `\"datetime-local\"` HTML input type\n///     without support for the millisecond variant.\n///\n///   * **[`time::Time`]**\n///\n///     Parses a time in `%R` or `%T` format, that is, `HH:MM` or `HH:MM:SS`.\n///     This is the `\"time\"` HTML input type without support for the millisecond\n///     variant.\n///\n/// # Push Parsing\n///\n/// `FromForm` describes a push-based parser for Rocket's [field wire format].\n/// Fields are preprocessed into either [`ValueField`]s or [`DataField`]s which\n/// are then pushed to the parser in [`FromForm::push_value()`] or\n/// [`FromForm::push_data()`], respectively. Both url-encoded forms and\n/// multipart forms are supported. All url-encoded form fields are preprocessed\n/// as [`ValueField`]s. Multipart form fields with Content-Types are processed\n/// as [`DataField`]s while those without a set Content-Type are processed as\n/// [`ValueField`]s. `ValueField` field names and values are percent-decoded.\n///\n/// [field wire format]: crate::form#field-wire-format\n///\n/// Parsing is split into 3 stages. After preprocessing, the three stages are:\n///\n///   1. **Initialization.** The type sets up a context for later `push`es.\n///\n///      ```rust\n///      # use rocket::form::prelude::*;\n///      # struct Foo;\n///      use rocket::form::Options;\n///\n///      # #[rocket::async_trait]\n///      # impl<'r> FromForm<'r> for Foo {\n///          # type Context = std::convert::Infallible;\n///      fn init(opts: Options) -> Self::Context {\n///          todo!(\"return a context for storing parse state\")\n///      }\n///          # fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) { todo!() }\n///          # async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) { todo!() }\n///          # fn finalize(ctxt: Self::Context) -> Result<'r, Self> { todo!() }\n///      # }\n///      ```\n///\n///   2. **Push.** The structure is repeatedly pushed form fields; the latest\n///      context is provided with each `push`. If the structure contains\n///      children, it uses the first [`key()`] to identify a child to which it\n///      then `push`es the remaining `field` to, likely with a [`shift()`ed]\n///      name. Otherwise, the structure parses the `value` itself. The context\n///      is updated as needed.\n///\n///      ```rust\n///      # use rocket::form::prelude::*;\n///      # struct Foo;\n///      use rocket::form::{ValueField, DataField};\n///\n///      # #[rocket::async_trait]\n///      # impl<'r> FromForm<'r> for Foo {\n///          # type Context = std::convert::Infallible;\n///          # fn init(opts: Options) -> Self::Context { todo!() }\n///      fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) {\n///          todo!(\"modify context as necessary for `field`\")\n///      }\n///\n///      async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) {\n///          todo!(\"modify context as necessary for `field`\")\n///      }\n///          # fn finalize(ctxt: Self::Context) -> Result<'r, Self> { todo!() }\n///      # }\n///      ```\n///\n///   3. **Finalization.** The structure is informed that there are no further\n///      fields. It systemizes the effects of previous `push`es via its context\n///      to return a parsed structure or generate [`Errors`].\n///\n///      ```rust\n///      # use rocket::form::prelude::*;\n///      # struct Foo;\n///      use rocket::form::Result;\n///\n///      # #[rocket::async_trait]\n///      # impl<'r> FromForm<'r> for Foo {\n///          # type Context = std::convert::Infallible;\n///          # fn init(opts: Options) -> Self::Context { todo!() }\n///          # fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) { todo!() }\n///          # async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) { todo!() }\n///      fn finalize(ctxt: Self::Context) -> Result<'r, Self> {\n///          todo!(\"inspect context to generate `Self` or `Errors`\")\n///      }\n///      # }\n///      ```\n///\n/// These three stages make up the entirety of the `FromForm` trait.\n///\n/// ## Nesting and [`NameView`]\n///\n/// Each field name key typically identifies a unique child of a structure. As\n/// such, when processed left-to-right, the keys of a field jointly identify a\n/// unique leaf of a structure. The value of the field typically represents the\n/// desired value of the leaf.\n///\n/// A [`NameView`] captures and simplifies this \"left-to-right\" processing of a\n/// field's name by exposing a sliding-prefix view into a name. A [`shift()`]\n/// shifts the view one key to the right. Thus, a `Name` of `a.b.c` when viewed\n/// through a new [`NameView`] is `a`. Shifted once, the view is `a.b`.\n/// [`key()`] returns the last (or \"current\") key in the view. A nested\n/// structure can thus handle a field with a `NameView`, operate on the\n/// [`key()`], [`shift()`] the `NameView`, and pass the field with the shifted\n/// `NameView` to the next processor which handles `b` and so on.\n///\n/// [`shift()`]: NameView::shift()\n/// [`key()`]: NameView::key()\n///\n/// ## A Simple Example\n///\n/// The following example uses `f1=v1&f2=v2` to illustrate field/value pairs\n/// `(f1, v2)` and `(f2, v2)`. This is the same encoding used to send HTML forms\n/// over HTTP, though Rocket's push-parsers are unaware of any specific\n/// encoding, dealing only with logical `field`s, `index`es, and `value`s.\n///\n/// ### A Single Field (`T: FormFormField`)\n///\n/// The simplest example parses a single value of type `T` from a string with an\n/// optional default value: this is `impl<T: FromFormField> FromForm for T`:\n///\n///   1. **Initialization.** The context stores form options and an `Option` of\n///      `Result<T, form::Error>` for storing the `result` of parsing `T`, which\n///      is initially set to `None`.\n///\n///      ```rust\n///      use rocket::form::{self, FromFormField};\n///\n///      struct Context<'r, T: FromFormField<'r>> {\n///          opts: form::Options,\n///          result: Option<form::Result<'r, T>>,\n///      }\n///\n///      # impl<'r, T: FromFormField<'r>> Context<'r, T> {\n///      fn init(opts: form::Options) -> Context<'r, T> {\n///         Context { opts, result: None }\n///      }\n///      # }\n///      ```\n///\n///   2. **Push.** If `ctxt.result` is `None`, `T` is parsed from `field`, and\n///      the result is stored in `context.result`. Otherwise a field has already\n///      been parsed and nothing is done.\n///\n///      ```rust\n///      # use rocket::form::{self, ValueField, FromFormField};\n///      # struct Context<'r, T: FromFormField<'r>> {\n///      #     opts: form::Options,\n///      #     result: Option<form::Result<'r, T>>,\n///      # }\n///      # impl<'r, T: FromFormField<'r>> Context<'r, T> {\n///      fn push_value(ctxt: &mut Context<'r, T>, field: ValueField<'r>) {\n///          if ctxt.result.is_none() {\n///              ctxt.result = Some(T::from_value(field));\n///          }\n///      }\n///      # }\n///      ```\n///\n///   3. **Finalization.** If `ctxt.result` is `None`, parsing is lenient, and\n///      `T` has a default, the default is returned. Otherwise a `Missing` error\n///      is returned. If `ctxt.result` is `Some(v)`, the result `v` is returned.\n///\n///      ```rust\n///      # use rocket::form::{self, FromFormField, error::{Errors, ErrorKind}};\n///      # struct Context<'r, T: FromFormField<'r>> {\n///      #     opts: form::Options,\n///      #     result: Option<form::Result<'r, T>>,\n///      # }\n///      # impl<'r, T: FromFormField<'r>> Context<'r, T> {\n///      fn finalize(ctxt: Context<'r, T>) -> form::Result<'r, T> {\n///          match ctxt.result {\n///              Some(result) => result,\n///              None if ctxt.opts.strict => Err(Errors::from(ErrorKind::Missing)),\n///              None => match T::default() {\n///                  Some(default) => Ok(default),\n///                  None => Err(Errors::from(ErrorKind::Missing)),\n///              }\n///          }\n///      }\n///      # }\n///      ```\n///\n/// This implementation is complete except for the following details:\n///\n///   * handling both `push_data` and `push_value`\n///   * checking for duplicate pushes when parsing is `strict`\n///   * tracking the field's name and value to generate a complete [`Error`]\n///\n/// # Implementing\n///\n/// Implementing `FromForm` should be a rare occurrence. Prefer instead to use\n/// Rocket's built-in derivation or, for custom types, implementing\n/// [`FromFormField`].\n///\n/// An implementation of `FromForm` consists of implementing the three stages\n/// outlined above. `FromForm` is an async trait, so implementations must be\n/// decorated with an attribute of `#[rocket::async_trait]`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # struct MyType;\n/// # struct MyContext;\n/// use rocket::form::{self, FromForm, DataField, ValueField};\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromForm<'r> for MyType {\n///     type Context = MyContext;\n///\n///     fn init(opts: form::Options) -> Self::Context {\n///         todo!()\n///     }\n///\n///     fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>) {\n///         todo!()\n///     }\n///\n///     async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>) {\n///         todo!()\n///     }\n///\n///     fn finalize(this: Self::Context) -> form::Result<'r, Self> {\n///         todo!()\n///     }\n/// }\n/// ```\n///\n/// The lifetime `'r` corresponds to the lifetime of the request.\n///\n/// ## A More Involved Example\n///\n/// We illustrate implementation of `FromForm` through an example. The example\n/// implements `FromForm` for a `Pair(A, B)` type where `A: FromForm` and `B:\n/// FromForm`, parseable from forms with at least two fields, one with a key of\n/// `0` and the other with a key of `1`. The field with key `0` is parsed as an\n/// `A` while the field with key `1` is parsed as a `B`. Specifically, to parse\n/// a `Pair(A, B)` from a field with prefix `pair`, a form with the following\n/// fields must be submitted:\n///\n///   * `pair[0]` - type A\n///   * `pair[1]` - type B\n///\n/// Examples include:\n///\n///   * `pair[0]=id&pair[1]=100` as `Pair(&str, usize)`\n///   * `pair[0]=id&pair[1]=100` as `Pair(&str, &str)`\n///   * `pair[0]=2012-10-12&pair[1]=100` as `Pair(time::Date, &str)`\n///   * `pair.0=2012-10-12&pair.1=100` as `Pair(time::Date, usize)`\n///\n/// ```rust\n/// use either::Either;\n/// use rocket::form::{self, FromForm, ValueField, DataField, Error, Errors};\n///\n/// /// A form guard parseable from fields `.0` and `.1`.\n/// struct Pair<A, B>(A, B);\n///\n/// // The parsing context. We'll be pushing fields with key `.0` to `left`\n/// // and fields with `.1` to `right`. We'll collect errors along the way.\n/// struct PairContext<'v, A: FromForm<'v>, B: FromForm<'v>> {\n///     left: A::Context,\n///     right: B::Context,\n///     errors: Errors<'v>,\n/// }\n///\n/// #[rocket::async_trait]\n/// impl<'v, A: FromForm<'v>, B: FromForm<'v>> FromForm<'v> for Pair<A, B> {\n///     type Context = PairContext<'v, A, B>;\n///\n///     // We initialize the `PairContext` as expected.\n///     fn init(opts: form::Options) -> Self::Context {\n///         PairContext {\n///             left: A::init(opts),\n///             right: B::init(opts),\n///             errors: Errors::new()\n///         }\n///     }\n///\n///     // For each value, we determine if the key is `.0` (left) or `.1`\n///     // (right) and push to the appropriate parser. If it was neither, we\n///     // store the error for emission on finalization. The parsers for `A` and\n///     // `B` will handle duplicate values and so on.\n///     fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n///         match ctxt.context(field.name) {\n///             Ok(Either::Left(ctxt)) => A::push_value(ctxt, field.shift()),\n///             Ok(Either::Right(ctxt)) => B::push_value(ctxt, field.shift()),\n///             Err(e) => ctxt.errors.push(e),\n///         }\n///     }\n///\n///     // This is identical to `push_value` but for data fields.\n///     async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n///         match ctxt.context(field.name) {\n///             Ok(Either::Left(ctxt)) => A::push_data(ctxt, field.shift()).await,\n///             Ok(Either::Right(ctxt)) => B::push_data(ctxt, field.shift()).await,\n///             Err(e) => ctxt.errors.push(e),\n///         }\n///     }\n///\n///     // Finally, we finalize `A` and `B`. If both returned `Ok` and we\n///     // encountered no errors during the push phase, we return our pair. If\n///     // there were errors, we return them. If `A` and/or `B` failed, we\n///     // return the commutative errors.\n///     fn finalize(mut ctxt: Self::Context) -> form::Result<'v, Self> {\n///         match (A::finalize(ctxt.left), B::finalize(ctxt.right)) {\n///             (Ok(l), Ok(r)) if ctxt.errors.is_empty() => Ok(Pair(l, r)),\n///             (Ok(_), Ok(_)) => Err(ctxt.errors),\n///             (left, right) => {\n///                 if let Err(e) = left { ctxt.errors.extend(e); }\n///                 if let Err(e) = right { ctxt.errors.extend(e); }\n///                 Err(ctxt.errors)\n///             }\n///         }\n///     }\n/// }\n///\n/// impl<'v, A: FromForm<'v>, B: FromForm<'v>> PairContext<'v, A, B> {\n///     // Helper method used by `push_{value, data}`. Determines which context\n///     // we should push to based on the field name's key. If the key is\n///     // neither `0` nor `1`, we return an error.\n///     fn context(\n///         &mut self,\n///         name: form::name::NameView<'v>\n///     ) -> Result<Either<&mut A::Context, &mut B::Context>, Error<'v>> {\n///         use std::borrow::Cow;\n///\n///         match name.key().map(|k| k.as_str()) {\n///             Some(\"0\") => Ok(Either::Left(&mut self.left)),\n///             Some(\"1\") => Ok(Either::Right(&mut self.right)),\n///             _ => Err(Error::from(&[Cow::Borrowed(\"0\"), Cow::Borrowed(\"1\")])\n///                 .with_entity(form::error::Entity::Index(0))\n///                 .with_name(name)),\n///         }\n///     }\n/// }\n/// ```\n#[crate::async_trait]\npub trait FromForm<'r>: Send + Sized {\n    /// The form guard's parsing context.\n    type Context: Send;\n\n    /// Initializes and returns the parsing context for `Self`.\n    fn init(opts: Options) -> Self::Context;\n\n    /// Processes the value field `field`.\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'r>);\n\n    /// Processes the data field `field`.\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'r, '_>);\n\n    /// Processes the external form or field error `_error`.\n    ///\n    /// The default implementation does nothing, which is always correct.\n    fn push_error(_ctxt: &mut Self::Context, _error: Error<'r>) { }\n\n    /// Finalizes parsing. Returns the parsed value when successful or\n    /// collection of [`Errors`] otherwise.\n    fn finalize(ctxt: Self::Context) -> Result<'r, Self>;\n\n    /// Returns a default value, if any, to use when a value is desired and\n    /// parsing fails.\n    ///\n    /// The default implementation initializes `Self` with `opts` and finalizes\n    /// immediately, returning the value if finalization succeeds. This is\n    /// always correct and should likely not be changed. Returning a different\n    /// value may result in ambiguous parses.\n    fn default(opts: Options) -> Option<Self> {\n        Self::finalize(Self::init(opts)).ok()\n    }\n}\n\n#[doc(hidden)]\npub struct VecContext<'v, T: FromForm<'v>> {\n    opts: Options,\n    last_key: Option<&'v Key>,\n    current: Option<T::Context>,\n    errors: Errors<'v>,\n    items: Vec<T>\n}\n\nimpl<'v, T: FromForm<'v>> VecContext<'v, T> {\n    fn new(opts: Options) -> Self {\n        VecContext {\n            opts,\n            last_key: None,\n            current: None,\n            items: vec![],\n            errors: Errors::new(),\n        }\n    }\n\n    fn shift(&mut self) {\n        if let Some(current) = self.current.take() {\n            match T::finalize(current) {\n                Ok(v) => self.items.push(v),\n                Err(e) => self.errors.extend(e)\n            }\n        }\n    }\n\n    fn context(&mut self, name: &NameView<'v>) -> &mut T::Context {\n        let this_key = name.key();\n        let keys_match = match (self.last_key, this_key) {\n            (Some(k1), Some(k2)) => k1 == k2,\n            _ => false\n        };\n\n        if !keys_match {\n            self.shift();\n            self.current = Some(T::init(self.opts));\n        }\n\n        self.last_key = name.key();\n        self.current.as_mut().expect(\"must have current if last == index\")\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromForm<'v> + 'v> FromForm<'v> for Vec<T> {\n    type Context = VecContext<'v, T>;\n\n    fn init(opts: Options) -> Self::Context {\n        VecContext::new(opts)\n    }\n\n    fn push_value(this: &mut Self::Context, field: ValueField<'v>) {\n        T::push_value(this.context(&field.name), field.shift());\n    }\n\n    async fn push_data(this: &mut Self::Context, field: DataField<'v, '_>) {\n        T::push_data(this.context(&field.name), field.shift()).await\n    }\n\n    fn finalize(mut this: Self::Context) -> Result<'v, Self> {\n        this.shift();\n        if !this.errors.is_empty() {\n            Err(this.errors)\n        } else if this.opts.strict && this.items.is_empty() {\n            Err(Errors::from(ErrorKind::Missing))\n        } else {\n            Ok(this.items)\n        }\n    }\n}\n\n// impl_strict_from_form_field_from_capped!(Vec<u8>);\n\n#[doc(hidden)]\npub struct MapContext<'v, K, V> where K: FromForm<'v>, V: FromForm<'v> {\n    opts: Options,\n    /// Maps an index key (&str, map.key=foo, map.k:key) to its entry.\n    /// NOTE: `table`, `entries`, and `metadata` are always the same size.\n    table: IndexMap<&'v str, usize>,\n    /// The `FromForm` context for the (key, value) indexed by `table`.\n    entries: Vec<(K::Context, V::Context)>,\n    /// Recorded metadata for a given key/value pair.\n    metadata: Vec<NameView<'v>>,\n    /// Errors collected while finalizing keys and values.\n    errors: Errors<'v>,\n}\n\nimpl<'v, K, V> MapContext<'v, K, V>\n    where K: FromForm<'v>, V: FromForm<'v>\n{\n    fn new(opts: Options) -> Self {\n        MapContext {\n            opts,\n            table: IndexMap::new(),\n            entries: vec![],\n            metadata: vec![],\n            errors: Errors::new(),\n        }\n    }\n\n    fn ctxt(&mut self, key: &'v str, name: NameView<'v>) -> &mut (K::Context, V::Context) {\n        match self.table.get(key) {\n            Some(i) => &mut self.entries[*i],\n            None => {\n                let i = self.entries.len();\n                self.table.insert(key, i);\n                self.entries.push((K::init(self.opts), V::init(self.opts)));\n                self.metadata.push(name);\n                &mut self.entries[i]\n            }\n        }\n    }\n\n    fn push(&mut self, name: NameView<'v>) -> Option<Either<&mut K::Context, &mut V::Context>> {\n        let index_pair = name.key()\n            .map(|k| k.indices())\n            .map(|mut i| (i.next(), i.next()))\n            .unwrap_or_default();\n\n        match index_pair {\n            (Some(key), None) => {\n                let is_new_key = !self.table.contains_key(key);\n                let (key_ctxt, val_ctxt) = self.ctxt(key, name);\n                if is_new_key {\n                    K::push_value(key_ctxt, ValueField::from_value(key));\n                }\n\n                return Some(Either::Right(val_ctxt));\n            },\n            (Some(kind), Some(key)) => {\n                if kind.as_uncased().starts_with(\"k\") {\n                    return Some(Either::Left(&mut self.ctxt(key, name).0));\n                } else if kind.as_uncased().starts_with(\"v\") {\n                    return Some(Either::Right(&mut self.ctxt(key, name).1));\n                } else {\n                    let error = Error::from(&[Cow::Borrowed(\"k\"), Cow::Borrowed(\"v\")])\n                        .with_entity(Entity::Index(0))\n                        .with_name(name);\n\n                    self.errors.push(error);\n                }\n            }\n            _ => {\n                let error = Error::from(ErrorKind::Missing)\n                    .with_entity(Entity::Key)\n                    .with_name(name);\n\n                self.errors.push(error);\n            }\n        };\n\n        None\n    }\n\n    fn push_value(&mut self, field: ValueField<'v>) {\n        match self.push(field.name) {\n            Some(Either::Left(ctxt)) => K::push_value(ctxt, field.shift()),\n            Some(Either::Right(ctxt)) => V::push_value(ctxt, field.shift()),\n            _ => {}\n        }\n    }\n\n    async fn push_data(&mut self, field: DataField<'v, '_>) {\n        match self.push(field.name) {\n            Some(Either::Left(ctxt)) => K::push_data(ctxt, field.shift()).await,\n            Some(Either::Right(ctxt)) => V::push_data(ctxt, field.shift()).await,\n            _ => {}\n        }\n    }\n\n    fn finalize<T: std::iter::FromIterator<(K, V)>>(mut self) -> Result<'v, T> {\n        let map: T = self.entries.into_iter()\n            .zip(self.metadata.iter())\n            .zip(self.table.keys())\n            .filter_map(|(((k_ctxt, v_ctxt), name), idx)| {\n                let key = K::finalize(k_ctxt)\n                    .map_err(|e| {\n                        // FIXME: Fix `NameBuf` to take in `k` and add it.\n                        // FIXME: Perhaps the `k` should come after: `map.0:k`.\n                        let form_key = format!(\"k:{}\", idx);\n                        self.errors.extend(e.with_name((name.parent(), form_key)));\n                    })\n                    .ok();\n\n                let val = V::finalize(v_ctxt)\n                    .map_err(|e| self.errors.extend(e.with_name((name.parent(), *idx))))\n                    .ok();\n\n                Some((key?, val?))\n            })\n            .collect();\n\n        if !self.errors.is_empty() {\n            Err(self.errors)\n        } else if self.opts.strict && self.table.is_empty() {\n            Err(Errors::from(ErrorKind::Missing))\n        } else {\n            Ok(map)\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, K, V> FromForm<'v> for HashMap<K, V>\n    where K: FromForm<'v> + Eq + Hash, V: FromForm<'v>\n{\n    type Context = MapContext<'v, K, V>;\n\n    fn init(opts: Options) -> Self::Context {\n        MapContext::new(opts)\n    }\n\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        ctxt.push_value(field);\n    }\n\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        ctxt.push_data(field).await;\n    }\n\n    fn finalize(this: Self::Context) -> Result<'v, Self> {\n        this.finalize()\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, K, V> FromForm<'v> for BTreeMap<K, V>\n    where K: FromForm<'v> + Ord, V: FromForm<'v>\n{\n    type Context = MapContext<'v, K, V>;\n\n    fn init(opts: Options) -> Self::Context {\n        MapContext::new(opts)\n    }\n\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        ctxt.push_value(field);\n    }\n\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        ctxt.push_data(field).await;\n    }\n\n    fn finalize(this: Self::Context) -> Result<'v, Self> {\n        this.finalize()\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromForm<'v>> FromForm<'v> for Option<T> {\n    type Context = <T as FromForm<'v>>::Context;\n\n    fn init(_: Options) -> Self::Context {\n        T::init(Options { strict: true })\n    }\n\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        T::push_value(ctxt, field)\n    }\n\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        T::push_data(ctxt, field).await\n    }\n\n    fn finalize(this: Self::Context) -> Result<'v, Self> {\n        Ok(T::finalize(this).ok())\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromForm<'v>> FromForm<'v> for Result<'v, T> {\n    type Context = <T as FromForm<'v>>::Context;\n\n    fn init(opts: Options) -> Self::Context {\n        T::init(opts)\n    }\n\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        T::push_value(ctxt, field)\n    }\n\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        T::push_data(ctxt, field).await\n    }\n\n    fn finalize(this: Self::Context) -> Result<'v, Self> {\n        Ok(T::finalize(this))\n    }\n}\n\n#[doc(hidden)]\npub struct PairContext<'v, A: FromForm<'v>, B: FromForm<'v>> {\n    left: A::Context,\n    right: B::Context,\n    errors: Errors<'v>,\n}\n\nimpl<'v, A: FromForm<'v>, B: FromForm<'v>> PairContext<'v, A, B> {\n    fn context(\n        &mut self,\n        name: NameView<'v>\n    ) -> std::result::Result<Either<&mut A::Context, &mut B::Context>, Error<'v>> {\n        match name.key().map(|k| k.as_str()) {\n            Some(\"0\") => Ok(Either::Left(&mut self.left)),\n            Some(\"1\") => Ok(Either::Right(&mut self.right)),\n            _ => Err(Error::from(&[Cow::Borrowed(\"0\"), Cow::Borrowed(\"1\")])\n                .with_entity(Entity::Index(0))\n                .with_name(name)),\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, A: FromForm<'v>, B: FromForm<'v>> FromForm<'v> for (A, B) {\n    type Context = PairContext<'v, A, B>;\n\n    fn init(opts: Options) -> Self::Context {\n        PairContext {\n            left: A::init(opts),\n            right: B::init(opts),\n            errors: Errors::new()\n        }\n    }\n\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        match ctxt.context(field.name) {\n            Ok(Either::Left(ctxt)) => A::push_value(ctxt, field.shift()),\n            Ok(Either::Right(ctxt)) => B::push_value(ctxt, field.shift()),\n            Err(e) => ctxt.errors.push(e),\n        }\n    }\n\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        match ctxt.context(field.name) {\n            Ok(Either::Left(ctxt)) => A::push_data(ctxt, field.shift()).await,\n            Ok(Either::Right(ctxt)) => B::push_data(ctxt, field.shift()).await,\n            Err(e) => ctxt.errors.push(e),\n        }\n    }\n\n    fn finalize(mut ctxt: Self::Context) -> Result<'v, Self> {\n        match (A::finalize(ctxt.left), B::finalize(ctxt.right)) {\n            (Ok(key), Ok(val)) if ctxt.errors.is_empty() => Ok((key, val)),\n            (Ok(_), Ok(_)) => Err(ctxt.errors)?,\n            (left, right) => {\n                if let Err(e) = left { ctxt.errors.extend(e); }\n                if let Err(e) = right { ctxt.errors.extend(e); }\n                Err(ctxt.errors)?\n            }\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromForm<'v> + Sync> FromForm<'v> for Arc<T> {\n    type Context = <T as FromForm<'v>>::Context;\n\n    fn init(opts: Options) -> Self::Context {\n        T::init(opts)\n    }\n\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        T::push_value(ctxt, field)\n    }\n\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        T::push_data(ctxt, field).await\n    }\n\n    fn finalize(this: Self::Context) -> Result<'v, Self> {\n        T::finalize(this).map(Arc::new)\n    }\n}\n\nmacro_rules! impl_via_proxy {\n    ($R:ident => struct $T:ident <$($G:ident),*> { $($f:ident : $F:ident),* }) => {\n        const _: () = {\n            use super::*;\n\n            mod proxy {\n                #[derive(rocket::FromForm)]\n                pub struct $T<$($G),*> {\n                    $(pub $f : $F),*\n                }\n            }\n\n            #[crate::async_trait]\n            impl<'v, $($G: Send),*> FromForm<'v> for $R<$($G),*>\n                where proxy::$T<$($G),*>: FromForm<'v>\n            {\n                type Context = <proxy::$T<$($G),*> as FromForm<'v>>::Context;\n\n                fn init(opts: Options) -> Self::Context {\n                    <proxy::$T<$($G),*>>::init(opts)\n                }\n\n                fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n                    <proxy::$T<$($G),*>>::push_value(ctxt, field)\n                }\n\n                async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n                    <proxy::$T<$($G),*>>::push_data(ctxt, field).await\n                }\n\n                fn finalize(this: Self::Context) -> Result<'v, Self> {\n                    let proxy = <proxy::$T<$($G),*>>::finalize(this)?;\n                    Ok($R {\n                        $($f : proxy.$f),*\n                    })\n                }\n            }\n        };\n    }\n}\n\nuse std::ops::{Range, RangeFrom, RangeTo, RangeToInclusive};\n\nimpl_via_proxy!(Range => struct Range<T> { start: T, end: T });\nimpl_via_proxy!(RangeFrom => struct RangeFrom<T> { start: T });\nimpl_via_proxy!(RangeTo => struct RangeTo<T> { end: T });\nimpl_via_proxy!(RangeToInclusive => struct RangeToInclusive<T> { end: T });\n"
  },
  {
    "path": "core/lib/src/form/from_form_field.rs",
    "content": "use std::borrow::Cow;\nuse std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr};\nuse std::num::{\n    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,\n    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,\n};\n\nuse time::{Date, Time, PrimitiveDateTime};\nuse time::{macros::format_description, format_description::FormatItem};\n\nuse crate::data::Capped;\nuse crate::http::uncased::AsUncased;\nuse crate::form::prelude::*;\n\n/// Implied form guard ([`FromForm`]) for parsing a single form field.\n///\n/// Types that implement `FromFormField` automatically implement [`FromForm`]\n/// via a blanket implementation. As such, all `FromFormField` types are form\n/// guards and can appear as the type of values in derived `FromForm` struct\n/// fields:\n///\n/// ```rust\n/// # use rocket::form::FromForm;\n/// #[derive(FromForm)]\n/// struct Person<'r> {\n///     name: &'r str,\n///     age: u16\n/// }\n/// ```\n///\n/// # Semantics\n///\n/// The implementation of `FromForm` for a `T: FromFormField` type operates as\n/// follows:\n///\n///   * When parsing is **strict**, the parser accepts the _first_ value or data\n///     field with the corresponding field name and calls `T::from_value()` or\n///     `T::from_data()` with the field's value, respectively. If more than one\n///     field value is seen, an [`ErrorKind::Duplicate`) is emitted. If no\n///     matching field is seen, an [`ErrorKind::Missing`] is emitted. Otherwise,\n///     the result from the call is emitted.\n///\n///   * When parsing is **lenient**, the parser accepts the first _expected_\n///     value or data field with the corresponding field name and calls\n///     `T::from_value()` or `T::from_data()` with the field's value,\n///     respectively. Unexpected values, identified by returning an\n///     [`ErrorKind::Unexpected`] from `from_value()` or `from_data()` are\n///     ignored. Any additional fields with a matching field name are ignored.\n///     If no matching field is seen and `T` has a default, it is used,\n///     otherwise an [`ErrorKind::Missing`] is emitted.\n///\n/// # Deriving\n///\n/// `FromFormField` can be derived for C-like enums, where the generated\n/// implementation case-insensitively parses fields with values equal to the\n/// name of the variant or the value in `field()`.\n///\n/// ```rust\n/// # use rocket::form::FromFormField;\n/// /// Fields with value `\"simple\"` parse as `Kind::Simple`. Fields with value\n/// /// `\"fancy\"` parse as `Kind::SoFancy`.\n/// #[derive(FromFormField)]\n/// enum Kind {\n///     Simple,\n///     #[field(value = \"fancy\")]\n///     SoFancy,\n/// }\n/// ```\n///\n/// # Provided Implementations\n///\n/// See [`FromForm`](crate::form::FromForm#provided-implementations) for a list\n/// of all form guards, including those implemented via `FromFormField`.\n///\n/// # Implementing\n///\n/// Implementing `FromFormField` requires implementing one or both of\n/// `from_value` or `from_data`, depending on whether the type can be parsed\n/// from a value field (text) and/or streaming binary data. Typically, a value\n/// can be parsed from either, either directly or by using request-local cache\n/// as an intermediary, and parsing from both should be preferred when sensible.\n///\n/// `FromFormField` is an async trait, so implementations must be decorated with\n/// an attribute of `#[rocket::async_trait]`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # struct MyType;\n/// use rocket::form::{self, FromFormField, DataField, ValueField};\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromFormField<'r> for MyType {\n///     fn from_value(field: ValueField<'r>) -> form::Result<'r, Self> {\n///         todo!(\"parse from a value or use default impl\")\n///     }\n///\n///     async fn from_data(field: DataField<'r, '_>) -> form::Result<'r, Self> {\n///         todo!(\"parse from a value or use default impl\")\n///     }\n/// }\n/// ```\n///\n/// ## Example\n///\n/// The following example parses a custom `Person` type with the format\n/// `$name:$data`, where `$name` is expected to be string and `data` is expected\n/// to be any slice of bytes.\n///\n/// ```rust\n/// # use rocket::post;\n/// use rocket::data::ToByteUnit;\n/// use rocket::form::{self, FromFormField, DataField, ValueField};\n///\n/// use memchr::memchr;\n///\n/// struct Person<'r> {\n///     name: &'r str,\n///     data: &'r [u8]\n/// }\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromFormField<'r> for Person<'r> {\n///     fn from_value(field: ValueField<'r>) -> form::Result<'r, Self> {\n///         match field.value.find(':') {\n///             Some(i) => Ok(Person {\n///                 name: &field.value[..i],\n///                 data: field.value[(i + 1)..].as_bytes()\n///             }),\n///             None => Err(form::Error::validation(\"does not contain ':'\"))?\n///         }\n///     }\n///\n///     async fn from_data(field: DataField<'r, '_>) -> form::Result<'r, Self> {\n///         // Retrieve the configured data limit or use `256KiB` as default.\n///         let limit = field.request.limits()\n///             .get(\"person\")\n///             .unwrap_or(256.kibibytes());\n///\n///         // Read the capped data stream, returning a limit error as needed.\n///         let bytes = field.data.open(limit).into_bytes().await?;\n///         if !bytes.is_complete() {\n///             Err((None, Some(limit)))?;\n///         }\n///\n///         // Store the bytes in request-local cache and split at ':'.\n///         let bytes = bytes.into_inner();\n///         let bytes = rocket::request::local_cache!(field.request, bytes);\n///         let (raw_name, data) = match memchr(b':', bytes) {\n///             Some(i) => (&bytes[..i], &bytes[(i + 1)..]),\n///             None => Err(form::Error::validation(\"does not contain ':'\"))?\n///         };\n///\n///         // Try to parse the name as UTF-8 or return an error if it fails.\n///         let name = std::str::from_utf8(raw_name)?;\n///         Ok(Person { name, data })\n///     }\n/// }\n///\n/// use rocket::form::{Form, FromForm};\n///\n/// // The type can be used directly, if only one field is expected...\n/// #[post(\"/person\", data = \"<person>\")]\n/// fn person(person: Form<Person<'_>>) { /* ... */ }\n///\n/// // ...or as a named field in another form guard...\n/// #[derive(FromForm)]\n/// struct NewPerson<'r> {\n///     person: Person<'r>\n/// }\n///\n/// #[post(\"/person\", data = \"<person>\")]\n/// fn new_person(person: Form<NewPerson<'_>>) { /* ... */ }\n/// ```\n// NOTE: Ideally, we would have two traits instead one with two fallible\n// methods: `FromFormValue` and `FromFormData`. This would be especially nice\n// for use with query values, where `FromFormData` would make no sense.\n//\n// However, blanket implementations of `FromForm` for these traits would result\n// in duplicate implementations of `FromForm`; we need specialization to resolve\n// this concern. Thus, for now, we keep this as one trait.\n#[crate::async_trait]\npub trait FromFormField<'v>: Send + Sized {\n    /// Parse a value of `T` from a form value field.\n    ///\n    /// The default implementation returns an error of\n    /// [`ValueField::unexpected()`].\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        Err(field.unexpected())?\n    }\n\n    /// Parse a value of `T` from a form data field.\n    ///\n    /// The default implementation returns an error of\n    /// [`DataField::unexpected()`].\n    async fn from_data(field: DataField<'v, '_>) -> Result<'v, Self> {\n        Err(field.unexpected())?\n    }\n\n    /// Returns a default value, if any exists, to be used during lenient\n    /// parsing when the form field is missing.\n    ///\n    /// A return value of `None` means that field is required to exist and parse\n    /// successfully, always. A return value of `Some(default)` means that\n    /// `default` should be used when a field is missing.\n    ///\n    /// The default implementation returns `None`.\n    fn default() -> Option<Self> { None }\n}\n\n#[doc(hidden)]\npub struct FromFieldContext<'v, T: FromFormField<'v>> {\n    field_name: Option<NameView<'v>>,\n    field_value: Option<&'v str>,\n    opts: Options,\n    value: Option<Result<'v, T>>,\n    pushes: usize\n}\n\nimpl<'v, T: FromFormField<'v>> FromFieldContext<'v, T> {\n    fn should_push(&mut self) -> bool {\n        self.pushes += 1;\n        self.value.is_none()\n    }\n\n    fn push(&mut self, name: NameView<'v>, result: Result<'v, T>) {\n        fn is_unexpected(e: &Errors<'_>) -> bool {\n            matches!(e.last().map(|e| &e.kind), Some(ErrorKind::Unexpected))\n        }\n\n        self.field_name = Some(name);\n        match result {\n            Err(e) if !self.opts.strict && is_unexpected(&e) => { /* ok */ },\n            result => self.value = Some(result),\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromFormField<'v>> FromForm<'v> for T {\n    type Context = FromFieldContext<'v, T>;\n\n    fn init(opts: Options) -> Self::Context {\n        FromFieldContext {\n            opts,\n            field_name: None,\n            field_value: None,\n            value: None,\n            pushes: 0,\n        }\n    }\n\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        if ctxt.should_push() {\n            ctxt.field_value = Some(field.value);\n            ctxt.push(field.name, Self::from_value(field))\n        }\n    }\n\n    async fn push_data(ctxt: &mut FromFieldContext<'v, T>, field: DataField<'v, '_>) {\n        if ctxt.should_push() {\n            ctxt.push(field.name, Self::from_data(field).await);\n        }\n    }\n\n    fn finalize(ctxt: Self::Context) -> Result<'v, Self> {\n        let mut errors = match ctxt.value {\n            Some(Ok(val)) if !ctxt.opts.strict || ctxt.pushes <= 1 => return Ok(val),\n            Some(Ok(_)) => Errors::from(ErrorKind::Duplicate),\n            Some(Err(errors)) => errors,\n            None if !ctxt.opts.strict => match <T as FromFormField>::default() {\n                Some(default) => return Ok(default),\n                None => Errors::from(ErrorKind::Missing)\n            },\n            None => Errors::from(ErrorKind::Missing),\n        };\n\n        if let Some(name) = ctxt.field_name {\n            errors.set_name(name);\n        }\n\n        if let Some(value) = ctxt.field_value {\n            errors.set_value(value);\n        }\n\n        Err(errors)\n    }\n}\n\n#[crate::async_trait]\nimpl<'v> FromFormField<'v> for Capped<&'v str> {\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        Ok(Capped::from(field.value))\n    }\n\n    async fn from_data(f: DataField<'v, '_>) -> Result<'v, Self> {\n        use crate::data::{Capped, Outcome, FromData};\n\n        match <Capped<&'v str> as FromData>::from_data(f.request, f.data).await {\n            Outcome::Success(p) => Ok(p),\n            Outcome::Error((_, e)) => Err(e)?,\n            Outcome::Forward(..) => {\n                Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?\n            }\n        }\n    }\n}\n\nimpl_strict_from_form_field_from_capped!(&'v str);\n\n#[crate::async_trait]\nimpl<'v> FromFormField<'v> for Capped<String> {\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        Ok(Capped::from(field.value.to_string()))\n    }\n\n    async fn from_data(f: DataField<'v, '_>) -> Result<'v, Self> {\n        use crate::data::{Capped, Outcome, FromData};\n\n        match <Capped<String> as FromData>::from_data(f.request, f.data).await {\n            Outcome::Success(p) => Ok(p),\n            Outcome::Error((_, e)) => Err(e)?,\n            Outcome::Forward(..) => {\n                Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?\n            }\n        }\n    }\n}\n\nimpl_strict_from_form_field_from_capped!(String);\n\nimpl<'v> FromFormField<'v> for bool {\n    fn default() -> Option<Self> {\n        Some(false)\n    }\n\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        match field.value.as_uncased() {\n            v if v == \"off\" || v == \"no\" || v == \"false\" => Ok(false),\n            v if v.is_empty() || v == \"on\" || v == \"yes\" || v == \"true\" => Ok(true),\n            // force a `ParseBoolError`\n            _ => Ok(\"\".parse()?),\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'v> FromFormField<'v> for Capped<&'v [u8]> {\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        Ok(Capped::from(field.value.as_bytes()))\n    }\n\n    async fn from_data(f: DataField<'v, '_>) -> Result<'v, Self> {\n        use crate::data::{Capped, Outcome, FromData};\n\n        match <Capped<&'v [u8]> as FromData>::from_data(f.request, f.data).await {\n            Outcome::Success(p) => Ok(p),\n            Outcome::Error((_, e)) => Err(e)?,\n            Outcome::Forward(..) => {\n                Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?\n            }\n        }\n    }\n}\n\nimpl_strict_from_form_field_from_capped!(&'v [u8]);\n\n#[crate::async_trait]\nimpl<'v> FromFormField<'v> for Capped<Cow<'v, str>> {\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        let capped = <Capped<&'v str>>::from_value(field)?;\n        Ok(capped.map(|s| s.into()))\n    }\n\n    async fn from_data(field: DataField<'v, '_>) -> Result<'v, Self> {\n        let capped = <Capped<&'v str>>::from_data(field).await?;\n        Ok(capped.map(|s| s.into()))\n    }\n}\n\nimpl_strict_from_form_field_from_capped!(Cow<'v, str>);\n\nmacro_rules! impl_with_parse {\n    ($($T:ident),+ $(,)?) => ($(\n        impl<'v> FromFormField<'v> for $T {\n            #[inline(always)]\n            fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n                Ok(field.value.parse()?)\n            }\n        }\n    )+)\n}\n\nimpl_with_parse!(\n    char,\n    f32, f64,\n    isize, i8, i16, i32, i64, i128,\n    usize, u8, u16, u32, u64, u128,\n    NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128,\n    NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,\n    Ipv4Addr, IpAddr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr\n);\n\n// Keep formats in sync with 'FromFormField' impls.\nstatic DATE_FMT: &[FormatItem<'_>] = format_description!(\"[year padding:none]-[month]-[day]\");\nstatic TIME_FMT1: &[FormatItem<'_>] = format_description!(\"[hour padding:none]:[minute]:[second]\");\nstatic TIME_FMT2: &[FormatItem<'_>] = format_description!(\"[hour padding:none]:[minute]\");\nstatic DATE_TIME_FMT1: &[FormatItem<'_>] =\n    format_description!(\"[year padding:none]-[month]-[day]T[hour padding:none]:[minute]:[second]\");\nstatic DATE_TIME_FMT2: &[FormatItem<'_>] =\n    format_description!(\"[year padding:none]-[month]-[day]T[hour padding:none]:[minute]\");\n\nimpl<'v> FromFormField<'v> for Date {\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        let date = Self::parse(field.value, &DATE_FMT)\n            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send>)?;\n\n        Ok(date)\n    }\n}\n\nimpl<'v> FromFormField<'v> for Time {\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        let time = Self::parse(field.value, &TIME_FMT1)\n            .or_else(|_| Self::parse(field.value, &TIME_FMT2))\n            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send>)?;\n\n        Ok(time)\n    }\n}\n\nimpl<'v> FromFormField<'v> for PrimitiveDateTime {\n    fn from_value(field: ValueField<'v>) -> Result<'v, Self> {\n        let dt = Self::parse(field.value, &DATE_TIME_FMT1)\n            .or_else(|_| Self::parse(field.value, &DATE_TIME_FMT2))\n            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send>)?;\n\n        Ok(dt)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/lenient.rs",
    "content": "use std::ops::{Deref, DerefMut};\n\nuse crate::form::prelude::*;\nuse crate::http::uri::fmt::{Query, FromUriParam};\n\n/// A form guard for parsing form types leniently.\n///\n/// This type implements the [`FromForm`] trait and thus can be used as a\n/// generic parameter to the [`Form`] data guard: `Form<Lenient<T>>`, where `T`\n/// implements `FromForm`. Unlike using `Form` directly, this type uses a\n/// _lenient_ parsing strategy.\n///\n/// # Lenient Parsing\n///\n/// A `Lenient<T>` will parse successfully from an incoming form even if the\n/// form contains extra or missing fields. If fields are missing, the form field\n/// type's default will be used, if there is one. Extra fields are ignored; only\n/// the first is parsed and validated. This is the default strategy for\n/// [`Form`].\n///\n/// # Usage\n///\n/// `Lenient<T>` implements [`FromForm`] as long as `T` implements `FromForm`.\n/// As such, `Form<Lenient<T>>` is a data guard.\n///\n/// Note that `Form<T>` _already_ parses leniently, so a `Form<Lenient<T>>` is\n/// redundant and equal to `Form<T>`. `Lenient`, however, can be used to make\n/// otherwise strict parses lenient, for example, in `Option<Lenient<T>>`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::form::Lenient;\n///\n/// #[derive(FromForm)]\n/// struct UserInput {\n///     // Parses as `Some(false)` when `lenient_inner_option` isn't present.\n///     // Without `Lenient`, this would otherwise parse as `None`.\n///     lenient_inner_option: Option<Lenient<bool>>,\n/// }\n/// ```\n#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct Lenient<T>(T);\n\nimpl<T> Lenient<T> {\n    /// Consumes `self` and returns the inner value.\n    ///\n    /// Note that since `Lenient` implements [`Deref`] and [`DerefMut`] with\n    /// target `T`, reading and writing an inner value can be accomplished\n    /// transparently.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::form::{Form, Lenient};\n    ///\n    /// #[derive(FromForm)]\n    /// struct MyForm {\n    ///     field: String,\n    /// }\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Lenient<MyForm>>) -> String {\n    ///     // We can read or mutate a value transparently:\n    ///     let field: &str = &form.field;\n    ///\n    ///     // To gain ownership, however, use `into_inner()`:\n    ///     form.into_inner().into_inner().field\n    /// }\n    /// ```\n    pub fn into_inner(self) -> T {\n        self.0\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromForm<'v>> FromForm<'v> for Lenient<T> {\n    type Context = T::Context;\n\n    #[inline(always)]\n    fn init(_: Options) -> Self::Context {\n        T::init(Options { strict: false })\n    }\n\n    #[inline(always)]\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        T::push_value(ctxt, field)\n    }\n\n    #[inline(always)]\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        T::push_data(ctxt, field).await\n    }\n\n    #[inline(always)]\n    fn finalize(this: Self::Context) -> Result<'v, Self> {\n        T::finalize(this).map(Self)\n    }\n}\n\nimpl<T> Deref for Lenient<T> {\n    type Target = T;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<T> DerefMut for Lenient<T> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n\nimpl<T> From<T> for Lenient<T> {\n    #[inline]\n    fn from(val: T) -> Lenient<T> {\n        Lenient(val)\n    }\n}\n\nimpl<'f, A, T: FromUriParam<Query, A> + FromForm<'f>> FromUriParam<Query, A> for Lenient<T> {\n    type Target = T::Target;\n\n    #[inline(always)]\n    fn from_uri_param(param: A) -> Self::Target {\n        T::from_uri_param(param)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/mod.rs",
    "content": "//! Parsing and validation of HTTP forms and fields.\n//!\n//! See the [forms guide](https://rocket.rs/master/guide/requests#forms) for\n//! general form support documentation.\n//!\n//! # Field Wire Format\n//!\n//! Rocket's field wire format is a flexible, non-self-descriptive, text-based\n//! encoding of arbitrarily nested structure keys and their corresponding\n//! values. The general grammar is:\n//!\n//! ```ebnf\n//! field := name ('=' value)?\n//!\n//! name := key*\n//!\n//! key := indices\n//!       | '[' indices ']'\n//!       | '.' indices\n//!\n//! indices := index (':' index)*\n//!\n//! index := STRING except ':', ']'\n//!\n//! value := STRING\n//! ```\n//!\n//! Each field name consists of any number of `key`s and at most one `value`.\n//! Keys are delimited by `[` or `.`. A `key` consists of indices delimited by\n//! `:`.\n//!\n//! The meaning of a key or index is type-dependent, hence the format is\n//! non-self-descriptive. _Any_ structure can be described by this format. The\n//! delimiters `.`, `[`, `:`, and `]` have no semantic meaning.\n//!\n//! Some examples of valid fields are:\n//!\n//!   * `=`\n//!   * `key=value`\n//!   * `key[]=value`\n//!   * `.0=value`\n//!   * `[0]=value`\n//!   * `people[].name=Bob`\n//!   * `bob.cousin.names[]=Bob`\n//!   * `map[k:1]=Bob`\n//!   * `people[bob]nickname=Stan`\n//!\n//! See [`FromForm`] for full details on push-parsing and complete examples, and\n//! [`Form`] for how to accept forms in a request handler.\n\n// ## Maps w/named Fields (`struct`)\n//\n// A `struct` with named fields parses values of multiple types, indexed by the\n// name of its fields:\n//\n// ```rust,ignore\n// struct Dog { name: String, barks: bool, friends: Vec<Cat>, }\n// struct Cat { name: String, meows: bool }\n// ```\n//\n// Candidates for parsing into a `Dog` include:\n//\n//   * `name=Fido&barks=0`\n//\n//     `Dog { \"Fido\", false }`\n//\n//   * `name=Fido&barks=1&friends[0]name=Sally&friends[0]meows=0`\n//     `name=Fido&barks=1&friends[0].name=Sally&friends[0].meows=0`\n//     `name=Fido&barks=1&friends.0.name=Sally&friends.0.meows=0`\n//\n//     `Dog { \"Fido\", true, vec![Cat { \"Sally\", false }] }`\n//\n// Parsers for structs are code-generated to proceed as follows:\n//\n//   1. **Initialization.** The context stores parsing options, a `T::Context`\n//      for each field of type `T`, and a vector called `extra`.\n//\n//      ```rust,ignore\n//      struct Context<'v> {\n//          opts: FormOptions,\n//          field_a: A::Context,\n//          field_b: B::Context,\n//          /* ... */\n//          extra: Vec<FormField<'v>>\n//      }\n//      ```\n//\n//   2. **Push.** The index of the first key is compared to known field names.\n//      If none matches, the index is added to `extra`. Otherwise the key is\n//      stripped from the field, and the remaining field is pushed to `T`.\n//\n//      ```rust,ignore\n//      fn push(this: &mut Self::Context, field: FormField<'v>) {\n//          match field.key() {\n//              \"field_a\" => A::push(&mut this.field_a, field.next()),\n//              \"field_b\" => B::push(&mut this.field_b, field.next()),\n//              /* ... */\n//              _ => this.extra.push(field)\n//          }\n//      }\n//      ```\n//\n//   3. **Finalization.** Every context is finalized; errors and `Ok` values\n//      are collected. If parsing is strict and extras is non-empty, an error\n//      added to the collection of errors. If there are no errors, all `Ok`\n//      values are used to create the `struct`, and the created struct is\n//      returned. Otherwise, `Err(errors)` is returned.\n//\n//      ```rust,ignore\n//      fn finalize(mut this: Self::Context) -> Result<Self, Self::Error> {\n//          let mut errors = vec![];\n//\n//          let field_a = A::finalize(&mut this.field_a)\n//             .map_err(|e| errors.push(e))\n//             .map(Some).unwrap_or(None);\n//\n//          let field_b = B::finalize(&mut this.field_b)\n//             .map_err(|e| errors.push(e))\n//             .map(Some).unwrap_or(None);\n//\n//          /* .. */\n//\n//          if !errors.is_empty() {\n//              return Err(Values(errors));\n//          } else if this.opts.is_strict() && !this.extra.is_empty() {\n//              return Err(Extra(this.extra));\n//          } else {\n//              // NOTE: All unwraps will succeed since `errors.is_empty()`.\n//              Struct {\n//                 field_a: field_a.unwrap(),\n//                 field_b: field_b.unwrap(),\n//                 /* .. */\n//              }\n//          }\n//      }\n//      ```\n//\n// ## Sequences: (`Vec<T: FromForm>`)\n//\n// A `Vec<T: FromForm>` invokes `T`'s push-parser on every push, adding instances\n// of `T` to an internal vector. The instance of `T` whose parser is invoked\n// depends on the index of the first key:\n//\n//   * if it is the first push, the index differs from the previous, or there is no\n//     index, a new `T::Context` is `init`ialized and added to the internal vector\n//   * if the index matches the previously seen index, the last initialized\n//     `T::Context` is `push`ed to.\n//\n// For instance, the sequentially pushed values `=1`, `=2`, and `=3` for a\n// `Vec<usize>` (or any other integer) is expected to parse as `vec![1, 2, 3]`. The\n// same is true for `[]=1&[]=2&[]=3`. In the first example (`=1&..`), the fields\n// passed to `Vec`'s push-parser (`=1`, ..) have no key and thus no index. In the\n// second example (`[]=1&..`), the key is `[]` (`[]=1`) without an index. In both\n// cases, there is no index. The `Vec` parser takes this to mean that a _new_ `T`\n// should be parsed using the field's value.\n//\n// If, instead, the index was non-empty and equal to the index of the field in the\n// _previous_ push, `Vec` pushes the value to the parser of the previously parsed\n// `T`: `[]=1&[0]=2&[0]=3` results in `vec![1, 2]` and `[0]=1&[0]=2&[]=3` results\n// in `vec![1, 3]` (see [`FromFormValue`]).\n//\n// This generalizes. Consider a `Vec<Vec<usize>>` named `x`, so `x` and an\n// optional `=` are stripped before being passed to `Vec`'s push-parser:\n//\n//   * `x=1&x=2&x=3` parses as `vec![vec![1], vec![2], vec![3]]`\n//\n//     Every push (`1`, `2`, `3`) has no key, thus no index: a new `T` (here,\n//     `Vec<usize>`) is thus initialized for every `push()` and passed the\n//     value (here, `1`, `2`, and `3`). Each of these `push`es proceeds\n//     recursively: every push again has no key, thus no index, so a new `T` is\n//     initialized for every push (now a `usize`), which finally parse as\n//     integers `1`, `2`, and `3`.\n//\n//     Note: `x=1&x=2&x=3` _also_ can also parse as `vec![1, 2, 3]` when viewed\n//     as a `Vec<usize>`; this is the non-self-descriptive part of the format.\n//\n//   * `x[]=1&x[]=2&x[]=3` parses as `vec![vec![1], vec![2], vec![3]]`\n//\n//     This proceeds nearly identically to the previous example, with the exception\n//     that the top-level `Vec` sees the values `[]=1`, `[]=2`, and `[]=3`.\n//\n//   * `x[0]=1&x[0]=2&x[]=3` parses as `vec![vec![1, 2], vec![3]]`\n//\n//     The top-level `Vec` sees the values `[0]=1`, `[0]=2`, and `[]=3`. The first\n//     value results in a new `Vec<usize>` being initialized, as before, which is\n//     pushed a `1`. The second value has the same index as the first, `0`, and so\n//     `2` is pushed to the previous `T`, the `Vec` which contains the `1`.\n//     Finally, the third value has no index, so a new `Vec<usize>` is initialized\n//     and pushed a `3`.\n//\n//   * `x[0]=1&x[0]=2&x[]=3&x[]=4` parses as `vec![vec![1, 2], vec![3], vec![4]]`\n//   * `x[0]=1&x[0]=2&x[1]=3&x[1]=4` parses as `vec![vec![1, 2], vec![3, 4]]`\n//\n// The indexing kind `[]` is purely by convention: the first two examples are\n// equivalent to `x.=1&x.=2`, while the third to `x.0=1&x.0=&x.=3`.\n//\n// The parser proceeds as follows:\n//\n//   1. **Initialization.** The context stores parsing options, the\n//      `last_index` encountered in a `push`, an `Option` of a `T::Context` for\n//      the `current` value being parsed, a `Vec<T::Errors>` of `errors`, and\n//      finally a `Vec<T>` of already parsed `items`.\n//\n//      ```rust,ignore\n//      struct VecContext<'v, T: FromForm<'v>> {\n//          opts: FormOptions,\n//          last_index: Index<'v>,\n//          current: Option<T::Context>,\n//          errors: Vec<T::Error>,\n//          items: Vec<T>\n//      }\n//      ```\n//\n//   2. **Push.** The index of the first key is compared against `last_index`.\n//      If it differs, a new context for `T` is created and the previous is\n//      finalized. The `Ok` result from finalization is stored in `items` and\n//      the `Err` in `errors`. Otherwise the `index` is the same, the `current`\n//      context is retrieved, and the field stripped of the current key is\n//      pushed to `T`. `last_index` is updated.\n//\n//      ```rust,ignore\n//      fn push(this: &mut Self::Context, field: FormField<'v>) {\n//          if this.last_index != field.index() {\n//              this.shift(); // finalize `current`, add to `items`, `errors`\n//              let mut context = T::init(this.opts);\n//              T::push(&mut context, field.next());\n//              this.current = Some(context);\n//          } else {\n//              let context = this.current.as_mut();\n//              T::push(context, field.next())\n//          }\n//\n//          this.last_index = field.index();\n//      }\n//      ```\n//\n//   3. **Finalization.** Any `current` context is finalized, storing the `Ok`\n//      or `Err` as before. `Ok(items)` is returned if `errors` is empty,\n//      otherwise `Err(errors)` is returned.\n//\n//      ```rust,ignore\n//      fn finalize(mut this: Self::Context) -> Result<Self, Self::Error> {\n//          this.shift(); // finalizes `current`, as before.\n//          match this.errors.is_empty() {\n//              true => Ok(this.items),\n//              false => Err(this.errors)\n//          }\n//      }\n//      ```\n//\n// ## Arbitrary Maps (`HashMap<K: FromForm, V: FromForm>`)\n//\n// A `HashMap<K, V>` can be parsed from keys with one index or, for composite\n// key values, such as structures or sequences, multiple indices. We begin with\n// a discussion of the simpler case: non-composite keys.\n//\n// ### Non-Composite Keys\n//\n// A non-composite value can be described by a single field with no indices.\n// Strings and integers are examples of non-composite values. The push-parser\n// for `HashMap<K, V>` for a non-composite `K` uses the index of the first key\n// as the value of `K`; the remainder of the field is pushed to `V`'s parser:\n//\n//   1. **Initialization.** The context stores a column-based representation of\n//      `keys` and `values`, a `key_map` from a string key to the column index,\n//      an `errors` vector for storing errors as they arise, and the parsing\n//      options.\n//\n//      ```rust,ignore\n//      struct MapContext<'v, K: FromForm<'v>, V: FromForm<'v>> {\n//          opts: FormOptions,\n//          key_map: HashMap<&'v str, usize>,\n//          keys: Vec<K::Context>,\n//          values: Vec<V::Context>,\n//          errors: Vec<MapError<'v, K::Error, V::Error>>,\n//      }\n//      ```\n//\n//   2. **Push.** The `key_map` index for the key associated with the index of\n//      the first key in the field is retrieved. If such a key has not yet been\n//      seen, a new key and value context are created, the key is pushed to\n//      `K`'s parser, and the field minus the first key is pushed to `V`'s\n//      parser.\n//\n//      ```rust,ignore\n//      fn push(this: &mut Self::Context, field: FormField<'v>) {\n//          let key = field.index();\n//          let value_context = match this.key_map.get(Key) {\n//              Some(i) => &mut this.values[i],\n//              None => {\n//                  let i = this.keys.len();\n//                  this.key_map.insert(key, i);\n//                  this.keys.push(K::init(this.opts));\n//                  this.values.push(V::init(this.opts));\n//                  K::push(&mut this.keys[i], key.into());\n//                  &mut this.values[i]\n//              }\n//          };\n//\n//          V::push(value_context, field.next());\n//      }\n//      ```\n//\n//   3. **Finalization.** All key and value contexts are finalized; any errors\n//      are collected in `errors`. If there are no errors, `keys` and `values`\n//      are collected into a `HashMap` and returned. Otherwise, the errors are\n//      returned.\n//\n//      ```rust,ignore\n//      fn finalize(mut this: Self::Context) -> Result<Self, Self::Error> {\n//          this.finalize_keys();\n//          this.finalize_values();\n//          if this.errors.is_empty() {\n//              Ok(this.keys.into_iter().zip(this.values.into_iter()).collect())\n//          } else {\n//              Err(this.errors)\n//          }\n//      }\n//      ```\n//\n// Examples of forms parseable via this parser are:\n//\n//   * `x[0].name=Bob&x[0].meows=true`as a `HashMap<usize, Cat>` parses with\n//     `0` mapping to `Cat { name: \"Bob\", meows: true }`\n//   * `x[0]name=Bob&x[0]meows=true`as a `HashMap<usize, Cat>` parses just as\n//      above.\n//   * `x[0]=Bob&x[0]=Sally&x[1]=Craig`as a `HashMap<usize, Vec<String>>`\n//      just as `{ 0 => vec![\"Bob\", \"Sally\"], 1 => vec![\"Craig\"] }`.\n//\n// A `HashMap<K, V>` can be thought of as a vector of key-value pairs: `Vec<(K,\n// V)` (row-based) or equivalently, as two vectors of keys and values: `Vec<K>`\n// and `Vec<V>` (column-based). The implication is that indexing into a\n// specific key or value requires _two_ indexes: the first to determine whether\n// a key or value is being indexed to, and the second to determine _which_ key\n// or value. The push-parser for maps thus optionally accepts two indexes for a\n// single key to allow piece-by-piece build-up of arbitrary keys and values.\n//\n// The parser proceeds as follows:\n//\n//   1. **Initialization.** The context stores parsing options, a vector of\n//      `key_contexts: Vec<K::Context>`, a vector of `value_contexts:\n//      Vec<V::Context>`, a `mapping` from a string index to an integer index\n//      into the `contexts`, and a vector of `errors`.\n//\n//   2. **Push.** An index is required; an error is emitted and `push` returns\n//      if they field's first key does not contain an index. If the first key\n//      contains _one_ index, a new `K::Context` and `V::Context` are created.\n//      The key is pushed as the value to `K` and the remaining field as the\n//      value to `V`. The key and value are finalized; if both succeed, the key\n//      and value are stored in `keys` and `values`; otherwise the error(s) is\n//      stored in `errors`.\n//\n//      If the first keys contains _two_ indices, the first must starts with\n//      `k` or `v`, while the `second` is arbitrary. `mapping` is indexed by\n//      `second`; the integer is retrieved. If none exists, new contexts are\n//      created an added to `{key,value}_contexts`, and their index is mapped\n//      to `second` in `mapping`. If the first index is `k`, the field,\n//      stripped of the first key, is pushed to the key's context; the same is\n//      done for the value's context is the first index is `v`.\n//\n//   3. **Finalization.** Every context is finalized; errors and `Ok` values\n//      are collected.\n\nmod field;\nmod options;\nmod from_form;\nmod from_form_field;\nmod form;\nmod context;\nmod strict;\nmod lenient;\nmod parser;\nmod buffer;\npub mod validate;\npub mod name;\npub mod error;\n\n#[cfg(test)]\nmod tests;\n\n/// Type alias for `Result` with an error type of [`Errors`].\npub type Result<'v, T> = std::result::Result<T, Errors<'v>>;\n\n#[doc(hidden)]\npub use rocket_codegen::{FromForm, FromFormField};\n\n#[doc(inline)]\npub use self::error::{Errors, Error};\n\n#[doc(hidden)]\npub use self::buffer::{SharedStack, Shareable};\n\npub use field::*;\npub use options::*;\npub use from_form_field::*;\npub use from_form::*;\npub use form::*;\npub use context::*;\npub use strict::*;\npub use lenient::*;\n\n#[doc(hidden)]\npub mod prelude {\n    pub use super::*;\n    pub use super::name::*;\n    pub use super::error::*;\n}\n"
  },
  {
    "path": "core/lib/src/form/name/buf.rs",
    "content": "use std::borrow::Cow;\n\nuse crate::form::name::*;\n\n/// A potentially owned [`Name`].\n///\n/// Constructible from a [`NameView`], [`Name`], `&str`, or `String`, a\n/// `NameBuf` acts much like a [`Name`] but can be converted into an owned\n/// version via [`IntoOwned`](crate::http::ext::IntoOwned).\n///\n/// ```rust\n/// use rocket::form::name::NameBuf;\n/// use rocket::http::ext::IntoOwned;\n///\n/// let alloc = String::from(\"a.b.c\");\n/// let name = NameBuf::from(alloc.as_str());\n/// let owned: NameBuf<'static> = name.into_owned();\n/// ```\n#[derive(Clone)]\npub struct NameBuf<'v> {\n    left: &'v Name,\n    right: Cow<'v, str>,\n}\n\nimpl<'v> NameBuf<'v> {\n    #[inline]\n    fn split(&self) -> (&Name, &Name) {\n        (self.left, Name::new(&self.right))\n    }\n\n    /// Returns an iterator over the keys of `self`, including empty keys.\n    ///\n    /// See [`Name`] for a description of \"keys\".\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameBuf;\n    ///\n    /// let name = NameBuf::from(\"apple.b[foo:bar]zoo.[barb].bat\");\n    /// let keys: Vec<_> = name.keys().map(|k| k.as_str()).collect();\n    /// assert_eq!(keys, &[\"apple\", \"b\", \"foo:bar\", \"zoo\", \"\", \"barb\", \"bat\"]);\n    /// ```\n    #[inline]\n    pub fn keys(&self) -> impl Iterator<Item = &Key> {\n        let (left, right) = self.split();\n        left.keys().chain(right.keys())\n    }\n\n    /// Returns `true` if `self` is empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameBuf;\n    ///\n    /// let name = NameBuf::from(\"apple.b[foo:bar]zoo.[barb].bat\");\n    /// assert!(!name.is_empty());\n    ///\n    /// let name = NameBuf::from(\"\");\n    /// assert!(name.is_empty());\n    /// ```\n    #[inline]\n    pub fn is_empty(&self) -> bool {\n        let (left, right) = self.split();\n        left.is_empty() && right.is_empty()\n    }\n}\n\nimpl crate::http::ext::IntoOwned for NameBuf<'_> {\n    type Owned = NameBuf<'static>;\n\n    fn into_owned(self) -> Self::Owned {\n        let right = match (self.left, self.right) {\n            (l, Cow::Owned(r)) if l.is_empty() => Cow::Owned(r),\n            (l, r) if l.is_empty() => r.to_string().into(),\n            (l, r) if r.is_empty() => l.to_string().into(),\n            (l, r) => format!(\"{}.{}\", l, r).into(),\n        };\n\n        NameBuf { left: \"\".into(), right }\n    }\n}\n\nimpl serde::Serialize for NameBuf<'_> {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n        where S: serde::Serializer\n    {\n        serializer.serialize_str(&self.to_string())\n    }\n}\n\nimpl<'v> From<NameView<'v>> for NameBuf<'v> {\n    fn from(nv: NameView<'v>) -> Self {\n        NameBuf { left: nv.as_name(), right: Cow::Borrowed(\"\") }\n    }\n}\n\nimpl<'v> From<&'v Name> for NameBuf<'v> {\n    fn from(name: &'v Name) -> Self {\n        NameBuf { left: name, right: Cow::Borrowed(\"\") }\n    }\n}\n\nimpl<'v> From<&'v str> for NameBuf<'v> {\n    fn from(name: &'v str) -> Self {\n        NameBuf::from((None, Cow::Borrowed(name)))\n    }\n}\n\nimpl<'v> From<String> for NameBuf<'v> {\n    fn from(name: String) -> Self {\n        NameBuf::from((None, Cow::Owned(name)))\n    }\n}\n\n#[doc(hidden)]\nimpl<'v> From<(Option<&'v Name>, Cow<'v, str>)> for NameBuf<'v> {\n    fn from((prefix, right): (Option<&'v Name>, Cow<'v, str>)) -> Self {\n        match prefix {\n            Some(left) => NameBuf { left, right },\n            None => NameBuf { left: \"\".into(), right }\n        }\n    }\n}\n\n#[doc(hidden)]\nimpl<'v> From<(Option<&'v Name>, String)> for NameBuf<'v> {\n    fn from((prefix, right): (Option<&'v Name>, String)) -> Self {\n        match prefix {\n            Some(left) => NameBuf { left, right: right.into() },\n            None => NameBuf { left: \"\".into(), right: right.into() }\n        }\n    }\n}\n\n#[doc(hidden)]\nimpl<'v> From<(Option<&'v Name>, &'v str)> for NameBuf<'v> {\n    fn from((prefix, suffix): (Option<&'v Name>, &'v str)) -> Self {\n        NameBuf::from((prefix, Cow::Borrowed(suffix)))\n    }\n}\n\n#[doc(hidden)]\nimpl<'v> From<(&'v Name, &'v str)> for NameBuf<'v> {\n    fn from((prefix, suffix): (&'v Name, &'v str)) -> Self {\n        NameBuf::from((Some(prefix), Cow::Borrowed(suffix)))\n    }\n}\n\nimpl std::fmt::Debug for NameBuf<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"\\\"\")?;\n\n        let (left, right) = self.split();\n        if !left.is_empty() { write!(f, \"{}\", left.escape_debug())? }\n        if !right.is_empty() {\n            if !left.is_empty() { f.write_str(\".\")?; }\n            write!(f, \"{}\", right.escape_debug())?;\n        }\n\n        write!(f, \"\\\"\")\n    }\n}\n\nimpl std::fmt::Display for NameBuf<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let (left, right) = self.split();\n        if !left.is_empty() { left.fmt(f)?; }\n        if !right.is_empty() {\n            if !left.is_empty() { f.write_str(\".\")?; }\n            right.fmt(f)?;\n        }\n\n        Ok(())\n    }\n}\n\nimpl PartialEq for NameBuf<'_> {\n    fn eq(&self, other: &Self) -> bool {\n        self.keys().eq(other.keys())\n    }\n}\n\nimpl<N: AsRef<Name> + ?Sized> PartialEq<N> for NameBuf<'_> {\n    fn eq(&self, other: &N) -> bool {\n        self.keys().eq(other.as_ref().keys())\n    }\n}\n\nimpl PartialEq<NameBuf<'_>> for Name {\n    fn eq(&self, other: &NameBuf<'_>) -> bool {\n        self.keys().eq(other.keys())\n    }\n}\n\nimpl PartialEq<NameBuf<'_>> for str {\n    fn eq(&self, other: &NameBuf<'_>) -> bool {\n        Name::new(self) == other\n    }\n}\n\nimpl PartialEq<NameBuf<'_>> for &str {\n    fn eq(&self, other: &NameBuf<'_>) -> bool {\n        Name::new(self) == other\n    }\n}\n\nimpl Eq for NameBuf<'_> { }\n\nimpl std::hash::Hash for NameBuf<'_> {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.keys().for_each(|k| k.hash(state))\n    }\n}\n\nimpl indexmap::Equivalent<Name> for NameBuf<'_> {\n    fn equivalent(&self, key: &Name) -> bool {\n        self.keys().eq(key.keys())\n    }\n}\n\nimpl indexmap::Equivalent<NameBuf<'_>> for Name {\n    fn equivalent(&self, key: &NameBuf<'_>) -> bool {\n        self.keys().eq(key.keys())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/name/key.rs",
    "content": "use std::ops::Deref;\n\nuse ref_cast::RefCast;\n\nuse crate::http::RawStr;\n\n/// A field name key composed of indices.\n///\n/// A form field name key is composed of _indices_, delimited by `:`. The\n/// graphic below illustrates this composition for a single field in\n/// `$name=$value` format:\n///\n/// ```text\n///       food.bart[bar:foo:baz]=some-value\n/// name  |--------------------|\n/// key   |--| |--| |---------|\n/// index |--| |--| |-| |-| |-|\n/// ```\n///\n/// A `Key` is a wrapper around a given key string with methods to easily access\n/// its indices.\n///\n/// # Serialization\n///\n/// A value of this type is serialized exactly as an `&str` consisting of the\n/// entire key.\n#[repr(transparent)]\n#[derive(RefCast, Debug, PartialEq, Eq, Hash)]\npub struct Key(str);\n\nimpl Key {\n    /// Wraps a string as a `Key`. This is cost-free.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::Key;\n    ///\n    /// let key = Key::new(\"a:b:c\");\n    /// assert_eq!(key.as_str(), \"a:b:c\");\n    /// ```\n    pub fn new<S: AsRef<str> + ?Sized>(string: &S) -> &Key {\n        Key::ref_cast(string.as_ref())\n    }\n\n    /// Returns an iterator over the indices of `self`, including empty indices.\n    ///\n    /// See the [top-level docs](Self) for a description of \"indices\".\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::Key;\n    ///\n    /// let key = Key::new(\"foo:bar::baz:a.b.c\");\n    /// let indices: Vec<_> = key.indices().collect();\n    /// assert_eq!(indices, &[\"foo\", \"bar\", \"\", \"baz\", \"a.b.c\"]);\n    /// ```\n    pub fn indices(&self) -> impl Iterator<Item = &str> {\n        self.split(':')\n    }\n\n    /// Borrows the underlying string.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::Key;\n    ///\n    /// let key = Key::new(\"a:b:c\");\n    /// assert_eq!(key.as_str(), \"a:b:c\");\n    /// ```\n    pub fn as_str(&self) -> &str {\n        self\n    }\n}\n\nimpl Deref for Key {\n    type Target = str;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl serde::Serialize for Key {\n    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>\n        where S: serde::Serializer\n    {\n        self.0.serialize(ser)\n    }\n}\n\nimpl<'de: 'a, 'a> serde::Deserialize<'de> for &'a Key {\n    fn deserialize<D>(de: D) -> Result<Self, D::Error>\n        where D: serde::Deserializer<'de>\n    {\n        <&'a str as serde::Deserialize<'de>>::deserialize(de).map(Key::new)\n    }\n}\n\nimpl<I: core::slice::SliceIndex<str, Output=str>> core::ops::Index<I> for Key {\n    type Output = Key;\n\n    #[inline]\n    fn index(&self, index: I) -> &Self::Output {\n        self.0[index].into()\n    }\n}\n\nimpl PartialEq<str> for Key {\n    fn eq(&self, other: &str) -> bool {\n        self == Key::new(other)\n    }\n}\n\nimpl PartialEq<Key> for str {\n    fn eq(&self, other: &Key) -> bool {\n        Key::new(self) == other\n    }\n}\n\nimpl<'a, S: AsRef<str> + ?Sized> From<&'a S> for &'a Key {\n    #[inline]\n    fn from(string: &'a S) -> Self {\n        Key::new(string)\n    }\n}\n\nimpl AsRef<Key> for str {\n    fn as_ref(&self) -> &Key {\n        Key::new(self)\n    }\n}\n\nimpl AsRef<Key> for RawStr {\n    fn as_ref(&self) -> &Key {\n        Key::new(self)\n    }\n}\n\nimpl std::fmt::Display for Key {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.0.fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/name/mod.rs",
    "content": "//! Types for field names, name keys, and key indices.\n\nmod name;\nmod view;\nmod key;\nmod buf;\n\npub use name::Name;\npub use view::NameView;\npub use key::Key;\npub use buf::NameBuf;\n"
  },
  {
    "path": "core/lib/src/form/name/name.rs",
    "content": "use std::ops::Deref;\n\nuse ref_cast::RefCast;\n\nuse crate::http::RawStr;\nuse crate::form::name::*;\n\n/// A field name composed of keys.\n///\n/// A form field name is composed of _keys_, delimited by `.` or `[]`. Keys, in\n/// turn, are composed of _indices_, delimited by `:`. The graphic below\n/// illustrates this composition for a single field in `$name=$value` format:\n///\n/// ```text\n///       food.bart[bar:foo].blam[0_0][1000]=some-value\n/// name  |--------------------------------|\n/// key   |--| |--| |-----|  |--| |-|  |--|\n/// index |--| |--| |-| |-|  |--| |-|  |--|\n/// ```\n///\n/// A `Name` is a wrapper around the field name string with methods to easily\n/// access its sub-components.\n///\n/// # Serialization\n///\n/// A value of this type is serialized exactly as an `&str` consisting of the\n/// entire field name.\n#[repr(transparent)]\n#[derive(RefCast)]\npub struct Name(str);\n\nimpl Name {\n    /// Wraps a string as a `Name`. This is cost-free.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::Name;\n    ///\n    /// let name = Name::new(\"a.b.c\");\n    /// assert_eq!(name.as_str(), \"a.b.c\");\n    /// ```\n    pub fn new<S: AsRef<str> + ?Sized>(string: &S) -> &Name {\n        Name::ref_cast(string.as_ref())\n    }\n\n    /// Returns an iterator over the keys of `self`, including empty keys.\n    ///\n    /// See the [top-level docs](Self) for a description of \"keys\".\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::Name;\n    ///\n    /// let name = Name::new(\"apple.b[foo:bar]zoo.[barb].bat\");\n    /// let keys: Vec<_> = name.keys().map(|k| k.as_str()).collect();\n    /// assert_eq!(keys, &[\"apple\", \"b\", \"foo:bar\", \"zoo\", \"\", \"barb\", \"bat\"]);\n    /// ```\n    pub fn keys(&self) -> impl Iterator<Item = &Key> {\n        struct Keys<'v>(NameView<'v>);\n\n        impl<'v> Iterator for Keys<'v> {\n            type Item = &'v Key;\n\n            fn next(&mut self) -> Option<Self::Item> {\n                if self.0.exhausted() {\n                    return None;\n                }\n\n                let key = self.0.key_lossy();\n                self.0.shift();\n                Some(key)\n            }\n        }\n\n        Keys(NameView::new(self))\n    }\n\n    /// Returns an iterator over overlapping name prefixes of `self`, each\n    /// succeeding prefix containing one more key than the previous.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::Name;\n    ///\n    /// let name = Name::new(\"apple.b[foo:bar]\");\n    /// let prefixes: Vec<_> = name.prefixes().map(|p| p.as_str()).collect();\n    /// assert_eq!(prefixes, &[\"apple\", \"apple.b\", \"apple.b[foo:bar]\"]);\n    ///\n    /// let name = Name::new(\"a.b.[foo]\");\n    /// let prefixes: Vec<_> = name.prefixes().map(|p| p.as_str()).collect();\n    /// assert_eq!(prefixes, &[\"a\", \"a.b\", \"a.b.\", \"a.b.[foo]\"]);\n    /// ```\n    pub fn prefixes(&self) -> impl Iterator<Item = &Name> {\n        struct Prefixes<'v>(NameView<'v>);\n\n        impl<'v> Iterator for Prefixes<'v> {\n            type Item = &'v Name;\n\n            fn next(&mut self) -> Option<Self::Item> {\n                if self.0.exhausted() {\n                    return None;\n                }\n\n                let name = self.0.as_name();\n                self.0.shift();\n                Some(name)\n            }\n        }\n\n        Prefixes(NameView::new(self))\n    }\n\n    /// Borrows the underlying string.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::Name;\n    ///\n    /// let name = Name::new(\"a.b.c\");\n    /// assert_eq!(name.as_str(), \"a.b.c\");\n    /// ```\n    pub fn as_str(&self) -> &str {\n        &self.0\n    }\n}\n\nimpl serde::Serialize for Name {\n    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>\n        where S: serde::Serializer\n    {\n        self.0.serialize(ser)\n    }\n}\n\nimpl<'de: 'a, 'a> serde::Deserialize<'de> for &'a Name {\n    fn deserialize<D>(de: D) -> Result<Self, D::Error>\n        where D: serde::Deserializer<'de>\n    {\n        <&'a str as serde::Deserialize<'de>>::deserialize(de).map(Name::new)\n    }\n}\n\nimpl<'a, S: AsRef<str> + ?Sized> From<&'a S> for &'a Name {\n    #[inline]\n    fn from(string: &'a S) -> Self {\n        Name::new(string)\n    }\n}\n\nimpl Deref for Name {\n    type Target = str;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<I: core::slice::SliceIndex<str, Output=str>> core::ops::Index<I> for Name {\n    type Output = Name;\n\n    #[inline]\n    fn index(&self, index: I) -> &Self::Output {\n        self.0[index].into()\n    }\n}\n\nimpl PartialEq for Name {\n    fn eq(&self, other: &Self) -> bool {\n        self.keys().eq(other.keys())\n    }\n}\n\nimpl PartialEq<str> for Name {\n    fn eq(&self, other: &str) -> bool {\n        self == Name::new(other)\n    }\n}\n\nimpl PartialEq<Name> for str {\n    fn eq(&self, other: &Name) -> bool {\n        Name::new(self) == other\n    }\n}\n\nimpl PartialEq<&str> for Name {\n    fn eq(&self, other: &&str) -> bool {\n        self == Name::new(other)\n    }\n}\n\nimpl PartialEq<Name> for &str {\n    fn eq(&self, other: &Name) -> bool {\n        Name::new(self) == other\n    }\n}\n\nimpl AsRef<Name> for str {\n    fn as_ref(&self) -> &Name {\n        Name::new(self)\n    }\n}\n\nimpl AsRef<Name> for RawStr {\n    fn as_ref(&self) -> &Name {\n        Name::new(self)\n    }\n}\n\nimpl AsRef<Name> for Name {\n    fn as_ref(&self) -> &Name {\n        self\n    }\n}\n\nimpl Eq for Name { }\n\nimpl std::hash::Hash for Name {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.keys().for_each(|k| k.hash(state))\n    }\n}\n\nimpl std::fmt::Display for Name {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl std::fmt::Debug for Name {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.0.fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/name/view.rs",
    "content": "use crate::form::name::*;\n\n/// A sliding-prefix view into a [`Name`].\n///\n/// A [`NameView`] maintains a sliding key view into a [`Name`]. The current key\n/// ([`key()`]) can be [`shift()`ed](NameView::shift()) one key to the right.\n/// The `Name` prefix including the current key can be extracted via\n/// [`as_name()`] and the prefix _not_ including the current key via\n/// [`parent()`].\n///\n/// [`key()`]: NameView::key()\n/// [`as_name()`]: NameView::as_name()\n/// [`parent()`]: NameView::parent()\n///\n/// This is best illustrated via an example:\n///\n/// ```rust\n/// use rocket::form::name::NameView;\n///\n/// // The view begins at the first key. Illustrated: `(a).b[c:d]` where\n/// // parenthesis enclose the current key.\n/// let mut view = NameView::new(\"a.b[c:d]\");\n/// assert_eq!(view.key().unwrap(), \"a\");\n/// assert_eq!(view.as_name(), \"a\");\n/// assert_eq!(view.parent(), None);\n///\n/// // Shifted once to the right views the second key: `a.(b)[c:d]`.\n/// view.shift();\n/// assert_eq!(view.key().unwrap(), \"b\");\n/// assert_eq!(view.as_name(), \"a.b\");\n/// assert_eq!(view.parent().unwrap(), \"a\");\n///\n/// // Shifting again now has predictable results: `a.b[(c:d)]`.\n/// view.shift();\n/// assert_eq!(view.key().unwrap(), \"c:d\");\n/// assert_eq!(view.as_name(), \"a.b[c:d]\");\n/// assert_eq!(view.parent().unwrap(), \"a.b\");\n///\n/// // Shifting past the end means we have no further keys.\n/// view.shift();\n/// assert_eq!(view.key(), None);\n/// assert_eq!(view.key_lossy(), \"\");\n/// assert_eq!(view.as_name(), \"a.b[c:d]\");\n/// assert_eq!(view.parent().unwrap(), \"a.b[c:d]\");\n///\n/// view.shift();\n/// assert_eq!(view.key(), None);\n/// assert_eq!(view.as_name(), \"a.b[c:d]\");\n/// assert_eq!(view.parent().unwrap(), \"a.b[c:d]\");\n/// ```\n///\n/// # Equality\n///\n/// `PartialEq`, `Eq`, and `Hash` all operate on the name prefix including the\n/// current key. Only key values are compared; delimiters are insignificant.\n/// Again, illustrated via examples:\n///\n/// ```rust\n/// use rocket::form::name::NameView;\n///\n/// let mut view = NameView::new(\"a.b[c:d]\");\n/// assert_eq!(view, \"a\");\n///\n/// // Shifted once to the right views the second key: `a.(b)[c:d]`.\n/// view.shift();\n/// assert_eq!(view.key().unwrap(), \"b\");\n/// assert_eq!(view.as_name(), \"a.b\");\n/// assert_eq!(view, \"a.b\");\n/// assert_eq!(view, \"a[b]\");\n///\n/// // Shifting again now has predictable results: `a.b[(c:d)]`.\n/// view.shift();\n/// assert_eq!(view, \"a.b[c:d]\");\n/// assert_eq!(view, \"a.b.c:d\");\n/// assert_eq!(view, \"a[b].c:d\");\n/// assert_eq!(view, \"a[b]c:d\");\n/// ```\n#[derive(Copy, Clone)]\npub struct NameView<'v> {\n    name: &'v Name,\n    start: usize,\n    end: usize,\n}\n\nimpl<'v> NameView<'v> {\n    /// Initializes a new `NameView` at the first key of `name`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a.b[c:d]\");\n    /// assert_eq!(view.key().unwrap(), \"a\");\n    /// assert_eq!(view.as_name(), \"a\");\n    /// assert_eq!(view.parent(), None);\n    /// ```\n    pub fn new<N: Into<&'v Name>>(name: N) -> Self {\n        let mut view = NameView { name: name.into(), start: 0, end: 0 };\n        view.shift();\n        view\n    }\n\n    /// Shifts the current key once to the right.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a.b[c:d][d.e]\");\n    /// assert_eq!(view.key().unwrap(), \"a\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key().unwrap(), \"b\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key().unwrap(), \"c:d\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key().unwrap(), \"d.e\");\n    /// ```\n    ///\n    /// Malformed strings can have interesting results:\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a[c.d\");\n    /// assert_eq!(view.key_lossy(), \"a\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key_lossy(), \"c.d\");\n    ///\n    /// let mut view = NameView::new(\"a[c[.d]\");\n    /// assert_eq!(view.key_lossy(), \"a\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key_lossy(), \"c[.d\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key(), None);\n    ///\n    /// let mut view = NameView::new(\"foo[c[.d]]\");\n    /// assert_eq!(view.key_lossy(), \"foo\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key_lossy(), \"c[.d\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key_lossy(), \"]\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key(), None);\n    /// ```\n    pub fn shift(&mut self) {\n        const START_DELIMS: &[char] = &['.', '['];\n\n        let string = &self.name[self.end..];\n        let bytes = string.as_bytes();\n        let shift = match bytes.first() {\n            None | Some(b'=') => 0,\n            Some(b'[') => match memchr::memchr(b']', bytes) {\n                Some(j) => j + 1,\n                None => bytes.len(),\n            },\n            Some(b'.') => match string[1..].find(START_DELIMS) {\n                Some(j) => j + 1,\n                None => bytes.len(),\n            },\n            _ => match string.find(START_DELIMS) {\n                Some(j) => j,\n                None => bytes.len()\n            }\n        };\n\n        debug_assert!(self.end + shift <= self.name.len());\n        *self = NameView {\n            name: self.name,\n            start: self.end,\n            end: self.end + shift,\n        };\n    }\n\n    /// Returns the key currently viewed by `self` if it is non-empty.\n    ///\n    /// ```text\n    ///                 food.bart[bar:foo].blam[0_0][][1000]=some-value\n    /// name            |----------------------------------|\n    /// non-empty key   |--| |--| |-----|  |--| |-|     |--|\n    /// empty key                                  |-|\n    /// ```\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a[b]\");\n    /// assert_eq!(view.key().unwrap(), \"a\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key().unwrap(), \"b\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key(), None);\n    /// # view.shift(); assert_eq!(view.key(), None);\n    /// # view.shift(); assert_eq!(view.key(), None);\n    /// ```\n    pub fn key(&self) -> Option<&'v Key> {\n        let lossy_key = self.key_lossy();\n        if lossy_key.is_empty() {\n            return None;\n        }\n\n        Some(lossy_key)\n    }\n\n    /// Returns the key currently viewed by `self`, even if it is non-empty.\n    ///\n    /// ```text\n    ///                 food.bart[bar:foo].blam[0_0][][1000]=some-value\n    /// name            |----------------------------------|\n    /// non-empty key   |--| |--| |-----|  |--| |-|     |--|\n    /// empty key                                  |-|\n    /// ```\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a[b]\");\n    /// assert_eq!(view.key_lossy(), \"a\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key_lossy(), \"b\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.key_lossy(), \"\");\n    /// # view.shift(); assert_eq!(view.key_lossy(), \"\");\n    /// # view.shift(); assert_eq!(view.key_lossy(), \"\");\n    /// ```\n    pub fn key_lossy(&self) -> &'v Key {\n        let view = &self.name[self.start..self.end];\n        let key = match view.as_bytes().first() {\n            Some(b'.') => &view[1..],\n            Some(b'[') if view.ends_with(']') => &view[1..view.len() - 1],\n            Some(b'[') if self.is_at_last() => &view[1..],\n            _ => view\n        };\n\n        key.as_str().into()\n    }\n\n    /// Returns the `Name` _up to and including_ the current key.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a[b]\");\n    /// assert_eq!(view.as_name(), \"a\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.as_name(), \"a[b]\");\n    /// # view.shift(); assert_eq!(view.as_name(), \"a[b]\");\n    /// # view.shift(); assert_eq!(view.as_name(), \"a[b]\");\n    /// ```\n    pub fn as_name(&self) -> &'v Name {\n        &self.name[..self.end]\n    }\n\n    /// Returns the `Name` _prior to_ the current key.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a[b]\");\n    /// assert_eq!(view.parent(), None);\n    ///\n    /// view.shift();\n    /// assert_eq!(view.parent().unwrap(), \"a\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.parent().unwrap(), \"a[b]\");\n    /// # view.shift(); assert_eq!(view.parent().unwrap(), \"a[b]\");\n    /// # view.shift(); assert_eq!(view.parent().unwrap(), \"a[b]\");\n    /// ```\n    pub fn parent(&self) -> Option<&'v Name> {\n        if self.start > 0 {\n            Some(&self.name[..self.start])\n        } else {\n            None\n        }\n    }\n\n    /// Returns the underlying `Name`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::name::NameView;\n    ///\n    /// let mut view = NameView::new(\"a[b]\");\n    /// assert_eq!(view.source(), \"a[b]\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.source(), \"a[b]\");\n    ///\n    /// view.shift();\n    /// assert_eq!(view.source(), \"a[b]\");\n    ///\n    /// # view.shift(); assert_eq!(view.source(), \"a[b]\");\n    /// # view.shift(); assert_eq!(view.source(), \"a[b]\");\n    /// ```\n    pub fn source(&self) -> &'v Name {\n        self.name\n    }\n\n    // This is the last key. The next `shift()` will exhaust `self`.\n    fn is_at_last(&self) -> bool {\n        self.end == self.name.len()\n    }\n\n    // There are no more keys. A `shift` will do nothing.\n    pub(crate) fn exhausted(&self) -> bool {\n        self.start == self.name.len()\n    }\n}\n\nimpl std::fmt::Debug for NameView<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.as_name().fmt(f)\n    }\n}\n\nimpl std::fmt::Display for NameView<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.as_name().fmt(f)\n    }\n}\n\nimpl<'a, 'b> PartialEq<NameView<'b>> for NameView<'a> {\n    fn eq(&self, other: &NameView<'b>) -> bool {\n        self.as_name() == other.as_name()\n    }\n}\n\nimpl<B: PartialEq<Name>> PartialEq<B> for NameView<'_> {\n    fn eq(&self, other: &B) -> bool {\n        other == self.as_name()\n    }\n}\n\nimpl Eq for NameView<'_> {  }\n\nimpl std::hash::Hash for NameView<'_> {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.as_name().hash(state)\n    }\n}\n\nimpl std::borrow::Borrow<Name> for NameView<'_> {\n    fn borrow(&self) -> &Name {\n        self.as_name()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/options.rs",
    "content": "/// Form guard options.\n///\n/// See [`Form#leniency`](crate::form::Form#leniency) for details.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub struct Options {\n    /// Whether parsing should be strict (no extra parameters) or not.\n    pub strict: bool,\n}\n\n#[allow(non_upper_case_globals, dead_code)]\nimpl Options {\n    /// `Options` with `strict` set to `false`.\n    pub const Lenient: Self = Options { strict: false };\n\n    /// `Options` with `strict` set to `true`.\n    pub const Strict: Self = Options { strict: true };\n}\n"
  },
  {
    "path": "core/lib/src/form/parser.rs",
    "content": "use multer::Multipart;\nuse either::Either;\n\nuse crate::request::{Request, local_cache_once};\nuse crate::data::{Data, Limits, Outcome};\nuse crate::http::{RawStr, Status};\nuse crate::form::prelude::*;\n\ntype Result<'r, T> = std::result::Result<T, Error<'r>>;\n\ntype Field<'r, 'i> = Either<ValueField<'r>, DataField<'r, 'i>>;\n\npub struct MultipartParser<'r, 'i> {\n    request: &'r Request<'i>,\n    buffer: &'r SharedStack<String>,\n    source: Multipart<'r>,\n    done: bool,\n}\n\npub struct RawStrParser<'r> {\n    buffer: &'r SharedStack<String>,\n    source: &'r RawStr,\n}\n\npub enum Parser<'r, 'i> {\n    Multipart(MultipartParser<'r, 'i>),\n    RawStr(RawStrParser<'r>),\n}\n\nimpl<'r, 'i> Parser<'r, 'i> {\n    pub async fn new(\n        req: &'r Request<'i>,\n        data: Data<'r>\n    ) -> Outcome<'r, Parser<'r, 'i>, Errors<'r>> {\n        let parser = match req.content_type() {\n            Some(c) if c.is_form() => Self::from_form(req, data).await,\n            Some(c) if c.is_form_data() => Self::from_multipart(req, data).await,\n            _ => return Outcome::Forward((data, Status::UnsupportedMediaType)),\n        };\n\n        match parser {\n            Ok(storage) => Outcome::Success(storage),\n            Err(e) => Outcome::Error((e.status(), e.into()))\n        }\n    }\n\n    async fn from_form(req: &'r Request<'i>, data: Data<'r>) -> Result<'r, Parser<'r, 'i>> {\n        let limit = req.limits().get(\"form\").unwrap_or(Limits::FORM);\n        let string = data.open(limit).into_string().await?;\n        if !string.is_complete() {\n            Err((None, Some(limit.as_u64())))?;\n        }\n\n        Ok(Parser::RawStr(RawStrParser {\n            buffer: local_cache_once!(req, SharedStack::new()),\n            source: RawStr::new(local_cache_once!(req, string.into_inner())),\n        }))\n    }\n\n    async fn from_multipart(req: &'r Request<'i>, data: Data<'r>) -> Result<'r, Parser<'r, 'i>> {\n        let boundary = req.content_type()\n            .ok_or(multer::Error::NoMultipart)?\n            .param(\"boundary\")\n            .ok_or(multer::Error::NoBoundary)?;\n\n        let form_limit = req.limits()\n            .get(\"data-form\")\n            .unwrap_or(Limits::DATA_FORM);\n\n        // Increase internal limit by 1 so multer can limit to `form_limit`.\n        let stream = data.open(form_limit + 1);\n        let constraints = multer::Constraints::new()\n            .size_limit(multer::SizeLimit::new()\n                .whole_stream(form_limit.into())\n                .per_field(form_limit.into()));\n\n        Ok(Parser::Multipart(MultipartParser {\n            request: req,\n            buffer: local_cache_once!(req, SharedStack::new()),\n            source: Multipart::with_reader_with_constraints(stream, boundary, constraints),\n            done: false,\n        }))\n    }\n\n    pub async fn next(&mut self) -> Option<Result<'r, Field<'r, 'i>>> {\n        match self {\n            Parser::Multipart(ref mut p) => p.next().await,\n            Parser::RawStr(ref mut p) => p.next().map(|f| Ok(Either::Left(f)))\n        }\n    }\n}\n\nimpl<'r> RawStrParser<'r> {\n    pub fn new(buffer: &'r SharedStack<String>, source: &'r RawStr) -> Self {\n        RawStrParser { buffer, source }\n    }\n}\n\nimpl<'r> Iterator for RawStrParser<'r> {\n    type Item = ValueField<'r>;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        use std::borrow::Cow::*;\n\n        let (name, value) = loop {\n            if self.source.is_empty() {\n                return None;\n            }\n\n            let (field_str, rest) = self.source.split_at_byte(b'&');\n            self.source = rest;\n\n            if !field_str.is_empty() {\n                break field_str.split_at_byte(b'=');\n            }\n        };\n\n        trace!(%name, %value, \"url-encoded field\");\n        let name_val = match (name.url_decode_lossy(), value.url_decode_lossy()) {\n            (Borrowed(name), Borrowed(val)) => (name, val),\n            (Borrowed(name), Owned(v)) => (name, self.buffer.push(v)),\n            (Owned(name), Borrowed(val)) => (self.buffer.push(name), val),\n            (Owned(mut name), Owned(val)) => {\n                let len = name.len();\n                name.push_str(&val);\n                self.buffer.push_split(name, len)\n            }\n        };\n\n        Some(ValueField::from(name_val))\n    }\n}\n\n#[cfg(test)]\nmod raw_str_parse_tests {\n    use crate::form::ValueField as Field;\n\n    #[test]\n    fn test_skips_empty() {\n        let buffer = super::SharedStack::new();\n        let fields: Vec<_> = super::RawStrParser::new(&buffer, \"a&b=c&&&c\".into()).collect();\n        assert_eq!(fields, &[Field::parse(\"a\"), Field::parse(\"b=c\"), Field::parse(\"c\")]);\n    }\n\n    #[test]\n    fn test_decodes() {\n        let buffer = super::SharedStack::new();\n        let fields: Vec<_> = super::RawStrParser::new(&buffer, \"a+b=c%20d&%26\".into()).collect();\n        assert_eq!(fields, &[Field::parse(\"a b=c d\"), Field::parse(\"&\")]);\n    }\n}\n\nimpl<'r, 'i> MultipartParser<'r, 'i> {\n    /// Returns `None` when there are no further fields. Otherwise tries to\n    /// parse the next multipart form field and returns the result.\n    async fn next(&mut self) -> Option<Result<'r, Field<'r, 'i>>> {\n        if self.done {\n            return None;\n        }\n\n        let field = match self.source.next_field().await {\n            Ok(Some(field)) => field,\n            Ok(None) => return None,\n            Err(e) => {\n                self.done = true;\n                return Some(Err(e.into()));\n            }\n        };\n\n        // A field with a content-type is data; one without is \"value\".\n        trace!(?field, \"multipart field\");\n        let content_type = field.content_type().and_then(|m| m.as_ref().parse().ok());\n        let field = if let Some(content_type) = content_type {\n            let (name, file_name) = match (field.name(), field.file_name()) {\n                (None, None) => (\"\", None),\n                (None, Some(file_name)) => (\"\", Some(self.buffer.push(file_name))),\n                (Some(name), None) => (self.buffer.push(name), None),\n                (Some(a), Some(b)) => {\n                    let (field_name, file_name) = self.buffer.push_two(a, b);\n                    (field_name, Some(file_name))\n                }\n            };\n\n            Either::Right(DataField {\n                content_type,\n                request: self.request,\n                name: NameView::new(name),\n                file_name: file_name.map(crate::fs::FileName::new),\n                data: Data::from(field),\n            })\n        } else {\n            let (mut buf, len) = match field.name() {\n                Some(s) => (s.to_string(), s.len()),\n                None => (String::new(), 0)\n            };\n\n            match field.text().await {\n                Ok(text) => buf.push_str(&text),\n                Err(e) => return Some(Err(e.into())),\n            };\n\n            let name_val = self.buffer.push_split(buf, len);\n            Either::Left(ValueField::from(name_val))\n        };\n\n        Some(Ok(field))\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/strict.rs",
    "content": "use std::ops::{Deref, DerefMut};\n\nuse crate::form::prelude::*;\nuse crate::http::uri::fmt::{Query, FromUriParam};\n\n/// A form guard for parsing form types strictly.\n///\n/// This type implements the [`FromForm`] trait and thus can be used as a\n/// generic parameter to the [`Form`] data guard: `Form<Strict<T>>`, where `T`\n/// implements `FromForm`. Unlike using `Form` directly, this type uses a\n/// _strict_ parsing strategy: forms that contains a superset of the expected\n/// fields (i.e, extra fields) will fail to parse and defaults will not be use\n/// for missing fields.\n///\n/// # Strictness\n///\n/// A `Strict<T>` will parse successfully from an incoming form only if\n/// the form contains the exact set of fields in `T`. Said another way, a\n/// `Strict<T>` will error on missing and/or extra fields. For instance, if an\n/// incoming form contains the fields \"a\", \"b\", and \"c\" while `T` only contains\n/// \"a\" and \"c\", the form _will not_ parse as `Strict<T>`.\n///\n/// # Usage\n///\n/// `Strict<T>` implements [`FromForm`] as long as `T` implements `FromForm`. As\n/// such, `Form<Strict<T>>` is a data guard:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::form::{Form, Strict};\n///\n/// #[derive(FromForm)]\n/// struct UserInput {\n///     value: String\n/// }\n///\n/// #[post(\"/submit\", data = \"<user_input>\")]\n/// fn submit_task(user_input: Form<Strict<UserInput>>) -> String {\n///     format!(\"Your value: {}\", user_input.value)\n/// }\n/// ```\n///\n/// `Strict` can also be used to make individual fields strict while keeping the\n/// overall structure and remaining fields lenient:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::form::{Form, Strict};\n///\n/// #[derive(FromForm)]\n/// struct UserInput {\n///     required: Strict<bool>,\n///     uses_default: bool\n/// }\n/// ```\n#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]\npub struct Strict<T>(T);\n\nimpl<T> Strict<T> {\n    /// Consumes `self` and returns the inner value.\n    ///\n    /// Note that since `Strict` implements [`Deref`] and [`DerefMut`] with\n    /// target `T`, reading and writing an inner value can be accomplished\n    /// transparently.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::form::{Form, Strict};\n    ///\n    /// #[derive(FromForm)]\n    /// struct MyForm {\n    ///     field: String,\n    /// }\n    ///\n    /// #[post(\"/submit\", data = \"<form>\")]\n    /// fn submit(form: Form<Strict<MyForm>>) -> String {\n    ///     // We can read or mutate a value transparently:\n    ///     let field: &str = &form.field;\n    ///\n    ///     // To gain ownership, however, use `into_inner()`:\n    ///     form.into_inner().into_inner().field\n    /// }\n    /// ```\n    pub fn into_inner(self) -> T {\n        self.0\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: FromForm<'v>> FromForm<'v> for Strict<T> {\n    type Context = T::Context;\n\n    #[inline(always)]\n    fn init(_: Options) -> Self::Context {\n        T::init(Options { strict: true })\n    }\n\n    #[inline(always)]\n    fn push_value(ctxt: &mut Self::Context, field: ValueField<'v>) {\n        T::push_value(ctxt, field)\n    }\n\n    #[inline(always)]\n    async fn push_data(ctxt: &mut Self::Context, field: DataField<'v, '_>) {\n        T::push_data(ctxt, field).await\n    }\n\n    #[inline(always)]\n    fn finalize(this: Self::Context) -> Result<'v, Self> {\n        T::finalize(this).map(Self)\n    }\n}\n\nimpl<T> Deref for Strict<T> {\n    type Target = T;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<T> DerefMut for Strict<T> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n\nimpl<T> From<T> for Strict<T> {\n    #[inline]\n    fn from(val: T) -> Strict<T> {\n        Strict(val)\n    }\n}\n\nimpl<'f, A, T: FromUriParam<Query, A> + FromForm<'f>> FromUriParam<Query, A> for Strict<T> {\n    type Target = T::Target;\n\n    #[inline(always)]\n    fn from_uri_param(param: A) -> Self::Target {\n        T::from_uri_param(param)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/tests.rs",
    "content": "use std::collections::HashMap;\n\nuse crate::form::*;\n\nfn parse<'v, T: FromForm<'v>>(values: &[&'v str]) -> Result<'v, T> {\n    Form::parse_iter(values.iter().cloned().map(ValueField::parse))\n}\n\nmacro_rules! map {\n    ($($key:expr => $value:expr),* $(,)?) => ({\n        let mut map = std::collections::HashMap::new();\n        $(map.insert($key.into(), $value.into());)*\n        map\n    });\n}\n\nmacro_rules! vec {\n    ($($value:expr),* $(,)?) => ({\n        let mut vec = Vec::new();\n        $(vec.push($value.into());)*\n        vec\n    });\n}\n\nmacro_rules! assert_values_parse_eq {\n    ($($v:expr => $T:ty = $expected:expr),* $(,)?) => (\n        $(\n            assert_value_parse_eq!($v as &[&str] => $T = $expected);\n        )*\n    )\n}\n\nmacro_rules! assert_value_parse_eq {\n    ($v:expr => $T:ty = $expected:expr) => (\n        let expected: $T = $expected;\n        match parse::<$T>($v) {\n            Ok(actual) if actual == expected => { /* ok */ },\n            Ok(actual) => {\n                panic!(\"unexpected parse of {:?} ({:?} instead of {:?})\",\n                    $v, actual, expected)\n            }\n            Err(e) => panic!(\"parse `{:?} {}` failed: {:?}\", $v, stringify!(=> $T = $expected), e)\n        }\n    )\n}\n\nmacro_rules! assert_parses_fail {\n    ($($v:expr => $T:ty),* $(,)?) => (\n        $(\n            assert_parse_fails!($v as &[&str] => $T);\n        )*\n    )\n}\n\nmacro_rules! assert_parse_fails {\n    ($v:expr => $T:ty) => (\n        let diag = format!(\"{:?} {}\", $v, stringify!(=> $T));\n        match parse::<$T>($v) {\n            Ok(actual) => panic!(\"unexpectedly parsed {} as {:?}\", diag, actual),\n            Err(_) => { /* ok */ }\n        }\n    )\n}\n\n#[test]\nfn time() {\n    use time::{macros::{date, time}, Date, Time, PrimitiveDateTime as DateTime};\n\n    assert_values_parse_eq! {\n        &[\"=2010-10-20\"] => Date = date!(2010-10-20),\n        &[\"=2012-01-20\"] => Date = date!(2012-01-20),\n        &[\"=2020-01-20T02:30\"] => DateTime = DateTime::new(date!(2020-01-20), time!(2:30)),\n        &[\"=2020-01-01T02:30:12\"] => DateTime = DateTime::new(date!(2020-01-01), time!(2:30:12)),\n        &[\"=20:20:52\"] => Time = time!(20:20:52),\n        &[\"=06:08\"] => Time = time!(06:08),\n    }\n}\n\n#[test]\nfn bool() {\n    assert_values_parse_eq! {\n        &[\"=true\", \"=yes\", \"=on\", \"\"] => Vec<bool> = vec![true, true, true, true],\n        &[\"=false\", \"=no\", \"=off\"] => Vec<bool> = vec![false, false, false],\n        &[\"=tRuE\", \"=YES\", \"=On\"] => Vec<bool> = vec![true, true, true],\n        &[\"=fAlSE\", \"=NO\", \"=OFF\"] => Vec<bool> = vec![false, false, false],\n    }\n\n    assert_parses_fail! {\n        &[] => Strict<bool>,\n        &[\"=unknown\"] => bool,\n        &[\"=unknown\", \"=please\"] => Vec<bool>,\n    }\n}\n\n#[test]\nfn defaults() {\n    assert_values_parse_eq! {\n        &[] => bool = false,\n        &[] => Option<&str> = None,\n        &[] => Option<time::Date> = None,\n\n        &[] => Option<bool> = None,\n        &[] => Option<Strict<bool>> = None,\n\n        &[] => Result<'_, bool> = Ok(false),\n        &[] => Result<'_, Strict<bool>> = Err(error::ErrorKind::Missing.into()),\n\n        &[\"=unknown\"] => Option<bool> = None,\n        &[\"=unknown\"] => Option<Strict<bool>> = None,\n        &[\"=unknown\"] => Option<Lenient<bool>> = None,\n\n        &[] => Option<Lenient<bool>> = Some(false.into()),\n        &[\"=123\"] => Option<time::Date> = None,\n\n        &[\"=no\"] => Option<bool> = Some(false),\n        &[\"=yes\"] => Option<bool> = Some(true),\n        &[\"=yes\"] => Option<Lenient<bool>> = Some(true.into()),\n        &[\"=yes\"] => Option<Strict<bool>> = Some(true.into()),\n    }\n}\n\n#[test]\nfn potpourri() {\n    assert_values_parse_eq! {\n        &[\"a.b=10\"] => usize = 10,\n        &[\"a=10\"] => u8 = 10,\n        &[\"=10\"] => u8 = 10,\n        &[\"=5\", \"=3\", \"=4\"] => Vec<&str> = vec![\"5\", \"3\", \"4\"],\n        &[\"=5\", \"=3\", \"=4\"] => Vec<&str> = vec![\"5\", \"3\", \"4\"],\n        &[\"a=3\", \"b=4\", \"c=5\"] => Vec<u8> = vec![3, 4, 5],\n        &[\"=3\", \"=4\", \"=5\"] => Vec<u8> = vec![3, 4, 5],\n        &[\"=3\", \"=4\", \"=5\"] => Vec<Vec<u8>> = vec![vec![3], vec![4], vec![5]],\n        &[\"[]=3\", \"[]=4\", \"[]=5\"] => Vec<Vec<u8>> = vec![vec![3], vec![4], vec![5]],\n        &[\"[][]=3\", \"[][]=4\", \"[][]=5\"] => Vec<Vec<u8>> = vec![vec![3], vec![4], vec![5]],\n        &[\"[]=5\", \"[]=3\", \"[]=4\"] => Vec<&str> = vec![\"5\", \"3\", \"4\"],\n        &[\"[0]=5\", \"[0]=3\", \"=4\", \"=6\"] => Vec<Vec<u8>>\n            = vec![vec![5, 3], vec![4], vec![6]],\n        &[\".0=5\", \".1=3\"] => (u8, usize) = (5, 3),\n        &[\"0=5\", \"1=3\"] => (u8, usize) = (5, 3),\n        &[\"[bob]=Robert\", \".j=Jack\", \"s=Stan\", \"[s]=Steve\"] => HashMap<&str, &str>\n            = map![\"bob\" => \"Robert\", \"j\" => \"Jack\", \"s\" => \"Stan\"],\n        &[\"[bob]=Robert\", \".j=Jack\", \"s=Stan\", \"[s]=Steve\"]\n            => HashMap<&str, Vec<&str>>\n            = map![\n                \"bob\" => vec![\"Robert\"],\n                \"j\" => vec![\"Jack\"],\n                \"s\" => vec![\"Stan\", \"Steve\"]\n            ],\n        &[\"[k:0]=5\", \"[k:0]=3\", \"[v:0]=20\", \"[56]=2\"] => HashMap<Vec<&str>, usize>\n            = map![vec![\"5\", \"3\"] => 20u8, vec![\"56\"] => 2u8],\n        &[\"[k:0]=5\", \"[k:0]=3\", \"[0]=20\", \"[56]=2\"] => HashMap<Vec<&str>, usize>\n            = map![vec![\"5\", \"3\"] => 20u8, vec![\"56\"] => 2u8],\n        &[\n            \"[k:a]0=5\", \"[a]=hi\", \"[v:b][0]=10\", \"[k:b].0=1\",\n            \"[k:b].1=hi\", \"[a]=hey\", \"[k:a]1=3\"\n        ] => HashMap<(usize, &str), Vec<&str>>\n            = map![\n                (5, \"3\".into()) => vec![\"hi\", \"hey\"],\n                (1, \"hi\".into()) => vec![\"10\"]\n            ],\n        &[\n            \"[0][hi]=10\", \"[0][hey]=12\", \"[1][bob]=0\", \"[1].blam=58\", \"[].0=1\",\n            \"[].whoops=999\",\n        ] => Vec<HashMap<&str, usize>>\n            = vec![\n                map![\"hi\" => 10u8, \"hey\" => 12u8],\n                map![\"bob\" => 0u8, \"blam\" => 58u8],\n                map![\"0\" => 1u8],\n                map![\"whoops\" => 999usize]\n            ],\n    }\n}\n"
  },
  {
    "path": "core/lib/src/form/validate.rs",
    "content": "//! Form field validation routines.\n//!\n//! Each function in this module can be used as the target of the\n//! `field(validate)` field attribute of the `FromForm` derive.\n//!\n//! ```rust\n//! use rocket::form::FromForm;\n//!\n//! #[derive(FromForm)]\n//! struct MyForm<'r> {\n//!     #[field(validate = range(2..10))]\n//!     id: usize,\n//!     #[field(validate = omits(\"password\"))]\n//!     password: &'r str,\n//! }\n//! ```\n//!\n//! The `validate` parameter takes any expression that returns a\n//! [`form::Result<()>`](crate::form::Result). If the expression is a function\n//! call, a reference to the field is inserted as the first parameter. Thus,\n//! functions calls to `validate` must take a reference to _some_ type,\n//! typically a generic with some bounds, as their first argument.\n//!\n//! ## Custom Error Messages\n//!\n//! To set a custom error messages, it is useful to chain results:\n//!\n//! ```rust\n//! use rocket::form::{Errors, Error, FromForm};\n//!\n//! #[derive(FromForm)]\n//! struct MyForm<'r> {\n//!     // By defining another function...\n//!     #[field(validate = omits(\"password\").map_err(pass_help))]\n//!     password: &'r str,\n//!     // or inline using the `msg` helper. `or_else` inverts the validator\n//!     #[field(validate = omits(\"password\").or_else(msg!(\"please omit `password`\")))]\n//!     password2: &'r str,\n//!     // You can even refer to the field in the message...\n//!     #[field(validate = range(1..).or_else(msg!(\"`{}` < 1\", self.n)))]\n//!     n: isize,\n//!     // ..or other fields!\n//!     #[field(validate = range(..self.n).or_else(msg!(\"`{}` > `{}`\", self.z, self.n)))]\n//!     z: isize,\n//! }\n//!\n//! fn pass_help<'a>(errors: Errors<'_>) -> Errors<'a> {\n//!     Error::validation(\"passwords can't contain the text \\\"password\\\"\").into()\n//! }\n//! ```\n//!\n//! ## Custom Validation\n//!\n//! Custom validation routines can be defined as regular functions. Consider a\n//! routine that tries to validate a credit card number:\n//!\n//! ```rust\n//! extern crate time;\n//!\n//! use rocket::form::{self, FromForm, Error};\n//!\n//! #[derive(FromForm)]\n//! struct CreditCard {\n//!     #[field(validate = luhn(self.cvv, &self.expiration))]\n//!     number: u64,\n//!     cvv: u16,\n//!     expiration: time::Date,\n//! }\n//!\n//! // Implementation of Luhn validator.\n//! fn luhn<'v>(number: &u64, cvv: u16, exp: &time::Date) -> form::Result<'v, ()> {\n//!     # let valid = false;\n//!     if !valid {\n//!         Err(Error::validation(\"invalid credit card number\"))?;\n//!     }\n//!\n//!     Ok(())\n//! }\n//! ```\n\nuse std::borrow::Cow;\nuse std::ops::{RangeBounds, Bound};\nuse std::fmt::Debug;\n\nuse crate::data::{ByteUnit, Capped};\nuse rocket_http::ContentType;\n\nuse crate::{fs::TempFile, form::{Result, Error}};\n\ncrate::export! {\n    /// A helper macro for custom validation error messages.\n    ///\n    /// The macro works similar to [`std::format!`]. It generates a form\n    /// [`Validation`] error message. While useful in other contexts, it is\n    /// designed to be chained to validation results in derived `FromForm`\n    /// `#[field]` attributes via `.or_else()` and `.and_then()`.\n    ///\n    /// [`Validation`]: crate::form::error::ErrorKind::Validation\n    /// [`form::validate`]: crate::form::validate\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::FromForm;\n    ///\n    /// #[derive(FromForm)]\n    /// struct Person<'r> {\n    ///     #[field(validate = len(3..).or_else(msg!(\"that's a short name...\")))]\n    ///     name: &'r str,\n    ///     #[field(validate = contains('f').and_then(msg!(\"please, no `f`!\")))]\n    ///     non_f_name: &'r str,\n    /// }\n    /// ```\n    ///\n    /// _**Note:** this macro _never_ needs to be imported when used with a\n    /// `FromForm` derive; all items in [`form::validate`] are automatically in\n    /// scope in `FromForm` derive attributes._\n    ///\n    /// See the [top-level docs](crate::form::validate) for more examples.\n    ///\n    /// # Syntax\n    ///\n    /// The macro has the following \"signatures\":\n    ///\n    /// ## Variant 1\n    ///\n    /// ```rust\n    /// # use rocket::form;\n    /// # trait Expr {}\n    /// fn msg<'a, T, P, E: Expr>(expr: E) -> impl Fn(P) -> form::Result<'a, T>\n    /// # { |_| unimplemented!() }\n    /// ```\n    ///\n    /// Takes any expression and returns a function that takes any argument type\n    /// and evaluates to a [`form::Result`](crate::form::Result) with an `Ok` of\n    /// any type. The `Result` is guaranteed to be an `Err` of kind\n    /// [`Validation`] with `expr` as the message.\n    ///\n    /// ## Variant 2\n    ///\n    /// ```\n    /// # use rocket::form;\n    /// # trait Format {}\n    /// # trait Args {}\n    /// fn msg<'a, T, P, A: Args>(fmt: &str, args: A) -> impl Fn(P) -> form::Result<'a, T>\n    /// # { |_| unimplemented!() }\n    /// ```\n    ///\n    /// Invokes the first variant as `msg!(format!(fmt, args))`.\n    macro_rules! msg {\n        ($e:expr) => (|_| {\n            Err($crate::form::Errors::from(\n                    $crate::form::Error::validation($e)\n            )) as $crate::form::Result<()>\n        });\n        ($($arg:tt)*) => ($crate::form::validate::msg!(format!($($arg)*)));\n    }\n}\n\n/// Equality validator: succeeds exactly when `a` == `b`, using [`PartialEq`].\n///\n/// On error, returns a validation error with the following message:\n///\n/// ```text\n/// value does not match expected value\n/// ```\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(FromFormField, PartialEq)]\n/// enum Kind {\n///     Car,\n///     Truck\n/// }\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     #[field(validate = eq(\"Bob Marley\"))]\n///     name: &'r str,\n///     #[field(validate = eq(Kind::Car))]\n///     vehicle: Kind,\n///     #[field(validate = eq(&[5, 7, 8]))]\n///     numbers: Vec<usize>,\n/// }\n/// ```\npub fn eq<'v, A, B>(a: &A, b: B) -> Result<'v, ()>\n    where A: PartialEq<B>\n{\n    if a != &b {\n        Err(Error::validation(\"value does not match expected value\"))?\n    }\n\n    Ok(())\n}\n\n/// Debug equality validator: like [`eq()`] but mentions `b` in the error\n/// message.\n///\n/// The is identical to [`eq()`] except that `b` must be `Debug` and the error\n/// message is as follows, where `$b` is the [`Debug`] representation of `b`:\n///\n/// ```text\n/// value must be $b\n/// ```\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(PartialEq, Debug, Clone, Copy, FromFormField)]\n/// enum Pet { Cat, Dog }\n///\n/// #[derive(FromForm)]\n/// struct Foo {\n///     number: usize,\n///     #[field(validate = dbg_eq(self.number))]\n///     confirm_num: usize,\n///     #[field(validate = dbg_eq(Pet::Dog))]\n///     best_pet: Pet,\n/// }\n/// ```\npub fn dbg_eq<'v, A, B>(a: &A, b: B) -> Result<'v, ()>\n    where A: PartialEq<B>, B: Debug\n{\n    if a != &b {\n        Err(Error::validation(format!(\"value must be {:?}\", b)))?\n    }\n\n    Ok(())\n}\n\n/// Negative equality validator: succeeds exactly when `a` != `b`, using\n/// [`PartialEq`].\n///\n/// On error, returns a validation error with the following message:\n///\n/// ```text\n/// value is equal to an invalid value\n/// ```\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(FromFormField, PartialEq)]\n/// enum Kind {\n///     Car,\n///     Truck\n/// }\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     #[field(validate = neq(\"Bob Marley\"))]\n///     name: &'r str,\n///     #[field(validate = neq(Kind::Car))]\n///     vehicle: Kind,\n///     #[field(validate = neq(&[5, 7, 8]))]\n///     numbers: Vec<usize>,\n/// }\n/// ```\npub fn neq<'v, A, B>(a: &A, b: B) -> Result<'v, ()>\n    where A: PartialEq<B>\n{\n    if a == &b {\n        Err(Error::validation(\"value is equal to an invalid value\"))?\n    }\n\n    Ok(())\n}\n\n/// Types for values that have a length.\n///\n/// At present, these are:\n///\n/// | type                              | length description                   |\n/// |-----------------------------------|--------------------------------------|\n/// | `&str`, `String`                  | length in bytes                      |\n/// | `Vec<T>`                          | number of elements in the vector     |\n/// | `HashMap<K, V>`, `BTreeMap<K, V>` | number of key/value pairs in the map |\n/// | [`TempFile`]                      | length of the file in bytes          |\n/// | `Option<T>` where `T: Len`        | length of `T` or 0 if `None`         |\n/// | [`form::Result<'_, T>`]           | length of `T` or 0 if `Err`          |\n///\n/// [`form::Result<'_, T>`]: crate::form::Result\npub trait Len<L> {\n    /// The length of the value.\n    fn len(&self) -> L;\n\n    /// Convert `len` into `u64`.\n    fn len_into_u64(len: L) -> u64;\n\n    /// The zero value for `L`.\n    fn zero_len() -> L;\n}\n\nmacro_rules! impl_len {\n    (<$($gen:ident),*> $T:ty => $L:ty) => (\n        impl <$($gen),*> Len<$L> for $T {\n            fn len(&self) -> $L { self.len() }\n            fn len_into_u64(len: $L) -> u64 { len as u64 }\n            fn zero_len() -> $L { 0 }\n        }\n    )\n}\n\nimpl_len!(<> str => usize);\nimpl_len!(<> String => usize);\nimpl_len!(<T> Vec<T> => usize);\nimpl_len!(<> TempFile<'_> => u64);\nimpl_len!(<K, V> std::collections::HashMap<K, V> => usize);\nimpl_len!(<K, V> std::collections::BTreeMap<K, V> => usize);\n\nimpl Len<ByteUnit> for TempFile<'_> {\n    fn len(&self) -> ByteUnit { self.len().into() }\n    fn len_into_u64(len: ByteUnit) -> u64 { len.into() }\n    fn zero_len() -> ByteUnit { ByteUnit::from(0) }\n}\n\nimpl<L, T: Len<L> + ?Sized> Len<L> for &T {\n    fn len(&self) -> L { <T as Len<L>>::len(self) }\n    fn len_into_u64(len: L) -> u64 { T::len_into_u64(len) }\n    fn zero_len() -> L { T::zero_len() }\n}\n\nimpl<L, T: Len<L>> Len<L> for Option<T> {\n    fn len(&self) -> L { self.as_ref().map(|v| v.len()).unwrap_or_else(T::zero_len) }\n    fn len_into_u64(len: L) -> u64 { T::len_into_u64(len) }\n    fn zero_len() -> L { T::zero_len() }\n}\n\nimpl<L, T: Len<L>> Len<L> for Capped<T> {\n    fn len(&self) -> L { self.value.len() }\n    fn len_into_u64(len: L) -> u64 { T::len_into_u64(len) }\n    fn zero_len() -> L { T::zero_len() }\n}\n\nimpl<L, T: Len<L>> Len<L> for Result<'_, T> {\n    fn len(&self) -> L { self.as_ref().ok().len() }\n    fn len_into_u64(len: L) -> u64 { T::len_into_u64(len) }\n    fn zero_len() -> L { T::zero_len() }\n}\n\n#[cfg(feature = \"json\")]\nimpl<L, T: Len<L>> Len<L> for crate::serde::json::Json<T> {\n    fn len(&self) -> L { self.0.len() }\n    fn len_into_u64(len: L) -> u64 { T::len_into_u64(len) }\n    fn zero_len() -> L { T::zero_len() }\n}\n\n#[cfg(feature = \"msgpack\")]\nimpl<L, T: Len<L>> Len<L> for crate::serde::msgpack::MsgPack<T> {\n    fn len(&self) -> L { self.0.len() }\n    fn len_into_u64(len: L) -> u64 { T::len_into_u64(len) }\n    fn zero_len() -> L { T::zero_len() }\n}\n\n/// Length validator: succeeds when the length of a value is within a `range`.\n///\n/// The value must implement [`Len`]. On error, returns an [`InvalidLength`]\n/// error. See [`Len`] for supported types and how their length is computed.\n///\n/// [`InvalidLength`]: crate::form::error::ErrorKind::InvalidLength\n///\n/// # Data Limits\n///\n/// All form types are constrained by a data limit. As such, the `len()`\n/// validator should be used only when a data limit is insufficiently specific.\n/// For example, prefer to use data [`Limits`](crate::data::Limits) to validate\n/// the length of files as not doing so will result in writing more data to disk\n/// than necessary.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::http::ContentType;\n/// use rocket::form::{FromForm, FromFormField};\n/// use rocket::data::ToByteUnit;\n/// use rocket::fs::TempFile;\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     #[field(validate = len(5..20))]\n///     name: &'r str,\n///     #[field(validate = len(..=200))]\n///     maybe_name: Option<&'r str>,\n///     #[field(validate = len(..=2.mebibytes()))]\n///     #[field(validate = ext(ContentType::Plain))]\n///     file: TempFile<'r>,\n/// }\n/// ```\npub fn len<'v, V, L, R>(value: V, range: R) -> Result<'v, ()>\n    where V: Len<L>,\n          L: Copy + PartialOrd,\n          R: RangeBounds<L>\n{\n    if !range.contains(&value.len()) {\n        let start = match range.start_bound() {\n            Bound::Included(v) => Some(V::len_into_u64(*v)),\n            Bound::Excluded(v) => Some(V::len_into_u64(*v).saturating_add(1)),\n            Bound::Unbounded => None\n        };\n\n        let end = match range.end_bound() {\n            Bound::Included(v) => Some(V::len_into_u64(*v)),\n            Bound::Excluded(v) => Some(V::len_into_u64(*v).saturating_sub(1)),\n            Bound::Unbounded => None,\n        };\n\n        Err((start, end))?\n    }\n\n    Ok(())\n}\n\n/// Types for values that contain items.\n///\n/// At present, these are:\n///\n/// | type                    | contains                                           |\n/// |-------------------------|----------------------------------------------------|\n/// | `&str`, `String`        | `&str`, `char`, `&[char]` `F: FnMut(char) -> bool` |\n/// | `Vec<T>`                | `T`, `&T`                                          |\n/// | `Option<T>`             | `I` where `T: Contains<I>`                         |\n/// | [`form::Result<'_, T>`] | `I` where `T: Contains<I>`                         |\n///\n/// [`form::Result<'_, T>`]: crate::form::Result\npub trait Contains<I> {\n    /// Returns `true` if `self` contains `item`.\n    fn contains(&self, item: I) -> bool;\n}\n\nmacro_rules! impl_contains {\n    ([$($gen:tt)*] $T:ty [contains] $I:ty [via] $P:ty) => {\n        impl_contains!([$($gen)*] $T [contains] $I [via] $P [with] |v| v);\n    };\n\n    ([$($gen:tt)*] $T:ty [contains] $I:ty [via] $P:ty [with] $f:expr) => {\n        impl<$($gen)*> Contains<$I> for $T {\n            fn contains(&self, item: $I) -> bool {\n                <$P>::contains(self, $f(item))\n            }\n        }\n    };\n}\n\nfn coerce<T, const N: usize>(slice: &[T; N]) -> &[T] {\n    &slice[..]\n}\n\nimpl_contains!([] str [contains] &str [via] str);\nimpl_contains!([] str [contains] char [via] str);\nimpl_contains!([] str [contains] &[char] [via] str);\nimpl_contains!([const N: usize] str [contains] &[char; N] [via] str [with] coerce);\nimpl_contains!([] String [contains] &str [via] str);\nimpl_contains!([] String [contains] char [via] str);\nimpl_contains!([] String [contains] &[char] [via] str);\nimpl_contains!([const N: usize] String [contains] &[char; N] [via] str [with] coerce);\nimpl_contains!([T: PartialEq] Vec<T> [contains] &T [via] [T]);\n\nimpl<F: FnMut(char) -> bool> Contains<F> for str {\n    fn contains(&self, f: F) -> bool {\n        <str>::contains(self, f)\n    }\n}\n\nimpl<F: FnMut(char) -> bool> Contains<F> for String {\n    fn contains(&self, f: F) -> bool {\n        <str>::contains(self, f)\n    }\n}\n\nimpl<T: PartialEq> Contains<T> for Vec<T> {\n    fn contains(&self, item: T) -> bool {\n        <[T]>::contains(self, &item)\n    }\n}\n\nimpl<I, T: Contains<I>> Contains<I> for Option<T> {\n    fn contains(&self, item: I) -> bool {\n        self.as_ref().map(|v| v.contains(item)).unwrap_or(false)\n    }\n}\n\nimpl<I, T: Contains<I>> Contains<I> for Result<'_, T> {\n    fn contains(&self, item: I) -> bool {\n        self.as_ref().map(|v| v.contains(item)).unwrap_or(false)\n    }\n}\n\nimpl<I, T: Contains<I> + ?Sized> Contains<I> for &T {\n    fn contains(&self, item: I) -> bool {\n        <T as Contains<I>>::contains(self, item)\n    }\n}\n\n/// Contains validator: succeeds when a value contains `item`.\n///\n/// This is the dual of [`omits()`]. The value must implement\n/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See\n/// [`Contains`] for supported types and items.\n///\n/// On error, returns a validation error with the following message:\n///\n/// ```text\n/// value is equal to an invalid value\n/// ```\n///\n/// If the collection is empty, this validator fails.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(PartialEq, FromFormField)]\n/// enum Pet { Cat, Dog }\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     best_pet: Pet,\n///     #[field(validate = contains(Pet::Cat))]\n///     #[field(validate = contains(&self.best_pet))]\n///     pets: Vec<Pet>,\n///     #[field(validate = contains('/'))]\n///     #[field(validate = contains(&['/', ':']))]\n///     license: &'r str,\n///     #[field(validate = contains(\"@rust-lang.org\"))]\n///     #[field(validate = contains(|c: char| c.to_ascii_lowercase() == 's'))]\n///     rust_lang_email: &'r str,\n/// }\n/// ```\npub fn contains<'v, V, I>(value: V, item: I) -> Result<'v, ()>\n    where V: Contains<I>\n{\n    if !value.contains(item) {\n        Err(Error::validation(\"value does not contain expected item\"))?\n    }\n\n    Ok(())\n}\n\n/// Debug contains validator: like [`contains()`] but mentions `item` in the\n/// error message.\n///\n/// This is the dual of [`dbg_omits()`]. The is identical to [`contains()`]\n/// except that `item` must be `Debug + Copy` and the error message is as\n/// follows, where `$item` is the [`Debug`] representation of `item`:\n///\n/// ```text\n/// values must contains $item\n/// ```\n///\n/// If the collection is empty, this validator fails.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(PartialEq, Debug, Clone, Copy, FromFormField)]\n/// enum Pet { Cat, Dog }\n///\n/// #[derive(FromForm)]\n/// struct Foo {\n///     best_pet: Pet,\n///     #[field(validate = dbg_contains(Pet::Dog))]\n///     #[field(validate = dbg_contains(&self.best_pet))]\n///     pets: Vec<Pet>,\n/// }\n/// ```\npub fn dbg_contains<'v, V, I>(value: V, item: I) -> Result<'v, ()>\n    where V: Contains<I>, I: Debug + Copy\n{\n    if !value.contains(item) {\n        Err(Error::validation(format!(\"value must contain {:?}\", item)))?\n    }\n\n    Ok(())\n}\n\n/// Omits validator: succeeds when a value _does not_ contains `item`.\n/// error message.\n///\n/// This is the dual of [`contains()`]. The value must implement\n/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See\n/// [`Contains`] for supported types and items.\n///\n/// On error, returns a validation error with the following message:\n///\n/// ```text\n/// value contains a disallowed item\n/// ```\n///\n/// If the collection is empty, this validator succeeds.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(PartialEq, FromFormField)]\n/// enum Pet { Cat, Dog }\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     #[field(validate = omits(Pet::Cat))]\n///     pets: Vec<Pet>,\n///     #[field(validate = omits('@'))]\n///     not_email: &'r str,\n///     #[field(validate = omits(\"@gmail.com\"))]\n///     non_gmail_email: &'r str,\n/// }\n/// ```\npub fn omits<'v, V, I>(value: V, item: I) -> Result<'v, ()>\n    where V: Contains<I>\n{\n    if value.contains(item) {\n        Err(Error::validation(\"value contains a disallowed item\"))?\n    }\n\n    Ok(())\n}\n\n/// Debug omits validator: like [`omits()`] but mentions `item` in the error\n/// message.\n///\n/// This is the dual of [`dbg_contains()`]. The is identical to [`omits()`]\n/// except that `item` must be `Debug + Copy` and the error message is as\n/// follows, where `$item` is the [`Debug`] representation of `item`:\n///\n/// ```text\n/// value cannot contain $item\n/// ```\n///\n/// If the collection is empty, this validator succeeds.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(PartialEq, Debug, Clone, Copy, FromFormField)]\n/// enum Pet { Cat, Dog }\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     #[field(validate = dbg_omits(Pet::Cat))]\n///     pets: Vec<Pet>,\n///     #[field(validate = dbg_omits('@'))]\n///     not_email: &'r str,\n///     #[field(validate = dbg_omits(\"@gmail.com\"))]\n///     non_gmail_email: &'r str,\n/// }\n/// ```\npub fn dbg_omits<'v, V, I>(value: V, item: I) -> Result<'v, ()>\n    where V: Contains<I>, I: Copy + Debug\n{\n    if value.contains(item) {\n        Err(Error::validation(format!(\"value cannot contain {:?}\", item)))?\n    }\n\n    Ok(())\n}\n\n/// Integer range validator: succeeds when an integer value is within a range.\n///\n/// The value must be an integer type that implement `TryInto<isize> + Copy`. On\n/// error, returns an [`OutOfRange`] error.\n///\n/// [`OutOfRange`]: crate::form::error::ErrorKind::OutOfRange\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::FromForm;\n///\n/// #[derive(FromForm)]\n/// struct Foo {\n///     #[field(validate = range(0..))]\n///     non_negative: isize,\n///     #[field(validate = range(18..=130))]\n///     maybe_adult: u8,\n/// }\n/// ```\npub fn range<'v, V, R>(value: &V, range: R) -> Result<'v, ()>\n    where V: TryInto<isize> + Copy, R: RangeBounds<isize>\n{\n    if let Ok(v) = (*value).try_into() {\n        if range.contains(&v) {\n            return Ok(());\n        }\n    }\n\n    let start = match range.start_bound() {\n        Bound::Included(v) => Some(*v),\n        Bound::Excluded(v) => Some(v.saturating_add(1)),\n        Bound::Unbounded => None\n    };\n\n    let end = match range.end_bound() {\n        Bound::Included(v) => Some(*v),\n        Bound::Excluded(v) => Some(v.saturating_sub(1)),\n        Bound::Unbounded => None,\n    };\n\n\n    Err((start, end))?\n}\n\n/// Contains one of validator: succeeds when a value contains at least one item\n/// in an `items` iterator.\n///\n/// The value must implement [`Contains<I>`](Contains) where `I` is the type of\n/// the `item`. The iterator must be [`Clone`]. See [`Contains`] for supported\n/// types and items. The item must be [`Debug`].\n///\n/// On error, returns a [`InvalidChoice`] error with the debug representation\n/// of each item in `items`.\n///\n/// [`InvalidChoice`]: crate::form::error::ErrorKind::InvalidChoice\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::FromForm;\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     #[field(validate = one_of(&[3, 5, 7]))]\n///     single_digit_primes: Vec<u8>,\n///     #[field(validate = one_of(\" \\t\\n\".chars()))]\n///     has_space_char: &'r str,\n///     #[field(validate = one_of(\" \\t\\n\".chars()).and_then(msg!(\"no spaces\")))]\n///     no_space: &'r str,\n/// }\n/// ```\npub fn one_of<'v, V, I, R>(value: V, items: R) -> Result<'v, ()>\n    where V: Contains<I>,\n          I: Debug,\n          R: IntoIterator<Item = I>,\n          <R as IntoIterator>::IntoIter: Clone\n{\n    let items = items.into_iter();\n    for item in items.clone() {\n        if value.contains(item) {\n            return Ok(());\n        }\n    }\n\n    let choices: Vec<Cow<'_, str>> = items\n        .map(|item| format!(\"{:?}\", item).into())\n        .collect();\n\n    Err(choices)?\n}\n\n/// File type validator: succeeds when a [`TempFile`] has the Content-Type\n/// `content_type`.\n///\n/// On error, returns a validation error with one of the following messages:\n///\n/// ```text\n/// // the file has an incorrect extension\n/// file type was .$file_ext but must be $type\n///\n/// // the file does not have an extension\n/// file type must be $type\n/// ```\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::FromForm;\n/// use rocket::data::ToByteUnit;\n/// use rocket::http::ContentType;\n/// use rocket::fs::TempFile;\n///\n/// #[derive(FromForm)]\n/// struct Foo<'r> {\n///     #[field(validate = ext(ContentType::PDF))]\n///     #[field(validate = len(..1.mebibytes()))]\n///     document: TempFile<'r>,\n/// }\n/// ```\npub fn ext<'v>(file: &TempFile<'_>, r#type: ContentType) -> Result<'v, ()> {\n    if let Some(file_ct) = file.content_type() {\n        if file_ct == &r#type {\n            return Ok(());\n        }\n    }\n\n    let msg = match (file.content_type().and_then(|c| c.extension()), r#type.extension()) {\n        (Some(a), Some(b)) => format!(\"invalid file type: .{}, must be .{}\", a, b),\n        (Some(a), None) => format!(\"invalid file type: .{}, must be {}\", a, r#type),\n        (None, Some(b)) => format!(\"file type must be .{}\", b),\n        (None, None) => format!(\"file type must be {}\", r#type),\n    };\n\n    Err(Error::validation(msg))?\n}\n\n/// With validator: succeeds when an arbitrary function or closure does.\n///\n/// This is the most generic validator and, for readability, should only be used\n/// when a more case-specific option does not exist. It succeeds exactly when\n/// `f` returns `true` and fails otherwise.\n///\n/// On error, returns a validation error with the message `msg`.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::form::{FromForm, FromFormField};\n///\n/// #[derive(PartialEq, FromFormField)]\n/// enum Pet { Cat, Dog }\n///\n/// fn is_dog(p: &Pet) -> bool {\n///     matches!(p, Pet::Dog)\n/// }\n///\n/// #[derive(FromForm)]\n/// struct Foo {\n///     // These are equivalent. Prefer the former.\n///     #[field(validate = contains(Pet::Dog))]\n///     #[field(validate = with(|pets| pets.iter().any(|p| *p == Pet::Dog), \"missing dog\"))]\n///     pets: Vec<Pet>,\n///     // These are equivalent. Prefer the former.\n///     #[field(validate = eq(Pet::Dog))]\n///     #[field(validate = with(|p| matches!(p, Pet::Dog), \"expected a dog\"))]\n///     #[field(validate = with(|p| is_dog(p), \"expected a dog\"))]\n///   # #[field(validate = with(|p| is_dog(&self.dog), \"expected a dog\"))]\n///     #[field(validate = with(is_dog, \"expected a dog\"))]\n///     dog: Pet,\n///     // These are equivalent. Prefer the former.\n///     #[field(validate = contains(&self.dog))]\n///   # #[field(validate = with(|p| is_dog(&self.dog), \"expected a dog\"))]\n///     #[field(validate = with(|pets| pets.iter().any(|p| p == &self.dog), \"missing dog\"))]\n///     one_dog_please: Vec<Pet>,\n/// }\n/// ```\npub fn with<'v, V, F, M>(value: V, f: F, msg: M) -> Result<'v, ()>\n    where F: FnOnce(V) -> bool,\n          M: Into<Cow<'static, str>>\n{\n    if !f(value) {\n        Err(Error::validation(msg.into()))?\n    }\n\n    Ok(())\n}\n\n/// _Try_ With validator: succeeds when an arbitrary function or closure does.\n///\n/// Along with [`with`], this is the most generic validator. It succeeds\n/// exactly when `f` returns `Ok` and fails otherwise.\n///\n/// On error, returns a validation error with the message in the `Err`\n/// variant converted into a string.\n///\n/// # Example\n///\n/// Assuming `Token` has a `from_str` method:\n///\n/// ```rust\n/// # use rocket::form::FromForm;\n/// # impl FromStr for Token<'_> {\n/// #     type Err = &'static str;\n/// #     fn from_str(s: &str) -> Result<Self, Self::Err> { todo!() }\n/// # }\n/// use std::str::FromStr;\n///\n/// #[derive(FromForm)]\n/// #[field(validate = try_with(|s| Token::from_str(s)))]\n/// struct Token<'r>(&'r str);\n///\n/// #[derive(FromForm)]\n/// #[field(validate = try_with(|s| s.parse::<Token>()))]\n/// struct Token2<'r>(&'r str);\n/// ```\npub fn try_with<'v, V, F, T, E>(value: V, f: F) -> Result<'v, ()>\n    where F: FnOnce(V) -> std::result::Result<T, E>,\n          E: std::fmt::Display\n{\n    match f(value) {\n        Ok(_) => Ok(()),\n        Err(e) => Err(Error::validation(e.to_string()).into())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fs/file_name.rs",
    "content": "use ref_cast::RefCast;\n\nuse crate::http::RawStr;\n\n/// A file name in a [`TempFile`] or multipart [`DataField`].\n///\n/// A `Content-Disposition` header, either in a response or a multipart field,\n/// can optionally specify a `filename` directive as identifying information for\n/// the attached file. This type represents the value of that directive.\n///\n/// # Safety\n///\n/// There are no restrictions on the value of the directive. In particular, the\n/// value can be wholly unsafe to use as a file name in common contexts. As\n/// such, Rocket sanitizes the value into a version that _is_ safe to use as a\n/// file name in common contexts; this sanitized version can be retrieved via\n/// [`FileName::as_str()`] and is returned by [`TempFile::name()`].\n///\n/// You will likely want to prepend or append random or user-specific components\n/// to the name to avoid collisions; UUIDs make for a good \"random\" data. You\n/// may also prefer to avoid the value in the directive entirely by using a\n/// safe, application-generated name instead.\n///\n/// [`TempFile::name()`]: crate::fs::TempFile::name\n/// [`DataField`]: crate::form::DataField\n/// [`TempFile`]: crate::fs::TempFile\n#[repr(transparent)]\n#[derive(RefCast, Debug)]\npub struct FileName(str);\n\nimpl FileName {\n    /// Wraps a string as a `FileName`. This is cost-free.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fs::FileName;\n    ///\n    /// let name = FileName::new(\"some-file.txt\");\n    /// assert_eq!(name.as_str(), Some(\"some-file\"));\n    ///\n    /// let name = FileName::new(\"some-file.txt\");\n    /// assert_eq!(name.dangerous_unsafe_unsanitized_raw(), \"some-file.txt\");\n    /// ```\n    pub fn new<S: AsRef<str> + ?Sized>(string: &S) -> &FileName {\n        FileName::ref_cast(string.as_ref())\n    }\n\n    /// The sanitized file name, stripped of any file extension and special\n    /// characters, safe for use as a file name.\n    ///\n    /// # Sanitization\n    ///\n    /// A \"sanitized\" file name is a non-empty string, stripped of its file\n    /// extension, which is not a platform-specific reserved name and does not\n    /// contain any platform-specific special characters.\n    ///\n    /// On Unix, these are the characters `'.', '/', '\\\\', '<', '>', '|', ':',\n    /// '(', ')', '&', ';', '#', '?', '*'`.\n    ///\n    /// On Windows (and non-Unix OSs), these are the characters `'.', '<', '>',\n    /// ':', '\"', '/', '\\', '|', '?', '*', ',', ';', '=', '(', ')', '&', '#'`,\n    /// and the reserved names `\"CON\", \"PRN\", \"AUX\", \"NUL\", \"COM1\", \"COM2\",\n    /// \"COM3\", \"COM4\", \"COM5\", \"COM6\", \"COM7\", \"COM8\", \"COM9\", \"LPT1\", \"LPT2\",\n    /// \"LPT3\", \"LPT4\", \"LPT5\", \"LPT6\", \"LPT7\", \"LPT8\", \"LPT9\"`.\n    ///\n    /// Additionally, all control characters are considered \"special\".\n    ///\n    /// An attempt is made to transform the raw file name into a sanitized\n    /// version by identifying a valid substring of the raw file name that meets\n    /// this criteria. If none is found, `None` is returned.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fs::FileName;\n    ///\n    /// let name = FileName::new(\"some-file.txt\");\n    /// assert_eq!(name.as_str(), Some(\"some-file\"));\n    ///\n    /// let name = FileName::new(\"some-file.txt.zip\");\n    /// assert_eq!(name.as_str(), Some(\"some-file\"));\n    ///\n    /// let name = FileName::new(\"../../../../etc/shadow\");\n    /// assert_eq!(name.as_str(), Some(\"shadow\"));\n    ///\n    /// let name = FileName::new(\"/etc/.shadow\");\n    /// assert_eq!(name.as_str(), Some(\"shadow\"));\n    ///\n    /// let name = FileName::new(\"/a/b/some/file.txt.zip\");\n    /// assert_eq!(name.as_str(), Some(\"file\"));\n    ///\n    /// let name = FileName::new(\"/a/b/some/.file.txt.zip\");\n    /// assert_eq!(name.as_str(), Some(\"file\"));\n    ///\n    /// let name = FileName::new(\"/a/b/some/.*file.txt.zip\");\n    /// assert_eq!(name.as_str(), Some(\"file\"));\n    ///\n    /// let name = FileName::new(\"a/\\\\b/some/.*file<.txt.zip\");\n    /// assert_eq!(name.as_str(), Some(\"file\"));\n    ///\n    /// let name = FileName::new(\">>>.foo.txt\");\n    /// assert_eq!(name.as_str(), Some(\"foo\"));\n    ///\n    /// let name = FileName::new(\"b:c\");\n    /// #[cfg(unix)] assert_eq!(name.as_str(), Some(\"b\"));\n    /// #[cfg(not(unix))] assert_eq!(name.as_str(), Some(\"c\"));\n    ///\n    /// let name = FileName::new(\"//./.<>\");\n    /// assert_eq!(name.as_str(), None);\n    /// ```\n    pub fn as_str(&self) -> Option<&str> {\n        #[cfg(not(unix))]\n        let (bad_char, bad_name) = {\n            static BAD_CHARS: &[char] = &[\n                // Microsoft says these are invalid.\n                '.', '<', '>', ':', '\"', '/', '\\\\', '|', '?', '*',\n\n                // `cmd.exe` treats these specially.\n                ',', ';', '=',\n\n                // These are treated specially by unix-like shells.\n                '(', ')', '&', '#',\n            ];\n\n            // Microsoft says these are reserved.\n            static BAD_NAMES: &[&str] = &[\n                \"CON\", \"PRN\", \"AUX\", \"NUL\", \"COM1\", \"COM2\", \"COM3\", \"COM4\",\n                \"COM5\", \"COM6\", \"COM7\", \"COM8\", \"COM9\", \"LPT1\", \"LPT2\",\n                \"LPT3\", \"LPT4\", \"LPT5\", \"LPT6\", \"LPT7\", \"LPT8\", \"LPT9\",\n            ];\n\n            let bad_char = |c| BAD_CHARS.contains(&c) || c.is_control();\n            let bad_name = |n| BAD_NAMES.contains(&n);\n            (bad_char, bad_name)\n        };\n\n        #[cfg(unix)]\n        let (bad_char, bad_name) = {\n            static BAD_CHARS: &[char] = &[\n                // These have special meaning in a file name.\n                '.', '/', '\\\\',\n\n                // These are treated specially by shells.\n                '<', '>', '|', ':', '(', ')', '&', ';', '#', '?', '*',\n            ];\n\n            let bad_char = |c| BAD_CHARS.contains(&c) || c.is_control();\n            let bad_name = |_| false;\n            (bad_char, bad_name)\n        };\n\n        // Get the file name as a `str` without any extension(s).\n        let file_name = std::path::Path::new(&self.0)\n            .file_name()\n            .and_then(|n| n.to_str())\n            .and_then(|n| n.split(bad_char).find(|s| !s.is_empty()))?;\n\n        // At this point, `file_name` can't contain `bad_chars` because of\n        // `.split()`, but it can be empty or reserved.\n        if file_name.is_empty() || bad_name(file_name) {\n            return None;\n        }\n\n        Some(file_name)\n    }\n\n    /// Returns `true` if the _complete_ raw file name is safe.\n    ///\n    /// Note that `.as_str()` returns a safe _subset_ of the raw file name, if\n    /// there is one. If this method returns `true`, then that subset is the\n    /// complete raw file name.\n    ///\n    /// This method should be use sparingly. In particular, there is no\n    /// advantage to calling `is_safe()` prior to calling `as_str()`; simply\n    /// call `as_str()`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fs::FileName;\n    ///\n    /// let name = FileName::new(\"some-file.txt\");\n    /// assert_eq!(name.as_str(), Some(\"some-file\"));\n    /// assert!(!name.is_safe());\n    ///\n    /// let name = FileName::new(\"some-file\");\n    /// assert_eq!(name.as_str(), Some(\"some-file\"));\n    /// assert!(name.is_safe());\n    /// ```\n    pub fn is_safe(&self) -> bool {\n        self.as_str().map_or(false, |s| s == &self.0)\n    }\n\n    /// The raw, unsanitized, potentially unsafe file name. Prefer to use\n    /// [`FileName::as_str()`], always.\n    ///\n    /// # ⚠️ DANGER ⚠️\n    ///\n    /// This method returns the file name exactly as it was specified by the\n    /// client. You should **_not_** use this name _unless_ you require the\n    /// originally specified `filename` _and_ it is known not to contain\n    /// special, potentially dangerous characters, _and_:\n    ///\n    ///   1. All clients are known to be trusted, perhaps because the server\n    ///      only runs locally, serving known, local requests, or...\n    ///\n    ///   2. You will not use the file name to store a file on disk or any\n    ///      context that expects a file name _and_ you will not use the\n    ///      extension to determine how to handle/parse the data, or...\n    ///\n    ///   3. You will expertly process the raw name into a sanitized version for\n    ///      use in specific contexts.\n    ///\n    /// If not all of these cases apply, use [`FileName::as_str()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fs::FileName;\n    ///\n    /// let name = FileName::new(\"some-file.txt\");\n    /// assert_eq!(name.dangerous_unsafe_unsanitized_raw(), \"some-file.txt\");\n    ///\n    /// let name = FileName::new(\"../../../../etc/shadow\");\n    /// assert_eq!(name.dangerous_unsafe_unsanitized_raw(), \"../../../../etc/shadow\");\n    ///\n    /// let name = FileName::new(\"../../.ssh/id_rsa\");\n    /// assert_eq!(name.dangerous_unsafe_unsanitized_raw(), \"../../.ssh/id_rsa\");\n    ///\n    /// let name = FileName::new(\"/Rocket.toml\");\n    /// assert_eq!(name.dangerous_unsafe_unsanitized_raw(), \"/Rocket.toml\");\n    /// ```\n    pub fn dangerous_unsafe_unsanitized_raw(&self) -> &RawStr {\n        self.0.into()\n    }\n}\n\nimpl<'a, S: AsRef<str> + ?Sized> From<&'a S> for &'a FileName {\n    #[inline]\n    fn from(string: &'a S) -> Self {\n        FileName::new(string)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fs/mod.rs",
    "content": "//! File serving, file accepting, and file metadata types.\n\nmod server;\nmod named_file;\nmod temp_file;\nmod file_name;\n\npub mod rewrite;\n\npub use server::*;\npub use named_file::*;\npub use temp_file::*;\npub use file_name::*;\n\ncrate::export! {\n    /// Generates a crate-relative version of a path.\n    ///\n    /// This macro is primarily intended for use with [`FileServer`] to serve\n    /// files from a path relative to the crate root.\n    ///\n    /// The macro accepts one parameter, `$path`, an absolute or (preferably)\n    /// relative path. It returns a path as an `&'static str` prefixed with the\n    /// path to the crate root. Use `Path::new(relative!($path))` to retrieve an\n    /// `&'static Path`.\n    ///\n    /// # Example\n    ///\n    /// Serve files from the crate-relative `static/` directory:\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::{FileServer, relative};\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build().mount(\"/\", FileServer::new(relative!(\"static\")))\n    /// }\n    /// ```\n    ///\n    /// Path equivalences:\n    ///\n    /// ```rust\n    /// use std::path::Path;\n    ///\n    /// use rocket::fs::relative;\n    ///\n    /// let manual = Path::new(env!(\"CARGO_MANIFEST_DIR\")).join(\"static\");\n    /// let automatic_1 = Path::new(relative!(\"static\"));\n    /// let automatic_2 = Path::new(relative!(\"/static\"));\n    /// assert_eq!(manual, automatic_1);\n    /// assert_eq!(automatic_1, automatic_2);\n    /// ```\n    ///\n    macro_rules! relative {\n        ($path:expr) => {\n            if cfg!(windows) {\n                concat!(env!(\"CARGO_MANIFEST_DIR\"), \"\\\\\", $path)\n            } else {\n                concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/\", $path)\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fs/named_file.rs",
    "content": "use std::io;\nuse std::path::{Path, PathBuf};\nuse std::ops::{Deref, DerefMut};\n\nuse tokio::fs::{File, OpenOptions};\n\nuse crate::request::Request;\nuse crate::response::{self, Responder};\nuse crate::http::ContentType;\n\n/// A [`Responder`] that sends file data with a Content-Type based on its\n/// file extension.\n///\n/// # Example\n///\n/// A simple static file server mimicking [`FileServer`]:\n///\n/// ```rust\n/// # use rocket::get;\n/// use std::path::{PathBuf, Path};\n///\n/// use rocket::fs::{NamedFile, relative};\n///\n/// #[get(\"/file/<path..>\")]\n/// pub async fn second(path: PathBuf) -> Option<NamedFile> {\n///     let mut path = Path::new(relative!(\"static\")).join(path);\n///     if path.is_dir() {\n///         path.push(\"index.html\");\n///     }\n///\n///     NamedFile::open(path).await.ok()\n/// }\n/// ```\n///\n/// Always prefer to use [`FileServer`] which has more functionality and a\n/// pithier API.\n///\n/// [`FileServer`]: crate::fs::FileServer\n#[derive(Debug)]\npub struct NamedFile(PathBuf, File);\n\nimpl NamedFile {\n    /// Attempts to open a file in read-only mode.\n    ///\n    /// # Errors\n    ///\n    /// This function will return an error if path does not already exist. Other\n    /// errors may also be returned according to\n    /// [`OpenOptions::open()`](std::fs::OpenOptions::open()).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::get;\n    /// use rocket::fs::NamedFile;\n    ///\n    /// #[get(\"/\")]\n    /// async fn index() -> Option<NamedFile> {\n    ///     NamedFile::open(\"index.html\").await.ok()\n    /// }\n    /// ```\n    pub async fn open<P: AsRef<Path>>(path: P) -> io::Result<NamedFile> {\n        // TODO: Grab the file size here and prohibit `seek`ing later (or else\n        // the file's effective size may change), to save on the cost of doing\n        // all of those `seek`s to determine the file size. But, what happens if\n        // the file gets changed between now and then?\n        let file = File::open(path.as_ref()).await?;\n        Ok(NamedFile(path.as_ref().to_path_buf(), file))\n    }\n\n    pub async fn open_with<P: AsRef<Path>>(path: P, opts: &OpenOptions) -> io::Result<NamedFile> {\n        let file = opts.open(path.as_ref()).await?;\n        Ok(NamedFile(path.as_ref().to_path_buf(), file))\n    }\n\n    /// Retrieve the underlying `File`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fs::NamedFile;\n    ///\n    /// # async fn f() -> std::io::Result<()> {\n    /// let named_file = NamedFile::open(\"index.html\").await?;\n    /// let file = named_file.file();\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[inline(always)]\n    pub fn file(&self) -> &File {\n        &self.1\n    }\n\n    /// Retrieve a mutable borrow to the underlying `File`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fs::NamedFile;\n    ///\n    /// # async fn f() -> std::io::Result<()> {\n    /// let mut named_file = NamedFile::open(\"index.html\").await?;\n    /// let file = named_file.file_mut();\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[inline(always)]\n    pub fn file_mut(&mut self) -> &mut File {\n        &mut self.1\n    }\n\n    /// Take the underlying `File`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fs::NamedFile;\n    ///\n    /// # async fn f() -> std::io::Result<()> {\n    /// let named_file = NamedFile::open(\"index.html\").await?;\n    /// let file = named_file.take_file();\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[inline(always)]\n    pub fn take_file(self) -> File {\n        self.1\n    }\n\n    /// Retrieve the path of this file.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use rocket::fs::NamedFile;\n    ///\n    /// # async fn demo_path() -> std::io::Result<()> {\n    /// let file = NamedFile::open(\"foo.txt\").await?;\n    /// assert_eq!(file.path().as_os_str(), \"foo.txt\");\n    /// # Ok(())\n    /// # }\n    /// ```\n    #[inline(always)]\n    pub fn path(&self) -> &Path {\n        self.0.as_path()\n    }\n}\n\n/// Streams the named file to the client. Sets or overrides the Content-Type in\n/// the response according to the file's extension if the extension is\n/// recognized. See [`ContentType::from_extension()`] for more information. If\n/// you would like to stream a file with a different Content-Type than that\n/// implied by its extension, use a [`File`] directly.\nimpl<'r> Responder<'r, 'static> for NamedFile {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n        let mut response = self.1.respond_to(req)?;\n        if let Some(ext) = self.0.extension() {\n            if let Some(ct) = ContentType::from_extension(&ext.to_string_lossy()) {\n                response.set_header(ct);\n            }\n        }\n\n        Ok(response)\n    }\n}\n\nimpl Deref for NamedFile {\n    type Target = File;\n\n    fn deref(&self) -> &File {\n        &self.1\n    }\n}\n\nimpl DerefMut for NamedFile {\n    fn deref_mut(&mut self) -> &mut File {\n        &mut self.1\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fs/rewrite.rs",
    "content": "use std::borrow::Cow;\nuse std::path::{Path, PathBuf};\n\nuse crate::Request;\nuse crate::http::{ext::IntoOwned, HeaderMap};\nuse crate::response::Redirect;\n\n/// A file server [`Rewrite`] rewriter.\n///\n/// A [`FileServer`] is a sequence of [`Rewriter`]s which transform the incoming\n/// request path into a [`Rewrite`] or `None`. The first rewriter is called with\n/// the request path as a [`Rewrite::File`]. Each `Rewriter` thereafter is\n/// called in-turn with the previously returned [`Rewrite`], and the value\n/// returned from the last `Rewriter` is used to respond to the request. If the\n/// final rewrite is `None` or a nonexistent path or a directory, [`FileServer`]\n/// responds with [`Status::NotFound`]. Otherwise it responds with the file\n/// contents, if [`Rewrite::File`] is specified, or a redirect, if\n/// [`Rewrite::Redirect`] is specified.\n///\n/// [`FileServer`]: super::FileServer\n/// [`Status::NotFound`]: crate::http::Status::NotFound\npub trait Rewriter: Send + Sync + 'static {\n    /// Alter the [`Rewrite`] as needed.\n    fn rewrite<'r>(&self, opt: Option<Rewrite<'r>>, req: &'r Request<'_>) -> Option<Rewrite<'r>>;\n}\n\n/// A Response from a [`FileServer`](super::FileServer)\n#[derive(Debug, Clone)]\n#[non_exhaustive]\npub enum Rewrite<'r> {\n    /// Return the contents of the specified file.\n    File(File<'r>),\n    /// Returns a Redirect.\n    Redirect(Redirect),\n}\n\n/// A File response from a [`FileServer`](super::FileServer) and a rewriter.\n#[derive(Debug, Clone)]\n#[non_exhaustive]\npub struct File<'r> {\n    /// The path to the file that [`FileServer`](super::FileServer) will respond with.\n    pub path: Cow<'r, Path>,\n    /// A list of headers to be added to the generated response.\n    pub headers: HeaderMap<'r>,\n}\n\nimpl<'r> File<'r> {\n    /// A new `File`, with not additional headers.\n    pub fn new(path: impl Into<Cow<'r, Path>>) -> Self {\n        Self { path: path.into(), headers: HeaderMap::new() }\n    }\n\n    /// A new `File`, with not additional headers.\n    ///\n    /// # Panics\n    ///\n    /// Panics if the `path` does not exist.\n    pub fn checked<P: AsRef<Path>>(path: P) -> Self {\n        let path = path.as_ref();\n        if !path.exists() {\n            let path = path.display();\n            error!(%path, \"FileServer path does not exist.\\n\\\n                Panicking to prevent inevitable handler error.\");\n            panic!(\"missing file {}: refusing to continue\", path);\n        }\n\n        Self::new(path.to_path_buf())\n    }\n\n    /// Replace the path in `self` with the result of applying `f` to the path.\n    pub fn map_path<F, P>(self, f: F) -> Self\n        where F: FnOnce(Cow<'r, Path>) -> P, P: Into<Cow<'r, Path>>,\n    {\n        Self {\n            path: f(self.path).into(),\n            headers: self.headers,\n        }\n    }\n\n    /// Returns `true` if the file is a dotfile. A dotfile is a file whose\n    /// name or any directory in it's path start with a period (`.`) and is\n    /// considered hidden.\n    ///\n    /// # Windows Note\n    ///\n    /// This does *not* check the file metadata on any platform, so hidden files\n    /// on Windows will not be detected by this method.\n    pub fn is_hidden(&self) -> bool {\n        self.path.iter().any(|s| s.as_encoded_bytes().starts_with(b\".\"))\n    }\n\n    /// Returns `true` if the file is not hidden. This is the inverse of\n    /// [`File::is_hidden()`].\n    pub fn is_visible(&self) -> bool {\n        !self.is_hidden()\n    }\n}\n\n/// Prefixes all paths with a given path.\n///\n/// # Example\n///\n/// ```rust,no_run\n/// use rocket::fs::FileServer;\n/// use rocket::fs::rewrite::Prefix;\n///\n/// FileServer::identity()\n///    .filter(|f, _| f.is_visible())\n///    .rewrite(Prefix::checked(\"static\"));\n/// ```\npub struct Prefix(PathBuf);\n\nimpl Prefix {\n    /// Panics if `path` does not exist.\n    pub fn checked<P: AsRef<Path>>(path: P) -> Self {\n        let path = path.as_ref();\n        if !path.is_dir() {\n            let path = path.display();\n            error!(%path, \"FileServer path is not a directory.\");\n            warn!(\"Aborting early to prevent inevitable handler error.\");\n            panic!(\"invalid directory: refusing to continue\");\n        }\n\n        Self(path.to_path_buf())\n    }\n\n    /// Creates a new `Prefix` from a path.\n    pub fn unchecked<P: AsRef<Path>>(path: P) -> Self {\n        Self(path.as_ref().to_path_buf())\n    }\n}\n\nimpl Rewriter for Prefix {\n    fn rewrite<'r>(&self, opt: Option<Rewrite<'r>>, _: &Request<'_>) -> Option<Rewrite<'r>> {\n        opt.map(|r| match r {\n            Rewrite::File(f) => Rewrite::File(f.map_path(|p| self.0.join(p))),\n            Rewrite::Redirect(r) => Rewrite::Redirect(r),\n        })\n    }\n}\n\nimpl Rewriter for PathBuf {\n    fn rewrite<'r>(&self, _: Option<Rewrite<'r>>, _: &Request<'_>) -> Option<Rewrite<'r>> {\n        Some(Rewrite::File(File::new(self.clone())))\n    }\n}\n\n/// Normalize directories to always include a trailing slash by redirecting\n/// (with a 302 temporary redirect) requests for directories without a trailing\n/// slash to the same path with a trailing slash.\n///\n/// # Example\n///\n/// ```rust,no_run\n/// use rocket::fs::FileServer;\n/// use rocket::fs::rewrite::{Prefix, TrailingDirs};\n///\n/// FileServer::identity()\n///     .filter(|f, _| f.is_visible())\n///     .rewrite(TrailingDirs);\n/// ```\npub struct TrailingDirs;\n\nimpl Rewriter for TrailingDirs {\n    fn rewrite<'r>(&self, opt: Option<Rewrite<'r>>, req: &Request<'_>) -> Option<Rewrite<'r>> {\n        if let Some(Rewrite::File(f)) = &opt {\n            if !req.uri().path().ends_with('/') && f.path.is_dir() {\n                let uri = req.uri().clone().into_owned();\n                let uri = uri.map_path(|p| format!(\"{p}/\")).unwrap();\n                return Some(Rewrite::Redirect(Redirect::temporary(uri)));\n            }\n        }\n\n        opt\n    }\n}\n\n/// Rewrite a directory to a file inside of that directory.\n///\n/// # Example\n///\n/// Rewrites all directory requests to `directory/index.html`.\n///\n/// ```rust,no_run\n/// use rocket::fs::FileServer;\n/// use rocket::fs::rewrite::DirIndex;\n///\n/// FileServer::without_index(\"static\")\n///     .rewrite(DirIndex::if_exists(\"index.htm\"))\n///     .rewrite(DirIndex::unconditional(\"index.html\"));\n/// ```\npub struct DirIndex {\n    path: PathBuf,\n    check: bool,\n}\n\nimpl DirIndex {\n    /// Appends `path` to every request for a directory.\n    pub fn unconditional(path: impl AsRef<Path>) -> Self {\n        Self { path: path.as_ref().to_path_buf(), check: false }\n    }\n\n    /// Only appends `path` to a request for a directory if the file exists.\n    pub fn if_exists(path: impl AsRef<Path>) -> Self {\n        Self { path: path.as_ref().to_path_buf(), check: true }\n    }\n}\n\nimpl Rewriter for DirIndex {\n    fn rewrite<'r>(&self, opt: Option<Rewrite<'r>>, _: &Request<'_>) -> Option<Rewrite<'r>> {\n        match opt? {\n            Rewrite::File(f) if f.path.is_dir() => {\n                let candidate = f.path.join(&self.path);\n                if self.check && !candidate.is_file() {\n                    return Some(Rewrite::File(f));\n                }\n\n                Some(Rewrite::File(f.map_path(|_| candidate)))\n            }\n            r => Some(r),\n        }\n    }\n}\n\nimpl<'r> From<File<'r>> for Rewrite<'r> {\n    fn from(value: File<'r>) -> Self {\n        Self::File(value)\n    }\n}\n\nimpl<'r> From<Redirect> for Rewrite<'r> {\n    fn from(value: Redirect) -> Self {\n        Self::Redirect(value)\n    }\n}\n\nimpl<F: Send + Sync + 'static> Rewriter for F\n    where F: for<'r> Fn(Option<Rewrite<'r>>, &Request<'_>) -> Option<Rewrite<'r>>\n{\n    fn rewrite<'r>(&self, f: Option<Rewrite<'r>>, r: &Request<'_>) -> Option<Rewrite<'r>> {\n        self(f, r)\n    }\n}\n\nimpl Rewriter for Rewrite<'static> {\n    fn rewrite<'r>(&self, _: Option<Rewrite<'r>>, _: &Request<'_>) -> Option<Rewrite<'r>> {\n        Some(self.clone())\n    }\n}\n\nimpl Rewriter for File<'static> {\n    fn rewrite<'r>(&self, _: Option<Rewrite<'r>>, _: &Request<'_>) -> Option<Rewrite<'r>> {\n        Some(Rewrite::File(self.clone()))\n    }\n}\n\nimpl Rewriter for Redirect {\n    fn rewrite<'r>(&self, _: Option<Rewrite<'r>>, _: &Request<'_>) -> Option<Rewrite<'r>> {\n        Some(Rewrite::Redirect(self.clone()))\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fs/server.rs",
    "content": "use std::fmt;\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\nuse std::borrow::Cow;\n\nuse crate::{response, Data, Request, Response};\nuse crate::outcome::IntoOutcome;\nuse crate::http::{uri::Segments, HeaderMap, Method, ContentType, Status};\nuse crate::route::{Route, Handler, Outcome};\nuse crate::response::Responder;\nuse crate::util::Formatter;\nuse crate::fs::rewrite::*;\n\n/// Custom handler for serving static files.\n///\n/// This handler makes is simple to serve static files from a directory on the\n/// local file system. To use it, construct a `FileServer` using\n/// [`FileServer::new()`], then `mount` the handler.\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate rocket;\n/// use rocket::fs::FileServer;\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build()\n///         .mount(\"/\", FileServer::new(\"/www/static\"))\n/// }\n/// ```\n///\n/// When mounted, the handler serves files from the specified path. If a\n/// requested file does not exist, the handler _forwards_ the request with a\n/// `404` status.\n///\n/// By default, the route has a rank of `10` which can be changed with\n/// [`FileServer::rank()`].\n///\n/// # Customization\n///\n/// `FileServer` works through a pipeline of _rewrites_ in which a requested\n/// path is transformed into a `PathBuf` via [`Segments::to_path_buf()`] and\n/// piped through a series of [`Rewriter`]s to obtain a final [`Rewrite`] which\n/// is then used to generate a final response. See [`Rewriter`] for complete\n/// details on implementing your own `Rewriter`s.\n///\n/// # Example\n///\n/// Serve files from the `/static` directory on the local file system at the\n/// `/public` path:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate rocket;\n/// use rocket::fs::FileServer;\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().mount(\"/public\", FileServer::new(\"/static\"))\n/// }\n/// ```\n///\n/// Requests for files at `/public/<path..>` will be handled by returning the\n/// contents of `/static/<path..>`. Requests for directories will return the\n/// contents of `index.html`.\n///\n/// ## Relative Paths\n///\n/// In the example above, `/static` is an absolute path. If your static files\n/// are stored relative to your crate and your project is managed by Cargo, use\n/// the [`relative!`] macro to obtain a path that is relative to your crate's\n/// root. For example, to serve files in the `static` subdirectory of your crate\n/// at `/`, you might write:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate rocket;\n/// use rocket::fs::{FileServer, relative};\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().mount(\"/\", FileServer::new(relative!(\"static\")))\n/// }\n/// ```\n///\n/// [`relative!`]: crate::fs::relative!\n#[derive(Clone)]\npub struct FileServer {\n    rewrites: Vec<Arc<dyn Rewriter>>,\n    rank: isize,\n}\n\nimpl FileServer {\n    /// The default rank use by `FileServer` routes.\n    const DEFAULT_RANK: isize = 10;\n\n    /// Constructs a new `FileServer` that serves files from the file system\n    /// `path` with the following rewrites:\n    ///\n    /// - `|f, _| f.is_visible()`: Serve only visible files (hide dotfiles).\n    /// - [`Prefix::checked(path)`]: Prefix requests with `path`.\n    /// - [`TrailingDirs`]: Ensure directory have a trailing slash.\n    /// - [`DirIndex::unconditional(\"index.html\")`]: Serve `$dir/index.html` for\n    ///   requests to directory `$dir`.\n    ///\n    /// If you don't want to serve index files or want a different index file,\n    /// use [`Self::without_index`]. To customize the entire request to file\n    /// path rewrite pipeline, use [`Self::identity`].\n    ///\n    /// [`Prefix::checked(path)`]: crate::fs::rewrite::Prefix::checked\n    /// [`TrailingDirs`]: crate::fs::rewrite::TrailingDirs\n    /// [`DirIndex::unconditional(\"index.html\")`]: DirIndex::unconditional()\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::FileServer;\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .mount(\"/\", FileServer::new(\"/www/static\"))\n    /// }\n    /// ```\n    pub fn new<P: AsRef<Path>>(path: P) -> Self {\n        Self::identity()\n            .filter(|f, _| f.is_visible())\n            .rewrite(Prefix::checked(path))\n            .rewrite(TrailingDirs)\n            .rewrite(DirIndex::unconditional(\"index.html\"))\n    }\n\n    /// Exactly like [`FileServer::new()`] except it _does not_ serve directory\n    /// index files via [`DirIndex`]. It rewrites with the following:\n    ///\n    /// - `|f, _| f.is_visible()`: Serve only visible files (hide dotfiles).\n    /// - [`Prefix::checked(path)`]: Prefix requests with `path`.\n    /// - [`TrailingDirs`]: Ensure directory have a trailing slash.\n    ///\n    /// # Example\n    ///\n    /// Constructs a default file server to serve files from `./static` using\n    /// `index.txt` as the index file if `index.html` doesn't exist.\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::{FileServer, rewrite::DirIndex};\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     let server = FileServer::new(\"static\")\n    ///         .rewrite(DirIndex::if_exists(\"index.html\"))\n    ///         .rewrite(DirIndex::unconditional(\"index.txt\"));\n    ///\n    ///     rocket::build()\n    ///         .mount(\"/\", server)\n    /// }\n    /// ```\n    ///\n    /// [`Prefix::checked(path)`]: crate::fs::rewrite::Prefix::checked\n    /// [`TrailingDirs`]: crate::fs::rewrite::TrailingDirs\n    pub fn without_index<P: AsRef<Path>>(path: P) -> Self {\n        Self::identity()\n            .filter(|f, _| f.is_visible())\n            .rewrite(Prefix::checked(path))\n            .rewrite(TrailingDirs)\n    }\n\n    /// Constructs a new `FileServer` with no rewrites.\n    ///\n    /// Without any rewrites, a `FileServer` will try to serve the requested\n    /// file from the current working directory. In other words, it represents\n    /// the identity rewrite. For example, a request `GET /foo/bar` will be\n    /// passed through unmodified and thus `./foo/bar` will be served. This is\n    /// very unlikely to be what you want.\n    ///\n    /// Prefer to use [`FileServer::new()`] or [`FileServer::without_index()`]\n    /// whenever possible and otherwise use one or more of the rewrites in\n    /// [`rocket::fs::rewrite`] or your own custom rewrites.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::{FileServer, rewrite};\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     // A file server that serves exactly one file: /www/foo.html. The\n    ///     // file is served irrespective of what's requested.\n    ///     let server = FileServer::identity()\n    ///         .rewrite(rewrite::File::checked(\"/www/foo.html\"));\n    ///\n    ///     rocket::build()\n    ///         .mount(\"/\", server)\n    /// }\n    /// ```\n    pub fn identity() -> Self {\n        Self {\n            rewrites: vec![],\n            rank: Self::DEFAULT_RANK\n        }\n    }\n\n    /// Sets the rank of the route emitted by the `FileServer` to `rank`.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # use rocket::fs::FileServer;\n    /// # fn make_server() -> FileServer {\n    /// FileServer::identity()\n    ///    .rank(5)\n    /// # }\n    pub fn rank(mut self, rank: isize) -> Self {\n        self.rank = rank;\n        self\n    }\n\n    /// Add `rewriter` to the rewrite pipeline.\n    ///\n    /// # Example\n    ///\n    /// Redirect filtered requests (`None`) to `/`.\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::{FileServer, rewrite::Rewrite};\n    /// use rocket::{request::Request, response::Redirect};\n    ///\n    /// fn redir_missing<'r>(p: Option<Rewrite<'r>>, _req: &Request<'_>) -> Option<Rewrite<'r>> {\n    ///     Some(p.unwrap_or_else(|| Redirect::temporary(uri!(\"/\")).into()))\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .mount(\"/\", FileServer::new(\"static\").rewrite(redir_missing))\n    /// }\n    /// ```\n    ///\n    /// Note that `redir_missing` is not a closure in this example. Making it a closure\n    /// causes compilation to fail with a lifetime error. It really shouldn't but it does.\n    pub fn rewrite<R: Rewriter>(mut self, rewriter: R) -> Self {\n        self.rewrites.push(Arc::new(rewriter));\n        self\n    }\n\n    /// Adds a rewriter to the pipeline that returns `Some` only when the\n    /// function `f` returns `true`, filtering out all other files.\n    ///\n    /// # Example\n    ///\n    /// Allow all files that don't have a file name or have a file name other\n    /// than \"hidden\".\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::FileServer;\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     let server = FileServer::new(\"static\")\n    ///         .filter(|f, _| f.path.file_name() != Some(\"hidden\".as_ref()));\n    ///\n    ///     rocket::build()\n    ///         .mount(\"/\", server)\n    /// }\n    /// ```\n    pub fn filter<F: Send + Sync + 'static>(self, f: F) -> Self\n        where F: Fn(&File<'_>, &Request<'_>) -> bool\n    {\n        struct Filter<F>(F);\n\n        impl<F> Rewriter for Filter<F>\n            where F: Fn(&File<'_>, &Request<'_>) -> bool + Send + Sync + 'static\n        {\n            fn rewrite<'r>(&self, f: Option<Rewrite<'r>>, r: &Request<'_>) -> Option<Rewrite<'r>> {\n                f.and_then(|f| match f {\n                    Rewrite::File(f) if self.0(&f, r) => Some(Rewrite::File(f)),\n                    _ => None,\n                })\n            }\n        }\n\n        self.rewrite(Filter(f))\n    }\n\n    /// Adds a rewriter to the pipeline that maps the current `File` to another\n    /// `Rewrite` using `f`. If the current `Rewrite` is a `Redirect`, it is\n    /// passed through without calling `f`.\n    ///\n    /// # Example\n    ///\n    /// Append `index.txt` to every path.\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::FileServer;\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     let server = FileServer::new(\"static\")\n    ///         .map(|f, _| f.map_path(|p| p.join(\"index.txt\")).into());\n    ///\n    ///     rocket::build()\n    ///         .mount(\"/\", server)\n    /// }\n    /// ```\n    pub fn map<F: Send + Sync + 'static>(self, f: F) -> Self\n        where F: for<'r> Fn(File<'r>, &Request<'_>) -> Rewrite<'r>\n    {\n        struct Map<F>(F);\n\n        impl<F> Rewriter for Map<F>\n            where F: for<'r> Fn(File<'r>, &Request<'_>) -> Rewrite<'r> + Send + Sync + 'static\n        {\n            fn rewrite<'r>(&self, f: Option<Rewrite<'r>>, r: &Request<'_>) -> Option<Rewrite<'r>> {\n                f.map(|f| match f {\n                    Rewrite::File(f) => self.0(f, r),\n                    Rewrite::Redirect(r) => Rewrite::Redirect(r),\n                })\n            }\n        }\n\n        self.rewrite(Map(f))\n    }\n}\n\nimpl From<FileServer> for Vec<Route> {\n    fn from(server: FileServer) -> Self {\n        let mut route = Route::ranked(server.rank, Method::Get, \"/<path..>\", server);\n        route.name = Some(\"FileServer\".into());\n        vec![route]\n    }\n}\n\n#[crate::async_trait]\nimpl Handler for FileServer {\n    async fn handle<'r>(&self, req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r> {\n        use crate::http::uri::fmt::Path as UriPath;\n        let path: Option<PathBuf> = req.segments::<Segments<'_, UriPath>>(0..).ok()\n            .and_then(|segments| segments.to_path_buf(true).ok());\n\n        let mut response = path.map(|p| Rewrite::File(File::new(p)));\n        for rewrite in &self.rewrites {\n            response = rewrite.rewrite(response, req);\n        }\n\n        let (outcome, status) = match response {\n            Some(Rewrite::File(f)) => (f.open().await.respond_to(req), Status::NotFound),\n            Some(Rewrite::Redirect(r)) => (r.respond_to(req), Status::InternalServerError),\n            None => return Outcome::forward(data, Status::NotFound),\n        };\n\n        outcome.or_forward((data, status))\n    }\n}\n\nimpl fmt::Debug for FileServer {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"FileServer\")\n            .field(\"rewrites\", &Formatter(|f| write!(f, \"<{} rewrites>\", self.rewrites.len())))\n            .field(\"rank\", &self.rank)\n            .finish()\n    }\n}\n\nimpl<'r> File<'r> {\n    async fn open(self) -> std::io::Result<NamedFile<'r>> {\n        let file = tokio::fs::File::open(&self.path).await?;\n        let metadata = file.metadata().await?;\n        if metadata.is_dir() {\n            return Err(std::io::Error::other(\"is a directory\"));\n        }\n\n        Ok(NamedFile {\n            file,\n            len: metadata.len(),\n            path: self.path,\n            headers: self.headers,\n        })\n    }\n}\n\nstruct NamedFile<'r> {\n    file: tokio::fs::File,\n    len: u64,\n    path: Cow<'r, Path>,\n    headers: HeaderMap<'r>,\n}\n\n// Do we want to allow the user to rewrite the Content-Type?\nimpl<'r> Responder<'r, 'r> for NamedFile<'r> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {\n        let mut response = Response::new();\n        response.set_header_map(self.headers);\n        if !response.headers().contains(\"Content-Type\") {\n            self.path.extension()\n                .and_then(|ext| ext.to_str())\n                .and_then(ContentType::from_extension)\n                .map(|content_type| response.set_header(content_type));\n        }\n\n        response.set_sized_body(self.len as usize, self.file);\n        Ok(response)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/fs/temp_file.rs",
    "content": "use std::{io, mem};\nuse std::path::{PathBuf, Path};\n\nuse crate::Request;\nuse crate::http::{ContentType, Status};\nuse crate::data::{self, FromData, Data, Capped, N, Limits};\nuse crate::form::{FromFormField, ValueField, DataField, error::Errors};\nuse crate::outcome::IntoOutcome;\nuse crate::fs::FileName;\n\nuse tokio::task;\nuse tokio::fs::{self, File};\nuse tokio::io::{AsyncBufRead, BufReader};\nuse tempfile::{NamedTempFile, TempPath};\nuse either::Either;\n\n/// A data and form guard that streams data into a temporary file.\n///\n/// `TempFile` is a data and form field (both value and data fields) guard that\n/// streams incoming data into file in a temporary location. The file is deleted\n/// when the `TempFile` handle is dropped unless it is persisted with\n/// [`TempFile::persist_to()`] or copied with [`TempFile::copy_to()`].\n///\n/// # Hazards\n///\n/// Temporary files are cleaned by system file cleaners periodically. While an\n/// attempt is made not to delete temporary files in use, _detection_ of when a\n/// temporary file is being used is unreliable. As a result, a time-of-check to\n/// time-of-use race condition from the creation of a `TempFile` to the\n/// persistence of the `TempFile` may occur. Specifically, the following\n/// sequence may occur:\n///\n/// 1. A `TempFile` is created at random path `foo`.\n/// 2. The system cleaner removes the file at path `foo`.\n/// 3. Another application creates a file at path `foo`.\n/// 4. The `TempFile`, ostensibly at path `foo`, is persisted unexpectedly\n///    with contents different from those in step 1.\n///\n/// To safe-guard against this issue, you should ensure that your temporary file\n/// cleaner, if any, does not delete files too eagerly.\n///\n/// # Configuration\n///\n/// `TempFile` is configured via the following [`config`](crate::config)\n/// parameters:\n///\n/// | Name               | Default             | Description                             |\n/// |--------------------|---------------------|-----------------------------------------|\n/// | `temp_dir`         | [`env::temp_dir()`] | Directory for temporary file storage.   |\n/// | `limits.file`      | 1MiB                | Default limit for all file extensions.  |\n/// | `limits.file/$ext` | _N/A_               | Limit for files with extension `$ext`.  |\n///\n/// [`env::temp_dir()`]: std::env::temp_dir()\n///\n/// When used as a form guard, the extension `$ext` is identified by the form\n/// field's `Content-Type` ([`ContentType::extension()`]). When used as a data\n/// guard, the extension is identified by the Content-Type of the request, if\n/// any. If there is no Content-Type, the limit `file` is used.\n///\n/// # Cappable\n///\n/// A data stream can be partially read into a `TempFile` even if the incoming\n/// stream exceeds the data limit via the [`Capped<TempFile>`] data and form\n/// guard.\n///\n/// # Examples\n///\n/// **Data Guard**\n///\n/// ```rust\n/// # use rocket::post;\n/// use rocket::fs::TempFile;\n///\n/// #[post(\"/upload\", data = \"<file>\")]\n/// async fn upload(mut file: TempFile<'_>) -> std::io::Result<()> {\n///     file.persist_to(\"/tmp/complete/file.txt\").await?;\n///     Ok(())\n/// }\n/// ```\n///\n/// **Form Field**\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::fs::TempFile;\n/// use rocket::form::Form;\n///\n/// #[derive(FromForm)]\n/// struct Upload<'f> {\n///     upload: TempFile<'f>\n/// }\n///\n/// #[post(\"/form\", data = \"<form>\")]\n/// async fn upload(mut form: Form<Upload<'_>>) -> std::io::Result<()> {\n///     form.upload.persist_to(\"/tmp/complete/file.txt\").await?;\n///     Ok(())\n/// }\n/// ```\n///\n/// See also the [`Capped`] documentation for an example of `Capped<TempFile>`\n/// as a data guard.\n#[derive(Debug)]\npub enum TempFile<'v> {\n    #[doc(hidden)]\n    File {\n        file_name: Option<&'v FileName>,\n        content_type: Option<ContentType>,\n        path: Either<TempPath, PathBuf>,\n        len: u64,\n    },\n    #[doc(hidden)]\n    Buffered {\n        content: &'v [u8],\n    }\n}\n\nimpl<'v> TempFile<'v> {\n    /// Persists the temporary file, moving it to `path`. If a file exists at\n    /// the target path, `self` will atomically replace it. `self.path()` is\n    /// updated to `path`.\n    ///\n    /// This method _does not_ create a copy of `self`, nor a new link to the\n    /// contents of `self`: it renames the temporary file to `path` and marks it\n    /// as non-temporary. As a result, this method _cannot_ be used to create\n    /// multiple copies of `self`. To create multiple links, use\n    /// [`std::fs::hard_link()`] with `path` as the `src` _after_ calling this\n    /// method.\n    ///\n    /// # Cross-Device Persistence\n    ///\n    /// Attempting to persist a temporary file across logical devices (or mount\n    /// points) will result in an error. This is a limitation of the underlying\n    /// OS. Your options are thus:\n    ///\n    ///   1. Store temporary file in the same logical device.\n    ///\n    ///      Change the `temp_dir` configuration parameter to be in the same\n    ///      logical device as the permanent location. This is the preferred\n    ///      solution.\n    ///\n    ///   2. Copy the temporary file using [`TempFile::copy_to()`] or\n    ///      [`TempFile::move_copy_to()`] instead.\n    ///\n    ///      This is a _full copy_ of the file, creating a duplicate version of\n    ///      the file at the destination. This should be avoided for performance\n    ///      reasons.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {\n    ///     # assert!(file.path().is_none());\n    ///     # let some_path = std::env::temp_dir().join(\"some-persist.txt\");\n    ///     file.persist_to(&some_path).await?;\n    ///     assert_eq!(file.path(), Some(&*some_path));\n    ///\n    ///     Ok(())\n    /// }\n    /// # let file = TempFile::Buffered { content: \"hi\".as_bytes() };\n    /// # rocket::async_test(handle(file)).unwrap();\n    /// ```\n    pub async fn persist_to<P>(&mut self, path: P) -> io::Result<()>\n        where P: AsRef<Path>\n    {\n        let new_path = path.as_ref().to_path_buf();\n        match self {\n            TempFile::File { path: either, .. } => {\n                let path = mem::replace(either, Either::Right(new_path.clone()));\n                match path {\n                    Either::Left(temp) => {\n                        let result = task::spawn_blocking(move || temp.persist(new_path)).await\n                            .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, \"spawn_block\"))?;\n\n                        if let Err(e) = result {\n                            *either = Either::Left(e.path);\n                            return Err(e.error);\n                        }\n                    },\n                    Either::Right(prev) => {\n                        if let Err(e) = fs::rename(&prev, new_path).await {\n                            *either = Either::Right(prev);\n                            return Err(e);\n                        }\n                    }\n                }\n            }\n            TempFile::Buffered { content } => {\n                fs::write(&new_path, &content).await?;\n                *self = TempFile::File {\n                    file_name: None,\n                    content_type: None,\n                    path: Either::Right(new_path),\n                    len: content.len() as u64\n                };\n            }\n        }\n\n        Ok(())\n    }\n\n    /// Persists the temporary file at its temporary path and creates a full\n    /// copy at `path`. The `self.path()` is _not_ updated, unless no temporary\n    /// file existed prior, and the temporary file is _not_ removed. Thus, there\n    /// will be _two_ files with the same contents.\n    ///\n    /// Unlike [`TempFile::persist_to()`], this method does not incur\n    /// cross-device limitations, at the performance cost of a full copy. Prefer\n    /// to use `persist_to()` with a valid `temp_dir` configuration parameter if\n    /// no more than one copy of a file is required.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {\n    ///     # assert!(file.path().is_none());\n    ///     # let some_path = std::env::temp_dir().join(\"some-file.txt\");\n    ///     file.copy_to(&some_path).await?;\n    ///     # assert_eq!(file.path(), Some(&*some_path));\n    ///     # let some_other_path = std::env::temp_dir().join(\"some-other.txt\");\n    ///     file.copy_to(&some_other_path).await?;\n    ///     assert_eq!(file.path(), Some(&*some_path));\n    ///     # assert_eq!(std::fs::read(some_path).unwrap(), b\"hi\");\n    ///     # assert_eq!(std::fs::read(some_other_path).unwrap(), b\"hi\");\n    ///\n    ///     Ok(())\n    /// }\n    /// # let file = TempFile::Buffered { content: b\"hi\" };\n    /// # rocket::async_test(handle(file)).unwrap();\n    /// ```\n    pub async fn copy_to<P>(&mut self, path: P) -> io::Result<()>\n        where P: AsRef<Path>\n    {\n        match self {\n            TempFile::File { path: either, .. } => {\n                let old_path = mem::replace(either, Either::Right(either.to_path_buf()));\n                match old_path {\n                    Either::Left(temp) => {\n                        let result = task::spawn_blocking(move || temp.keep()).await\n                            .map_err(|_| io::Error::new(io::ErrorKind::BrokenPipe, \"spawn_block\"))?;\n\n                        if let Err(e) = result {\n                            *either = Either::Left(e.path);\n                            return Err(e.error);\n                        }\n                    },\n                    Either::Right(_) => { /* do nada */ }\n                };\n\n                tokio::fs::copy(&either, path).await?;\n            }\n            TempFile::Buffered { content } => {\n                let path = path.as_ref();\n                fs::write(&path, &content).await?;\n                *self = TempFile::File {\n                    file_name: None,\n                    content_type: None,\n                    path: Either::Right(path.to_path_buf()),\n                    len: content.len() as u64\n                };\n            }\n        }\n\n        Ok(())\n    }\n\n    /// Persists the temporary file at its temporary path, creates a full copy\n    /// at `path`, and then deletes the temporary file. `self.path()` is updated\n    /// to `path`.\n    ///\n    /// Like [`TempFile::copy_to()`] and unlike [`TempFile::persist_to()`], this\n    /// method does not incur cross-device limitations, at the performance cost\n    /// of a full copy and file deletion. Prefer to use `persist_to()` with a\n    /// valid `temp_dir` configuration parameter if no more than one copy of a\n    /// file is required.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {\n    ///     # assert!(file.path().is_none());\n    ///     # let some_path = std::env::temp_dir().join(\"some-copy.txt\");\n    ///     file.move_copy_to(&some_path).await?;\n    ///     # assert_eq!(file.path(), Some(&*some_path));\n    ///\n    ///     Ok(())\n    /// }\n    /// # let file = TempFile::Buffered { content: \"hi\".as_bytes() };\n    /// # rocket::async_test(handle(file)).unwrap();\n    /// ```\n    pub async fn move_copy_to<P>(&mut self, path: P) -> io::Result<()>\n        where P: AsRef<Path>\n    {\n        let dest = path.as_ref();\n        self.copy_to(dest).await?;\n\n        if let TempFile::File { path, .. } = self {\n            fs::remove_file(&path).await?;\n            *path = Either::Right(dest.to_path_buf());\n        }\n\n        Ok(())\n    }\n\n    /// Open the file for reading, returning an `async` stream of the file.\n    ///\n    /// This method should be used sparingly. `TempFile` is intended to be used\n    /// when the incoming data is destined to be stored on disk. If the incoming\n    /// data is intended to be streamed elsewhere, prefer to implement a custom\n    /// form guard via [`FromFormField`] that directly streams the incoming data\n    /// to the ultimate destination.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    /// use rocket::tokio::io;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// async fn handle(file: TempFile<'_>) -> std::io::Result<()> {\n    ///     let mut stream = file.open().await?;\n    ///     io::copy(&mut stream, &mut io::stdout()).await?;\n    ///     Ok(())\n    /// }\n    /// # let file = TempFile::Buffered { content: \"hi\".as_bytes() };\n    /// # rocket::async_test(handle(file)).unwrap();\n    /// ```\n    pub async fn open(&self) -> io::Result<impl AsyncBufRead + '_> {\n        use tokio_util::either::Either;\n\n        match self {\n            TempFile::File { path, .. } => {\n                let path = match path {\n                    either::Either::Left(p) => p.as_ref(),\n                    either::Either::Right(p) => p.as_path(),\n                };\n\n                let reader = BufReader::new(File::open(path).await?);\n                Ok(Either::Left(reader))\n            },\n            TempFile::Buffered { content } => {\n                Ok(Either::Right(*content))\n            },\n        }\n    }\n\n    /// Returns whether the file is empty.\n    ///\n    /// This is equivalent to `file.len() == 0`.\n    ///\n    /// This method does not perform any system calls.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// fn handler(file: TempFile<'_>) {\n    ///     if file.is_empty() {\n    ///         assert_eq!(file.len(), 0);\n    ///     }\n    /// }\n    /// ```\n    pub fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    /// Returns the size, in bytes, of the file.\n    ///\n    /// This method does not perform any system calls.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// fn handler(file: TempFile<'_>) {\n    ///     let file_len = file.len();\n    /// }\n    /// ```\n    pub fn len(&self) -> u64 {\n        match self {\n            TempFile::File { len, .. } => *len,\n            TempFile::Buffered { content } => content.len() as u64,\n        }\n    }\n\n    /// Returns the path to the file if it is known.\n    ///\n    /// Once a file is persisted with [`TempFile::persist_to()`], this method is\n    /// guaranteed to return `Some`. Prior to this point, however, this method\n    /// may return `Some` or `None`, depending on whether the file is on disk or\n    /// partially buffered in memory.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {\n    ///     # assert!(file.path().is_none());\n    ///     # let some_path = std::env::temp_dir().join(\"some-path.txt\");\n    ///     file.persist_to(&some_path).await?;\n    ///     assert_eq!(file.path(), Some(&*some_path));\n    ///     # assert_eq!(std::fs::read(some_path).unwrap(), b\"hi\");\n    ///\n    ///     Ok(())\n    /// }\n    /// # let file = TempFile::Buffered { content: b\"hi\" };\n    /// # rocket::async_test(handle(file)).unwrap();\n    /// ```\n    pub fn path(&self) -> Option<&Path> {\n        match self {\n            TempFile::File { path: Either::Left(p), .. } => Some(p.as_ref()),\n            TempFile::File { path: Either::Right(p), .. } => Some(p.as_path()),\n            TempFile::Buffered { .. } => None,\n        }\n    }\n\n    /// Returns the sanitized file name as specified in the form field.\n    ///\n    /// A multipart data form field can optionally specify the name of a file. A\n    /// browser will typically send the actual name of a user's selected file in\n    /// this field, but clients are also able to specify _any_ name, including\n    /// invalid or dangerous file names. This method returns a sanitized version\n    /// of that value, if it was specified, suitable and safe for use as a\n    /// permanent file name.\n    ///\n    /// Note that you will likely want to prepend or append random or\n    /// user-specific components to the name to avoid collisions; UUIDs make for\n    /// a good \"random\" data.\n    ///\n    /// See [`FileName::as_str()`] for specifics on sanitization.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// async fn handle(mut file: TempFile<'_>) -> std::io::Result<()> {\n    ///     # let some_dir = std::env::temp_dir();\n    ///     if let Some(name) = file.name() {\n    ///         // Because of Rocket's sanitization, this is safe.\n    ///         file.persist_to(&some_dir.join(name)).await?;\n    ///     }\n    ///\n    ///     Ok(())\n    /// }\n    /// ```\n    pub fn name(&self) -> Option<&str> {\n        self.raw_name().and_then(|f| f.as_str())\n    }\n\n    /// Returns the raw name of the file as specified in the form field.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// async fn handle(mut file: TempFile<'_>) {\n    ///     let raw_name = file.raw_name();\n    /// }\n    /// ```\n    pub fn raw_name(&self) -> Option<&FileName> {\n        match *self {\n            TempFile::File { file_name, .. } => file_name,\n            TempFile::Buffered { .. } => None\n        }\n    }\n\n    /// Returns the Content-Type of the file as specified in the form field.\n    ///\n    /// A multipart data form field can optionally specify the content-type of a\n    /// file. A browser will typically sniff the file's extension to set the\n    /// content-type. This method returns that value, if it was specified.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fs::TempFile;\n    ///\n    /// #[post(\"/\", data = \"<file>\")]\n    /// fn handle(file: TempFile<'_>) {\n    ///     let content_type = file.content_type();\n    /// }\n    /// ```\n    pub fn content_type(&self) -> Option<&ContentType> {\n        match self {\n            TempFile::File { content_type, .. } => content_type.as_ref(),\n            TempFile::Buffered { .. } => None\n        }\n    }\n\n    async fn from<'a>(\n        req: &Request<'_>,\n        data: Data<'_>,\n        file_name: Option<&'a FileName>,\n        content_type: Option<ContentType>,\n    ) -> io::Result<Capped<TempFile<'a>>> {\n        let limit = content_type.as_ref()\n            .and_then(|ct| ct.extension())\n            .and_then(|ext| req.limits().find([\"file\", ext.as_str()]))\n            .or_else(|| req.limits().get(\"file\"))\n            .unwrap_or(Limits::FILE);\n\n        let temp_dir = req.rocket().config().temp_dir.relative();\n        let file = task::spawn_blocking(move || NamedTempFile::new_in(temp_dir));\n        let file = file.await;\n        let file = file.map_err(|_| io::Error::new(io::ErrorKind::Other, \"spawn_block panic\"))??;\n        let (file, temp_path) = file.into_parts();\n\n        let mut file = File::from_std(file);\n        let fut = data.open(limit).stream_to(tokio::io::BufWriter::new(&mut file));\n        let n = fut.await;\n        let n = n?;\n        let temp_file = TempFile::File {\n            content_type, file_name,\n            path: Either::Left(temp_path),\n            len: n.written,\n        };\n\n        Ok(Capped::new(temp_file, n))\n    }\n}\n\n#[crate::async_trait]\nimpl<'v> FromFormField<'v> for Capped<TempFile<'v>> {\n    fn from_value(field: ValueField<'v>) -> Result<Self, Errors<'v>> {\n        let n = N { written: field.value.len() as u64, complete: true  };\n        Ok(Capped::new(TempFile::Buffered { content: field.value.as_bytes() }, n))\n    }\n\n    async fn from_data(\n        f: DataField<'v, '_>\n    ) -> Result<Self, Errors<'v>> {\n        Ok(TempFile::from(f.request, f.data, f.file_name, Some(f.content_type)).await?)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromData<'r> for Capped<TempFile<'_>> {\n    type Error = io::Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {\n        let has_form = |ty: &ContentType| ty.is_form_data() || ty.is_form();\n        if req.content_type().map_or(false, has_form) {\n            warn!(request.content_type = req.content_type().map(display),\n                \"Request contains a form that is not being processed.\\n\\\n                Bare `TempFile` data guard writes raw, unprocessed streams to disk\\n\\\n                Perhaps you meant to use `Form<TempFile<'_>>` instead?\");\n        }\n\n        TempFile::from(req, data, None, req.content_type().cloned())\n            .await\n            .or_error(Status::BadRequest)\n    }\n}\n\nimpl_strict_from_form_field_from_capped!(TempFile<'v>);\nimpl_strict_from_data_from_capped!(TempFile<'_>);\n"
  },
  {
    "path": "core/lib/src/http/cookies.rs",
    "content": "use std::fmt;\n\nuse parking_lot::Mutex;\n\nuse crate::{Rocket, Orbit};\n\n#[doc(inline)]\npub use cookie::{Cookie, SameSite, Iter};\n\n/// Collection of one or more HTTP cookies.\n///\n/// `CookieJar` allows for retrieval of cookies from an incoming request. It\n/// also tracks modifications (additions and removals) and marks them as\n/// pending.\n///\n/// # Pending\n///\n/// Changes to a `CookieJar` are _not_ visible via the normal [`get()`] and\n/// [`get_private()`] methods. This is typically the desired effect as a\n/// `CookieJar` always reflects the cookies in an incoming request. In cases\n/// where this is not desired, the [`get_pending()`] method is available, which\n/// always returns the latest changes.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::http::{CookieJar, Cookie};\n///\n/// #[get(\"/message\")]\n/// fn message(jar: &CookieJar<'_>) {\n///     jar.add((\"message\", \"hello!\"));\n///     jar.add(Cookie::build((\"session\", \"bye!\")).expires(None));\n///\n///     // `get()` does not reflect changes.\n///     assert!(jar.get(\"session\").is_none());\n///     assert_eq!(jar.get(\"message\").map(|c| c.value()), Some(\"hi\"));\n///\n///     // `get_pending()` does.\n///     let session_pending = jar.get_pending(\"session\");\n///     let message_pending = jar.get_pending(\"message\");\n///     assert_eq!(session_pending.as_ref().map(|c| c.value()), Some(\"bye!\"));\n///     assert_eq!(message_pending.as_ref().map(|c| c.value()), Some(\"hello!\"));\n///     # jar.remove(\"message\");\n///     # assert_eq!(jar.get(\"message\").map(|c| c.value()), Some(\"hi\"));\n///     # assert!(jar.get_pending(\"message\").is_none());\n/// }\n/// # fn main() {\n/// #     use rocket::local::blocking::Client;\n/// #     let client = Client::debug_with(routes![message]).unwrap();\n/// #     let response = client.get(\"/message\")\n/// #         .cookie((\"message\", \"hi\"))\n/// #         .dispatch();\n/// #\n/// #     assert!(response.status().class().is_success());\n/// # }\n/// ```\n///\n/// # Usage\n///\n/// A type of `&CookieJar` can be retrieved via its `FromRequest` implementation\n/// as a request guard or via the [`Request::cookies()`] method. Individual\n/// cookies can be retrieved via the [`get()`] and [`get_private()`] methods.\n/// Pending changes can be observed via the [`get_pending()`] method. Cookies\n/// can be added or removed via the [`add()`], [`add_private()`], [`remove()`],\n/// and [`remove_private()`] methods.\n///\n/// [`Request::cookies()`]: crate::Request::cookies()\n/// [`get()`]: #method.get\n/// [`get_private()`]: #method.get_private\n/// [`get_pending()`]: #method.get_pending\n/// [`add()`]: #method.add\n/// [`add_private()`]: #method.add_private\n/// [`remove()`]: #method.remove\n/// [`remove_private()`]: #method.remove_private\n///\n/// ## Examples\n///\n/// The following example shows `&CookieJar` being used as a request guard in a\n/// handler to retrieve the value of a \"message\" cookie.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::http::CookieJar;\n///\n/// #[get(\"/message\")]\n/// fn message<'a>(jar: &'a CookieJar<'_>) -> Option<&'a str> {\n///     jar.get(\"message\").map(|cookie| cookie.value())\n/// }\n/// # fn main() {  }\n/// ```\n///\n/// The following snippet shows `&CookieJar` being retrieved from a `Request` in\n/// a custom request guard implementation for `User`. A [private cookie]\n/// containing a user's ID is retrieved. If the cookie exists and the ID parses\n/// as an integer, a `User` structure is validated. Otherwise, the guard\n/// forwards.\n///\n/// [private cookie]: #method.add_private\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[cfg(feature = \"secrets\")] {\n/// use rocket::http::Status;\n/// use rocket::request::{self, Request, FromRequest};\n/// use rocket::outcome::IntoOutcome;\n///\n/// // In practice, we'd probably fetch the user from the database.\n/// struct User(usize);\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for User {\n///     type Error = std::convert::Infallible;\n///\n///     async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n///         request.cookies()\n///             .get_private(\"user_id\")\n///             .and_then(|c| c.value().parse().ok())\n///             .map(|id| User(id))\n///             .or_forward(Status::Unauthorized)\n///     }\n/// }\n/// # }\n/// # fn main() { }\n/// ```\n///\n/// # Private Cookies\n///\n/// _Private_ cookies are just like regular cookies except that they are\n/// encrypted using authenticated encryption, a form of encryption which\n/// simultaneously provides confidentiality, integrity, and authenticity. This\n/// means that private cookies cannot be inspected, tampered with, or\n/// manufactured by clients. If you prefer, you can think of private cookies as\n/// being signed and encrypted.\n///\n/// Private cookies can be retrieved, added, and removed from a `CookieJar`\n/// collection via the [`get_private()`], [`add_private()`], and\n/// [`remove_private()`] methods.\n///\n/// ## Encryption Key\n///\n/// To encrypt private cookies, Rocket uses the 256-bit key specified in the\n/// `secret_key` configuration parameter. If one is not specified, Rocket will\n/// automatically generate a fresh key. Note, however, that a private cookie can\n/// only be decrypted with the same key with which it was encrypted. As such, it\n/// is important to set a `secret_key` configuration parameter when using\n/// private cookies so that cookies decrypt properly after an application\n/// restart. Rocket will emit a warning if an application is run in production\n/// mode without a configured `secret_key`.\n///\n/// Generating a string suitable for use as a `secret_key` configuration value\n/// is usually done through tools like `openssl`. Using `openssl`, for instance,\n/// a 256-bit base64 key can be generated with the command `openssl rand -base64\n/// 32`.\npub struct CookieJar<'a> {\n    jar: cookie::CookieJar,\n    ops: Mutex<Vec<Op>>,\n    pub(crate) state: CookieState<'a>,\n}\n\n#[derive(Copy, Clone)]\npub(crate) struct CookieState<'a> {\n    pub secure: bool,\n    #[cfg_attr(not(feature = \"secrets\"), allow(unused))]\n    pub config: &'a crate::Config,\n}\n\n#[derive(Clone)]\nenum Op {\n    Add(Cookie<'static>, bool),\n    Remove(Cookie<'static>),\n}\n\nimpl<'a> CookieJar<'a> {\n    pub(crate) fn new(base: Option<cookie::CookieJar>, rocket: &'a Rocket<Orbit>) -> Self {\n        CookieJar {\n            jar: base.unwrap_or_default(),\n            ops: Mutex::new(Vec::new()),\n            state: CookieState {\n                // This is updated dynamically when headers are received.\n                secure: rocket.endpoints().all(|e| e.is_tls()),\n                config: rocket.config(),\n            }\n        }\n    }\n\n    /// Returns a reference to the _original_ `Cookie` inside this container\n    /// with the name `name`. If no such cookie exists, returns `None`.\n    ///\n    /// **Note:** This method _does not_ observe changes made via additions and\n    /// removals to the cookie jar. To observe those changes, use\n    /// [`CookieJar::get_pending()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::CookieJar;\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     let cookie = jar.get(\"name\");\n    /// }\n    /// ```\n    pub fn get(&self, name: &str) -> Option<&Cookie<'static>> {\n        self.jar.get(name)\n    }\n\n    /// Retrieves the _original_ `Cookie` inside this collection with the name\n    /// `name` and authenticates and decrypts the cookie's value. If the cookie\n    /// cannot be found, or the cookie fails to authenticate or decrypt, `None`\n    /// is returned.\n    ///\n    /// **Note:** This method _does not_ observe changes made via additions and\n    /// removals to the cookie jar. To observe those changes, use\n    /// [`CookieJar::get_pending()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::CookieJar;\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     let cookie = jar.get_private(\"name\");\n    /// }\n    /// ```\n    #[cfg(feature = \"secrets\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\n    pub fn get_private(&self, name: &str) -> Option<Cookie<'static>> {\n        self.jar.private(&self.state.config.secret_key.key).get(name)\n    }\n\n    /// Returns a reference to the _original or pending_ `Cookie` inside this\n    /// container with the name `name`, irrespective of whether the cookie was\n    /// private or not. If no such cookie exists, returns `None`.\n    ///\n    /// In general, due to performance overhead, calling this method should be\n    /// avoided if it is known that a cookie called `name` is not pending.\n    /// Instead, prefer to use [`CookieJar::get()`] or\n    /// [`CookieJar::get_private()`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::CookieJar;\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     let pending_cookie = jar.get_pending(\"name\");\n    /// }\n    /// ```\n    pub fn get_pending(&self, name: &str) -> Option<Cookie<'static>> {\n        let ops = self.ops.lock();\n        if let Some(op) = ops.iter().rev().find(|op| op.cookie().name() == name) {\n            return match op {\n                Op::Add(c, _) => Some(c.clone()),\n                Op::Remove(_) => None,\n            };\n        }\n\n        drop(ops);\n\n        #[cfg(feature = \"secrets\")] {\n            self.get_private(name).or_else(|| self.get(name).cloned())\n        }\n\n        #[cfg(not(feature = \"secrets\"))] {\n            self.get(name).cloned()\n        }\n    }\n\n    /// Adds `cookie` to this collection.\n    ///\n    /// Unless a value is set for the given property, the following defaults are\n    /// set on `cookie` before being added to `self`:\n    ///\n    ///    * `path`: `\"/\"`\n    ///    * `SameSite`: `Strict`\n    ///    * `Secure`: `true` if [`Request::context_is_likely_secure()`]\n    ///\n    /// These defaults ensure maximum usability and security. For additional\n    /// security, you may wish to set the `secure` flag explicitly.\n    ///\n    /// [`Request::context_is_likely_secure()`]: crate::Request::context_is_likely_secure()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::{Cookie, SameSite, CookieJar};\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     jar.add((\"first\", \"value\"));\n    ///\n    ///     let cookie = Cookie::build((\"other\", \"value_two\"))\n    ///         .path(\"/\")\n    ///         .secure(true)\n    ///         .same_site(SameSite::Lax);\n    ///\n    ///     jar.add(cookie);\n    /// }\n    /// ```\n    pub fn add<C: Into<Cookie<'static>>>(&self, cookie: C) {\n        let mut cookie = cookie.into();\n        self.set_defaults(&mut cookie);\n        self.ops.lock().push(Op::Add(cookie, false));\n    }\n\n    /// Adds `cookie` to the collection. The cookie's value is encrypted with\n    /// authenticated encryption assuring confidentiality, integrity, and\n    /// authenticity. The cookie can later be retrieved using\n    /// [`get_private`](#method.get_private) and removed using\n    /// [`remove_private`](#method.remove_private).\n    ///\n    /// Unless a value is set for the given property, the following defaults are\n    /// set on `cookie` before being added to `self`:\n    ///\n    ///    * `path`: `\"/\"`\n    ///    * `SameSite`: `Strict`\n    ///    * `HttpOnly`: `true`\n    ///    * `Expires`: 1 week from now\n    ///    * `Secure`: `true` if [`Request::context_is_likely_secure()`]\n    ///\n    /// These defaults ensure maximum usability and security. For additional\n    /// security, you may wish to set the `secure` flag explicitly and\n    /// unconditionally.\n    ///\n    /// [`Request::context_is_likely_secure()`]: crate::Request::context_is_likely_secure()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::CookieJar;\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     jar.add_private((\"name\", \"value\"));\n    /// }\n    /// ```\n    #[cfg(feature = \"secrets\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\n    pub fn add_private<C: Into<Cookie<'static>>>(&self, cookie: C) {\n        let mut cookie = cookie.into();\n        self.set_private_defaults(&mut cookie);\n        self.ops.lock().push(Op::Add(cookie, true));\n    }\n\n    /// Removes `cookie` from this collection and generates a \"removal\" cookie\n    /// to send to the client on response. A \"removal\" cookie is a cookie that\n    /// has the same name as the original cookie but has an empty value, a\n    /// max-age of 0, and an expiration date far in the past.\n    ///\n    /// **For successful removal, `cookie` must contain the same `path` and\n    /// `domain` as the cookie that was originally set. The cookie will fail to\n    /// be deleted if any other `path` and `domain` are provided. For\n    /// convenience, a path of `\"/\"` is automatically set when one is not\n    /// specified.** The full list of defaults when corresponding values aren't\n    /// specified is:\n    ///\n    ///    * `path`: `\"/\"`\n    ///    * `SameSite`: `Lax`\n    ///\n    /// <small>Note: a default setting of `Lax` for `SameSite` carries no\n    /// security implications: the removal cookie has expired, so it is never\n    /// transferred to any origin.</small>\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::{Cookie, CookieJar};\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     // `path` and `SameSite` are set to defaults (`/` and `Lax`)\n    ///     jar.remove(\"name\");\n    ///\n    ///     // Use a custom-built cookie to set a custom path.\n    ///     jar.remove(Cookie::build(\"name\").path(\"/login\"));\n    ///\n    ///     // Use a custom-built cookie to set a custom path and domain.\n    ///     jar.remove(Cookie::build(\"id\").path(\"/guide\").domain(\"rocket.rs\"));\n    /// }\n    /// ```\n    pub fn remove<C: Into<Cookie<'static>>>(&self, cookie: C) {\n        let mut cookie = cookie.into();\n        Self::set_removal_defaults(&mut cookie);\n        self.ops.lock().push(Op::Remove(cookie));\n    }\n\n    /// Removes the private `cookie` from the collection.\n    ///\n    /// **For successful removal, `cookie` must contain the same `path` and\n    /// `domain` as the cookie that was originally set. The cookie will fail to\n    /// be deleted if any other `path` and `domain` are provided. For\n    /// convenience, a path of `\"/\"` is automatically set when one is not\n    /// specified.** The full list of defaults when corresponding values aren't\n    /// specified is:\n    ///\n    ///    * `path`: `\"/\"`\n    ///    * `SameSite`: `Lax`\n    ///\n    /// <small>Note: a default setting of `Lax` for `SameSite` carries no\n    /// security implications: the removal cookie has expired, so it is never\n    /// transferred to any origin.</small>\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::{CookieJar, Cookie};\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     // `path` and `SameSite` are set to defaults (`/` and `Lax`)\n    ///     jar.remove_private(\"name\");\n    ///\n    ///     // Use a custom-built cookie to set a custom path.\n    ///     jar.remove_private(Cookie::build(\"name\").path(\"/login\"));\n    ///\n    ///     // Use a custom-built cookie to set a custom path and domain.\n    ///     let cookie = Cookie::build(\"id\").path(\"/guide\").domain(\"rocket.rs\");\n    ///     jar.remove_private(cookie);\n    /// }\n    /// ```\n    #[cfg(feature = \"secrets\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\n    pub fn remove_private<C: Into<Cookie<'static>>>(&self, cookie: C) {\n        let mut cookie = cookie.into();\n        Self::set_removal_defaults(&mut cookie);\n        self.ops.lock().push(Op::Remove(cookie));\n    }\n\n    /// Returns an iterator over all of the _original_ cookies present in this\n    /// collection.\n    ///\n    /// **Note:** This method _does not_ observe changes made via additions and\n    /// removals to the cookie jar.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::http::CookieJar;\n    ///\n    /// #[get(\"/\")]\n    /// fn handler(jar: &CookieJar<'_>) {\n    ///     for c in jar.iter() {\n    ///         println!(\"Name: {:?}, Value: {:?}\", c.name(), c.value());\n    ///     }\n    /// }\n    /// ```\n    pub fn iter(&self) -> impl Iterator<Item=&Cookie<'static>> {\n        self.jar.iter()\n    }\n\n    /// Removes all delta cookies.\n    #[inline(always)]\n    pub(crate) fn reset_delta(&self) {\n        self.ops.lock().clear();\n    }\n\n    /// TODO: This could be faster by just returning the cookies directly via\n    /// an ordered hash-set of sorts.\n    pub(crate) fn take_delta_jar(&self) -> cookie::CookieJar {\n        let ops = std::mem::take(&mut *self.ops.lock());\n        let mut jar = cookie::CookieJar::new();\n\n        for op in ops {\n            match op {\n                Op::Add(c, false) => jar.add(c),\n                #[cfg(feature = \"secrets\")]\n                Op::Add(c, true) => {\n                    jar.private_mut(&self.state.config.secret_key.key).add(c);\n                }\n                Op::Remove(mut c) => {\n                    if self.jar.get(c.name()).is_some() {\n                        c.make_removal();\n                        jar.add(c);\n                    } else {\n                        jar.remove(c);\n                    }\n                }\n                #[allow(unreachable_patterns)]\n                _ => unreachable!()\n            }\n        }\n\n        jar\n    }\n\n    /// Adds an original `cookie` to this collection.\n    #[inline(always)]\n    pub(crate) fn add_original(&mut self, cookie: Cookie<'static>) {\n        self.jar.add_original(cookie)\n    }\n\n    /// Adds an original, private `cookie` to the collection.\n    #[cfg(feature = \"secrets\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\n    #[inline(always)]\n    pub(crate) fn add_original_private(&mut self, cookie: Cookie<'static>) {\n        self.jar.private_mut(&self.state.config.secret_key.key).add_original(cookie);\n    }\n\n    /// For each property mentioned below, this method checks if there is a\n    /// provided value and if there is none, sets a default value. Default\n    /// values are:\n    ///\n    ///    * `path`: `\"/\"`\n    ///    * `SameSite`: `Strict`\n    ///    * `Secure`: `true` if `Request::context_is_likely_secure()`\n    fn set_defaults(&self, cookie: &mut Cookie<'static>) {\n        if cookie.path().is_none() {\n            cookie.set_path(\"/\");\n        }\n\n        if cookie.same_site().is_none() {\n            cookie.set_same_site(SameSite::Strict);\n        }\n\n        if cookie.secure().is_none() && self.state.secure {\n            cookie.set_secure(true);\n        }\n    }\n\n    /// For each property below, this method checks if there is a provided value\n    /// and if there is none, sets a default value. Default values are:\n    ///\n    ///    * `path`: `\"/\"`\n    ///    * `SameSite`: `Lax`\n    fn set_removal_defaults(cookie: &mut Cookie<'static>) {\n        if cookie.path().is_none() {\n            cookie.set_path(\"/\");\n        }\n\n        if cookie.same_site().is_none() {\n            cookie.set_same_site(SameSite::Lax);\n        }\n    }\n\n    /// For each property mentioned below, this method checks if there is a\n    /// provided value and if there is none, sets a default value. Default\n    /// values are:\n    ///\n    ///    * `path`: `\"/\"`\n    ///    * `SameSite`: `Strict`\n    ///    * `HttpOnly`: `true`\n    ///    * `Expires`: 1 week from now\n    ///    * `Secure`: `true` if `Request::context_is_likely_secure()`\n    #[cfg(feature = \"secrets\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\n    fn set_private_defaults(&self, cookie: &mut Cookie<'static>) {\n        self.set_defaults(cookie);\n\n        if cookie.http_only().is_none() {\n            cookie.set_http_only(true);\n        }\n\n        if cookie.expires().is_none() {\n            cookie.set_expires(time::OffsetDateTime::now_utc() + time::Duration::weeks(1));\n        }\n    }\n}\n\nimpl fmt::Debug for CookieJar<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let pending: Vec<_> = self.ops.lock()\n            .iter()\n            .map(|c| c.cookie())\n            .cloned()\n            .collect();\n\n        f.debug_struct(\"CookieJar\")\n            .field(\"original\", &self.jar)\n            .field(\"pending\", &pending)\n            .finish()\n    }\n}\n\nimpl<'a> Clone for CookieJar<'a> {\n    fn clone(&self) -> Self {\n        CookieJar {\n            jar: self.jar.clone(),\n            ops: Mutex::new(self.ops.lock().clone()),\n            state: self.state,\n        }\n    }\n}\n\nimpl Op {\n    fn cookie(&self) -> &Cookie<'static> {\n        match self {\n            Op::Add(c, _) | Op::Remove(c) => c\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/http/mod.rs",
    "content": "//! Types that map to concepts in HTTP.\n//!\n//! This module exports types that map to HTTP concepts or to the underlying\n//! HTTP library when needed.\n\nmod cookies;\n\n#[doc(inline)]\npub use rocket_http::*;\n\n#[doc(inline)]\npub use cookies::*;\n"
  },
  {
    "path": "core/lib/src/lib.rs",
    "content": "#![recursion_limit=\"256\"]\n\n#![doc(html_root_url = \"https://api.rocket.rs/master\")]\n#![doc(html_favicon_url = \"https://rocket.rs/images/favicon.ico\")]\n#![doc(html_logo_url = \"https://rocket.rs/images/logo-boxed.png\")]\n#![cfg_attr(nightly, feature(doc_cfg))]\n#![cfg_attr(nightly, feature(decl_macro))]\n\n//! # Rocket - Core API Documentation\n//!\n//! Hello, and welcome to the core Rocket API documentation!\n//!\n//! This API documentation is highly technical and is purely a reference.\n//! There's an [overview] of Rocket on the main site as well as a [full,\n//! detailed guide]. If you'd like pointers on getting started, see the\n//! [quickstart] or [getting started] chapters of the guide.\n//!\n//! [overview]: https://rocket.rs/master/overview\n//! [full, detailed guide]: https://rocket.rs/master/guide\n//! [quickstart]: https://rocket.rs/master/guide/quickstart\n//! [getting started]: https://rocket.rs/master/guide/getting-started\n//!\n//! ## Usage\n//!\n//! Depend on `rocket` in `Cargo.toml`:\n//!\n//! ```toml\n//! [dependencies]\n//! rocket = \"0.6.0-dev\"\n//! ```\n//!\n//! <small>Note that development versions, tagged with `-dev`, are not published\n//! and need to be specified as [git dependencies].</small>\n//!\n//! See the [guide](https://rocket.rs/master/guide) for more information on how\n//! to write Rocket applications. Here's a simple example to get you started:\n//!\n//! [git dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories\n//!\n//! ```rust,no_run\n//! #[macro_use] extern crate rocket;\n//!\n//! #[get(\"/\")]\n//! fn hello() -> &'static str {\n//!     \"Hello, world!\"\n//! }\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//!     rocket::build().mount(\"/\", routes![hello])\n//! }\n//! ```\n//!\n//! ## Features\n//!\n//! To avoid compiling unused dependencies, Rocket feature-gates optional\n//! functionality, some enabled by default:\n//!\n//! | Feature         | Default? | Description                                             |\n//! |-----------------|----------|---------------------------------------------------------|\n//! | `trace`         | Yes      | Enables the default Rocket tracing [subscriber].        |\n//! | `http2`         | Yes      | Support for HTTP/2 (enabled by default).                |\n//! | `secrets`       | No       | Support for authenticated, encrypted [private cookies]. |\n//! | `tls`           | No       | Support for [TLS] encrypted connections.                |\n//! | `mtls`          | No       | Support for verified clients via [mutual TLS].          |\n//! | `json`          | No       | Support for [JSON (de)serialization].                   |\n//! | `msgpack`       | No       | Support for [MessagePack (de)serialization].            |\n//! | `uuid`          | No       | Support for [UUID value parsing and (de)serialization]. |\n//! | `tokio-macros`  | No       | Enables the `macros` feature in the exported `tokio`    |\n//! | `http3-preview` | No       | Experimental preview support for [HTTP/3].              |\n//!\n//! Disabled features can be selectively enabled in `Cargo.toml`:\n//!\n//! ```toml\n//! [dependencies]\n//! rocket = { version = \"0.6.0-dev\", features = [\"secrets\", \"tls\", \"json\"] }\n//! ```\n//!\n//! Conversely, HTTP/2 can be disabled:\n//!\n//! ```toml\n//! [dependencies]\n//! rocket = { version = \"0.6.0-dev\", default-features = false }\n//! ```\n//!\n//! [subscriber]: crate::trace::subscriber\n//! [JSON (de)serialization]: crate::serde::json\n//! [MessagePack (de)serialization]: crate::serde::msgpack\n//! [UUID value parsing and (de)serialization]: crate::serde::uuid\n//! [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies\n//! [TLS]: https://rocket.rs/master/guide/configuration/#tls\n//! [mutual TLS]: crate::mtls\n//! [HTTP/3]: crate::listener::quic\n//!\n//! ## Configuration\n//!\n//! Rocket offers a rich, extensible configuration system built on [Figment]. By\n//! default, Rocket applications are configured via a `Rocket.toml` file\n//! and/or `ROCKET_{PARAM}` environment variables, but applications may\n//! configure their own sources. See the [configuration guide] for full details.\n//!\n//! ## Testing\n//!\n//! The [`local`] module contains structures that facilitate unit and\n//! integration testing of a Rocket application. The top-level [`local`] module\n//! documentation and the [testing guide] include detailed examples.\n//!\n//! [configuration guide]: https://rocket.rs/master/guide/configuration/\n//! [testing guide]: https://rocket.rs/master/guide/testing/#testing\n//! [Figment]: https://docs.rs/figment\n\n// Allows using Rocket's codegen in Rocket itself.\nextern crate self as rocket;\n\n/// These are public dependencies! Update docs if these are changed, especially\n/// figment's version number in docs.\n#[doc(hidden)]\npub use yansi;\n#[doc(hidden)]\npub use async_stream;\npub use futures;\npub use tokio;\npub use figment;\npub use time;\npub use tracing;\npub use either;\n\n#[macro_use]\npub mod trace;\n#[macro_use]\npub mod outcome;\n#[macro_use]\npub mod data;\n#[doc(hidden)]\npub mod sentinel;\npub mod local;\npub mod request;\npub mod response;\npub mod config;\npub mod form;\npub mod fairing;\npub mod error;\npub mod catcher;\npub mod route;\npub mod serde;\npub mod shield;\npub mod fs;\npub mod http;\npub mod listener;\npub mod shutdown;\n#[cfg(feature = \"tls\")]\n#[cfg_attr(nightly, doc(cfg(feature = \"tls\")))]\npub mod tls;\n#[cfg(feature = \"mtls\")]\n#[cfg_attr(nightly, doc(cfg(feature = \"mtls\")))]\npub mod mtls;\n\n#[path = \"rocket.rs\"]\nmod rkt;\nmod util;\nmod server;\nmod lifecycle;\nmod state;\nmod router;\nmod phase;\nmod erased;\n\n#[doc(inline)] pub use rocket_codegen::*;\n\n#[doc(inline)] pub use crate::response::Response;\n#[doc(inline)] pub use crate::data::Data;\n#[doc(inline)] pub use crate::config::Config;\n#[doc(inline)] pub use crate::catcher::Catcher;\n#[doc(inline)] pub use crate::route::Route;\n#[doc(inline)] pub use crate::phase::{Phase, Build, Ignite, Orbit};\n#[doc(inline)] pub use crate::error::Error;\n#[doc(inline)] pub use crate::sentinel::{Sentinel, Sentry};\n#[doc(inline)] pub use crate::request::Request;\n#[doc(inline)] pub use crate::rkt::Rocket;\n#[doc(inline)] pub use crate::shutdown::Shutdown;\n#[doc(inline)] pub use crate::state::State;\n\n/// Retrofits support for `async fn` in trait impls and declarations.\n///\n/// Any trait declaration or trait `impl` decorated with `#[async_trait]` is\n/// retrofitted with support for `async fn`s:\n///\n/// ```rust\n/// # use rocket::*;\n/// #[async_trait]\n/// trait MyAsyncTrait {\n///     async fn do_async_work();\n/// }\n///\n/// #[async_trait]\n/// impl MyAsyncTrait for () {\n///     async fn do_async_work() { /* .. */ }\n/// }\n/// ```\n///\n/// All `impl`s for a trait declared with `#[async_trait]` must themselves be\n/// decorated with `#[async_trait]`. Many of Rocket's traits, such as\n/// [`FromRequest`](crate::request::FromRequest) and\n/// [`Fairing`](crate::fairing::Fairing) are `async`. As such, implementations\n/// of said traits must be decorated with `#[async_trait]`. See the individual\n/// trait docs for trait-specific details.\n///\n/// For more details on `#[async_trait]`, see [`async_trait`](mod@async_trait).\n#[doc(inline)]\npub use async_trait::async_trait;\n\nconst WORKER_PREFIX: &str = \"rocket-worker\";\n\n/// Creates a [`Rocket`] instance with the default config provider: aliases\n/// [`Rocket::build()`].\npub fn build() -> Rocket<Build> {\n    Rocket::build()\n}\n\n/// Creates a [`Rocket`] instance with a custom config provider: aliases\n/// [`Rocket::custom()`].\npub fn custom<T: figment::Provider>(provider: T) -> Rocket<Build> {\n    Rocket::custom(provider)\n}\n\n/// WARNING: This is unstable! Do not use this method outside of Rocket!\n#[doc(hidden)]\npub fn async_run<F, R>(fut: F, workers: usize, sync: usize, force_end: bool, name: &str) -> R\n    where F: std::future::Future<Output = R>\n{\n    let runtime = tokio::runtime::Builder::new_multi_thread()\n        .thread_name(name)\n        .worker_threads(workers)\n        .max_blocking_threads(sync)\n        .enable_all()\n        .build()\n        .expect(\"create tokio runtime\");\n\n    let result = runtime.block_on(fut);\n    if force_end {\n        runtime.shutdown_timeout(std::time::Duration::from_millis(500));\n    }\n\n    result\n}\n\n/// WARNING: This is unstable! Do not use this method outside of Rocket!\n#[doc(hidden)]\npub fn async_test<R>(fut: impl std::future::Future<Output = R>) -> R {\n    async_run(fut, 1, 32, true, &format!(\"{WORKER_PREFIX}-test-thread\"))\n}\n\n/// WARNING: This is unstable! Do not use this method outside of Rocket!\n#[doc(hidden)]\npub fn async_main<R>(fut: impl std::future::Future<Output = R> + Send) -> R {\n    fn bail<T, E: crate::trace::Trace>(e: E) -> T {\n        e.trace_error();\n        panic!(\"aborting due to error\")\n    }\n\n    // FIXME: We need to run `fut` to get the user's `Figment` to properly set\n    // up the async env, but we need the async env to run `fut`. So we're stuck.\n    // Tokio doesn't let us take the state from one async env and migrate it to\n    // another, so we need to use one, making this impossible.\n    //\n    // So as a result, we only use values from Rocket's figment. These\n    // values won't reflect swaps of `Rocket` in attach fairings with different\n    // config values, or values from non-Rocket configs. See tokio-rs/tokio#3329\n    // for a necessary resolution in `tokio`.\n    let fig = Config::figment();\n    let workers = fig.extract_inner(Config::WORKERS).unwrap_or_else(bail);\n    let max_blocking = fig.extract_inner(Config::MAX_BLOCKING).unwrap_or_else(bail);\n    let force = fig.focus(Config::SHUTDOWN).extract_inner(\"force\").unwrap_or_else(bail);\n    async_run(fut, workers, max_blocking, force, &format!(\"{WORKER_PREFIX}-thread\"))\n}\n\n/// Executes a `future` to completion on a new tokio-based Rocket async runtime.\n///\n/// The runtime is terminated on shutdown, and the future's resolved value is\n/// returned.\n///\n/// # Considerations\n///\n/// This function is a low-level mechanism intended to be used to execute the\n/// future returned by [`Rocket::launch()`] in a self-contained async runtime\n/// designed for Rocket. It runs futures in exactly the same manner as\n/// [`#[launch]`](crate::launch) and [`#[main]`](crate::main) do and is thus\n/// _never_ the preferred mechanism for running a Rocket application. _Always_\n/// prefer to use the [`#[launch]`](crate::launch) or [`#[main]`](crate::main)\n/// attributes. For example [`#[main]`](crate::main) can be used even when\n/// Rocket is just a small part of a bigger application:\n///\n/// ```rust,no_run\n/// #[rocket::main]\n/// async fn main() {\n///     # let should_start_server_in_foreground = false;\n///     # let should_start_server_in_background = false;\n///     let rocket = rocket::build();\n///     if should_start_server_in_foreground {\n///         rocket::build().launch().await;\n///     } else if should_start_server_in_background {\n///         rocket::tokio::spawn(rocket.launch());\n///     } else {\n///         // do something else\n///     }\n/// }\n/// ```\n///\n/// See [Rocket#launching] for more on using these attributes.\n///\n/// # Example\n///\n/// Build an instance of Rocket, launch it, and wait for shutdown:\n///\n/// ```rust,no_run\n/// use rocket::fairing::AdHoc;\n///\n/// let rocket = rocket::build()\n///     .attach(AdHoc::on_liftoff(\"Liftoff Printer\", |_| Box::pin(async move {\n///         println!(\"Stalling liftoff for a second...\");\n///         rocket::tokio::time::sleep(std::time::Duration::from_secs(1)).await;\n///         println!(\"And we're off!\");\n///     })));\n///\n/// rocket::execute(rocket.launch());\n/// ```\n///\n/// Launch a pre-built instance of Rocket and wait for it to shutdown:\n///\n/// ```rust,no_run\n/// use rocket::{Rocket, Ignite, Phase, Error};\n///\n/// fn launch<P: Phase>(rocket: Rocket<P>) -> Result<Rocket<Ignite>, Error> {\n///     rocket::execute(rocket.launch())\n/// }\n/// ```\n///\n/// Do async work to build an instance of Rocket, launch, and wait for shutdown:\n///\n/// ```rust,no_run\n/// use rocket::fairing::AdHoc;\n///\n/// // This line can also be inside of the `async` block.\n/// let rocket = rocket::build();\n///\n/// rocket::execute(async move {\n///     let rocket = rocket.ignite().await?;\n///     let config = rocket.config();\n///     rocket.launch().await\n/// });\n/// ```\npub fn execute<R, F>(future: F) -> R\n    where F: std::future::Future<Output = R> + Send\n{\n    async_main(future)\n}\n\n/// Returns a future that evaluates to `true` exactly when there is a presently\n/// running tokio async runtime that was likely started by Rocket.\nfn running_within_rocket_async_rt() -> impl std::future::Future<Output = bool> {\n    use futures::FutureExt;\n\n    tokio::task::spawn_blocking(|| {\n        let this = std::thread::current();\n        this.name().map_or(false, |s| s.starts_with(WORKER_PREFIX))\n    }).map(|r| r.unwrap_or(false))\n}\n"
  },
  {
    "path": "core/lib/src/lifecycle.rs",
    "content": "use futures::future::{FutureExt, Future};\n\nuse crate::trace::Trace;\nuse crate::util::Formatter;\nuse crate::data::IoHandler;\nuse crate::http::{Method, Status, Header};\nuse crate::outcome::Outcome;\nuse crate::form::Form;\nuse crate::{route, catcher, Rocket, Orbit, Request, Response, Data};\n\n// A token returned to force the execution of one method before another.\npub(crate) struct RequestToken;\n\nasync fn catch_handle<Fut, T, F>(name: Option<&str>, run: F) -> Option<T>\n    where F: FnOnce() -> Fut, Fut: Future<Output = T>,\n{\n    macro_rules! panic_info {\n        ($name:expr, $e:expr) => {{\n            error!(handler = name.as_ref().map(display),\n                \"handler panicked\\n\\\n                This is an application bug.\\n\\\n                A panic in Rust must be treated as an exceptional event.\\n\\\n                Panicking is not a suitable error handling mechanism.\\n\\\n                Unwinding, the result of a panic, is an expensive operation.\\n\\\n                Panics will degrade application performance.\\n\\\n                Instead of panicking, return `Option` and/or `Result`.\\n\\\n                Values of either type can be returned directly from handlers.\\n\\\n                A panic is treated as an internal server error.\");\n\n            $e\n        }}\n    }\n\n    let run = std::panic::AssertUnwindSafe(run);\n    let fut = std::panic::catch_unwind(run)\n        .map_err(|e| panic_info!(name, e))\n        .ok()?;\n\n    std::panic::AssertUnwindSafe(fut)\n        .catch_unwind()\n        .await\n        .map_err(|e| panic_info!(name, e))\n        .ok()\n}\n\nimpl Rocket<Orbit> {\n    /// Preprocess the request for Rocket things. Currently, this means:\n    ///\n    ///   * Rewriting the method in the request if _method form field exists.\n    ///   * Run the request fairings.\n    ///\n    /// This is the only place during lifecycle processing that `Request` is\n    /// mutable. Keep this in-sync with the `FromForm` derive.\n    pub(crate) async fn preprocess(\n        &self,\n        req: &mut Request<'_>,\n        data: &mut Data<'_>\n    ) -> RequestToken {\n        // Check if this is a form and if the form contains the special _method\n        // field which we use to reinterpret the request's method.\n        if req.method() == Method::Post && req.content_type().map_or(false, |v| v.is_form()) {\n            let peek_buffer = data.peek(32).await;\n            let method = std::str::from_utf8(peek_buffer).ok()\n                .and_then(|raw_form| Form::values(raw_form).next())\n                .filter(|field| field.name == \"_method\")\n                .and_then(|field| field.value.parse().ok());\n\n            if let Some(method) = method {\n                req.set_method(method);\n            }\n        }\n\n        // Run request fairings.\n        self.fairings.handle_request(req, data).await;\n\n        RequestToken\n    }\n\n    /// Dispatches the request to the router and processes the outcome to\n    /// produce a response. If the initial outcome is a *forward* and the\n    /// request was a HEAD request, the request is rewritten and rerouted as a\n    /// GET. This is automatic HEAD handling.\n    ///\n    /// After performing the above, if the outcome is a forward or error, the\n    /// appropriate error catcher is invoked to produce the response. Otherwise,\n    /// the successful response is used directly.\n    ///\n    /// Finally, new cookies in the cookie jar are added to the response,\n    /// Rocket-specific headers are written, and response fairings are run. Note\n    /// that error responses have special cookie handling. See `handle_error`.\n    pub(crate) async fn dispatch<'r, 's: 'r>(\n        &'s self,\n        _token: RequestToken,\n        request: &'r Request<'s>,\n        data: Data<'r>,\n        // io_stream: impl Future<Output = io::Result<IoStream>> + Send,\n    ) -> Response<'r> {\n        // Remember if the request is `HEAD` for later body stripping.\n        let was_head_request = request.method() == Method::Head;\n\n        // Route the request and run the user's handlers.\n        let mut response = match self.route(request, data).await {\n            Outcome::Success(response) => response,\n            Outcome::Forward((data, _)) if request.method() == Method::Head => {\n                tracing::Span::current().record(\"autohandled\", true);\n\n                // Dispatch the request again with Method `GET`.\n                request._set_method(Method::Get);\n                match self.route(request, data).await {\n                    Outcome::Success(response) => response,\n                    Outcome::Error(status) => self.dispatch_error(status, request).await,\n                    Outcome::Forward((_, status)) => self.dispatch_error(status, request).await,\n                }\n            }\n            Outcome::Forward((_, status)) => self.dispatch_error(status, request).await,\n            Outcome::Error(status) => self.dispatch_error(status, request).await,\n        };\n\n        // Set the cookies. Note that error responses will only include cookies\n        // set by the error handler. See `handle_error` for more.\n        let delta_jar = request.cookies().take_delta_jar();\n        for cookie in delta_jar.delta() {\n            response.adjoin_header(cookie);\n        }\n\n        // Add a default 'Server' header if it isn't already there.\n        // TODO: If removing Hyper, write out `Date` header too.\n        if let Some(ident) = request.rocket().config.ident.as_str() {\n            if !response.headers().contains(\"Server\") {\n                response.set_header(Header::new(\"Server\", ident));\n            }\n        }\n\n        // Run the response fairings.\n        self.fairings.handle_response(request, &mut response).await;\n\n        // Strip the body if this is a `HEAD` request or a 304 response.\n        if was_head_request || response.status() == Status::NotModified {\n            response.strip_body();\n        }\n\n        // If the response status is 204, strip the body and its size (no\n        // content-length header). Otherwise, check if the body is sized and use\n        // that size to set the content-length headr appropriately.\n        if response.status() == Status::NoContent {\n            *response.body_mut() = crate::response::Body::unsized_none();\n        } else if let Some(size) = response.body_mut().size().await {\n            response.set_raw_header(\"Content-Length\", size.to_string());\n        }\n\n        if let Some(alt_svc) = request.rocket().alt_svc() {\n            response.set_raw_header(\"Alt-Svc\", alt_svc);\n        }\n\n        // TODO: Should upgrades be handled here? We miss them on local clients.\n        response\n    }\n\n    pub(crate) fn extract_io_handler<'r>(\n        request: &'r Request<'_>,\n        response: &mut Response<'r>,\n        // io_stream: impl Future<Output = io::Result<IoStream>> + Send,\n    ) -> Option<(String, Box<dyn IoHandler + 'r>)> {\n        let upgrades = request.headers().get(\"upgrade\");\n        let Ok(upgrade) = response.search_upgrades(upgrades) else {\n            info!(\n                upgrades = %Formatter(|f| f.debug_list()\n                    .entries(request.headers().get(\"upgrade\"))\n                    .finish()),\n                \"request wants upgrade but no i/o handler matched\\n\\\n                refusing to upgrade request\"\n            );\n\n            return None;\n        };\n\n        if let Some((proto, io_handler)) = upgrade {\n            let proto = proto.to_string();\n            response.set_status(Status::SwitchingProtocols);\n            response.set_raw_header(\"Connection\", \"Upgrade\");\n            response.set_raw_header(\"Upgrade\", proto.clone());\n            return Some((proto, io_handler));\n        }\n\n        None\n    }\n\n    /// Calls the handler for each matching route until one of the handlers\n    /// returns success or error, or there are no additional routes to try, in\n    /// which case a `Forward` with the last forwarding state is returned.\n    #[inline]\n    #[tracing::instrument(\"routing\", skip_all, fields(\n        method = %request.method(),\n        uri = %request.uri(),\n        format = request.format().map(display),\n    ))]\n    async fn route<'s, 'r: 's>(\n        &'s self,\n        request: &'r Request<'s>,\n        mut data: Data<'r>,\n    ) -> route::Outcome<'r> {\n        // Go through all matching routes until we fail or succeed or run out of\n        // routes to try, in which case we forward with the last status.\n        let mut status = Status::NotFound;\n        for route in self.router.route(request) {\n            // Retrieve and set the requests parameters.\n            route.trace_info();\n            request.set_route(route);\n\n            let name = route.name.as_deref();\n            let outcome = catch_handle(name, || route.handler.handle(request, data)).await\n                .unwrap_or(Outcome::Error(Status::InternalServerError));\n\n            // Check if the request processing completed (Some) or if the\n            // request needs to be forwarded. If it does, continue the loop\n            outcome.trace_info();\n            match outcome {\n                o@Outcome::Success(_) | o@Outcome::Error(_) => return o,\n                Outcome::Forward(forwarded) => (data, status) = forwarded,\n            }\n        }\n\n        Outcome::Forward((data, status))\n    }\n\n    // Invokes the catcher for `status`. Returns the response on success.\n    //\n    // Resets the cookie jar delta state to prevent any modifications from\n    // earlier unsuccessful paths from being reflected in the error response.\n    //\n    // On catcher error, the 500 error catcher is attempted. If _that_ errors,\n    // the (infallible) default 500 error cather is used.\n    #[tracing::instrument(\"catching\", skip_all, fields(status = status.code, uri = %req.uri()))]\n    pub(crate) async fn dispatch_error<'r, 's: 'r>(\n        &'s self,\n        mut status: Status,\n        req: &'r Request<'s>\n    ) -> Response<'r> {\n        // We may wish to relax this in the future.\n        req.cookies().reset_delta();\n\n        loop {\n            // Dispatch to the `status` catcher.\n            match self.invoke_catcher(status, req).await {\n                Ok(r) => return r,\n                // If the catcher failed, try `500` catcher, unless this is it.\n                Err(e) if status.code != 500 => {\n                    warn!(status = e.map(|r| r.code), \"catcher failed: trying 500 catcher\");\n                    status = Status::InternalServerError;\n                }\n                // The 500 catcher failed. There's no recourse. Use default.\n                Err(e) => {\n                    error!(status = e.map(|r| r.code), \"500 catcher failed\");\n                    return catcher::default_handler(Status::InternalServerError, req);\n                }\n            }\n        }\n    }\n\n    /// Invokes the handler with `req` for catcher with status `status`.\n    ///\n    /// In order of preference, invoked handler is:\n    ///   * the user's registered handler for `status`\n    ///   * the user's registered `default` handler\n    ///   * Rocket's default handler for `status`\n    ///\n    /// Return `Ok(result)` if the handler succeeded. Returns `Ok(Some(Status))`\n    /// if the handler ran to completion but failed. Returns `Ok(None)` if the\n    /// handler panicked while executing.\n    async fn invoke_catcher<'s, 'r: 's>(\n        &'s self,\n        status: Status,\n        req: &'r Request<'s>\n    ) -> Result<Response<'r>, Option<Status>> {\n        if let Some(catcher) = self.router.catch(status, req) {\n            catcher.trace_info();\n            catch_handle(catcher.name.as_deref(), || catcher.handler.handle(status, req)).await\n                .map(|result| result.map_err(Some))\n                .unwrap_or_else(|| Err(None))\n        } else {\n            info!(name: \"catcher\", name = \"rocket::default\", \"uri.base\" = \"/\", code = status.code,\n                \"no registered catcher: using Rocket default\");\n            Ok(catcher::default_handler(status, req))\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/bind.rs",
    "content": "use std::error::Error;\n\nuse crate::listener::{Endpoint, Listener};\nuse crate::{Rocket, Ignite};\n\npub trait Bind: Listener + 'static {\n    type Error: Error + Send + 'static;\n\n    #[crate::async_bound(Send)]\n    async fn bind(rocket: &Rocket<Ignite>) -> Result<Self, Self::Error>;\n\n    fn bind_endpoint(to: &Rocket<Ignite>) -> Result<Endpoint, Self::Error>;\n}\n"
  },
  {
    "path": "core/lib/src/listener/bounced.rs",
    "content": "use std::{io, time::Duration};\n\nuse crate::listener::{Listener, Endpoint};\n\nstatic DURATION: Duration = Duration::from_millis(250);\n\npub struct Bounced<L> {\n    listener: L,\n}\n\npub trait BouncedExt: Sized {\n    fn bounced(self) -> Bounced<Self> {\n        Bounced { listener: self }\n    }\n}\n\nimpl<L> BouncedExt for L { }\n\nfn is_recoverable(e: &io::Error) -> bool {\n    matches!(e.kind(),\n        | io::ErrorKind::ConnectionRefused\n        | io::ErrorKind::ConnectionAborted\n        | io::ErrorKind::ConnectionReset)\n}\n\nimpl<L: Listener + Sync> Bounced<L> {\n    #[inline]\n    pub async fn accept_next(&self) -> <Self as Listener>::Accept {\n        loop {\n            match self.listener.accept().await {\n                Ok(accept) => return accept,\n                Err(e) if is_recoverable(&e) => warn!(\"recoverable connection error: {e}\"),\n                Err(e) => {\n                    warn!(\"accept error: {e} [retrying in {}ms]\", DURATION.as_millis());\n                    tokio::time::sleep(DURATION).await;\n                }\n            };\n        }\n    }\n}\n\nimpl<L: Listener + Sync> Listener for Bounced<L> {\n    type Accept = L::Accept;\n\n    type Connection = L::Connection;\n\n    async fn accept(&self) -> io::Result<Self::Accept> {\n        Ok(self.accept_next().await)\n    }\n\n    async fn connect(&self, accept: Self::Accept) -> io::Result<Self::Connection> {\n        self.listener.connect(accept).await\n    }\n\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        self.listener.endpoint()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/cancellable.rs",
    "content": "use std::io;\nuse std::task::{Poll, Context};\nuse std::pin::Pin;\n\nuse futures::Stream;\nuse tokio::io::{AsyncRead, AsyncWrite, ReadBuf};\nuse futures::future::FutureExt;\nuse pin_project_lite::pin_project;\n\nuse crate::shutdown::Stages;\n\npin_project! {\n    /// I/O that can be cancelled when a future `F` resolves.\n    #[must_use = \"futures do nothing unless polled\"]\n    pub struct Cancellable<I> {\n        #[pin]\n        io: Option<I>,\n        stages: Stages,\n        state: State,\n    }\n}\n\n#[derive(Debug)]\nenum State {\n    /// I/O has not been cancelled. Proceed as normal until `Shutdown`.\n    Active,\n    /// I/O has been cancelled. Try to finish before `Shutdown`.\n    Grace,\n    /// Grace has elapsed. Shutdown connections. After `Shutdown`, force close.\n    Mercy,\n}\n\npub trait CancellableExt: Sized {\n    fn cancellable(self, stages: Stages) -> Cancellable<Self> {\n        Cancellable {\n            io: Some(self),\n            state: State::Active,\n            stages,\n        }\n    }\n}\n\nimpl<T> CancellableExt for T { }\n\nfn time_out() -> io::Error {\n    io::Error::new(io::ErrorKind::TimedOut, \"shutdown grace period elapsed\")\n}\n\nfn gone() -> io::Error {\n    io::Error::new(io::ErrorKind::BrokenPipe, \"I/O driver terminated\")\n}\n\nimpl<I: AsyncCancel> Cancellable<I> {\n    pub fn inner(&self) -> Option<&I> {\n        self.io.as_ref()\n    }\n}\n\npub trait AsyncCancel {\n    fn poll_cancel(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>;\n}\n\nimpl<T: AsyncWrite> AsyncCancel for T {\n    fn poll_cancel(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {\n        <T as AsyncWrite>::poll_shutdown(self, cx)\n    }\n}\n\nimpl<I: AsyncCancel> Cancellable<I> {\n    /// Run `do_io` while connection processing should continue.\n    pub fn poll_with<T>(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        do_io: impl FnOnce(Pin<&mut I>, &mut Context<'_>) -> Poll<io::Result<T>>,\n    ) -> Poll<io::Result<T>> {\n        let me = self.as_mut().project();\n        let io = match me.io.as_pin_mut() {\n            Some(io) => io,\n            None => return Poll::Ready(Err(gone())),\n        };\n\n        loop {\n            match me.state {\n                State::Active => {\n                    if me.stages.start.poll_unpin(cx).is_ready() {\n                        *me.state = State::Grace;\n                    } else {\n                        return do_io(io, cx);\n                    }\n                }\n                State::Grace => {\n                    if me.stages.grace.poll_unpin(cx).is_ready() {\n                        *me.state = State::Mercy;\n                    } else {\n                        return do_io(io, cx);\n                    }\n                }\n                State::Mercy => {\n                    if me.stages.mercy.poll_unpin(cx).is_ready() {\n                        self.project().io.set(None);\n                        return Poll::Ready(Err(time_out()));\n                    } else {\n                        let result = futures::ready!(io.poll_cancel(cx));\n                        self.project().io.set(None);\n                        return match result {\n                            Ok(()) => Poll::Ready(Err(gone())),\n                            Err(e) => Poll::Ready(Err(e)),\n                        };\n                    }\n                },\n            }\n        }\n    }\n}\n\nimpl<I: AsyncRead + AsyncCancel> AsyncRead for Cancellable<I> {\n    fn poll_read(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        self.poll_with(cx, |io, cx| io.poll_read(cx, buf))\n    }\n}\n\nimpl<I: AsyncWrite> AsyncWrite for Cancellable<I> {\n    fn poll_write(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &[u8],\n    ) -> Poll<io::Result<usize>> {\n        self.poll_with(cx, |io, cx| io.poll_write(cx, buf))\n    }\n\n    fn poll_flush(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>\n    ) -> Poll<io::Result<()>> {\n        self.poll_with(cx, |io, cx| io.poll_flush(cx))\n    }\n\n    fn poll_shutdown(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>\n    ) -> Poll<io::Result<()>> {\n        self.poll_with(cx, |io, cx| io.poll_shutdown(cx))\n    }\n\n    fn poll_write_vectored(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        bufs: &[io::IoSlice<'_>],\n    ) -> Poll<io::Result<usize>> {\n        self.poll_with(cx, |io, cx| io.poll_write_vectored(cx, bufs))\n    }\n\n    fn is_write_vectored(&self) -> bool {\n        self.inner().map(|io| io.is_write_vectored()).unwrap_or(false)\n    }\n}\n\nimpl<T, I: Stream<Item = io::Result<T>> + AsyncCancel> Stream for Cancellable<I> {\n    type Item = I::Item;\n\n    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {\n        use futures::ready;\n\n        match ready!(self.poll_with(cx, |io, cx| io.poll_next(cx).map(Ok))) {\n            Ok(Some(v)) => Poll::Ready(Some(v)),\n            Ok(None) => Poll::Ready(None),\n            Err(e) => Poll::Ready(Some(Err(e))),\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/connection.rs",
    "content": "use std::io;\nuse std::borrow::Cow;\n\nuse tokio::io::{AsyncRead, AsyncWrite};\nuse tokio_util::either::Either;\n\nuse super::Endpoint;\n\n/// A collection of raw certificate data.\n#[derive(Clone)]\npub struct Certificates<'r>(Cow<'r, [der::CertificateDer<'r>]>);\n\npub trait Connection: AsyncRead + AsyncWrite + Send + Unpin {\n    fn endpoint(&self) -> io::Result<Endpoint>;\n\n    /// DER-encoded X.509 certificate chain presented by the client, if any.\n    ///\n    /// The certificate order must be as it appears in the TLS protocol: the\n    /// first certificate relates to the peer, the second certifies the first,\n    /// the third certifies the second, and so on.\n    ///\n    /// Defaults to an empty vector to indicate that no certificates were\n    /// presented.\n    fn certificates(&self) -> Option<Certificates<'_>> { None }\n\n    fn server_name(&self) -> Option<&str> { None }\n}\n\nimpl<A: Connection, B: Connection> Connection for Either<A, B> {\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        match self {\n            Either::Left(c) => c.endpoint(),\n            Either::Right(c) => c.endpoint(),\n        }\n    }\n\n    fn certificates(&self) -> Option<Certificates<'_>> {\n        match self {\n            Either::Left(c) => c.certificates(),\n            Either::Right(c) => c.certificates(),\n        }\n    }\n}\n\nimpl Certificates<'_> {\n    pub fn into_owned(self) -> Certificates<'static> {\n        let cow = self.0.iter()\n            .map(|der| der.clone().into_owned())\n            .collect::<Vec<_>>()\n            .into();\n\n        Certificates(cow)\n    }\n}\n\n#[cfg(feature = \"mtls\")]\n#[cfg_attr(nightly, doc(cfg(feature = \"mtls\")))]\nmod der {\n    use super::*;\n\n    pub use crate::mtls::CertificateDer;\n\n    impl<'r> Certificates<'r> {\n        pub(crate) fn inner(&self) -> &[CertificateDer<'r>] {\n            &self.0\n        }\n    }\n\n    impl<'r> From<&'r [CertificateDer<'r>]> for Certificates<'r> {\n        fn from(value: &'r [CertificateDer<'r>]) -> Self {\n            Certificates(value.into())\n        }\n    }\n\n    impl From<Vec<CertificateDer<'static>>> for Certificates<'static> {\n        fn from(value: Vec<CertificateDer<'static>>) -> Self {\n            Certificates(value.into())\n        }\n    }\n}\n\n#[cfg(not(feature = \"mtls\"))]\nmod der {\n    use std::marker::PhantomData;\n\n    /// A thin wrapper over raw, DER-encoded X.509 client certificate data.\n    #[derive(Clone)]\n    pub struct CertificateDer<'r>(PhantomData<&'r [u8]>);\n\n    impl CertificateDer<'_> {\n        pub fn into_owned(self) -> CertificateDer<'static> {\n            CertificateDer(PhantomData)\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/default.rs",
    "content": "use core::fmt;\n\nuse serde::Deserialize;\nuse tokio_util::either::Either::{Left, Right};\nuse either::Either;\n\nuse crate::{Ignite, Rocket};\nuse crate::listener::{Bind, Endpoint, tcp::TcpListener};\n\n#[cfg(unix)] use crate::listener::unix::UnixListener;\n#[cfg(feature = \"tls\")] use crate::tls::{TlsListener, TlsConfig};\n\nmod private {\n    use super::*;\n    use tokio_util::either::Either;\n\n    #[cfg(feature = \"tls\")] type TlsListener<T> = super::TlsListener<T>;\n    #[cfg(not(feature = \"tls\"))] type TlsListener<T> = T;\n    #[cfg(unix)] type UnixListener = super::UnixListener;\n    #[cfg(not(unix))] type UnixListener = TcpListener;\n\n    pub type Listener = Either<\n        Either<TlsListener<TcpListener>, TlsListener<UnixListener>>,\n        Either<TcpListener, UnixListener>,\n    >;\n\n    /// The default connection listener.\n    ///\n    /// # Configuration\n    ///\n    /// Reads the following optional configuration parameters:\n    ///\n    /// | parameter   | type              | default               |\n    /// | ----------- | ----------------- | --------------------- |\n    /// | `address`   | [`Endpoint`]      | `tcp:127.0.0.1:8000`  |\n    /// | `tls`       | [`TlsConfig`]     | None                  |\n    /// | `reuse`     | boolean           | `true`                |\n    ///\n    /// # Listener\n    ///\n    /// Based on the above configuration, this listener defers to one of the\n    /// following existing listeners:\n    ///\n    /// | listener                      | `address` type     | `tls` enabled |\n    /// |-------------------------------|--------------------|---------------|\n    /// | [`TcpListener`]               | [`Endpoint::Tcp`]  | no            |\n    /// | [`UnixListener`]              | [`Endpoint::Unix`] | no            |\n    /// | [`TlsListener<TcpListener>`]  | [`Endpoint::Tcp`]  | yes           |\n    /// | [`TlsListener<UnixListener>`] | [`Endpoint::Unix`] | yes           |\n    ///\n    /// [`UnixListener`]: crate::listener::unix::UnixListener\n    /// [`TlsListener<TcpListener>`]: crate::tls::TlsListener\n    /// [`TlsListener<UnixListener>`]: crate::tls::TlsListener\n    ///\n    ///  * **address type** is the variant the `address` parameter parses as.\n    ///  * **`tls` enabled** is `yes` when the `tls` feature is enabled _and_ a\n    ///    `tls` configuration is provided.\n    #[cfg(doc)]\n    pub struct DefaultListener(());\n}\n\n#[derive(Deserialize)]\nstruct Config {\n    #[serde(default)]\n    address: Endpoint,\n    #[cfg(feature = \"tls\")]\n    tls: Option<TlsConfig>,\n}\n\n#[cfg(doc)]\npub use private::DefaultListener;\n\n#[cfg(doc)]\ntype Connection = crate::listener::tcp::TcpStream;\n\n#[cfg(doc)]\nimpl Bind for DefaultListener {\n    type Error = Error;\n    async fn bind(_: &Rocket<Ignite>) -> Result<Self, Error>  { unreachable!() }\n    fn bind_endpoint(_: &Rocket<Ignite>) -> Result<Endpoint, Error> { unreachable!() }\n}\n\n#[cfg(doc)]\nimpl super::Listener for DefaultListener {\n    #[doc(hidden)] type Accept = Connection;\n    #[doc(hidden)] type Connection = Connection;\n    #[doc(hidden)]\n    async fn accept(&self) -> std::io::Result<Connection>  { unreachable!() }\n    #[doc(hidden)]\n    async fn connect(&self, _: Self::Accept) -> std::io::Result<Connection>  { unreachable!() }\n    #[doc(hidden)]\n    fn endpoint(&self) -> std::io::Result<Endpoint> { unreachable!() }\n}\n\n#[cfg(not(doc))]\npub type DefaultListener = private::Listener;\n\n#[cfg(not(doc))]\nimpl Bind for DefaultListener {\n    type Error = Error;\n\n    async fn bind(rocket: &Rocket<Ignite>) -> Result<Self, Self::Error> {\n        let config: Config = rocket.figment().extract()?;\n        match config.address {\n            #[cfg(feature = \"tls\")]\n            Endpoint::Tcp(_) if config.tls.is_some() => {\n                let listener = <TlsListener<TcpListener> as Bind>::bind(rocket).await?;\n                Ok(Left(Left(listener)))\n            }\n            Endpoint::Tcp(_) => {\n                let listener = <TcpListener as Bind>::bind(rocket).await?;\n                Ok(Right(Left(listener)))\n            }\n            #[cfg(all(unix, feature = \"tls\"))]\n            Endpoint::Unix(_) if config.tls.is_some() => {\n                let listener = <TlsListener<UnixListener> as Bind>::bind(rocket).await?;\n                Ok(Left(Right(listener)))\n            }\n            #[cfg(unix)]\n            Endpoint::Unix(_) => {\n                let listener = <UnixListener as Bind>::bind(rocket).await?;\n                Ok(Right(Right(listener)))\n            }\n            endpoint => Err(Error::Unsupported(endpoint)),\n        }\n    }\n\n    fn bind_endpoint(rocket: &Rocket<Ignite>) -> Result<Endpoint, Self::Error> {\n        let config: Config = rocket.figment().extract()?;\n        Ok(config.address)\n    }\n}\n\n#[derive(Debug)]\npub enum Error {\n    Config(figment::Error),\n    Io(std::io::Error),\n    Unsupported(Endpoint),\n    #[cfg(feature = \"tls\")]\n    Tls(crate::tls::Error),\n}\n\nimpl From<figment::Error> for Error {\n    fn from(value: figment::Error) -> Self {\n        Error::Config(value)\n    }\n}\n\nimpl From<std::io::Error> for Error {\n    fn from(value: std::io::Error) -> Self {\n        Error::Io(value)\n    }\n}\n\n#[cfg(feature = \"tls\")]\nimpl From<crate::tls::Error> for Error {\n    fn from(value: crate::tls::Error) -> Self {\n        Error::Tls(value)\n    }\n}\n\nimpl From<Either<figment::Error, std::io::Error>> for Error {\n    fn from(value: Either<figment::Error, std::io::Error>) -> Self {\n        value.either(Error::Config, Error::Io)\n    }\n}\n\nimpl fmt::Display for Error {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Error::Config(e) => e.fmt(f),\n            Error::Io(e) => e.fmt(f),\n            Error::Unsupported(e) => write!(f, \"unsupported endpoint: {e:?}\"),\n            #[cfg(feature = \"tls\")]\n            Error::Tls(error) => error.fmt(f),\n        }\n    }\n}\n\nimpl std::error::Error for Error {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        match self {\n            Error::Config(e) => Some(e),\n            Error::Io(e) => Some(e),\n            Error::Unsupported(_) => None,\n            #[cfg(feature = \"tls\")]\n            Error::Tls(e) => Some(e),\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/endpoint.rs",
    "content": "use std::fmt;\nuse std::any::Any;\nuse std::net::{self, AddrParseError, IpAddr, Ipv4Addr};\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse std::sync::Arc;\n\nuse figment::Figment;\nuse serde::de;\n\nuse crate::http::uncased::AsUncased;\n\n#[cfg(feature = \"tls\")]      type TlsInfo = Option<Box<crate::tls::TlsConfig>>;\n#[cfg(not(feature = \"tls\"))] type TlsInfo = Option<()>;\n\npub trait CustomEndpoint: fmt::Display + fmt::Debug + Sync + Send + Any { }\n\nimpl<T: fmt::Display + fmt::Debug + Sync + Send + Any> CustomEndpoint for T {}\n\n/// # Conversions\n///\n/// * [`&str`] - parse with [`FromStr`]\n/// * [`tokio::net::unix::SocketAddr`] - must be path: [`Endpoint::Unix`]\n/// * [`PathBuf`] - infallibly as [`Endpoint::Unix`]\n///\n/// # Syntax\n///\n/// The string syntax is:\n///\n/// ```text\n/// endpoint = 'tcp' ':' socket | 'quic' ':' socket | 'unix' ':' path | socket\n/// socket := IP_ADDR | SOCKET_ADDR\n/// path := PATH\n///\n/// IP_ADDR := `std::net::IpAddr` string as defined by Rust\n/// SOCKET_ADDR := `std::net::SocketAddr` string as defined by Rust\n/// PATH := `PathBuf` (any UTF-8) string as defined by Rust\n/// ```\n///\n/// If `IP_ADDR` is specified in socket, port defaults to `8000`.\n#[derive(Clone)]\n#[non_exhaustive]\npub enum Endpoint {\n    Tcp(net::SocketAddr),\n    Quic(net::SocketAddr),\n    Unix(PathBuf),\n    Tls(Arc<Endpoint>, TlsInfo),\n    Custom(Arc<dyn CustomEndpoint>),\n}\n\nimpl Endpoint {\n    pub fn new<T: CustomEndpoint>(value: T) -> Endpoint {\n        Endpoint::Custom(Arc::new(value))\n    }\n\n    pub fn tcp(&self) -> Option<net::SocketAddr> {\n        match self {\n            Endpoint::Tcp(addr) => Some(*addr),\n            Endpoint::Tls(addr, _) => addr.tcp(),\n            _ => None,\n        }\n    }\n\n    pub fn quic(&self) -> Option<net::SocketAddr> {\n        match self {\n            Endpoint::Quic(addr) => Some(*addr),\n            Endpoint::Tls(addr, _) => addr.tcp(),\n            _ => None,\n        }\n    }\n\n    pub fn socket_addr(&self) -> Option<net::SocketAddr> {\n        match self {\n            Endpoint::Quic(addr) => Some(*addr),\n            Endpoint::Tcp(addr) => Some(*addr),\n            Endpoint::Tls(inner, _) => inner.socket_addr(),\n            _ => None,\n        }\n    }\n\n    pub fn ip(&self) -> Option<IpAddr> {\n        match self {\n            Endpoint::Quic(addr) => Some(addr.ip()),\n            Endpoint::Tcp(addr) => Some(addr.ip()),\n            Endpoint::Tls(inner, _) => inner.ip(),\n            _ => None,\n        }\n    }\n\n    pub fn port(&self) -> Option<u16> {\n        match self {\n            Endpoint::Quic(addr) => Some(addr.port()),\n            Endpoint::Tcp(addr) => Some(addr.port()),\n            Endpoint::Tls(inner, _) => inner.port(),\n            _ => None,\n        }\n    }\n\n    pub fn unix(&self) -> Option<&Path> {\n        match self {\n            Endpoint::Unix(addr) => Some(addr),\n            Endpoint::Tls(addr, _) => addr.unix(),\n            _ => None,\n        }\n    }\n\n    pub fn tls(&self) -> Option<&Endpoint> {\n        match self {\n            Endpoint::Tls(addr, _) => Some(addr),\n            _ => None,\n        }\n    }\n\n    #[cfg(feature = \"tls\")]\n    pub fn tls_config(&self) -> Option<&crate::tls::TlsConfig> {\n        match self {\n            Endpoint::Tls(_, Some(ref config)) => Some(config),\n            _ => None,\n        }\n    }\n\n    #[cfg(feature = \"mtls\")]\n    pub fn mtls_config(&self) -> Option<&crate::mtls::MtlsConfig> {\n        match self {\n            Endpoint::Tls(_, Some(config)) => config.mutual(),\n            _ => None,\n        }\n    }\n\n    pub fn downcast<T: 'static>(&self) -> Option<&T> {\n        match self {\n            Endpoint::Tcp(addr) => (addr as &dyn Any).downcast_ref(),\n            Endpoint::Quic(addr) => (addr as &dyn Any).downcast_ref(),\n            Endpoint::Unix(addr) => (addr as &dyn Any).downcast_ref(),\n            Endpoint::Custom(addr) => (addr as &dyn Any).downcast_ref(),\n            Endpoint::Tls(inner, ..) => inner.downcast(),\n        }\n    }\n\n    pub fn is_tcp(&self) -> bool {\n        self.tcp().is_some()\n    }\n\n    pub fn is_quic(&self) -> bool {\n        self.quic().is_some()\n    }\n\n    pub fn is_unix(&self) -> bool {\n        self.unix().is_some()\n    }\n\n    pub fn is_tls(&self) -> bool {\n        self.tls().is_some()\n    }\n\n    #[cfg(feature = \"tls\")]\n    pub fn with_tls(self, tls: &crate::tls::TlsConfig) -> Endpoint {\n        if self.is_tls() {\n            return self;\n        }\n\n        Self::Tls(Arc::new(self), Some(Box::new(tls.clone())))\n    }\n\n    pub fn assume_tls(self) -> Endpoint {\n        if self.is_tls() {\n            return self;\n        }\n\n        Self::Tls(Arc::new(self), None)\n    }\n\n    /// Fetch the endpoint at `path` in `figment` of kind `kind` (e.g, \"tcp\")\n    /// then map the value using `f(Some(value))` if present and `f(None)` if\n    /// missing into a different value of typr `T`.\n    ///\n    /// If the conversion succeeds, returns `Ok(value)`. If the conversion fails\n    /// and `Some` value was passed in, returns an error indicating the endpoint\n    /// was an invalid `kind` and otherwise returns a \"missing field\" error.\n    pub(crate) fn fetch<T, F>(figment: &Figment, kind: &str, path: &str, f: F) -> figment::Result<T>\n        where F: FnOnce(Option<&Endpoint>) -> Option<T>\n    {\n        match figment.extract_inner::<Endpoint>(path) {\n            Ok(endpoint) => f(Some(&endpoint)).ok_or_else(|| {\n                let msg = format!(\"invalid {kind} endpoint: {endpoint:?}\");\n                let mut error = figment::Error::from(msg).with_path(path);\n                error.profile = Some(figment.profile().clone());\n                error.metadata = figment.find_metadata(path).cloned();\n                error\n            }),\n            Err(e) if e.missing() => f(None).ok_or(e),\n            Err(e) => Err(e)\n        }\n    }\n}\n\nimpl fmt::Display for Endpoint {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        use Endpoint::*;\n\n        match self {\n            Tcp(addr) | Quic(addr) => write!(f, \"http://{addr}\"),\n            Unix(addr) => write!(f, \"unix:{}\", addr.display()),\n            Custom(inner) => inner.fmt(f),\n            Tls(inner, _c) => {\n                match (inner.tcp(), inner.quic()) {\n                    (Some(addr), _) => write!(f, \"https://{addr} (TCP\")?,\n                    (_, Some(addr)) => write!(f, \"https://{addr} (QUIC\")?,\n                    (None, None) => write!(f, \"{inner} (TLS\")?,\n                }\n\n                #[cfg(feature = \"mtls\")]\n                if _c.as_ref().and_then(|c| c.mutual()).is_some() {\n                    write!(f, \" + mTLS\")?;\n                }\n\n                write!(f, \")\")\n            }\n        }\n    }\n}\n\nimpl fmt::Debug for Endpoint {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Self::Tcp(a) => write!(f, \"tcp:{a}\"),\n            Self::Quic(a) => write!(f, \"quic:{a}]\"),\n            Self::Unix(a) => write!(f, \"unix:{}\", a.display()),\n            Self::Tls(e, _) => write!(f, \"unix:{:?}\", &**e),\n            Self::Custom(e) => e.fmt(f),\n        }\n    }\n}\n\nimpl Default for Endpoint {\n    fn default() -> Self {\n        Endpoint::Tcp(net::SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 8000))\n    }\n}\n\nimpl FromStr for Endpoint {\n    type Err = AddrParseError;\n\n    fn from_str(string: &str) -> Result<Self, Self::Err> {\n        fn parse_tcp(str: &str, def_port: u16) -> Result<net::SocketAddr, AddrParseError> {\n            str.parse().or_else(|_| str.parse().map(|ip| net::SocketAddr::new(ip, def_port)))\n        }\n\n        if let Some((proto, string)) = string.split_once(':') {\n            if proto.trim().as_uncased() == \"tcp\" {\n                return parse_tcp(string.trim(), 8000).map(Self::Tcp);\n            } else if proto.trim().as_uncased() == \"unix\" {\n                return Ok(Self::Unix(PathBuf::from(string.trim())));\n            }\n        }\n\n        parse_tcp(string.trim(), 8000).map(Self::Tcp)\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for Endpoint {\n    fn deserialize<D: de::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = Endpoint;\n\n            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n                formatter.write_str(\"valid TCP (ip) or unix (path) endpoint\")\n            }\n\n            fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {\n                v.parse::<Endpoint>().map_err(|e| E::custom(e.to_string()))\n            }\n        }\n\n        de.deserialize_any(Visitor)\n    }\n}\n\nimpl Eq for Endpoint { }\n\nimpl PartialEq for Endpoint {\n    fn eq(&self, other: &Self) -> bool {\n        match (self, other) {\n            (Self::Tcp(l0), Self::Tcp(r0)) => l0 == r0,\n            (Self::Quic(l0), Self::Quic(r0)) => l0 == r0,\n            (Self::Unix(l0), Self::Unix(r0)) => l0 == r0,\n            (Self::Tls(l0, _), Self::Tls(r0, _)) => l0 == r0,\n            (Self::Custom(l0), Self::Custom(r0)) => l0.to_string() == r0.to_string(),\n            _ => false,\n        }\n    }\n}\n\nimpl PartialEq<PathBuf> for Endpoint {\n    fn eq(&self, other: &PathBuf) -> bool {\n        self.unix() == Some(other.as_path())\n    }\n}\n\nimpl PartialEq<Path> for Endpoint {\n    fn eq(&self, other: &Path) -> bool {\n        self.unix() == Some(other)\n    }\n}\n\n#[cfg(unix)]\nimpl TryFrom<tokio::net::unix::SocketAddr> for Endpoint {\n    type Error = std::io::Error;\n\n    fn try_from(v: tokio::net::unix::SocketAddr) -> Result<Self, Self::Error> {\n        v.as_pathname()\n            .ok_or_else(|| std::io::Error::other(\"unix socket is not path\"))\n            .map(|path| Endpoint::Unix(path.to_path_buf()))\n    }\n}\n\nimpl TryFrom<&str> for Endpoint {\n    type Error = AddrParseError;\n\n    fn try_from(value: &str) -> Result<Self, Self::Error> {\n        value.parse()\n    }\n}\n\nmacro_rules! impl_from {\n    ($T:ty => $V:ident) => {\n        impl From<$T> for Endpoint {\n            fn from(value: $T) -> Self {\n                Self::$V(value.into())\n            }\n        }\n    }\n}\n\nimpl_from!(std::net::SocketAddr => Tcp);\nimpl_from!(std::net::SocketAddrV4 => Tcp);\nimpl_from!(std::net::SocketAddrV6 => Tcp);\nimpl_from!(PathBuf => Unix);\n"
  },
  {
    "path": "core/lib/src/listener/listener.rs",
    "content": "use std::io;\n\nuse futures::TryFutureExt;\nuse tokio_util::either::Either;\n\nuse crate::listener::{Connection, Endpoint};\n\npub trait Listener: Sized + Send + Sync {\n    type Accept: Send;\n\n    type Connection: Connection;\n\n    #[crate::async_bound(Send)]\n    async fn accept(&self) -> io::Result<Self::Accept>;\n\n    #[crate::async_bound(Send)]\n    async fn connect(&self, accept: Self::Accept) -> io::Result<Self::Connection>;\n\n    fn endpoint(&self) -> io::Result<Endpoint>;\n}\n\nimpl<L: Listener> Listener for &L {\n    type Accept = L::Accept;\n\n    type Connection = L::Connection;\n\n    async fn accept(&self) -> io::Result<Self::Accept> {\n        <L as Listener>::accept(self).await\n    }\n\n    async fn connect(&self, accept: Self::Accept) -> io::Result<Self::Connection> {\n        <L as Listener>::connect(self, accept).await\n    }\n\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        <L as Listener>::endpoint(self)\n    }\n}\n\nimpl<A: Listener, B: Listener> Listener for Either<A, B> {\n    type Accept = Either<A::Accept, B::Accept>;\n\n    type Connection = Either<A::Connection, B::Connection>;\n\n    async fn accept(&self) -> io::Result<Self::Accept> {\n        match self {\n            Either::Left(l) => l.accept().map_ok(Either::Left).await,\n            Either::Right(l) => l.accept().map_ok(Either::Right).await,\n        }\n    }\n\n    async fn connect(&self, accept: Self::Accept) -> io::Result<Self::Connection>  {\n        match (self, accept) {\n            (Either::Left(l), Either::Left(a)) => l.connect(a).map_ok(Either::Left).await,\n            (Either::Right(l), Either::Right(a)) => l.connect(a).map_ok(Either::Right).await,\n            _ => unreachable!()\n        }\n    }\n\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        match self {\n            Either::Left(l) => l.endpoint(),\n            Either::Right(l) => l.endpoint(),\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/mod.rs",
    "content": "mod cancellable;\nmod bounced;\nmod listener;\nmod endpoint;\nmod connection;\nmod bind;\nmod default;\n\n#[cfg(unix)]\n#[cfg_attr(nightly, doc(cfg(unix)))]\npub mod unix;\npub mod tcp;\n#[cfg(feature = \"http3-preview\")]\npub mod quic;\n\npub use endpoint::*;\npub use listener::*;\npub use connection::*;\npub use bind::*;\npub use default::*;\n\npub(crate) use cancellable::*;\npub(crate) use bounced::*;\n"
  },
  {
    "path": "core/lib/src/listener/quic.rs",
    "content": "//! Experimental support for Quic and HTTP/3.\n//!\n//! To enable Rocket's experimental support for HTTP/3 and Quic, enable the\n//! `http3-preview` feature and provide a valid TLS configuration:\n//!\n//! ```toml\n//! // Add the following to your Cargo.toml:\n//! [dependencies]\n//! rocket = { version = \"0.6.0-dev\", features = [\"http3-preview\"] }\n//!\n//! // In your Rocket.toml or other equivalent config source:\n//! [default.tls]\n//! certs = \"private/rsa_sha256_cert.pem\"\n//! key = \"private/rsa_sha256_key.pem\"\n//! ```\n//!\n//! The launch message confirms that Rocket is serving traffic over Quic in\n//! addition to TCP:\n//!\n//! ```sh\n//! > 🚀 Rocket has launched on https://127.0.0.1:8000 (QUIC + mTLS)\n//! ```\n//!\n//! mTLS is not yet supported via this implementation.\n\nuse std::io;\nuse std::fmt;\nuse std::net::SocketAddr;\nuse std::pin::pin;\n\nuse s2n_quic as quic;\nuse s2n_quic_h3 as quic_h3;\nuse quic_h3::h3 as h3;\n\nuse bytes::Bytes;\nuse futures::Stream;\nuse tokio::sync::Mutex;\nuse tokio_stream::StreamExt;\n\nuse crate::tls::{TlsConfig, Error};\nuse crate::listener::Endpoint;\n\ntype H3Conn = h3::server::Connection<quic_h3::Connection, bytes::Bytes>;\n\npub struct QuicListener {\n    endpoint: SocketAddr,\n    listener: Mutex<quic::Server>,\n    tls: TlsConfig,\n}\n\npub struct H3Stream(H3Conn, quic::connection::Result<SocketAddr>);\n\npub struct H3Connection {\n    pub(crate) remote: quic::connection::Result<SocketAddr>,\n    pub(crate) parts: http::request::Parts,\n    pub(crate) tx: QuicTx,\n    pub(crate) rx: QuicRx,\n}\n\n#[doc(hidden)]\npub struct QuicRx(h3::server::RequestStream<quic_h3::RecvStream, Bytes>);\n\n#[doc(hidden)]\npub struct QuicTx(h3::server::RequestStream<quic_h3::SendStream<Bytes>, Bytes>);\n\nimpl QuicListener {\n    pub async fn bind(address: SocketAddr, tls: TlsConfig) -> Result<Self, Error> {\n        use quic::provider::tls::rustls::Server as H3TlsServer;\n\n        let cert_chain = tls.load_certs()?\n            .into_iter()\n            .map(|v| v.to_vec())\n            .collect::<Vec<_>>();\n\n        let h3tls = H3TlsServer::builder()\n            .with_application_protocols([\"h3\"].into_iter())\n            .map_err(|e| Error::Bind(e))?\n            .with_certificate(cert_chain, tls.load_key()?.secret_der())\n            .map_err(|e| Error::Bind(e))?\n            .with_prefer_server_cipher_suite_order(tls.prefer_server_cipher_order)\n            .map_err(|e| Error::Bind(e))?\n            .build()\n            .map_err(|e| Error::Bind(e))?;\n\n        let listener = quic::Server::builder()\n            .with_tls(h3tls)?\n            .with_io(address)?\n            .start()\n            .map_err(|e| Error::Bind(Box::new(e)))?;\n\n        Ok(QuicListener {\n            tls,\n            endpoint: listener.local_addr()?,\n            listener: Mutex::new(listener),\n        })\n    }\n}\n\nimpl QuicListener {\n    pub async fn accept(&self) -> Option<quic::Connection> {\n        self.listener\n            .lock().await\n            .accept().await\n    }\n\n    pub async fn connect(&self, accept: quic::Connection) -> io::Result<H3Stream> {\n        let remote = accept.remote_addr();\n        let quic_conn = quic_h3::Connection::new(accept);\n        let conn = H3Conn::new(quic_conn).await.map_err(io::Error::other)?;\n        Ok(H3Stream(conn, remote))\n    }\n\n    pub fn endpoint(&self) -> io::Result<Endpoint> {\n        Ok(Endpoint::Quic(self.endpoint).with_tls(&self.tls))\n    }\n}\n\nimpl H3Stream {\n    pub async fn accept(&mut self) -> io::Result<Option<H3Connection>> {\n        let remote = self.1.clone();\n        let ((parts, _), (tx, rx)) = match self.0.accept().await {\n            Ok(Some((req, stream))) => (req.into_parts(), stream.split()),\n            Ok(None) => return Ok(None),\n            Err(e) => {\n                if matches!(e.try_get_code().map(|c| c.value()), Some(0 | 0x100)) {\n                    return Ok(None)\n                }\n\n                return Err(io::Error::other(e));\n            }\n        };\n\n        Ok(Some(H3Connection { remote, parts, tx: QuicTx(tx), rx: QuicRx(rx) }))\n    }\n}\n\nimpl QuicTx {\n    pub async fn send_response<S>(&mut self, response: http::Response<S>) -> io::Result<()>\n        where S: Stream<Item = io::Result<Bytes>>\n    {\n        let (parts, body) = response.into_parts();\n        let response = http::Response::from_parts(parts, ());\n        self.0.send_response(response).await.map_err(io::Error::other)?;\n\n        let mut body = pin!(body);\n        while let Some(bytes) = body.next().await {\n            let bytes = bytes.map_err(io::Error::other)?;\n            self.0.send_data(bytes).await.map_err(io::Error::other)?;\n        }\n\n        self.0.finish().await.map_err(io::Error::other)\n    }\n\n    pub fn cancel(&mut self) {\n        self.0.stop_stream(h3::error::Code::H3_NO_ERROR);\n    }\n}\n\n// FIXME: Expose certificates when possible.\nimpl H3Connection {\n    pub fn endpoint(&self) -> io::Result<Endpoint> {\n        Ok(Endpoint::Quic(self.remote?).assume_tls())\n    }\n}\n\nmod async_traits {\n    use std::io;\n    use std::pin::Pin;\n    use std::task::{ready, Context, Poll};\n\n    use super::{Bytes, QuicRx};\n    use crate::listener::AsyncCancel;\n\n    use futures::Stream;\n    use s2n_quic_h3::h3;\n\n    impl Stream for QuicRx {\n        type Item = io::Result<Bytes>;\n\n        fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {\n            use bytes::Buf;\n\n            match ready!(self.0.poll_recv_data(cx)) {\n                Ok(Some(mut buf)) => Poll::Ready(Some(Ok(buf.copy_to_bytes(buf.remaining())))),\n                Ok(None) => Poll::Ready(None),\n                Err(e) => Poll::Ready(Some(Err(io::Error::other(e)))),\n            }\n        }\n    }\n\n    impl AsyncCancel for QuicRx {\n        fn poll_cancel(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {\n            self.0.stop_sending(h3::error::Code::H3_NO_ERROR);\n            Poll::Ready(Ok(()))\n        }\n    }\n}\n\nimpl fmt::Debug for H3Stream {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_tuple(\"H3Stream\").finish()\n    }\n}\n\nimpl fmt::Debug for H3Connection {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"H3Connection\").finish()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/tcp.rs",
    "content": "//! TCP listener.\n//!\n//! # Configuration\n//!\n//! Reads the following configuration parameters:\n//!\n//! | parameter | type         | default     | note                            |\n//! |-----------|--------------|-------------|---------------------------------|\n//! | `address` | [`Endpoint`] | `127.0.0.1` | must be `tcp:ip`                |\n//! | `port`    | `u16`        | `8000`      | replaces the port in `address ` |\n\nuse std::io;\nuse std::net::{Ipv4Addr, SocketAddr};\n\nuse either::{Either, Left, Right};\n\n#[doc(inline)]\npub use tokio::net::{TcpListener, TcpStream};\n\nuse crate::{Ignite, Rocket};\nuse crate::listener::{Bind, Connection, Endpoint, Listener};\n\nimpl Bind for TcpListener {\n    type Error = Either<figment::Error, io::Error>;\n\n    async fn bind(rocket: &Rocket<Ignite>) -> Result<Self, Self::Error> {\n        let endpoint = Self::bind_endpoint(rocket)?;\n        let addr = endpoint.tcp()\n            .ok_or_else(|| io::Error::other(\"internal error: invalid endpoint\"))\n            .map_err(Right)?;\n\n        Self::bind(addr).await.map_err(Right)\n    }\n\n    fn bind_endpoint(rocket: &Rocket<Ignite>) -> Result<Endpoint, Self::Error> {\n        let figment = rocket.figment();\n        let mut address = Endpoint::fetch(figment, \"tcp\", \"address\", |e| {\n            let default = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 8000);\n            e.map(|e| e.tcp()).unwrap_or(Some(default))\n        }).map_err(Left)?;\n\n        if figment.contains(\"port\") {\n            let port = figment.extract_inner(\"port\").map_err(Left)?;\n            address.set_port(port);\n        }\n\n        Ok(Endpoint::Tcp(address))\n    }\n}\n\nimpl Listener for TcpListener {\n    type Accept = Self::Connection;\n\n    type Connection = TcpStream;\n\n    async fn accept(&self) -> io::Result<Self::Accept> {\n        let conn = self.accept().await?.0;\n        let _ = conn.set_nodelay(true);\n        let _ = conn.set_linger(None);\n        Ok(conn)\n    }\n\n    async fn connect(&self, conn: Self::Connection) -> io::Result<Self::Connection> {\n        Ok(conn)\n    }\n\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        self.local_addr().map(Endpoint::Tcp)\n    }\n}\n\nimpl Connection for TcpStream {\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        self.peer_addr().map(Endpoint::Tcp)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/listener/unix.rs",
    "content": "use std::io;\nuse std::path::{Path, PathBuf};\n\nuse either::{Either, Left, Right};\nuse figment::error::Kind;\nuse tokio::time::{sleep, Duration};\n\nuse crate::fs::NamedFile;\nuse crate::listener::{Listener, Bind, Connection, Endpoint};\nuse crate::util::unix;\nuse crate::{Ignite, Rocket};\n\npub use tokio::net::UnixStream;\n\n/// Unix domain sockets listener.\n///\n/// # Configuration\n///\n/// Reads the following configuration parameters:\n///\n/// | parameter | type         | default | note                                      |\n/// |-----------|--------------|---------|-------------------------------------------|\n/// | `address` | [`Endpoint`] |         | required: must be `unix:path`             |\n/// | `reuse`   | boolean      | `true`  | whether to create/reuse/delete the socket |\npub struct UnixListener {\n    path: PathBuf,\n    lock: Option<NamedFile>,\n    listener: tokio::net::UnixListener,\n}\n\nimpl UnixListener {\n    pub async fn bind<P: AsRef<Path>>(path: P, reuse: bool) -> io::Result<Self> {\n        let path = path.as_ref();\n        let lock = if reuse {\n            let lock_ext = match path.extension().and_then(|s| s.to_str()) {\n                Some(ext) if !ext.is_empty() => format!(\"{}.lock\", ext),\n                _ => \"lock\".to_string()\n            };\n\n            let mut opts = tokio::fs::File::options();\n            opts.create(true).write(true);\n            let lock_path = path.with_extension(lock_ext);\n            let lock_file = NamedFile::open_with(lock_path, &opts).await?;\n\n            unix::lock_exclusive_nonblocking(lock_file.file())?;\n            if path.exists() {\n                tokio::fs::remove_file(&path).await?;\n            }\n\n            Some(lock_file)\n        } else {\n            None\n        };\n\n        // Sometimes, we get `AddrInUse`, even though we've tried deleting the\n        // socket. If all is well, eventually the socket will _really_ be gone,\n        // and this will succeed. So let's try a few times.\n        let mut retries = 5;\n        let listener = loop {\n            match tokio::net::UnixListener::bind(&path) {\n                Ok(listener) => break listener,\n                Err(e) if path.exists() && lock.is_none() => return Err(e),\n                Err(_) if retries > 0 => {\n                    retries -= 1;\n                    sleep(Duration::from_millis(100)).await;\n                },\n                Err(e) => return Err(e),\n            }\n        };\n\n        Ok(UnixListener { lock, listener, path: path.into() })\n    }\n}\n\nimpl Bind for UnixListener {\n    type Error = Either<figment::Error, io::Error>;\n\n    async fn bind(rocket: &Rocket<Ignite>) -> Result<Self, Self::Error> {\n        let endpoint = Self::bind_endpoint(rocket)?;\n        let path = endpoint.unix()\n            .ok_or_else(|| Right(io::Error::other(\"internal error: invalid endpoint\")))?;\n\n        let reuse: bool = rocket.figment()\n            .extract_inner(\"reuse\")\n            .or_else(|e| if e.missing() { Ok(true) } else { Err(e) } )\n            .map_err(Left)?;\n        Ok(Self::bind(path, reuse).await.map_err(Right)?)\n    }\n\n    fn bind_endpoint(rocket: &Rocket<Ignite>) -> Result<Endpoint, Self::Error> {\n        let as_pathbuf = |e: Option<&Endpoint>| e.and_then(|e| e.unix().map(|p| p.to_path_buf()));\n        Endpoint::fetch(rocket.figment(), \"unix\", \"address\", as_pathbuf)\n            .map(Endpoint::Unix)\n            .map_err(Left)\n    }\n}\n\nimpl Listener for UnixListener {\n    type Accept = UnixStream;\n\n    type Connection = Self::Accept;\n\n    async fn accept(&self) -> io::Result<Self::Accept> {\n        Ok(self.listener.accept().await?.0)\n    }\n\n    async fn connect(&self, accept:Self::Accept) -> io::Result<Self::Connection> {\n        Ok(accept)\n    }\n\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        self.listener.local_addr()?.try_into()\n    }\n}\n\nimpl Connection for UnixStream {\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        self.local_addr()?.try_into()\n    }\n}\n\nimpl Drop for UnixListener {\n    fn drop(&mut self) {\n        if let Some(lock) = &self.lock {\n            let _ = std::fs::remove_file(&self.path);\n            let _ = std::fs::remove_file(lock.path());\n            let _ = unix::unlock_nonblocking(lock.file());\n        } else {\n            let _ = std::fs::remove_file(&self.path);\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/local/asynchronous/client.rs",
    "content": "use std::fmt;\n\nuse parking_lot::RwLock;\n\nuse crate::{Rocket, Phase, Orbit, Ignite, Error};\nuse crate::local::asynchronous::{LocalRequest, LocalResponse};\nuse crate::http::{Method, uri::Origin};\nuse crate::listener::Endpoint;\n\n/// An `async` client to construct and dispatch local requests.\n///\n/// For details, see [the top-level documentation](../index.html#client).\n/// For the `blocking` version, see\n/// [`blocking::Client`](crate::local::blocking::Client).\n///\n/// ## Multithreaded Tracking Synchronization Pitfalls\n///\n/// Unlike its [`blocking`](crate::local::blocking) variant, this `async`\n/// `Client` implements `Sync`. However, using it in a multithreaded environment\n/// while tracking cookies can result in surprising, non-deterministic behavior.\n/// This is because while cookie modifications are serialized, the ordering\n/// depends on the ordering of request dispatch.\n///\n/// If possible, refrain from sharing a single instance of a tracking `Client`\n/// across multiple threads. Instead, prefer to create a unique instance of\n/// `Client` per thread. If this is not possible, ensure that you are not\n/// depending on the ordering of cookie modifications or have arranged for\n/// request dispatch to occur in a deterministic manner.\n///\n/// Alternatively, use an untracked client, which does not suffer from these\n/// pitfalls.\n///\n/// ## Example\n///\n/// The following snippet creates a `Client` from a `Rocket` instance and\n/// dispatches a local `POST /` request with a body of `Hello, world!`.\n///\n/// ```rust,no_run\n/// use rocket::local::asynchronous::Client;\n///\n/// # rocket::async_test(async {\n/// let rocket = rocket::build();\n/// let client = Client::tracked(rocket).await.expect(\"valid rocket\");\n/// let response = client.post(\"/\")\n///     .body(\"Hello, world!\")\n///     .dispatch()\n///     .await;\n/// # });\n/// ```\npub struct Client {\n    rocket: Rocket<Orbit>,\n    cookies: RwLock<cookie::CookieJar>,\n    pub(in super) tracked: bool,\n}\n\nimpl Client {\n    pub(crate) async fn _new<P: Phase>(\n        rocket: Rocket<P>,\n        tracked: bool,\n        secure: bool,\n    ) -> Result<Client, Error> {\n        let mut endpoint = Endpoint::new(\"local client\");\n        if secure {\n            endpoint = endpoint.assume_tls();\n        }\n\n        let rocket = rocket.local_launch(endpoint).await?;\n        let cookies = RwLock::new(cookie::CookieJar::new());\n        Ok(Client { rocket, cookies, tracked })\n    }\n\n    // WARNING: This is unstable! Do not use this method outside of Rocket!\n    // This is used by the `Client` doctests.\n    #[doc(hidden)]\n    pub fn _test<T, F>(f: F) -> T\n        where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send\n    {\n        crate::async_test(async {\n            let client = Client::debug(crate::build()).await.unwrap();\n            let request = client.get(\"/\");\n            let response = request.clone().dispatch().await;\n            f(&client, request, response)\n        })\n    }\n\n    #[inline(always)]\n    pub(crate) fn _rocket(&self) -> &Rocket<Orbit> {\n        &self.rocket\n    }\n\n    #[inline(always)]\n    pub(crate) fn _with_raw_cookies<F, T>(&self, f: F) -> T\n        where F: FnOnce(&cookie::CookieJar) -> T\n    {\n        f(&self.cookies.read())\n    }\n\n    #[inline(always)]\n    pub(crate) fn _with_raw_cookies_mut<F, T>(&self, f: F) -> T\n        where F: FnOnce(&mut cookie::CookieJar) -> T\n    {\n        f(&mut self.cookies.write())\n    }\n\n    #[inline(always)]\n    fn _req<'c, 'u: 'c, U>(&'c self, method: Method, uri: U) -> LocalRequest<'c>\n        where U: TryInto<Origin<'u>> + fmt::Display\n    {\n        LocalRequest::new(self, method, uri)\n    }\n\n    pub(crate) async fn _terminate(self) -> Rocket<Ignite> {\n        let rocket = self.rocket;\n        rocket.shutdown().notify();\n        rocket.fairings.handle_shutdown(&rocket).await;\n        rocket.deorbit()\n    }\n\n    // Generates the public API methods, which call the private methods above.\n    pub_client_impl!(\"use rocket::local::asynchronous::Client;\" @async await);\n}\n\nimpl std::fmt::Debug for Client {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self._rocket().fmt(f)\n    }\n}\n\n#[cfg(test)]\nmod test {\n    #[test]\n    fn test_local_client_impl_send_sync() {\n        fn assert_sync_send<T: Sync + Send>() {}\n        assert_sync_send::<super::Client>();\n    }\n}\n"
  },
  {
    "path": "core/lib/src/local/asynchronous/mod.rs",
    "content": "//! Asynchronous local dispatching of requests.\n//!\n//! This module contains the `asynchronous` variant of the `local` API: it can\n//! be used with `#[rocket::async_test]` or another asynchronous test harness.\n//! For the blocking variant, see [`blocking`](super::blocking).\n//!\n//! See the [top-level documentation](super) for more usage details.\n\nmod client;\nmod request;\nmod response;\n\npub use client::*;\npub use request::*;\npub use response::*;\n"
  },
  {
    "path": "core/lib/src/local/asynchronous/request.rs",
    "content": "use std::fmt;\n\nuse rocket_http::HttpVersion;\n\nuse crate::{Request, Data};\nuse crate::http::{Status, Method};\nuse crate::http::uri::Origin;\n\nuse super::{Client, LocalResponse};\n\n/// An `async` local request as returned by [`Client`](super::Client).\n///\n/// For details, see [the top-level documentation](../index.html#localrequest).\n///\n/// ## Example\n///\n/// The following snippet uses the available builder methods to construct and\n/// dispatch a `POST` request to `/` with a JSON body:\n///\n/// ```rust,no_run\n/// use rocket::local::asynchronous::{Client, LocalRequest};\n/// use rocket::http::{ContentType, Cookie};\n///\n/// # rocket::async_test(async {\n/// let client = Client::tracked(rocket::build()).await.expect(\"valid rocket\");\n/// let req = client.post(\"/\")\n///     .header(ContentType::JSON)\n///     .remote(\"127.0.0.1:8000\")\n///     .cookie((\"name\", \"value\"))\n///     .body(r#\"{ \"value\": 42 }\"#);\n///\n/// let response = req.dispatch().await;\n/// # });\n/// ```\npub struct LocalRequest<'c> {\n    pub(in super) client: &'c Client,\n    pub(in super) request: Request<'c>,\n    data: Vec<u8>,\n    // The `Origin` on the right is INVALID! It should _not_ be used!\n    uri: Result<Origin<'c>, Origin<'static>>,\n}\n\nimpl<'c> LocalRequest<'c> {\n    pub(crate) fn new<'u: 'c, U>(client: &'c Client, method: Method, uri: U) -> Self\n        where U: TryInto<Origin<'u>> + fmt::Display\n    {\n        // Try to parse `uri` into an `Origin`, storing whether it's good.\n        let uri_str = uri.to_string();\n        let try_origin = uri.try_into().map_err(|_| Origin::path_only(uri_str));\n\n        // Create a request. We'll handle bad URIs later, in `_dispatch`.\n        let origin = try_origin.clone().unwrap_or_else(|bad| bad);\n        let mut request = Request::new(client.rocket(), method, origin, None);\n\n        // Add any cookies we know about.\n        if client.tracked {\n            client._with_raw_cookies(|jar| {\n                for cookie in jar.iter() {\n                    request.cookies_mut().add_original(cookie.clone());\n                }\n            })\n        }\n\n        LocalRequest { client, request, uri: try_origin, data: vec![] }\n    }\n\n    #[inline]\n    pub fn override_version(&mut self, version: HttpVersion) {\n        self.version = Some(version);\n    }\n\n    pub(crate) fn _request(&self) -> &Request<'c> {\n        &self.request\n    }\n\n    pub(crate) fn _request_mut(&mut self) -> &mut Request<'c> {\n        &mut self.request\n    }\n\n    pub(crate) fn _body_mut(&mut self) -> &mut Vec<u8> {\n        &mut self.data\n    }\n\n    // Performs the actual dispatch.\n    async fn _dispatch(mut self) -> LocalResponse<'c> {\n        // First, revalidate the URI, returning an error response (generated\n        // from an error catcher) immediately if it's invalid. If it's valid,\n        // then `request` already contains a correct URI.\n        let rocket = self.client.rocket();\n        if let Err(ref invalid) = self.uri {\n            // The user may have changed the URI in the request in which case we\n            // _shouldn't_ error. Check that now and error only if not.\n            if self.inner().uri() == invalid {\n                error!(\"invalid request URI: {:?}\", invalid.path());\n                return LocalResponse::new(self.request, move |req| {\n                    rocket.dispatch_error(Status::BadRequest, req)\n                }).await\n            }\n        }\n\n        // Actually dispatch the request.\n        let mut data = Data::local(self.data);\n        let token = rocket.preprocess(&mut self.request, &mut data).await;\n        let response = LocalResponse::new(self.request, move |req| {\n            rocket.dispatch(token, req, data)\n        }).await;\n\n        // If the client is tracking cookies, updates the internal cookie jar\n        // with the changes reflected by `response`.\n        if self.client.tracked {\n            self.client._with_raw_cookies_mut(|jar| {\n                let current_time = time::OffsetDateTime::now_utc();\n                for cookie in response.cookies().iter() {\n                    if let Some(expires) = cookie.expires_datetime() {\n                        if expires <= current_time {\n                            jar.force_remove(cookie.name());\n                            continue;\n                        }\n                    }\n\n                    jar.add_original(cookie.clone());\n                }\n            })\n        }\n\n        response\n    }\n\n    pub_request_impl!(\"# use rocket::local::asynchronous::Client;\\n\\\n        use rocket::local::asynchronous::LocalRequest;\" async await);\n}\n\nimpl<'c> Clone for LocalRequest<'c> {\n    fn clone(&self) -> Self {\n        LocalRequest {\n            client: self.client,\n            request: self.request.clone(),\n            data: self.data.clone(),\n            uri: self.uri.clone(),\n        }\n    }\n}\n\nimpl std::fmt::Debug for LocalRequest<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self._request().fmt(f)\n    }\n}\n\nimpl<'c> std::ops::Deref for LocalRequest<'c> {\n    type Target = Request<'c>;\n\n    fn deref(&self) -> &Self::Target {\n        self.inner()\n    }\n}\n\nimpl<'c> std::ops::DerefMut for LocalRequest<'c> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        self.inner_mut()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/local/asynchronous/response.rs",
    "content": "use std::io;\nuse std::future::Future;\nuse std::{pin::Pin, task::{Context, Poll}};\n\nuse tokio::io::{AsyncRead, ReadBuf};\n\nuse crate::http::CookieJar;\nuse crate::{Request, Response};\n\n/// An `async` response from a dispatched [`LocalRequest`](super::LocalRequest).\n///\n/// This `LocalResponse` implements [`tokio::io::AsyncRead`]. As such, if\n/// [`into_string()`](LocalResponse::into_string()) and\n/// [`into_bytes()`](LocalResponse::into_bytes()) do not suffice, the response's\n/// body can be read directly:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use std::io;\n///\n/// use rocket::local::asynchronous::Client;\n/// use rocket::tokio::io::AsyncReadExt;\n/// use rocket::http::Status;\n///\n/// #[get(\"/\")]\n/// fn hello_world() -> &'static str {\n///     \"Hello, world!\"\n/// }\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().mount(\"/\", routes![hello_world])\n///     #    .reconfigure(rocket::Config::debug_default())\n/// }\n///\n/// # async fn read_body_manually() -> io::Result<()> {\n/// // Dispatch a `GET /` request.\n/// let client = Client::tracked(rocket()).await.expect(\"valid rocket\");\n/// let mut response = client.get(\"/\").dispatch().await;\n///\n/// // Check metadata validity.\n/// assert_eq!(response.status(), Status::Ok);\n/// assert_eq!(response.body().preset_size(), Some(13));\n///\n/// // Read 10 bytes of the body. Note: in reality, we'd use `into_string()`.\n/// let mut buffer = [0; 10];\n/// response.read(&mut buffer).await?;\n/// assert_eq!(buffer, \"Hello, wor\".as_bytes());\n/// # Ok(())\n/// # }\n/// # rocket::async_test(read_body_manually()).expect(\"read okay\");\n/// ```\n///\n/// For more, see [the top-level documentation](../index.html#localresponse).\npub struct LocalResponse<'c> {\n    // XXX: SAFETY: This (dependent) field must come first due to drop order!\n    response: Response<'c>,\n    cookies: CookieJar<'c>,\n    _request: Box<Request<'c>>,\n}\n\nimpl Drop for LocalResponse<'_> {\n    fn drop(&mut self) { }\n}\n\nimpl<'c> LocalResponse<'c> {\n    pub(crate) fn new<F, O>(req: Request<'c>, f: F) -> impl Future<Output = LocalResponse<'c>>\n        where F: FnOnce(&'c Request<'c>) -> O + Send,\n              O: Future<Output = Response<'c>> + Send\n    {\n        // `LocalResponse` is a self-referential structure. In particular,\n        // `response` and `cookies` can refer to `_request` and its contents. As\n        // such, we must\n        //   1) Ensure `Request` has a stable address.\n        //\n        //      This is done by `Box`ing the `Request`, using only the stable\n        //      address thereafter.\n        //\n        //   2) Ensure no refs to `Request` or its contents leak with a lifetime\n        //      extending beyond that of `&self`.\n        //\n        //      We have no methods that return an `&Request`. However, we must\n        //      also ensure that `Response` doesn't leak any such references. To\n        //      do so, we don't expose the `Response` directly in any way;\n        //      otherwise, methods like `.headers()` could, in conjunction with\n        //      particular crafted `Responder`s, potentially be used to obtain a\n        //      reference to contents of `Request`. All methods, instead, return\n        //      references bounded by `self`. This is easily verified by noting\n        //      that 1) `LocalResponse` fields are private, and 2) all `impl`s\n        //      of `LocalResponse` aside from this method abstract the lifetime\n        //      away as `'_`, ensuring it is not used for any output value.\n        let boxed_req = Box::new(req);\n        let request: &'c Request<'c> = unsafe { &*(&*boxed_req as *const _) };\n\n        async move {\n            // NOTE: The cookie jar `secure` state will not reflect the last\n            // known value in `request.cookies()`. This is okay: new cookies\n            // should never be added to the resulting jar which is the only time\n            // the value is used to set cookie defaults.\n            let response: Response<'c> = f(request).await;\n            let mut cookies = CookieJar::new(None, request.rocket());\n            for cookie in response.cookies() {\n                cookies.add_original(cookie.into_owned());\n            }\n\n            LocalResponse { _request: boxed_req, cookies, response, }\n        }\n    }\n}\n\nimpl LocalResponse<'_> {\n    pub(crate) fn _response(&self) -> &Response<'_> {\n        &self.response\n    }\n\n    pub(crate) fn _cookies(&self) -> &CookieJar<'_> {\n        &self.cookies\n    }\n\n    pub(crate) async fn _into_string(mut self) -> io::Result<String> {\n        self.response.body_mut().to_string().await\n    }\n\n    pub(crate) async fn _into_bytes(mut self) -> io::Result<Vec<u8>> {\n        self.response.body_mut().to_bytes().await\n    }\n\n    #[cfg(feature = \"json\")]\n    async fn _into_json<T>(self) -> Option<T>\n        where T: Send + serde::de::DeserializeOwned + 'static\n    {\n        self.blocking_read(|r| serde_json::from_reader(r)).await?.ok()\n    }\n\n    #[cfg(feature = \"msgpack\")]\n    async fn _into_msgpack<T>(self) -> Option<T>\n        where T: Send + serde::de::DeserializeOwned + 'static\n    {\n        self.blocking_read(|r| rmp_serde::from_read(r)).await?.ok()\n    }\n\n    #[cfg(any(feature = \"json\", feature = \"msgpack\"))]\n    async fn blocking_read<T, F>(mut self, f: F) -> Option<T>\n        where T: Send + 'static,\n              F: FnOnce(&mut dyn io::Read) -> T + Send + 'static\n    {\n        use tokio::sync::mpsc;\n        use tokio::io::AsyncReadExt;\n\n        struct ChanReader {\n            last: Option<io::Cursor<Vec<u8>>>,\n            rx: mpsc::Receiver<io::Result<Vec<u8>>>,\n        }\n\n        impl std::io::Read for ChanReader {\n            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n                loop {\n                    if let Some(ref mut cursor) = self.last {\n                        if cursor.position() < cursor.get_ref().len() as u64 {\n                            return std::io::Read::read(cursor, buf);\n                        }\n                    }\n\n                    if let Some(buf) = self.rx.blocking_recv() {\n                        self.last = Some(io::Cursor::new(buf?));\n                    } else {\n                        return Ok(0);\n                    }\n                }\n            }\n        }\n\n        let (tx, rx) = mpsc::channel(2);\n        let reader = tokio::task::spawn_blocking(move || {\n            let mut reader = ChanReader { last: None, rx };\n            f(&mut reader)\n        });\n\n        loop {\n            // TODO: Try to fill as much as the buffer before send it off?\n            let mut buf = Vec::with_capacity(1024);\n            match self.read_buf(&mut buf).await {\n                Ok(0) => break,\n                Ok(_) => tx.send(Ok(buf)).await.ok()?,\n                Err(e) => {\n                    tx.send(Err(e)).await.ok()?;\n                    break;\n                }\n            }\n        }\n\n        // NOTE: We _must_ drop tx now to prevent a deadlock!\n        drop(tx);\n\n        reader.await.ok()\n    }\n\n    // Generates the public API methods, which call the private methods above.\n    pub_response_impl!(\"# use rocket::local::asynchronous::Client;\\n\\\n        use rocket::local::asynchronous::LocalResponse;\" async await);\n}\n\nimpl AsyncRead for LocalResponse<'_> {\n    fn poll_read(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        Pin::new(self.response.body_mut()).poll_read(cx, buf)\n    }\n}\n\nimpl std::fmt::Debug for LocalResponse<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self._response().fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/local/blocking/client.rs",
    "content": "use std::fmt;\nuse std::cell::RefCell;\n\nuse crate::{Rocket, Phase, Orbit, Ignite, Error};\nuse crate::local::{asynchronous, blocking::{LocalRequest, LocalResponse}};\nuse crate::http::{Method, uri::Origin};\n\n/// A `blocking` client to construct and dispatch local requests.\n///\n/// For details, see [the top-level documentation](../index.html#client). For\n/// the `async` version, see [`asynchronous::Client`].\n///\n/// ## Example\n///\n/// The following snippet creates a `Client` from a `Rocket` instance and\n/// dispatches a local `POST /` request with a body of `Hello, world!`.\n///\n/// ```rust,no_run\n/// use rocket::local::blocking::Client;\n///\n/// let rocket = rocket::build();\n/// let client = Client::tracked(rocket).expect(\"valid rocket\");\n/// let response = client.post(\"/\")\n///     .body(\"Hello, world!\")\n///     .dispatch();\n/// ```\npub struct Client {\n    pub(crate) inner: Option<asynchronous::Client>,\n    runtime: RefCell<tokio::runtime::Runtime>,\n}\n\nimpl Client {\n    fn _new<P: Phase>(rocket: Rocket<P>, tracked: bool, secure: bool) -> Result<Client, Error> {\n        let runtime = tokio::runtime::Builder::new_multi_thread()\n            .thread_name(\"rocket-local-client-worker-thread\")\n            .worker_threads(1)\n            .enable_all()\n            .build()\n            .expect(\"create tokio runtime\");\n\n        // Initialize the Rocket instance\n        let inner = Some(runtime.block_on(asynchronous::Client::_new(rocket, tracked, secure))?);\n        Ok(Self { inner, runtime: RefCell::new(runtime) })\n    }\n\n    // WARNING: This is unstable! Do not use this method outside of Rocket!\n    #[doc(hidden)]\n    pub fn _test<T, F>(f: F) -> T\n        where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send\n    {\n        let client = Client::debug(crate::build()).unwrap();\n        let request = client.get(\"/\");\n        let response = request.clone().dispatch();\n        f(&client, request, response)\n    }\n\n    #[inline(always)]\n    pub(crate) fn inner(&self) -> &asynchronous::Client {\n        self.inner.as_ref().expect(\"internal invariant broken: self.inner is Some\")\n    }\n\n    #[inline(always)]\n    pub(crate) fn block_on<F, R>(&self, fut: F) -> R\n        where F: std::future::Future<Output=R>,\n    {\n        self.runtime.borrow_mut().block_on(fut)\n    }\n\n    #[inline(always)]\n    fn _rocket(&self) -> &Rocket<Orbit> {\n        self.inner()._rocket()\n    }\n\n    #[inline(always)]\n    pub(crate) fn _with_raw_cookies<F, T>(&self, f: F) -> T\n        where F: FnOnce(&cookie::CookieJar) -> T\n    {\n        self.inner()._with_raw_cookies(f)\n    }\n\n    pub(crate) fn _terminate(mut self) -> Rocket<Ignite> {\n        let runtime = tokio::runtime::Builder::new_current_thread().build().unwrap();\n        let runtime = self.runtime.replace(runtime);\n        let inner = self.inner.take().expect(\"invariant broken: self.inner is Some\");\n        let rocket = runtime.block_on(inner._terminate());\n        runtime.shutdown_timeout(std::time::Duration::from_secs(1));\n        rocket\n    }\n\n    #[inline(always)]\n    fn _req<'c, 'u: 'c, U>(&'c self, method: Method, uri: U) -> LocalRequest<'c>\n        where U: TryInto<Origin<'u>> + fmt::Display\n    {\n        LocalRequest::new(self, method, uri)\n    }\n\n    // Generates the public API methods, which call the private methods above.\n    pub_client_impl!(\"use rocket::local::blocking::Client;\");\n}\n\nimpl std::fmt::Debug for Client {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self._rocket().fmt(f)\n    }\n}\n\nimpl Drop for Client {\n    fn drop(&mut self) {\n        if let Some(client) = self.inner.take() {\n            self.block_on(async { drop(client) });\n        }\n    }\n}\n\n#[cfg(doctest)]\nmod doctest {\n    /// ```compile_fail\n    /// use rocket::local::blocking::Client;\n    ///\n    /// fn not_sync<T: Sync>() {};\n    /// not_sync::<Client>();\n    /// ```\n    #[allow(dead_code)]\n    fn test_not_sync() {}\n}\n"
  },
  {
    "path": "core/lib/src/local/blocking/mod.rs",
    "content": "//! Blocking local dispatching of requests.\n//!\n//! This module contains the `blocking` variant of the `local` API: it can be\n//! used in Rust's synchronous `#[test]` harness. This is accomplished by\n//! starting and running an internal asynchronous Runtime as needed. For the\n//! asynchronous variant, see [`asynchronous`](super::asynchronous).\n//!\n//! See the [top-level documentation](super) for more usage details.\n\nmod client;\nmod request;\nmod response;\n\npub use self::client::*;\npub use self::request::*;\npub use self::response::*;\n"
  },
  {
    "path": "core/lib/src/local/blocking/request.rs",
    "content": "use std::fmt;\n\nuse rocket_http::HttpVersion;\n\nuse crate::{Request, http::Method, local::asynchronous};\nuse crate::http::uri::Origin;\n\nuse super::{Client, LocalResponse};\n\n/// A `blocking` local request as returned by [`Client`](super::Client).\n///\n/// For details, see [the top-level documentation](../index.html#localrequest).\n///\n/// ## Example\n///\n/// The following snippet uses the available builder methods to construct and\n/// dispatch a `POST` request to `/` with a JSON body:\n///\n/// ```rust,no_run\n/// use rocket::local::blocking::{Client, LocalRequest};\n/// use rocket::http::{ContentType, Cookie};\n///\n/// let client = Client::tracked(rocket::build()).expect(\"valid rocket\");\n/// let req = client.post(\"/\")\n///     .header(ContentType::JSON)\n///     .remote(\"127.0.0.1:8000\")\n///     .cookie((\"name\", \"value\"))\n///     .body(r#\"{ \"value\": 42 }\"#);\n///\n/// let response = req.dispatch();\n/// ```\n#[derive(Clone)]\npub struct LocalRequest<'c> {\n    inner: asynchronous::LocalRequest<'c>,\n    client: &'c Client,\n}\n\nimpl<'c> LocalRequest<'c> {\n    #[inline]\n    pub(crate) fn new<'u: 'c, U>(client: &'c Client, method: Method, uri: U) -> Self\n        where U: TryInto<Origin<'u>> + fmt::Display\n    {\n        let inner = asynchronous::LocalRequest::new(client.inner(), method, uri);\n        Self { inner, client }\n    }\n\n    #[inline]\n    pub fn override_version(&mut self, version: HttpVersion) {\n        self.inner.override_version(version);\n    }\n\n    #[inline]\n    fn _request(&self) -> &Request<'c> {\n        self.inner._request()\n    }\n\n    #[inline]\n    fn _request_mut(&mut self) -> &mut Request<'c> {\n        self.inner._request_mut()\n    }\n\n    fn _body_mut(&mut self) -> &mut Vec<u8> {\n        self.inner._body_mut()\n    }\n\n    fn _dispatch(self) -> LocalResponse<'c> {\n        let inner = self.client.block_on(self.inner.dispatch());\n        LocalResponse { inner, client: self.client }\n    }\n\n    pub_request_impl!(\"# use rocket::local::blocking::Client;\\n\\\n        use rocket::local::blocking::LocalRequest;\");\n}\n\nimpl std::fmt::Debug for LocalRequest<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self._request().fmt(f)\n    }\n}\n\nimpl<'c> std::ops::Deref for LocalRequest<'c> {\n    type Target = Request<'c>;\n\n    fn deref(&self) -> &Self::Target {\n        self.inner()\n    }\n}\n\nimpl<'c> std::ops::DerefMut for LocalRequest<'c> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        self.inner_mut()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/local/blocking/response.rs",
    "content": "use std::io;\nuse tokio::io::AsyncReadExt;\n\nuse crate::{Response, local::asynchronous, http::CookieJar};\n\nuse super::Client;\n\n/// A `blocking` response from a dispatched [`LocalRequest`](super::LocalRequest).\n///\n/// This `LocalResponse` implements [`io::Read`]. As such, if\n/// [`into_string()`](LocalResponse::into_string()) and\n/// [`into_bytes()`](LocalResponse::into_bytes()) do not suffice, the response's\n/// body can be read directly:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use std::io::{self, Read};\n///\n/// use rocket::local::blocking::Client;\n/// use rocket::http::Status;\n///\n/// #[get(\"/\")]\n/// fn hello_world() -> &'static str {\n///     \"Hello, world!\"\n/// }\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().mount(\"/\", routes![hello_world])\n///     #    .reconfigure(rocket::Config::debug_default())\n/// }\n///\n/// # fn read_body_manually() -> io::Result<()> {\n/// // Dispatch a `GET /` request.\n/// let client = Client::tracked(rocket()).expect(\"valid rocket\");\n/// let mut response = client.get(\"/\").dispatch();\n///\n/// // Check metadata validity.\n/// assert_eq!(response.status(), Status::Ok);\n/// assert_eq!(response.body().preset_size(), Some(13));\n///\n/// // Read 10 bytes of the body. Note: in reality, we'd use `into_string()`.\n/// let mut buffer = [0; 10];\n/// response.read(&mut buffer)?;\n/// assert_eq!(buffer, \"Hello, wor\".as_bytes());\n/// # Ok(())\n/// # }\n/// # read_body_manually().expect(\"read okay\");\n/// ```\n///\n/// For more, see [the top-level documentation](../index.html#localresponse).\npub struct LocalResponse<'c> {\n    pub(in super) inner: asynchronous::LocalResponse<'c>,\n    pub(in super) client: &'c Client,\n}\n\nimpl LocalResponse<'_> {\n    fn _response(&self) -> &Response<'_> {\n        self.inner._response()\n    }\n\n    pub(crate) fn _cookies(&self) -> &CookieJar<'_> {\n        self.inner._cookies()\n    }\n\n    fn _into_string(self) -> io::Result<String> {\n        self.client.block_on(self.inner._into_string())\n    }\n\n    fn _into_bytes(self) -> io::Result<Vec<u8>> {\n        self.client.block_on(self.inner._into_bytes())\n    }\n\n    #[cfg(feature = \"json\")]\n    fn _into_json<T: Send + 'static>(self) -> Option<T>\n        where T: serde::de::DeserializeOwned\n    {\n        serde_json::from_reader(self).ok()\n    }\n\n    #[cfg(feature = \"msgpack\")]\n    fn _into_msgpack<T: Send + 'static>(self) -> Option<T>\n        where T: serde::de::DeserializeOwned\n    {\n        rmp_serde::from_read(self).ok()\n    }\n\n    // Generates the public API methods, which call the private methods above.\n    pub_response_impl!(\"# use rocket::local::blocking::Client;\\n\\\n        use rocket::local::blocking::LocalResponse;\");\n}\n\nimpl io::Read for LocalResponse<'_> {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        self.client.block_on(self.inner.read(buf))\n    }\n}\n\nimpl std::fmt::Debug for LocalResponse<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self._response().fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/local/client.rs",
    "content": "macro_rules! req_method {\n    ($import:literal, $NAME:literal, $f:ident, $method:expr) => (\n        req_method!(@\n            $import,\n            $NAME,\n            concat!(\"let req = client.\", stringify!($f), r#\"(\"/hello\");\"#),\n            $f,\n            $method\n        );\n    );\n\n    (@$import:literal, $NAME:literal, $use_it:expr, $f:ident, $method:expr) => (\n        /// Create a local `\n        #[doc = $NAME]\n        /// ` request to the URI `uri`.\n        ///\n        /// When dispatched, the request will be served by the instance of Rocket\n        /// within `self`. The request is not dispatched automatically. To actually\n        /// dispatch the request, call [`LocalRequest::dispatch()`] on the returned\n        /// request.\n        ///\n        /// # Example\n        ///\n        /// ```rust,no_run\n        #[doc = $import]\n        ///\n        /// # Client::_test(|client, _, _| {\n        /// let client: &Client = client;\n        #[doc = $use_it]\n        /// # });\n        /// ```\n        #[inline(always)]\n        pub fn $f<'c, 'u: 'c, U>(&'c self, uri: U) -> LocalRequest<'c>\n            where U: TryInto<Origin<'u>> + fmt::Display\n        {\n            self.req($method, uri)\n        }\n    )\n}\n\nmacro_rules! pub_client_impl {\n    ($import:literal $(@$prefix:tt $suffix:tt)?) =>\n{\n    /// Construct a new `Client` from an instance of `Rocket` _with_ cookie\n    /// tracking. This is typically the desired mode of operation for testing.\n    ///\n    /// # Cookie Tracking\n    ///\n    /// With cookie tracking enabled, a `Client` propagates cookie changes made\n    /// by responses to previously dispatched requests. In other words,\n    /// succeeding requests reflect changes (additions and removals) made by any\n    /// prior responses.\n    ///\n    /// Cookie tracking requires synchronization between dispatches. **As such,\n    /// cookie tracking _should not_ be enabled if a local client is being used\n    /// to serve requests on multiple threads.**\n    ///\n    /// # Errors\n    ///\n    /// If launching the `Rocket` instance would fail, excepting network errors,\n    /// the `Error` is returned.\n    ///\n    /// ```rust,no_run\n    #[doc = $import]\n    ///\n    /// let rocket = rocket::build();\n    /// let client = Client::tracked(rocket);\n    /// ```\n    #[inline(always)]\n    pub $($prefix)? fn tracked<P: Phase>(rocket: Rocket<P>) -> Result<Self, Error> {\n        Self::_new(rocket, true, false) $(.$suffix)?\n    }\n\n    #[inline(always)]\n    pub $($prefix)? fn tracked_secure<P: Phase>(rocket: Rocket<P>) -> Result<Self, Error> {\n        Self::_new(rocket, true, true) $(.$suffix)?\n    }\n\n    /// Construct a new `Client` from an instance of `Rocket` _without_\n    /// cookie tracking.\n    ///\n    /// # Cookie Tracking\n    ///\n    /// Unlike the [`tracked()`](Client::tracked()) constructor, a `Client`\n    /// returned from this method _does not_ automatically propagate cookie\n    /// changes and thus requires no synchronization between dispatches.\n    ///\n    /// # Errors\n    ///\n    /// If launching the `Rocket` instance would fail, excepting network\n    /// errors, the `Error` is returned.\n    ///\n    /// ```rust,no_run\n    #[doc = $import]\n    ///\n    /// let rocket = rocket::build();\n    /// let client = Client::untracked(rocket);\n    /// ```\n    pub $($prefix)? fn untracked<P: Phase>(rocket: Rocket<P>) -> Result<Self, Error> {\n        Self::_new(rocket, false, false) $(.$suffix)?\n    }\n\n    pub $($prefix)? fn untracked_secure<P: Phase>(rocket: Rocket<P>) -> Result<Self, Error> {\n        Self::_new(rocket, false, true) $(.$suffix)?\n    }\n\n    /// Terminates `Client` by initiating a graceful shutdown via\n    /// [`Shutdown::notify()`] and running shutdown fairings.\n    ///\n    /// This method _must_ be called on a `Client` if graceful shutdown is\n    /// required for testing as `Drop` _does not_ signal `Shutdown` nor run\n    /// shutdown fairings. Returns the instance of `Rocket` being managed by\n    /// this client after all shutdown fairings run to completion.\n    ///\n    /// [`Shutdown::notify()`]: crate::Shutdown::notify()\n    ///\n    /// ```rust,no_run\n    #[doc = $import]\n    ///\n    /// # fn f(client: Client) {\n    /// let client: Client = client;\n    /// let rocket = client.terminate();\n    /// # }\n    /// ```\n    #[inline(always)]\n    pub $($prefix)? fn terminate(self) -> Rocket<Ignite> {\n        Self::_terminate(self) $(.$suffix)?\n    }\n\n    #[doc(hidden)]\n    pub $($prefix)? fn debug_with(routes: Vec<crate::Route>) -> Result<Self, Error> {\n        let rocket = crate::custom(crate::Config::debug_default());\n        Self::debug(rocket.mount(\"/\", routes)) $(.$suffix)?\n    }\n\n    #[doc(hidden)]\n    pub $($prefix)? fn debug(rocket: Rocket<crate::Build>) -> Result<Self, Error> {\n        use crate::config;\n\n        let figment = rocket.figment().clone()\n            .merge((config::Config::LOG_LEVEL, \"debug\"))\n            .select(config::Config::DEBUG_PROFILE);\n\n        Self::tracked(rocket.reconfigure(figment)) $(.$suffix)?\n    }\n\n    /// Returns a reference to the `Rocket` this client is creating requests\n    /// for.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $import]\n    ///\n    /// # Client::_test(|client, _, _| {\n    /// let client: &Client = client;\n    /// let rocket = client.rocket();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub fn rocket(&self) -> &Rocket<Orbit> {\n        &*self._rocket()\n    }\n\n    /// Returns a cookie jar containing all of the cookies this client is\n    /// currently tracking.\n    ///\n    /// If cookie tracking is disabled, the returned jar will always be empty.\n    /// Otherwise, it will contains all of the cookies collected from responses\n    /// to requests dispatched by this client that have not expired.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $import]\n    ///\n    /// # Client::_test(|client, _, _| {\n    /// let client: &Client = client;\n    /// let cookie = client.cookies();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub fn cookies(&self) -> crate::http::CookieJar<'_> {\n        let jar = self._with_raw_cookies(|jar| jar.clone());\n        crate::http::CookieJar::new(Some(jar), self.rocket())\n    }\n\n    req_method!($import, \"GET\", get, Method::Get);\n    req_method!($import, \"PUT\", put, Method::Put);\n    req_method!($import, \"POST\", post, Method::Post);\n    req_method!($import, \"DELETE\", delete, Method::Delete);\n    req_method!($import, \"OPTIONS\", options, Method::Options);\n    req_method!($import, \"HEAD\", head, Method::Head);\n    req_method!($import, \"PATCH\", patch, Method::Patch);\n\n    /// Create a local `GET` request to the URI `uri`.\n    ///\n    /// When dispatched, the request will be served by the instance of\n    /// Rocket within `self`. The request is not dispatched automatically.\n    /// To actually dispatch the request, call [`LocalRequest::dispatch()`]\n    /// on the returned request.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    #[doc = $import]\n    /// use rocket::http::Method;\n    ///\n    /// # Client::_test(|client, _, _| {\n    /// let client: &Client = client;\n    /// client.req(Method::Get, \"/hello\");\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub fn req<'c, 'u: 'c, U>(\n        &'c self,\n        method: Method,\n        uri: U\n    ) -> LocalRequest<'c>\n        where U: TryInto<Origin<'u>> + fmt::Display\n    {\n        self._req(method, uri)\n    }\n\n    #[cfg(test)]\n    #[allow(dead_code)]\n    fn _ensure_impls_exist() {\n        fn is_send<T: Send>() {}\n        is_send::<Self>();\n\n        fn is_debug<T: std::fmt::Debug>() {}\n        is_debug::<Self>();\n    }\n}}\n"
  },
  {
    "path": "core/lib/src/local/mod.rs",
    "content": "//! Structures for local dispatching of requests, primarily for testing.\n//!\n//! This module allows for simple request dispatching against a local,\n//! non-networked instance of Rocket. The primary use of this module is to unit\n//! and integration test Rocket applications by crafting requests, dispatching\n//! them, and verifying the response.\n//!\n//! # Async. vs. Blocking\n//!\n//! This module contains two variants, in its two submodules, of the same local\n//! API: [`asynchronous`], and [`blocking`]. As their names imply, the\n//! `asynchronous` API is `async`, returning a `Future` for operations that\n//! would otherwise block, while `blocking` blocks for the same operations.\n//!\n//! Unless your request handling requires concurrency to make progress, or\n//! you're making use of a `Client` in an environment that necessitates or would\n//! benefit from concurrency, you should use the `blocking` set of APIs due\n//! their ease-of-use. If your request handling _does_ require concurrency to\n//! make progress, for instance by having one handler `await` a response\n//! generated from a request to another handler, use the `asynchronous` set of\n//! APIs.\n//!\n//! Both APIs include a `Client` structure that is used to create `LocalRequest`\n//! structures that can be dispatched against a given [`Rocket`](crate::Rocket)\n//! instance to yield a `LocalResponse` structure. The APIs are identical except\n//! in that the `asynchronous` APIs return `Future`s for otherwise blocking\n//! operations.\n//!\n//! # Unit/Integration Testing\n//!\n//! This module is primarily intended to be used to test a Rocket application by\n//! constructing requests via `Client`, dispatching them, and validating the\n//! resulting response. As a complete example, consider the following \"Hello,\n//! world!\" application, with testing.\n//!\n//! ```rust\n//! #[macro_use] extern crate rocket;\n//!\n//! #[get(\"/\")]\n//! fn hello() -> &'static str {\n//!     \"Hello, world!\"\n//! }\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//!     rocket::build().mount(\"/\", routes![hello])\n//! }\n//!\n//! #[cfg(test)]\n//! mod test {\n//!     // Using the preferred `blocking` API.\n//!     #[test]\n//!     fn test_hello_world_blocking() {\n//!         use rocket::local::blocking::Client;\n//!\n//!         // Construct a client to use for dispatching requests.\n//!         let client = Client::tracked(super::rocket())\n//!             .expect(\"valid `Rocket`\");\n//!\n//!         // Dispatch a request to 'GET /' and validate the response.\n//!         let response = client.get(\"/\").dispatch();\n//!         assert_eq!(response.into_string().unwrap(), \"Hello, world!\");\n//!     }\n//!\n//!     // Using the `asynchronous` API.\n//!     #[rocket::async_test]\n//!     async fn test_hello_world_async() {\n//!         use rocket::local::asynchronous::Client;\n//!\n//!         // Construct a client to use for dispatching requests.\n//!         let client = Client::tracked(super::rocket()).await\n//!             .expect(\"valid `Rocket`\");\n//!\n//!         // Dispatch a request to 'GET /' and validate the response.\n//!         let response = client.get(\"/\").dispatch().await;\n//!         assert_eq!(response.into_string().await.unwrap(), \"Hello, world!\");\n//!     }\n//! }\n//! ```\n//!\n//! For more details on testing, see the [testing guide].\n//!\n//! [testing guide]: https://rocket.rs/master/guide/testing/\n//! [`Client`]: crate::local::asynchronous::Client\n//!\n//! # `Client`\n//!\n//! A `Client`, either [`blocking::Client`] or [`asynchronous::Client`],\n//! referred to as simply [`Client`] and [`async` `Client`], respectively,\n//! constructs requests for local dispatching.\n//!\n//! **Usage**\n//!\n//! A `Client` is constructed via the [`tracked()`] ([`async` `tracked()`]) or\n//! [`untracked()`] ([`async` `untracked()`]) methods from an already\n//! constructed `Rocket` instance. Once a value of `Client` has been\n//! constructed, [`get()`], [`put()`], [`post()`], and so on ([`async` `get()`],\n//! [`async` `put()`], [`async` `post()`]) can be called to create a\n//! [`LocalRequest`] ([`async` `LocalRequest`]) for dispatching.\n//!\n//! **Cookie Tracking**\n//!\n//! A `Client` constructed using `tracked()` propagates cookie changes made by\n//! responses to previously dispatched requests. In other words, if a previously\n//! dispatched request resulted in a response that adds a cookie, any future\n//! requests will contain that cookie. Similarly, cookies removed by a response\n//! won't be propagated further.\n//!\n//! This is typically the desired mode of operation for a `Client` as it removes\n//! the burden of manually tracking cookies. Under some circumstances, however,\n//! disabling this tracking may be desired. In these cases, use the\n//! `untracked()` constructor to create a `Client` that _will not_ track\n//! cookies.\n//!\n//! [`Client`]: blocking::Client\n//! [`async` `Client`]: asynchronous::Client\n//! [`LocalRequest`]: blocking::LocalRequest\n//! [`async` `LocalRequest`]: asynchronous::LocalRequest\n//!\n//! [`tracked()`]: blocking::Client::tracked()\n//! [`untracked()`]: blocking::Client::untracked()\n//! [`async` `tracked()`]: asynchronous::Client::tracked()\n//! [`async` `untracked()`]: asynchronous::Client::untracked()\n//!\n//! [`get()`]: blocking::Client::get()\n//! [`put()`]: blocking::Client::put()\n//! [`post()`]: blocking::Client::post()\n//! [`async` `get()`]: asynchronous::Client::get()\n//! [`async` `put()`]: asynchronous::Client::put()\n//! [`async` `post()`]: asynchronous::Client::post()\n//!\n//! **Example**\n//!\n//! For a usage example, see [`Client`] or [`async` `Client`].\n//!\n//! # `LocalRequest`\n//!\n//! A [`LocalRequest`] ([`async` `LocalRequest`]) is constructed via a `Client`.\n//! Once obtained, headers, cookies, including private cookies, the remote IP\n//! address, and the request body can all be set via methods on the\n//! `LocalRequest` structure.\n//!\n//! **Dispatching**\n//!\n//! A `LocalRequest` is dispatched by calling [`dispatch()`] ([`async`\n//! `dispatch()`]). The `LocalRequest` is consumed and a [`LocalResponse`]\n//! ([`async` `LocalResponse`]) is returned.\n//!\n//! Note that `LocalRequest` implements [`Clone`]. As such, if the same request\n//! needs to be dispatched multiple times, the request can first be cloned and\n//! then dispatched: `request.clone().dispatch()`.\n//!\n//! **Example**\n//!\n//! For a usage example, see [`LocalRequest`] or [`async` `LocalRequest`].\n//!\n//! [`LocalResponse`]: blocking::LocalResponse\n//! [`async` `LocalResponse`]: asynchronous::LocalResponse\n//! [`dispatch()`]: blocking::LocalRequest::dispatch()\n//! [`async` `dispatch()`]: asynchronous::LocalRequest::dispatch()\n//!\n//! # `LocalResponse`\n//!\n//! The result of `dispatch()`ing a `LocalRequest` is a [`LocalResponse`]\n//! ([`async` `LocalResponse`]). A `LocalResponse` can be queried for response\n//! metadata, including the HTTP status, headers, and cookies, via its getter\n//! methods. Additionally, the body of the response can be read into a string\n//! ([`into_string()`] or [`async` `into_string()`]) or a vector\n//! ([`into_bytes()`] or [`async` `into_bytes()`]).\n//!\n//! The response body must also be read directly using standard I/O mechanisms:\n//! the `blocking` `LocalResponse` implements `Read` while the `async`\n//! `LocalResponse` implements `AsyncRead`.\n//!\n//! For a usage example, see [`LocalResponse`] or [`async` `LocalResponse`].\n//!\n//! [`into_string()`]: blocking::LocalResponse::into_string()\n//! [`async` `into_string()`]: asynchronous::LocalResponse::into_string()\n//! [`into_bytes()`]: blocking::LocalResponse::into_bytes()\n//! [`async` `into_bytes()`]: asynchronous::LocalResponse::into_bytes()\n\n#[macro_use] mod client;\n#[macro_use] mod request;\n#[macro_use] mod response;\n\npub mod asynchronous;\npub mod blocking;\n"
  },
  {
    "path": "core/lib/src/local/request.rs",
    "content": "macro_rules! pub_request_impl {\n    ($import:literal $($prefix:tt $suffix:tt)?) =>\n{\n    /// Borrows the inner `Request` as seen by Rocket.\n    ///\n    /// Note that no routing has occurred and that there is no remote\n    /// address unless one has been explicitly set with\n    /// [`set_remote()`](Request::set_remote()).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $import]\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let inner: &rocket::Request = request.inner();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub fn inner(&self) -> &Request<'c> {\n        self._request()\n    }\n\n    /// Mutably borrows the inner `Request` as seen by Rocket.\n    ///\n    /// Note that no routing has occurred and that there is no remote\n    /// address unless one has been explicitly set with\n    /// [`set_remote()`](Request::set_remote()).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $import]\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let mut request: LocalRequest = request;\n    /// let inner: &mut rocket::Request = request.inner_mut();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub fn inner_mut(&mut self) -> &mut Request<'c> {\n        self._request_mut()\n    }\n\n    /// Add a header to this request.\n    ///\n    /// Any type that implements `Into<Header>` can be used here. Among\n    /// others, this includes [`ContentType`] and [`Accept`].\n    ///\n    /// [`ContentType`]: crate::http::ContentType\n    /// [`Accept`]: crate::http::Accept\n    ///\n    /// # Examples\n    ///\n    /// Add the Content-Type header:\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::http::Header;\n    /// use rocket::http::ContentType;\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let req = request\n    ///     .header(ContentType::JSON)\n    ///     .header(Header::new(\"X-Custom\", \"custom-value\"));\n    /// # });\n    /// ```\n    #[inline]\n    pub fn header<H>(mut self, header: H) -> Self\n        where H: Into<crate::http::Header<'static>>\n    {\n        self._request_mut().add_header(header.into());\n        self\n    }\n\n    /// Adds a header to this request without consuming `self`.\n    ///\n    /// # Examples\n    ///\n    /// Add the Content-Type header:\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::http::ContentType;\n    ///\n    /// # Client::_test(|_, mut request, _| {\n    /// let mut request: LocalRequest = request;\n    /// request.add_header(ContentType::JSON);\n    /// # });\n    /// ```\n    #[inline]\n    pub fn add_header<H>(&mut self, header: H)\n        where H: Into<crate::http::Header<'static>>\n    {\n        self._request_mut().add_header(header.into());\n    }\n\n    /// Set the remote address of this request to `address`.\n    ///\n    /// `address` may be any type that [can be converted into a `Endpoint`].\n    /// If `address` fails to convert, the remote is left unchanged.\n    ///\n    /// [can be converted into a `Endpoint`]: crate::listener::Endpoint#conversions\n    ///\n    /// # Examples\n    ///\n    /// Set the remote address to \"8.8.8.8:80\":\n    ///\n    /// ```rust\n    /// use std::net::Ipv4Addr;\n    ///\n    #[doc = $import]\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let req = request.remote(\"tcp:8.8.8.8:80\");\n    ///\n    /// let remote = req.inner().remote().unwrap().tcp().unwrap();\n    /// assert_eq!(remote.ip(), Ipv4Addr::new(8, 8, 8, 8));\n    /// assert_eq!(remote.port(), 80);\n    /// # });\n    /// ```\n    #[inline]\n    pub fn remote<T>(mut self, endpoint: T) -> Self\n        where T: TryInto<crate::listener::Endpoint>\n    {\n        if let Ok(endpoint) = endpoint.try_into() {\n            self.set_remote(endpoint);\n        } else {\n            warn!(\"remote failed to convert\");\n        }\n\n        self\n    }\n\n    /// Add a cookie to this request.\n    ///\n    /// # Examples\n    ///\n    /// Add `user_id` cookie:\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::http::Cookie;\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let req = request\n    ///     .cookie((\"username\", \"sb\"))\n    ///     .cookie((\"user_id\", \"12\"));\n    /// # });\n    /// ```\n    #[inline]\n    pub fn cookie<'a, C>(mut self, cookie: C) -> Self\n        where C: Into<crate::http::Cookie<'a>>\n    {\n        self._request_mut().cookies_mut().add_original(cookie.into().into_owned());\n        self\n    }\n\n    /// Add all of the cookies in `cookies` to this request.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::http::Cookie;\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let cookies = vec![(\"a\", \"b\"), (\"c\", \"d\")];\n    /// let req = request.cookies(cookies);\n    /// # });\n    /// ```\n    #[inline]\n    pub fn cookies<'a, C, I>(mut self, cookies: I) -> Self\n        where C: Into<crate::http::Cookie<'a>>,\n              I: IntoIterator<Item = C>\n    {\n        for cookie in cookies {\n            let cookie: crate::http::Cookie<'_> = cookie.into();\n            self._request_mut().cookies_mut().add_original(cookie.into_owned());\n        }\n\n        self\n    }\n\n    /// Add a [private cookie] to this request.\n    ///\n    /// [private cookie]: crate::http::CookieJar::add_private()\n    ///\n    /// # Examples\n    ///\n    /// Add `user_id` as a private cookie:\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::http::Cookie;\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let req = request.private_cookie((\"user_id\", \"sb\"));\n    /// # });\n    /// ```\n    #[cfg(feature = \"secrets\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"secrets\")))]\n    #[inline]\n    pub fn private_cookie<C>(mut self, cookie: C) -> Self\n        where C: Into<crate::http::Cookie<'static>>\n    {\n        self._request_mut().cookies_mut().add_original_private(cookie.into());\n        self\n    }\n\n    /// Set mTLS client certificates to send along with the request.\n    ///\n    /// If the request already contained certificates, they are replaced with\n    /// those in `reader.`\n    ///\n    /// `reader` is expected to be PEM-formatted and contain X509 certificates.\n    /// If it contains more than one certificate, the entire chain is set on the\n    /// request. If it contains items other than certificates, the certificate\n    /// chain up to the first non-certificate item is set on the request. If\n    /// `reader` is syntactically invalid PEM, certificates are cleared on the\n    /// request.\n    ///\n    /// The type `C` can be anything that implements [`std::io::Read`]. This\n    /// includes: `&[u8]`, `File`, `&File`, `Stdin`, and so on. To read a file\n    /// in at compile-time, use [`include_bytes!()`].\n    ///\n    /// ```rust\n    /// use std::fs::File;\n    ///\n    #[doc = $import]\n    /// use rocket::fs::relative;\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let path = relative!(\"../../examples/tls/private/ed25519_cert.pem\");\n    /// let req = request.identity(File::open(path).unwrap());\n    /// # });\n    /// ```\n    #[cfg(feature = \"mtls\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"mtls\")))]\n    pub fn identity<C: std::io::Read>(mut self, reader: C) -> Self {\n        use std::sync::Arc;\n        use crate::listener::Certificates;\n\n        let mut reader = std::io::BufReader::new(reader);\n        self._request_mut().connection.peer_certs = rustls_pemfile::certs(&mut reader)\n            .collect::<Result<Vec<_>, _>>()\n            .map(|certs| Arc::new(Certificates::from(certs)))\n            .ok();\n\n        self\n    }\n\n    /// Sets the body data of the request.\n    ///core/lib/src/local/request.rs\n    /// # Examples\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::http::ContentType;\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let req = request\n    ///     .header(ContentType::Text)\n    ///     .body(\"Hello, world!\");\n    /// # });\n    /// ```\n    #[inline]\n    pub fn body<S: AsRef<[u8]>>(mut self, body: S) -> Self {\n        // TODO: For CGI, we want to be able to set the body to be stdin\n        // without actually reading everything into a vector. Can we allow\n        // that here while keeping the simplicity? Looks like it would\n        // require us to reintroduce a NetStream::Local(Box<Read>) or\n        // something like that.\n        *self._body_mut() = body.as_ref().into();\n        self\n    }\n\n    /// Sets the body to `value` serialized as JSON with `Content-Type`\n    /// [`ContentType::JSON`](crate::http::ContentType::JSON).\n    ///\n    /// If `value` fails to serialize, the body is set to empty. The\n    /// `Content-Type` header is _always_ set.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::serde::Serialize;\n    /// use rocket::http::ContentType;\n    ///\n    /// #[derive(Serialize)]\n    /// struct Task {\n    ///     id: usize,\n    ///     complete: bool,\n    /// }\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let task = Task { id: 10, complete: false };\n    ///\n    /// let request: LocalRequest = request;\n    /// let req = request.json(&task);\n    /// assert_eq!(req.content_type(), Some(&ContentType::JSON));\n    /// # });\n    /// ```\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"json\")))]\n    pub fn json<T: crate::serde::Serialize>(self, value: &T) -> Self {\n        let json = serde_json::to_vec(&value).unwrap_or_default();\n        self.header(crate::http::ContentType::JSON).body(json)\n    }\n\n    /// Sets the body to `value` serialized as MessagePack with `Content-Type`\n    /// [`ContentType::MsgPack`](crate::http::ContentType::MsgPack).\n    ///\n    /// If `value` fails to serialize, the body is set to empty. The\n    /// `Content-Type` header is _always_ set.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::serde::Serialize;\n    /// use rocket::http::ContentType;\n    ///\n    /// #[derive(Serialize)]\n    /// struct Task {\n    ///     id: usize,\n    ///     complete: bool,\n    /// }\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let task = Task { id: 10, complete: false };\n    ///\n    /// let request: LocalRequest = request;\n    /// let req = request.msgpack(&task);\n    /// assert_eq!(req.content_type(), Some(&ContentType::MsgPack));\n    /// # });\n    /// ```\n    #[cfg(feature = \"msgpack\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"msgpack\")))]\n    pub fn msgpack<T: crate::serde::Serialize>(self, value: &T) -> Self {\n        let msgpack = rmp_serde::to_vec(value).unwrap_or_default();\n        self.header(crate::http::ContentType::MsgPack).body(msgpack)\n    }\n\n    /// Set the body (data) of the request without consuming `self`.\n    ///\n    /// # Examples\n    ///\n    /// Set the body to be a JSON structure; also sets the Content-Type.\n    ///\n    /// ```rust\n    #[doc = $import]\n    /// use rocket::http::ContentType;\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let mut request = request.header(ContentType::JSON);\n    /// request.set_body(r#\"{ \"key\": \"value\", \"array\": [1, 2, 3] }\"#);\n    /// # });\n    /// ```\n    #[inline]\n    pub fn set_body<S: AsRef<[u8]>>(&mut self, body: S) {\n        *self._body_mut() = body.as_ref().into();\n    }\n\n    /// Dispatches the request, returning the response.\n    ///\n    /// This method consumes `self` and is the preferred mechanism for\n    /// dispatching.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $import]\n    ///\n    /// # Client::_test(|_, request, _| {\n    /// let request: LocalRequest = request;\n    /// let response = request.dispatch();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub $($prefix)? fn dispatch(self) -> LocalResponse<'c> {\n        self._dispatch()$(.$suffix)?\n    }\n\n    #[cfg(test)]\n    #[allow(dead_code)]\n    fn _ensure_impls_exist() {\n        fn is_clone_debug<T: Clone + std::fmt::Debug>() {}\n        is_clone_debug::<Self>();\n\n        fn is_deref_req<'a, T: std::ops::Deref<Target = Request<'a>>>() {}\n        is_deref_req::<Self>();\n\n        fn is_deref_mut_req<'a, T: std::ops::DerefMut<Target = Request<'a>>>() {}\n        is_deref_mut_req::<Self>();\n    }\n}}\n"
  },
  {
    "path": "core/lib/src/local/response.rs",
    "content": "macro_rules! getter_method {\n    ($doc_prelude:literal, $desc:literal, $f:ident -> $r:ty) => (\n        getter_method!(@$doc_prelude, $f, $desc, $r,\n            concat!(\"let \", stringify!($f), \" = response.\", stringify!($f), \"();\"));\n    );\n    (@$doc_prelude:literal, $f:ident, $desc:expr, $r:ty, $use_it:expr) => (\n        /// Returns the\n        #[doc = $desc]\n        /// of `self`.\n        ///\n        /// # Example\n        ///\n        /// ```rust\n        #[doc = $doc_prelude]\n        ///\n        /// # Client::_test(|_, _, response| {\n        /// let response: LocalResponse = response;\n        #[doc = $use_it]\n        /// # });\n        /// ```\n        #[inline(always)]\n        pub fn $f(&self) -> $r {\n            self._response().$f()\n        }\n    )\n}\n\nmacro_rules! pub_response_impl {\n    ($doc_prelude:literal $($prefix:tt $suffix:tt)?) =>\n{\n    getter_method!($doc_prelude, \"HTTP status\",\n        status -> crate::http::Status);\n\n    getter_method!($doc_prelude, \"Content-Type, if a valid one is set,\",\n        content_type -> Option<crate::http::ContentType>);\n\n    getter_method!($doc_prelude, \"HTTP headers\",\n        headers -> &crate::http::HeaderMap<'_>);\n\n    /// Return a cookie jar containing the HTTP cookies in the response.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $doc_prelude]\n    ///\n    /// # Client::_test(|_, _, response| {\n    /// let response: LocalResponse = response;\n    /// let string = response.cookies();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub fn cookies(&self) -> &crate::http::CookieJar<'_> {\n        self._cookies()\n    }\n\n    getter_method!($doc_prelude, \"response body, if there is one,\",\n        body -> &crate::response::Body<'_>);\n\n    /// Consumes `self` and reads the entirety of its body into a string.\n    ///\n    /// If reading fails, the body contains invalid UTF-8 characters, or the\n    /// body is unset in the response, returns `None`. Otherwise, returns\n    /// `Some`. The string may be empty if the body is empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $doc_prelude]\n    ///\n    /// # Client::_test(|_, _, response| {\n    /// let response: LocalResponse = response;\n    /// let string = response.into_string();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub $($prefix)? fn into_string(self) -> Option<String> {\n        if self._response().body().is_none() {\n            return None;\n        }\n\n        self._into_string() $(.$suffix)? .ok()\n    }\n\n    /// Consumes `self` and reads the entirety of its body into a `Vec` of\n    /// bytes.\n    ///\n    /// If reading fails or the body is unset in the response, returns `None`.\n    /// Otherwise, returns `Some`. The returned vector may be empty if the body\n    /// is empty.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $doc_prelude]\n    ///\n    /// # Client::_test(|_, _, response| {\n    /// let response: LocalResponse = response;\n    /// let bytes = response.into_bytes();\n    /// # });\n    /// ```\n    #[inline(always)]\n    pub $($prefix)? fn into_bytes(self) -> Option<Vec<u8>> {\n        if self._response().body().is_none() {\n            return None;\n        }\n\n        self._into_bytes() $(.$suffix)? .ok()\n    }\n\n    /// Consumes `self` and deserializes its body as JSON without buffering in\n    /// memory.\n    ///\n    /// If deserialization fails or the body is unset in the response, returns\n    /// `None`. Otherwise, returns `Some`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $doc_prelude]\n    /// use rocket::serde::Deserialize;\n    ///\n    /// #[derive(Deserialize)]\n    /// struct Task {\n    ///     id: usize,\n    ///     complete: bool,\n    ///     text: String,\n    /// }\n    ///\n    /// # Client::_test(|_, _, response| {\n    /// let response: LocalResponse = response;\n    /// let task = response.into_json::<Task>();\n    /// # });\n    /// ```\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"json\")))]\n    pub $($prefix)? fn into_json<T>(self) -> Option<T>\n        where T: Send + serde::de::DeserializeOwned + 'static\n    {\n        if self._response().body().is_none() {\n            return None;\n        }\n\n        self._into_json() $(.$suffix)?\n    }\n\n    /// Consumes `self` and deserializes its body as MessagePack without\n    /// buffering in memory.\n    ///\n    /// If deserialization fails or the body is unset in the response, returns\n    /// `None`. Otherwise, returns `Some`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    #[doc = $doc_prelude]\n    /// use rocket::serde::Deserialize;\n    ///\n    /// #[derive(Deserialize)]\n    /// struct Task {\n    ///     id: usize,\n    ///     complete: bool,\n    ///     text: String,\n    /// }\n    ///\n    /// # Client::_test(|_, _, response| {\n    /// let response: LocalResponse = response;\n    /// let task = response.into_msgpack::<Task>();\n    /// # });\n    /// ```\n    #[cfg(feature = \"msgpack\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"msgpack\")))]\n    pub $($prefix)? fn into_msgpack<T>(self) -> Option<T>\n        where T: Send + serde::de::DeserializeOwned + 'static\n    {\n        if self._response().body().is_none() {\n            return None;\n        }\n\n        self._into_msgpack() $(.$suffix)?\n    }\n\n    #[cfg(test)]\n    #[allow(dead_code)]\n    fn _ensure_impls_exist() {\n        fn is_debug<T: std::fmt::Debug>() {}\n        is_debug::<Self>();\n    }\n}}\n"
  },
  {
    "path": "core/lib/src/mtls/certificate.rs",
    "content": "use ref_cast::RefCast;\n\nuse crate::mtls::{x509, oid, bigint, Name, Result, Error};\nuse crate::request::{Request, FromRequest, Outcome};\nuse crate::http::Status;\n\n/// A request guard for validated, verified client certificates.\n///\n/// This type is a wrapper over [`x509::TbsCertificate`] with convenient\n/// methods and complete documentation. Should the data exposed by the inherent\n/// methods not suffice, this type derefs to [`x509::TbsCertificate`].\n///\n/// # Request Guard\n///\n/// The request guard implementation succeeds if:\n///\n///   * MTLS is [configured](crate::mtls).\n///   * The client presents certificates.\n///   * The certificates are valid and not expired.\n///   * The client's certificate chain was signed by the CA identified by the\n///     configured `ca_certs` and with respect to SNI, if any. See [module level\n///     docs](crate::mtls) for configuration details.\n///\n/// If the client does not present certificates, the guard _forwards_ with a\n/// status of 401 Unauthorized.\n///\n/// If the certificate chain fails to validate or verify, the guard _fails_ with\n/// the respective [`Error`] a status of 401 Unauthorized.\n///\n/// # Wrapping\n///\n/// To implement roles, the `Certificate` guard can be wrapped with a more\n/// semantically meaningful type with extra validation. For example, if a\n/// certificate with a specific serial number is known to belong to an\n/// administrator, a `CertifiedAdmin` type can authorize as follow:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::mtls::{self, bigint::BigUint, Certificate};\n/// use rocket::request::{Request, FromRequest, Outcome};\n/// use rocket::outcome::try_outcome;\n/// use rocket::http::Status;\n///\n/// // The serial number for the certificate issued to the admin.\n/// const ADMIN_SERIAL: &str = \"65828378108300243895479600452308786010218223563\";\n///\n/// // A request guard that authenticates and authorizes an administrator.\n/// struct CertifiedAdmin<'r>(Certificate<'r>);\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for CertifiedAdmin<'r> {\n///     type Error = mtls::Error;\n///\n///     async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n///         let cert = try_outcome!(req.guard::<Certificate<'r>>().await);\n///         if let Some(true) = cert.has_serial(ADMIN_SERIAL) {\n///             Outcome::Success(CertifiedAdmin(cert))\n///         } else {\n///             Outcome::Forward(Status::Unauthorized)\n///         }\n///     }\n/// }\n///\n/// #[get(\"/admin\")]\n/// fn admin(admin: CertifiedAdmin<'_>) {\n///     // This handler can only execute if an admin is authenticated.\n/// }\n///\n/// #[get(\"/admin\", rank = 2)]\n/// fn unauthorized(user: Option<Certificate<'_>>) {\n///     // This handler always executes, whether there's a non-admin user that's\n///     // authenticated (user = Some()) or not (user = None).\n/// }\n/// ```\n///\n/// # Example\n///\n/// To retrieve certificate data in a route, use `Certificate` as a guard:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::get;\n/// use rocket::mtls::{self, Certificate};\n///\n/// #[get(\"/auth\")]\n/// fn auth(cert: Certificate<'_>) {\n///     // This handler only runs when a valid certificate was presented.\n/// }\n///\n/// #[get(\"/maybe\")]\n/// fn maybe_auth(cert: Option<Certificate<'_>>) {\n///     // This handler runs even if no certificate was presented or an invalid\n///     // certificate was presented.\n/// }\n///\n/// #[get(\"/ok\")]\n/// fn ok_auth(cert: mtls::Result<Certificate<'_>>) {\n///     // This handler does not run if a certificate was not presented but\n///     // _does_ run if a valid (Ok) or invalid (Err) one was presented.\n/// }\n/// ```\n#[derive(Debug, PartialEq)]\npub struct Certificate<'a> {\n    x509: x509::X509Certificate<'a>,\n    data: &'a CertificateDer<'a>,\n}\n\npub use rustls::pki_types::CertificateDer;\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for Certificate<'r> {\n    type Error = Error;\n\n    async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n        use crate::outcome::{try_outcome, IntoOutcome};\n\n        let certs = req.connection\n            .peer_certs\n            .as_ref()\n            .or_forward(Status::Unauthorized);\n\n        let chain = try_outcome!(certs);\n        Certificate::parse(chain.inner()).or_error(Status::Unauthorized)\n    }\n}\n\nimpl<'a> Certificate<'a> {\n    /// PRIVATE: For internal Rocket use only!\n    fn parse<'r>(chain: &'r [CertificateDer<'r>]) -> Result<Certificate<'r>> {\n        let data = chain.first().ok_or(Error::Empty)?;\n        let x509 = Certificate::parse_one(data)?;\n        Ok(Certificate { x509, data })\n    }\n\n    fn parse_one(raw: &[u8]) -> Result<x509::X509Certificate<'_>> {\n        use oid::OID_X509_EXT_SUBJECT_ALT_NAME as SUBJECT_ALT_NAME;\n        use x509::FromDer;\n\n        let (left, x509) = x509::X509Certificate::from_der(raw)?;\n        if !left.is_empty() {\n            return Err(Error::Trailing(left.len()));\n        }\n\n        // Ensure we have a subject or a subjectAlt.\n        if x509.subject().as_raw().is_empty() {\n            if let Some(ext) = x509.extensions().iter().find(|e| e.oid == SUBJECT_ALT_NAME) {\n                if let x509::ParsedExtension::SubjectAlternativeName(..) = ext.parsed_extension() {\n                    return Err(Error::NoSubject);\n                } else if !ext.critical {\n                    return Err(Error::NonCriticalSubjectAlt);\n                }\n            } else {\n                return Err(Error::NoSubject);\n            }\n        }\n\n        Ok(x509)\n    }\n\n    #[inline(always)]\n    fn inner(&self) -> &x509::TbsCertificate<'a> {\n        &self.x509.tbs_certificate\n    }\n\n    /// Returns the serial number of the X.509 certificate.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::get;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     let cert = cert.serial();\n    /// }\n    /// ```\n    pub fn serial(&self) -> &bigint::BigUint {\n        &self.inner().serial\n    }\n\n    /// Returns the version of the X.509 certificate.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::get;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     let cert = cert.version();\n    /// }\n    /// ```\n    pub fn version(&self) -> u32 {\n        self.inner().version.0\n    }\n\n    /// Returns the subject (a \"DN\" or \"Distinguished Name\") of the X.509\n    /// certificate.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::get;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     if let Some(name) = cert.subject().common_name() {\n    ///         println!(\"Hello, {}!\", name);\n    ///     }\n    /// }\n    /// ```\n    pub fn subject(&self) -> &Name<'a> {\n        Name::ref_cast(&self.inner().subject)\n    }\n\n    /// Returns the issuer (a \"DN\" or \"Distinguished Name\") of the X.509\n    /// certificate.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::get;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     if let Some(name) = cert.issuer().common_name() {\n    ///         println!(\"Issued by: {}\", name);\n    ///     }\n    /// }\n    /// ```\n    pub fn issuer(&self) -> &Name<'a> {\n        Name::ref_cast(&self.inner().issuer)\n    }\n\n    /// Returns a slice of the extensions in the X.509 certificate.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::get;\n    /// use rocket::mtls::{oid, x509, Certificate};\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     let subject_alt = cert.extensions().iter()\n    ///         .find(|e| e.oid == oid::OID_X509_EXT_SUBJECT_ALT_NAME)\n    ///         .and_then(|e| match e.parsed_extension() {\n    ///             x509::ParsedExtension::SubjectAlternativeName(s) => Some(s),\n    ///             _ => None\n    ///         });\n    ///\n    ///     if let Some(subject_alt) = subject_alt {\n    ///         for name in &subject_alt.general_names {\n    ///             if let x509::GeneralName::RFC822Name(name) = name {\n    ///                 println!(\"An email, perhaps? {}\", name);\n    ///             }\n    ///         }\n    ///     }\n    /// }\n    /// ```\n    pub fn extensions(&self) -> &[x509::X509Extension<'a>] {\n        self.inner().extensions()\n    }\n\n    /// Checks if the certificate has the serial number `number`.\n    ///\n    /// If `number` is not a valid unsigned integer in base 10, returns `None`.\n    ///\n    /// Otherwise, returns `Some(true)` if it does and `Some(false)` if it does\n    /// not.\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::get;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// const SERIAL: &str = \"65828378108300243895479600452308786010218223563\";\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     if cert.has_serial(SERIAL).unwrap_or(false) {\n    ///         println!(\"certificate has the expected serial number\");\n    ///     }\n    /// }\n    /// ```\n    pub fn has_serial(&self, number: &str) -> Option<bool> {\n        let uint: bigint::BigUint = number.parse().ok()?;\n        Some(&uint == self.serial())\n    }\n\n    /// Returns the raw, unmodified, DER-encoded X.509 certificate data bytes.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::get;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// const SHA256_FINGERPRINT: &str =\n    ///     \"CE C2 4E 01 00 FF F7 78 CB A4 AA CB D2 49 DD 09 \\\n    ///      02 EF 0E 9B DA 89 2A E4 0D F4 09 83 97 C1 97 0D\";\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     # fn sha256_fingerprint(bytes: &[u8]) -> String { todo!() }\n    ///     if sha256_fingerprint(cert.as_bytes()) == SHA256_FINGERPRINT {\n    ///         println!(\"certificate fingerprint matched\");\n    ///     }\n    /// }\n    /// ```\n    pub fn as_bytes(&self) -> &'a [u8] {\n        self.data\n    }\n}\n\nimpl<'a> std::ops::Deref for Certificate<'a> {\n    type Target = x509::TbsCertificate<'a>;\n\n    fn deref(&self) -> &Self::Target {\n        self.inner()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/mtls/config.rs",
    "content": "use std::io;\n\nuse figment::value::magic::{RelativePathBuf, Either};\nuse serde::{Serialize, Deserialize};\n\nuse crate::tls::{Result, Error};\n\n/// Mutual TLS configuration.\n///\n/// Configuration works in concert with the [`mtls`](crate::mtls) module, which\n/// provides a request guard to validate, verify, and retrieve client\n/// certificates in routes.\n///\n/// By default, mutual TLS is disabled and client certificates are not required,\n/// validated or verified. To enable mutual TLS, the `mtls` feature must be\n/// enabled and support configured via two `tls.mutual` parameters:\n///\n///   * `ca_certs`\n///\n///     A required path to a PEM file or raw bytes to a DER-encoded X.509 TLS\n///     certificate chain for the certificate authority to verify client\n///     certificates against. When a path is configured in a file, such as\n///     `Rocket.toml`, relative paths are interpreted as relative to the source\n///     file's directory.\n///\n///   * `mandatory`\n///\n///     An optional boolean that control whether client authentication is\n///     required.\n///\n///     When `true`, client authentication is required. TLS connections where\n///     the client does not present a certificate are immediately terminated.\n///     When `false`, the client is not required to present a certificate. In\n///     either case, if a certificate _is_ presented, it must be valid or the\n///     connection is terminated.\n///\n/// In a `Rocket.toml`, configuration might look like:\n///\n/// ```toml\n/// [default.tls.mutual]\n/// ca_certs = \"/ssl/ca_cert.pem\"\n/// mandatory = true                # when absent, defaults to false\n/// ```\n///\n/// Programmatically, configuration might look like:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::mtls::MtlsConfig;\n/// use rocket::figment::providers::Serialized;\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     let mtls = MtlsConfig::from_path(\"/ssl/ca_cert.pem\");\n///     rocket::custom(rocket::Config::figment().merge((\"tls.mutual\", mtls)))\n/// }\n/// ```\n///\n/// Once mTLS is configured, the [`mtls::Certificate`](crate::mtls::Certificate)\n/// request guard can be used to retrieve client certificates in routes.\n#[derive(PartialEq, Debug, Clone, Deserialize, Serialize)]\npub struct MtlsConfig {\n    /// Path to a PEM file with, or raw bytes for, DER-encoded Certificate\n    /// Authority certificates which will be used to verify client-presented\n    /// certificates.\n    // TODO: Support more than one CA root.\n    pub(crate) ca_certs: Either<RelativePathBuf, Vec<u8>>,\n    /// Whether the client is required to present a certificate.\n    ///\n    /// When `true`, the client is required to present a valid certificate to\n    /// proceed with TLS. When `false`, the client is not required to present a\n    /// certificate. In either case, if a certificate _is_ presented, it must be\n    /// valid or the connection is terminated.\n    #[serde(default)]\n    #[serde(deserialize_with = \"figment::util::bool_from_str_or_int\")]\n    pub mandatory: bool,\n}\n\nimpl MtlsConfig {\n    /// Constructs a `MtlsConfig` from a path to a PEM file with a certificate\n    /// authority `ca_certs` DER-encoded X.509 TLS certificate chain. This\n    /// method does no validation; it simply creates an [`MtlsConfig`] for later\n    /// use.\n    ///\n    /// These certificates will be used to verify client-presented certificates\n    /// in TLS connections.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::mtls::MtlsConfig;\n    ///\n    /// let tls_config = MtlsConfig::from_path(\"/ssl/ca_certs.pem\");\n    /// ```\n    pub fn from_path<C: AsRef<std::path::Path>>(ca_certs: C) -> Self {\n        MtlsConfig {\n            ca_certs: Either::Left(ca_certs.as_ref().to_path_buf().into()),\n            mandatory: Default::default()\n        }\n    }\n\n    /// Constructs a `MtlsConfig` from a byte buffer to a certificate authority\n    /// `ca_certs` DER-encoded X.509 TLS certificate chain. This method does no\n    /// validation; it simply creates an [`MtlsConfig`] for later use.\n    ///\n    /// These certificates will be used to verify client-presented certificates\n    /// in TLS connections.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::mtls::MtlsConfig;\n    ///\n    /// # let ca_certs_buf = &[];\n    /// let mtls_config = MtlsConfig::from_bytes(ca_certs_buf);\n    /// ```\n    pub fn from_bytes(ca_certs: &[u8]) -> Self {\n        MtlsConfig {\n            ca_certs: Either::Right(ca_certs.to_vec()),\n            mandatory: Default::default()\n        }\n    }\n\n    /// Sets whether client authentication is required. Disabled by default.\n    ///\n    /// When `true`, client authentication will be required. TLS connections\n    /// where the client does not present a certificate will be immediately\n    /// terminated. When `false`, the client is not required to present a\n    /// certificate. In either case, if a certificate _is_ presented, it must be\n    /// valid or the connection is terminated.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::mtls::MtlsConfig;\n    ///\n    /// # let ca_certs_buf = &[];\n    /// let mtls_config = MtlsConfig::from_bytes(ca_certs_buf).mandatory(true);\n    /// ```\n    pub fn mandatory(mut self, mandatory: bool) -> Self {\n        self.mandatory = mandatory;\n        self\n    }\n\n    /// Returns the value of the `ca_certs` parameter.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::mtls::MtlsConfig;\n    ///\n    /// # let ca_certs_buf = &[];\n    /// let mtls_config = MtlsConfig::from_bytes(ca_certs_buf).mandatory(true);\n    /// assert_eq!(mtls_config.ca_certs().unwrap_right(), ca_certs_buf);\n    /// ```\n    pub fn ca_certs(&self) -> either::Either<std::path::PathBuf, &[u8]> {\n        match &self.ca_certs {\n            Either::Left(path) => either::Either::Left(path.relative()),\n            Either::Right(bytes) => either::Either::Right(bytes),\n        }\n    }\n\n    #[inline(always)]\n    pub fn ca_certs_reader(&self) -> io::Result<Box<dyn io::BufRead + Sync + Send>> {\n        crate::tls::config::to_reader(&self.ca_certs)\n    }\n\n    /// Load and decode CA certificates from `reader`.\n    pub(crate) fn load_ca_certs(&self) -> Result<rustls::RootCertStore> {\n        let mut roots = rustls::RootCertStore::empty();\n        for cert in rustls_pemfile::certs(&mut self.ca_certs_reader()?) {\n            roots.add(cert?).map_err(Error::CertAuth)?;\n        }\n\n        Ok(roots)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::path::Path;\n    use figment::{Figment, providers::{Toml, Format}};\n\n    use crate::mtls::MtlsConfig;\n\n    #[test]\n    fn test_mtls_config() {\n        figment::Jail::expect_with(|jail| {\n            jail.create_file(\"MTLS.toml\", r#\"\n                certs = \"/ssl/cert.pem\"\n                key = \"/ssl/key.pem\"\n            \"#)?;\n\n            let figment = || Figment::from(Toml::file(\"MTLS.toml\"));\n            figment().extract::<MtlsConfig>().expect_err(\"no ca\");\n\n            jail.create_file(\"MTLS.toml\", r#\"\n                ca_certs = \"/ssl/ca.pem\"\n            \"#)?;\n\n            let mtls: MtlsConfig = figment().extract()?;\n            assert_eq!(mtls.ca_certs().unwrap_left(), Path::new(\"/ssl/ca.pem\"));\n            assert!(!mtls.mandatory);\n\n            jail.create_file(\"MTLS.toml\", r#\"\n                ca_certs = \"/ssl/ca.pem\"\n                mandatory = true\n            \"#)?;\n\n            let mtls: MtlsConfig = figment().extract()?;\n            assert_eq!(mtls.ca_certs().unwrap_left(), Path::new(\"/ssl/ca.pem\"));\n            assert!(mtls.mandatory);\n\n            jail.create_file(\"MTLS.toml\", r#\"\n                ca_certs = \"relative/ca.pem\"\n            \"#)?;\n\n            let mtls: MtlsConfig = figment().extract()?;\n            assert_eq!(mtls.ca_certs().unwrap_left(), jail.directory().join(\"relative/ca.pem\"));\n\n            Ok(())\n        });\n    }\n}\n"
  },
  {
    "path": "core/lib/src/mtls/error.rs",
    "content": "use std::fmt;\nuse std::num::NonZeroUsize;\n\nuse crate::mtls::x509::{self, nom};\n\n/// An error returned by the [`Certificate`](crate::mtls::Certificate) guard.\n///\n/// To retrieve this error in a handler, use an `mtls::Result<Certificate>`\n/// guard type:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::get;\n/// use rocket::mtls::{self, Certificate};\n///\n/// #[get(\"/auth\")]\n/// fn auth(cert: mtls::Result<Certificate<'_>>) {\n///     match cert {\n///         Ok(cert) => { /* do something with the client cert */ },\n///         Err(e) => { /* do something with the error */ },\n///     }\n/// }\n/// ```\n#[derive(Debug, Clone)]\n#[non_exhaustive]\npub enum Error {\n    /// The certificate chain presented by the client had no certificates.\n    Empty,\n    /// The certificate contained neither a subject nor a subjectAlt extension.\n    NoSubject,\n    /// There is no subject and the subjectAlt is not marked as critical.\n    NonCriticalSubjectAlt,\n    /// An error occurred while parsing the certificate.\n    Parse(x509::X509Error),\n    /// The certificate parsed partially but is incomplete.\n    ///\n    /// If `Some(n)`, then `n` more bytes were expected. Otherwise, the number\n    /// of expected bytes is unknown.\n    Incomplete(Option<NonZeroUsize>),\n    /// The certificate contained `.0` bytes of trailing data.\n    Trailing(usize),\n}\n\nimpl fmt::Display for Error {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Error::Parse(e) => write!(f, \"parse error: {}\", e),\n            Error::Incomplete(_) => write!(f, \"incomplete certificate data\"),\n            Error::Trailing(n) => write!(f, \"found {} trailing bytes\", n),\n            Error::Empty => write!(f, \"empty certificate chain\"),\n            Error::NoSubject => write!(f, \"empty subject without subjectAlt\"),\n            Error::NonCriticalSubjectAlt => write!(f, \"empty subject without critical subjectAlt\"),\n        }\n    }\n}\n\nimpl From<nom::Err<x509::X509Error>> for Error {\n    fn from(e: nom::Err<x509::X509Error>) -> Self {\n        match e {\n            nom::Err::Incomplete(nom::Needed::Unknown) => Error::Incomplete(None),\n            nom::Err::Incomplete(nom::Needed::Size(n)) => Error::Incomplete(Some(n)),\n            nom::Err::Error(e) | nom::Err::Failure(e) => Error::Parse(e),\n        }\n    }\n}\n\nimpl std::error::Error for Error {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        match self {\n            Error::Parse(e) => Some(e),\n            _ => None\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/mtls/mod.rs",
    "content": "//! Support for mutual TLS client certificates.\n//!\n//! For details on how to configure mutual TLS, see [`MtlsConfig`] and the [TLS\n//! guide](https://rocket.rs/master/guide/configuration/#tls). See\n//! [`Certificate`] for a request guard that validates, verifies, and retrieves\n//! client certificates.\n\npub mod oid {\n    //! Lower-level OID types re-exported from\n    //! [`oid_registry`](https://docs.rs/oid-registry/0.4) and\n    //! [`der-parser`](https://docs.rs/der-parser/7).\n\n    pub use x509_parser::oid_registry::*;\n    pub use x509_parser::objects::*;\n}\n\npub mod bigint {\n    //! Signed and unsigned big integer types re-exported from\n    //! [`num_bigint`](https://docs.rs/num-bigint/0.4).\n    pub use x509_parser::der_parser::num_bigint::*;\n}\n\npub mod x509 {\n    //! Lower-level X.509 types re-exported from\n    //! [`x509_parser`](https://docs.rs/x509-parser/0.13).\n    //!\n    //! Lack of documentation is directly inherited from the source crate.\n    //! Prefer to use Rocket's wrappers when possible.\n\n    pub use x509_parser::prelude::*;\n}\n\nmod certificate;\nmod error;\nmod name;\nmod config;\n\npub use error::Error;\npub use name::Name;\npub use config::MtlsConfig;\npub use certificate::{Certificate, CertificateDer};\n\n/// A type alias for `Result` with the error type set to [`Error`].\npub type Result<T, E = Error> = std::result::Result<T, E>;\n"
  },
  {
    "path": "core/lib/src/mtls/name.rs",
    "content": "use std::fmt;\nuse std::ops::Deref;\n\nuse ref_cast::RefCast;\n\nuse crate::mtls::x509::X509Name;\nuse crate::mtls::oid;\n\n/// An X.509 Distinguished Name (DN) found in a\n/// [`Certificate`](crate::mtls::Certificate).\n///\n/// This type is a wrapper over [`X509Name`] with convenient methods and\n/// complete documentation. Should the data exposed by the inherent methods not\n/// suffice, this type derefs to [`X509Name`].\n#[repr(transparent)]\n#[derive(Debug, PartialEq, RefCast)]\npub struct Name<'a>(X509Name<'a>);\n\nimpl<'a> Name<'a> {\n    /// Returns the _first_ UTF-8 _string_ common name, if any.\n    ///\n    /// Note that common names need not be UTF-8 strings, or strings at all.\n    /// This method returns the first common name attribute that is.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     if let Some(name) = cert.subject().common_name() {\n    ///         println!(\"Hello, {}!\", name);\n    ///     }\n    /// }\n    /// ```\n    pub fn common_name(&self) -> Option<&'a str> {\n        self.common_names().next()\n    }\n\n    /// Returns an iterator over all of the UTF-8 _string_ common names in\n    /// `self`.\n    ///\n    /// Note that common names need not be UTF-8 strings, or strings at all.\n    /// This method filters the common names in `self` to those that are. Use\n    /// the raw [`iter_common_name()`](#method.iter_common_name) to iterate over\n    /// all value types.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     for name in cert.issuer().common_names() {\n    ///         println!(\"Issued by {}.\", name);\n    ///     }\n    /// }\n    /// ```\n    pub fn common_names(&self) -> impl Iterator<Item = &'a str> + '_ {\n        self.iter_by_oid(&oid::OID_X509_COMMON_NAME).filter_map(|n| n.as_str().ok())\n    }\n\n    /// Returns the _first_ UTF-8 _string_ email address, if any.\n    ///\n    /// Note that email addresses need not be UTF-8 strings, or strings at all.\n    /// This method returns the first email address attribute that is.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     if let Some(email) = cert.subject().email() {\n    ///         println!(\"Hello, {}!\", email);\n    ///     }\n    /// }\n    /// ```\n    pub fn email(&self) -> Option<&'a str> {\n        self.emails().next()\n    }\n\n    /// Returns an iterator over all of the UTF-8 _string_ email addresses in\n    /// `self`.\n    ///\n    /// Note that email addresses need not be UTF-8 strings, or strings at all.\n    /// This method filters the email address in `self` to those that are. Use\n    /// the raw [`iter_email()`](#method.iter_email) to iterate over all value\n    /// types.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     for email in cert.subject().emails() {\n    ///         println!(\"Reach me at: {}\", email);\n    ///     }\n    /// }\n    /// ```\n    pub fn emails(&self) -> impl Iterator<Item = &'a str> + '_ {\n        self.iter_by_oid(&oid::OID_PKCS9_EMAIL_ADDRESS).filter_map(|n| n.as_str().ok())\n    }\n\n    /// Returns `true` if `self` has no data.\n    ///\n    /// When this is the case for a `subject()`, the subject data can be found\n    /// in the `subjectAlt` [`extension`].\n    ///\n    /// [`extension`]: crate::mtls::Certificate::extensions()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::mtls::Certificate;\n    ///\n    /// #[get(\"/auth\")]\n    /// fn auth(cert: Certificate<'_>) {\n    ///     let no_data = cert.subject().is_empty();\n    /// }\n    /// ```\n    pub fn is_empty(&self) -> bool {\n        self.0.as_raw().is_empty()\n    }\n}\n\nimpl<'a> Deref for Name<'a> {\n    type Target = X509Name<'a>;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl fmt::Display for Name<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/outcome.rs",
    "content": "//! Success, error, and forward handling.\n//!\n//! The `Outcome<S, E, F>` type is similar to the standard library's `Result<S,\n//! E>` type. It is an enum with three variants, each containing a value:\n//! `Success(S)`, which represents a successful outcome, `Error(E)`, which\n//! represents an erroring outcome, and `Forward(F)`, which represents neither a\n//! success or error, but instead, indicates that processing could not be\n//! handled and should instead be _forwarded_ to whatever can handle the\n//! processing next.\n//!\n//! The `Outcome` type is the return type of many of the core Rocket traits,\n//! including [`FromRequest`](crate::request::FromRequest), [`FromData`]\n//! [`Responder`]. It is also the return type of request handlers via the\n//! [`Response`](crate::response::Response) type.\n//!\n//! [`FromData`]: crate::data::FromData\n//! [`Responder`]: crate::response::Responder\n//!\n//! # Success\n//!\n//! A successful `Outcome<S, E, F>`, `Success(S)`, is returned from functions\n//! that complete successfully. The meaning of a `Success` outcome depends on\n//! the context. For instance, the `Outcome` of the `from_data` method of the\n//! [`FromData`] trait will be matched against the type expected by\n//! the user. For example, consider the following handler:\n//!\n//! ```rust\n//! # use rocket::post;\n//! # type S = String;\n//! #[post(\"/\", data = \"<my_val>\")]\n//! fn hello(my_val: S) { /* ... */  }\n//! ```\n//!\n//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a\n//! `Success(S)`. If `from_data` returns a `Success`, the `Success` value will\n//! be unwrapped and the value will be used as the value of `my_val`.\n//!\n//! # Error\n//!\n//! An error `Outcome<S, E, F>`, `Error(E)`, is returned when a function\n//! fails with some error and no processing can or should continue as a result.\n//! The meaning of an error depends on the context.\n//!\n//! In Rocket, an `Error` generally means that a request is taken out of normal\n//! processing. The request is then given to the catcher corresponding to some\n//! status code. Users can catch errors by requesting a type of `Result<S, E>`\n//! or `Option<S>` in request handlers. For example, if a user's handler looks\n//! like:\n//!\n//! ```rust\n//! # use rocket::post;\n//! # type S = Option<String>;\n//! # type E = std::convert::Infallible;\n//! #[post(\"/\", data = \"<my_val>\")]\n//! fn hello(my_val: Result<S, E>) { /* ... */ }\n//! ```\n//!\n//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a\n//! `Success(S)` and `Error(E)`. If `from_data` returns an `Error`, the `Error`\n//! value will be unwrapped and the value will be used as the `Err` value of\n//! `my_val` while a `Success` will be unwrapped and used the `Ok` value.\n//!\n//! # Forward\n//!\n//! A forward `Outcome<S, E, F>`, `Forward(F)`, is returned when a function\n//! wants to indicate that the requested processing should be _forwarded_ to the\n//! next available processor. Again, the exact meaning depends on the context.\n//!\n//! In Rocket, a `Forward` generally means that a request is forwarded to the\n//! next available request handler. For example, consider the following request\n//! handler:\n//!\n//! ```rust\n//! # use rocket::post;\n//! # type S = String;\n//! #[post(\"/\", data = \"<my_val>\")]\n//! fn hello(my_val: S) { /* ... */ }\n//! ```\n//!\n//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a\n//! `Success(S)`, `Error(E)`, and `Forward(F)`. If the `Outcome` is a\n//! `Forward`, the `hello` handler isn't called. Instead, the incoming request\n//! is forwarded, or passed on to, the next matching route, if any. Ultimately,\n//! if there are no non-forwarding routes, forwarded requests are handled by the\n//! 404 catcher. Similar to `Error`s, users can catch `Forward`s by requesting\n//! a type of `Option<S>`. If an `Outcome` is a `Forward`, the `Option` will be\n//! `None`.\n\nuse crate::{route, request, response};\nuse crate::data::{self, Data, FromData};\nuse crate::http::Status;\n\nuse self::Outcome::*;\n\n/// An enum representing success (`Success`), error (`Error`), or forwarding\n/// (`Forward`).\n///\n/// See the [top level documentation](crate::outcome) for detailed information.\n#[must_use]\n#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]\npub enum Outcome<S, E, F> {\n    /// Contains the success value.\n    Success(S),\n    /// Contains the error error value.\n    Error(E),\n    /// Contains the value to forward on.\n    Forward(F),\n}\n\nimpl<S, E, F> Outcome<S, E, F> {\n    /// Unwraps the Outcome, yielding the contents of a Success.\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is not `Success`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.unwrap(), 10);\n    /// ```\n    #[inline]\n    #[track_caller]\n    pub fn unwrap(self) -> S {\n        match self {\n            Success(val) => val,\n            _ => panic!(\"unwrapped a non-successful outcome\")\n        }\n    }\n\n    /// Unwraps the Outcome, yielding the contents of a Success.\n    ///\n    /// # Panics\n    ///\n    /// If the value is not `Success`, panics with the given `message`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.expect(\"success value\"), 10);\n    /// ```\n    #[inline]\n    #[track_caller]\n    pub fn expect(self, message: &str) -> S {\n        match self {\n            Success(val) => val,\n            _ => panic!(\"unwrapped a non-successful outcome: {}\", message)\n        }\n    }\n\n    /// Return true if this `Outcome` is a `Success`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.is_success(), true);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.is_success(), false);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.is_success(), false);\n    /// ```\n    #[inline]\n    pub fn is_success(&self) -> bool {\n        matches!(self, Success(_))\n    }\n\n    /// Return true if this `Outcome` is an `Error`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.is_error(), false);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.is_error(), true);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.is_error(), false);\n    /// ```\n    #[inline]\n    pub fn is_error(&self) -> bool {\n        matches!(self, Error(_))\n    }\n\n    /// Return true if this `Outcome` is a `Forward`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.is_forward(), false);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.is_forward(), false);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.is_forward(), true);\n    /// ```\n    #[inline]\n    pub fn is_forward(&self) -> bool {\n        matches!(self, Forward(_))\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Option<S>`.\n    ///\n    /// Returns the `Some` of the `Success` if this is a `Success`, otherwise\n    /// returns `None`. `self` is consumed, and all other values are discarded.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.succeeded(), Some(10));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.succeeded(), None);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.succeeded(), None);\n    /// ```\n    #[inline]\n    pub fn succeeded(self) -> Option<S> {\n        match self {\n            Success(val) => Some(val),\n            _ => None\n        }\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Option<E>`.\n    ///\n    /// Returns the `Some` of the `Error` if this is an `Error`, otherwise\n    /// returns `None`. `self` is consumed, and all other values are discarded.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.failed(), None);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.failed(), Some(\"Hi! I'm an error.\"));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.failed(), None);\n    /// ```\n    #[inline]\n    pub fn failed(self) -> Option<E> {\n        match self {\n            Error(val) => Some(val),\n            _ => None\n        }\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Option<F>`.\n    ///\n    /// Returns the `Some` of the `Forward` if this is a `Forward`, otherwise\n    /// returns `None`. `self` is consumed, and all other values are discarded.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.forwarded(), None);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.forwarded(), None);\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.forwarded(), Some(25));\n    /// ```\n    #[inline]\n    pub fn forwarded(self) -> Option<F> {\n        match self {\n            Forward(val) => Some(val),\n            _ => None\n        }\n    }\n\n    /// Returns a `Success` value as `Ok()` or `value` in `Err`. Converts from\n    /// `Outcome<S, E, F>` to `Result<S, T>` for a given `T`.\n    ///\n    /// Returns `Ok` with the `Success` value if this is a `Success`, otherwise\n    /// returns an `Err` with the provided value. `self` is consumed, and all\n    /// other values are discarded.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.success_or(false), Ok(10));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.success_or(false), Err(false));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.success_or(\"whoops\"), Err(\"whoops\"));\n    /// ```\n    #[inline]\n    pub fn success_or<T>(self, value: T) -> Result<S, T> {\n        match self {\n            Success(val) => Ok(val),\n            _ => Err(value)\n        }\n    }\n\n    /// Returns a `Success` value as `Ok()` or `f()` in `Err`. Converts from\n    /// `Outcome<S, E, F>` to `Result<S, T>` for a given `T` produced from a\n    /// supplied function or closure.\n    ///\n    /// Returns `Ok` with the `Success` value if this is a `Success`, otherwise\n    /// returns an `Err` with the result of calling `f`. `self` is consumed, and\n    /// all other values are discarded.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.success_or_else(|| false), Ok(10));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.success_or_else(|| false), Err(false));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(25);\n    /// assert_eq!(x.success_or_else(|| \"whoops\"), Err(\"whoops\"));\n    /// ```\n    #[inline]\n    pub fn success_or_else<T, V: FnOnce() -> T>(self, f: V) -> Result<S, T> {\n        match self {\n            Success(val) => Ok(val),\n            _ => Err(f())\n        }\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Outcome<&S, &E, &F>`.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.as_ref(), Success(&10));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"Hi! I'm an error.\");\n    /// assert_eq!(x.as_ref(), Error(&\"Hi! I'm an error.\"));\n    /// ```\n    #[inline]\n    pub fn as_ref(&self) -> Outcome<&S, &E, &F> {\n        match *self {\n            Success(ref val) => Success(val),\n            Error(ref val) => Error(val),\n            Forward(ref val) => Forward(val),\n        }\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Outcome<&mut S, &mut E, &mut F>`.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let mut x: Outcome<i32, &str, usize> = Success(10);\n    /// if let Success(val) = x.as_mut() {\n    ///     *val = 20;\n    /// }\n    ///\n    /// assert_eq!(x.unwrap(), 20);\n    /// ```\n    #[inline]\n    pub fn as_mut(&mut self) -> Outcome<&mut S, &mut E, &mut F> {\n        match *self {\n            Success(ref mut val) => Success(val),\n            Error(ref mut val) => Error(val),\n            Forward(ref mut val) => Forward(val),\n        }\n    }\n\n    /// Maps the `Success` value using `f`. Maps an `Outcome<S, E, F>` to an\n    /// `Outcome<T, E, F>` by applying the function `f` to the value of type `S`\n    /// in `self` if `self` is an `Outcome::Success`.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    ///\n    /// let mapped = x.map(|v| if v == 10 { \"10\" } else { \"not 10\" });\n    /// assert_eq!(mapped, Success(\"10\"));\n    /// ```\n    #[inline]\n    pub fn map<T, M: FnOnce(S) -> T>(self, f: M) -> Outcome<T, E, F> {\n        match self {\n            Success(val) => Success(f(val)),\n            Error(val) => Error(val),\n            Forward(val) => Forward(val),\n        }\n    }\n\n    /// Maps the `Error` value using `f`. Maps an `Outcome<S, E, F>` to an\n    /// `Outcome<S, T, F>` by applying the function `f` to the value of type `E`\n    /// in `self` if `self` is an `Outcome::Error`.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Error(\"hi\");\n    ///\n    /// let mapped = x.map_error(|v| if v == \"hi\" { 10 } else { 0 });\n    /// assert_eq!(mapped, Error(10));\n    /// ```\n    #[inline]\n    pub fn map_error<T, M: FnOnce(E) -> T>(self, f: M) -> Outcome<S, T, F> {\n        match self {\n            Success(val) => Success(val),\n            Error(val) => Error(f(val)),\n            Forward(val) => Forward(val),\n        }\n    }\n\n    /// Maps the `Forward` value using `f`. Maps an `Outcome<S, E, F>` to an\n    /// `Outcome<S, E, T>` by applying the function `f` to the value of type `F`\n    /// in `self` if `self` is an `Outcome::Forward`.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Forward(5);\n    ///\n    /// let mapped = x.map_forward(|v| if v == 5 { \"a\" } else { \"b\" });\n    /// assert_eq!(mapped, Forward(\"a\"));\n    /// ```\n    #[inline]\n    pub fn map_forward<T, M: FnOnce(F) -> T>(self, f: M) -> Outcome<S, E, T> {\n        match self {\n            Success(val) => Success(val),\n            Error(val) => Error(val),\n            Forward(val) => Forward(f(val)),\n        }\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Outcome<T, E, F>` using `f` to map\n    /// `Success(S)` to `Success(T)`.\n    ///\n    /// If `self` is not `Success`, `self` is returned.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, bool> = Success(10);\n    ///\n    /// let mapped = x.and_then(|v| match v {\n    ///    10 => Success(\"10\"),\n    ///    1 => Forward(false),\n    ///    _ => Error(\"30\")\n    /// });\n    ///\n    /// assert_eq!(mapped, Success(\"10\"));\n    /// ```\n    #[inline]\n    pub fn and_then<T, M: FnOnce(S) -> Outcome<T, E, F>>(self, f: M) -> Outcome<T, E, F> {\n        match self {\n            Success(val) => f(val),\n            Error(val) => Error(val),\n            Forward(val) => Forward(val),\n        }\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Outcome<S, T, F>` using `f` to map\n    /// `Error(E)` to `Error(T)`.\n    ///\n    /// If `self` is not `Error`, `self` is returned.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, bool> = Error(\"hi\");\n    ///\n    /// let mapped = x.error_then(|v| match v {\n    ///    \"hi\" => Error(10),\n    ///    \"test\" => Forward(false),\n    ///    _ => Success(10)\n    /// });\n    ///\n    /// assert_eq!(mapped, Error(10));\n    /// ```\n    #[inline]\n    pub fn error_then<T, M: FnOnce(E) -> Outcome<S, T, F>>(self, f: M) -> Outcome<S, T, F> {\n        match self {\n            Success(val) => Success(val),\n            Error(val) => f(val),\n            Forward(val) => Forward(val),\n        }\n    }\n\n    /// Converts from `Outcome<S, E, F>` to `Outcome<S, E, T>` using `f` to map\n    /// `Forward(F)` to `Forward(T)`.\n    ///\n    /// If `self` is not `Forward`, `self` is returned.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, Option<bool>> = Forward(Some(false));\n    ///\n    /// let mapped = x.forward_then(|v| match v {\n    ///    Some(true) => Success(10),\n    ///    Some(false) => Forward(20),\n    ///    None => Error(\"10\")\n    /// });\n    ///\n    /// assert_eq!(mapped, Forward(20));\n    /// ```\n    #[inline]\n    pub fn forward_then<T, M: FnOnce(F) -> Outcome<S, E, T>>(self, f: M) -> Outcome<S, E, T> {\n        match self {\n            Success(val) => Success(val),\n            Error(val) => Error(val),\n            Forward(val) => f(val),\n        }\n    }\n\n    /// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping\n    /// `Success(S)` and `Error(E)` to `Result<T, E>` and mapping `Forward(F)`\n    /// to `Result<T, E>` using `f`.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(10));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"hello\");\n    /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Err(\"hello\"));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(0);\n    /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(1));\n    /// ```\n    #[inline]\n    pub fn ok_map_forward<M>(self, f: M) -> Result<S, E>\n        where M: FnOnce(F) -> Result<S, E>\n    {\n        match self {\n            Outcome::Success(s) => Ok(s),\n            Outcome::Error(e) => Err(e),\n            Outcome::Forward(v) => f(v),\n        }\n    }\n\n    /// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping\n    /// `Success(S)` and `Forward(F)` to `Result<T, F>` and mapping `Error(E)`\n    /// to `Result<T, F>` using `f`.\n    ///\n    /// ```rust\n    /// # use rocket::outcome::Outcome;\n    /// # use rocket::outcome::Outcome::*;\n    /// #\n    /// let x: Outcome<i32, &str, usize> = Success(10);\n    /// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(10));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Error(\"hello\");\n    /// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(123));\n    ///\n    /// let x: Outcome<i32, &str, usize> = Forward(0);\n    /// assert_eq!(x.ok_map_error(|s| Ok(123)), Err(0));\n    /// ```\n    #[inline]\n    pub fn ok_map_error<M>(self, f: M) -> Result<S, F>\n        where M: FnOnce(E) -> Result<S, F>\n    {\n        match self {\n            Outcome::Success(s) => Ok(s),\n            Outcome::Error(e) => f(e),\n            Outcome::Forward(v) => Err(v),\n        }\n    }\n}\n\nimpl<'a, S: Send + 'a, E: Send + 'a, F: Send + 'a> Outcome<S, E, F> {\n    /// Pins a future that resolves to `self`, returning a\n    /// [`BoxFuture`](crate::futures::future::BoxFuture) that resolves to\n    /// `self`.\n    #[inline]\n    pub fn pin(self) -> futures::future::BoxFuture<'a, Self> {\n        Box::pin(async move { self })\n    }\n}\n\ncrate::export! {\n    /// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or\n    /// `Error` by returning early.\n    ///\n    /// # Syntax\n    ///\n    /// The macro has the following \"signature\":\n    ///\n    /// ```rust\n    /// use rocket::outcome::Outcome;\n    ///\n    /// // Returns the inner `S` if `outcome` is `Outcome::Success`. Otherwise\n    /// // returns from the caller with `Outcome<impl From<E>, impl From<F>>`.\n    /// fn try_outcome<S, E, F>(outcome: Outcome<S, E, F>) -> S\n    /// # { unimplemented!() }\n    /// ```\n    ///\n    /// This is just like `?` (or previously, `try!`), but for `Outcome`. In the\n    /// case of a `Forward` or `Error` variant, the inner type is passed to\n    /// [`From`](std::convert::From), allowing for the conversion between\n    /// specific and more general types. The resulting forward/error is\n    /// immediately returned. Because of the early return, `try_outcome!` can\n    /// only be used in methods that return [`Outcome`].\n    ///\n    /// [`Outcome`]: crate::outcome::Outcome\n    ///\n    /// ## Example\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use std::sync::atomic::{AtomicUsize, Ordering};\n    ///\n    /// use rocket::State;\n    /// use rocket::request::{self, Request, FromRequest};\n    /// use rocket::outcome::{try_outcome, Outcome::*};\n    ///\n    /// #[derive(Default)]\n    /// struct Atomics {\n    ///     uncached: AtomicUsize,\n    ///     cached: AtomicUsize,\n    /// }\n    ///\n    /// struct Guard1;\n    /// struct Guard2;\n    ///\n    /// #[rocket::async_trait]\n    /// impl<'r> FromRequest<'r> for Guard1 {\n    ///     type Error = ();\n    ///\n    ///     async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n    ///         // Attempt to fetch the guard, passing through any error or forward.\n    ///         let atomics = try_outcome!(req.guard::<&State<Atomics>>().await);\n    ///         atomics.uncached.fetch_add(1, Ordering::Relaxed);\n    ///         req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));\n    ///\n    ///         Success(Guard1)\n    ///     }\n    /// }\n    ///\n    /// #[rocket::async_trait]\n    /// impl<'r> FromRequest<'r> for Guard2 {\n    ///     type Error = ();\n    ///\n    ///     async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n    ///         // Attempt to fetch the guard, passing through any error or forward.\n    ///         let guard1: Guard1 = try_outcome!(req.guard::<Guard1>().await);\n    ///         Success(Guard2)\n    ///     }\n    /// }\n    /// ```\n    macro_rules! try_outcome {\n        ($expr:expr $(,)?) => (match $expr {\n            $crate::outcome::Outcome::Success(val) => val,\n            $crate::outcome::Outcome::Error(e) => {\n                return $crate::outcome::Outcome::Error(::std::convert::From::from(e))\n            },\n            $crate::outcome::Outcome::Forward(f) => {\n                return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))\n            },\n        });\n    }\n}\n\n/// Conversion trait from some type into an Outcome type.\npub trait IntoOutcome<Outcome> {\n    /// The type to use when returning an `Outcome::Error`.\n    type Error: Sized;\n\n    /// The type to use when returning an `Outcome::Forward`.\n    type Forward: Sized;\n\n    /// Converts `self` into an `Outcome`. If `self` represents a success, an\n    /// `Outcome::Success` is returned. Otherwise, an `Outcome::Error` is\n    /// returned with `error` as the inner value.\n    fn or_error(self, error: Self::Error) -> Outcome;\n\n    /// Converts `self` into an `Outcome`. If `self` represents a success, an\n    /// `Outcome::Success` is returned. Otherwise, an `Outcome::Forward` is\n    /// returned with `forward` as the inner value.\n    fn or_forward(self, forward: Self::Forward) -> Outcome;\n}\n\nimpl<S, E, F> IntoOutcome<Outcome<S, E, F>> for Option<S> {\n    type Error = E;\n    type Forward = F;\n\n    #[inline]\n    fn or_error(self, error: E) -> Outcome<S, E, F> {\n        match self {\n            Some(val) => Success(val),\n            None => Error(error)\n        }\n    }\n\n    #[inline]\n    fn or_forward(self, forward: F) -> Outcome<S, E, F> {\n        match self {\n            Some(val) => Success(val),\n            None => Forward(forward)\n        }\n    }\n}\n\nimpl<'r, T: FromData<'r>> IntoOutcome<data::Outcome<'r, T>> for Result<T, T::Error> {\n    type Error = Status;\n    type Forward = (Data<'r>, Status);\n\n    #[inline]\n    fn or_error(self, error: Status) -> data::Outcome<'r, T> {\n        match self {\n            Ok(val) => Success(val),\n            Err(err) => Error((error, err))\n        }\n    }\n\n    #[inline]\n    fn or_forward(self, (data, forward): (Data<'r>, Status)) -> data::Outcome<'r, T> {\n        match self {\n            Ok(val) => Success(val),\n            Err(_) => Forward((data, forward))\n        }\n    }\n}\n\nimpl<S, E> IntoOutcome<request::Outcome<S, E>> for Result<S, E> {\n    type Error = Status;\n    type Forward = Status;\n\n    #[inline]\n    fn or_error(self, error: Status) -> request::Outcome<S, E> {\n        match self {\n            Ok(val) => Success(val),\n            Err(err) => Error((error, err))\n        }\n    }\n\n    #[inline]\n    fn or_forward(self, status: Status) -> request::Outcome<S, E> {\n        match self {\n            Ok(val) => Success(val),\n            Err(_) => Forward(status)\n        }\n    }\n}\n\nimpl<'r, 'o: 'r> IntoOutcome<route::Outcome<'r>> for response::Result<'o> {\n    type Error = ();\n    type Forward = (Data<'r>, Status);\n\n    #[inline]\n    fn or_error(self, _: ()) -> route::Outcome<'r> {\n        match self {\n            Ok(val) => Success(val),\n            Err(status) => Error(status),\n        }\n    }\n\n    #[inline]\n    fn or_forward(self, (data, forward): (Data<'r>, Status)) -> route::Outcome<'r> {\n        match self {\n            Ok(val) => Success(val),\n            Err(_) => Forward((data, forward))\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/phase.rs",
    "content": "use state::TypeMap;\nuse figment::Figment;\n\nuse crate::listener::Endpoint;\nuse crate::shutdown::Stages;\nuse crate::{Catcher, Config, Rocket, Route};\nuse crate::router::{Router, Finalized};\nuse crate::fairing::Fairings;\n\nmod private {\n    pub trait Sealed {  }\n}\n\n#[doc(hidden)]\npub trait Stateful: private::Sealed {\n    fn into_state(self) -> State;\n    fn as_ref(&self) -> StateRef<'_>;\n    fn as_mut(&mut self) -> StateRefMut<'_>;\n}\n\n/// A marker trait for Rocket's launch phases.\n///\n/// This treat is implemented by the three phase marker types: [`Build`],\n/// [`Ignite`], and [`Orbit`], representing the three phases to launch an\n/// instance of [`Rocket`]. This trait is _sealed_ and cannot be implemented\n/// outside of Rocket.\n///\n/// For a description of the three phases, see [`Rocket#phases`].\npub trait Phase: private::Sealed {\n    #[doc(hidden)]\n    type State: std::fmt::Debug + Stateful + Sync + Send + Unpin;\n}\n\nmacro_rules! phase {\n    ($(#[$o:meta])* $P:ident ($(#[$i:meta])* $S:ident) { $($fields:tt)* }) => (\n        $(#[$o])*\n        pub enum $P { }\n\n        impl Phase for $P {\n            #[doc(hidden)]\n            type State = $S;\n        }\n\n        $(#[$i])*\n        #[doc(hidden)]\n        pub struct $S {\n            $($fields)*\n        }\n\n        impl Stateful for $S {\n            fn into_state(self) -> State { State::$P(self) }\n            fn as_ref(&self) -> StateRef<'_> { StateRef::$P(self) }\n            fn as_mut(&mut self) -> StateRefMut<'_> { StateRefMut::$P(self) }\n        }\n\n        #[doc(hidden)]\n        impl From<$S> for Rocket<$P> {\n            fn from(s: $S) -> Self { Rocket(s) }\n        }\n\n        impl private::Sealed for $P {}\n\n        impl private::Sealed for $S {}\n    )\n}\n\nmacro_rules! phases {\n    ($($(#[$o:meta])* $P:ident ($(#[$i:meta])* $S:ident) { $($fields:tt)* })*) => (\n        #[doc(hidden)]\n        pub enum State { $($P($S)),* }\n\n        #[doc(hidden)]\n        pub enum StateRef<'a> { $($P(&'a $S)),* }\n\n        #[doc(hidden)]\n        pub enum StateRefMut<'a> { $($P(&'a mut $S)),* }\n\n        $(phase!($(#[$o])* $P ($(#[$i])* $S) { $($fields)* });)*\n    )\n}\n\nphases! {\n    /// The initial launch [`Phase`]. See [Rocket#build](`Rocket#build`) for\n    /// phase details.\n    ///\n    /// An instance of `Rocket` in this phase is typed as [`Rocket<Build>`]: a\n    /// transient, in-progress build.\n    Build (#[derive(Default, Debug)] Building) {\n        pub(crate) routes: Vec<Route>,\n        pub(crate) catchers: Vec<Catcher>,\n        pub(crate) fairings: Fairings,\n        pub(crate) figment: Figment,\n        pub(crate) state: TypeMap![Send + Sync],\n    }\n\n    /// The second launch [`Phase`]: post-build but pre-orbit. See\n    /// [Rocket#ignite](`Rocket#ignite`) for details.\n    ///\n    /// An instance of `Rocket` in this phase is typed as [`Rocket<Ignite>`] and\n    /// represents a fully built and finalized application server ready for\n    /// launch into orbit. See [`Rocket#ignite`] for full details.\n    Ignite (#[derive(Debug)] Igniting) {\n        pub(crate) router: Router<Finalized>,\n        pub(crate) fairings: Fairings,\n        pub(crate) figment: Figment,\n        pub(crate) config: Config,\n        pub(crate) state: TypeMap![Send + Sync],\n        pub(crate) shutdown: Stages,\n    }\n\n    /// The final launch [`Phase`]. See [Rocket#orbit](`Rocket#orbit`) for\n    /// details.\n    ///\n    /// An instance of `Rocket` in this phase is typed as [`Rocket<Orbit>`] and\n    /// represents a running application.\n    Orbit (#[derive(Debug)] Orbiting) {\n        pub(crate) router: Router<Finalized>,\n        pub(crate) fairings: Fairings,\n        pub(crate) figment: Figment,\n        pub(crate) config: Config,\n        pub(crate) state: TypeMap![Send + Sync],\n        pub(crate) shutdown: Stages,\n        pub(crate) endpoints: Vec<Endpoint>,\n    }\n}\n"
  },
  {
    "path": "core/lib/src/request/atomic_method.rs",
    "content": "use crate::http::Method;\n\npub struct AtomicMethod(ref_swap::RefSwap<'static, Method>);\n\nimpl AtomicMethod {\n    #[inline]\n    pub fn new(value: Method) -> Self {\n        Self(ref_swap::RefSwap::new(value.as_ref()))\n    }\n\n    #[inline]\n    pub fn load(&self) -> Method {\n        *self.0.load(std::sync::atomic::Ordering::Acquire)\n    }\n\n    #[inline]\n    pub fn set(&mut self, new: Method) {\n        *self = Self::new(new);\n    }\n\n    #[inline]\n    pub fn store(&self, new: Method) {\n        self.0.store(new.as_ref(), std::sync::atomic::Ordering::Release)\n    }\n}\n\nimpl Clone for AtomicMethod {\n    fn clone(&self) -> Self {\n        let inner = self.0.load(std::sync::atomic::Ordering::Acquire);\n        Self(ref_swap::RefSwap::new(inner))\n    }\n}\n"
  },
  {
    "path": "core/lib/src/request/from_param.rs",
    "content": "use std::str::FromStr;\nuse std::path::PathBuf;\n\nuse crate::error::Empty;\nuse crate::either::Either;\nuse crate::http::uri::{Segments, error::PathError, fmt::Path};\n\n/// Trait to convert a dynamic path segment string to a concrete value.\n///\n/// This trait is used by Rocket's code generation facilities to parse dynamic\n/// path segment string values into a given type. That is, when a path contains\n/// a dynamic segment `<param>` where `param` has some type `T` that implements\n/// `FromParam`, `T::from_param` will be called.\n///\n/// # Deriving\n///\n/// The `FromParam` trait can be automatically derived for C-like enums. See\n/// [`FromParam` derive](macro@rocket::FromParam) for more information.\n///\n/// # Forwarding\n///\n/// If the conversion fails, the incoming request will be forwarded to the next\n/// matching route, if any. For instance, consider the following route and\n/// handler for the dynamic `\"/<id>\"` path:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #[get(\"/<id>\")]\n/// fn hello(id: usize) -> String {\n/// # let _id = id;\n/// # /*\n///     ...\n/// # */\n/// # \"\".to_string()\n/// }\n/// # fn main() {  }\n/// ```\n///\n/// If `usize::from_param` returns an `Ok(usize)` variant, the encapsulated\n/// value is used as the `id` function parameter. If not, the request is\n/// forwarded to the next matching route. Since there are no additional matching\n/// routes, this example will result in a 422 error for requests with invalid\n/// `id` values.\n///\n/// # Catching Errors\n///\n/// Sometimes, a forward is not desired, and instead, we simply want to know\n/// that the dynamic path segment could not be parsed into some desired type\n/// `T`. In these cases, types of `Option<T>`, `Result<T, T::Error>`, or\n/// `Either<A, B>` can be used, which implement `FromParam` themselves.\n///\n///   * **`Option<T>`** _where_ **`T: FromParam`**\n///\n///     Always returns successfully.\n///\n///     If the conversion to `T` fails, `None` is returned. If the conversion\n///     succeeds, `Some(value)` is returned.\n///\n///   * **`Result<T, T::Error>`** _where_ **`T: FromParam`**\n///\n///     Always returns successfully.\n///\n///     If the conversion to `T` fails, `Err(error)` is returned. If the\n///     conversion succeeds, `Ok(value)` is returned.\n///\n///   * **`Either<A, B>`** _where_ **`A: FromParam`** _and_ **`B: FromParam`**\n///\n///      Fails only when both `A::from_param` and `B::from_param` fail. If one\n///      of the two succeeds, the successful value is returned in\n///      `Either::Left(A)` or `Either::Right(B)` variant, respectively. If both\n///      fail, the error values from both calls are returned in a tuple in the\n///      `Err` variant.\n///\n/// `Either<A, B>` is particularly useful with a `B` type of `&str`, allowing\n/// you to retrieve the invalid path segment. Because `&str`'s implementation of\n/// `FromParam` always succeeds, the `Right` variant of the `Either` will always\n/// contain the path segment in case of failure.\n///\n/// For instance, consider the following route and handler:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::either::{Either, Left, Right};\n///\n/// #[get(\"/<id>\")]\n/// fn hello(id: Either<usize, &str>) -> String {\n///     match id {\n///         Left(id_num) => format!(\"usize: {}\", id_num),\n///         Right(string) => format!(\"Not a usize: {}\", string)\n///     }\n/// }\n/// # fn main() {  }\n/// ```\n///\n/// In the above example, if the dynamic path segment cannot be parsed into a\n/// `usize`, the raw path segment is returned in the `Right` variant of the\n/// `Either<usize, &str>` value.\n///\n/// # Provided Implementations\n///\n/// Rocket implements `FromParam` for several standard library types. Their\n/// behavior is documented here.\n///\n///   *\n///       * Primitive types: **f32, f64, isize, i8, i16, i32, i64, i128,\n///         usize, u8, u16, u32, u64, u128, bool**\n///       * `IpAddr` and `SocketAddr` types: **IpAddr, Ipv4Addr, Ipv6Addr,\n///         SocketAddrV4, SocketAddrV6, SocketAddr**\n///       * `NonZero*` types: **NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64,\n///         NonZeroI128, NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32,\n///         NonZeroU64, NonZeroU128, NonZeroUsize**\n///\n///     A value is parsed successfully if the `from_str` method from the given\n///     type returns successfully. Otherwise, the raw path segment is returned\n///     in the `Err` value.\n///\n///   * **&str, String**\n///\n///     _This implementation always returns successfully._\n///\n///     Returns the percent-decoded path segment with invalid UTF-8 byte\n///     sequences replaced by � U+FFFD.\n///\n///   * **Option&lt;T>** _where_ **T: FromParam**\n///\n///     _This implementation always returns successfully._\n///\n///     The path segment is parsed by `T`'s `FromParam` implementation. If the\n///     parse succeeds, a `Some(parsed_value)` is returned. Otherwise, a `None`\n///     is returned.\n///\n///   * **Result&lt;T, T::Error>** _where_ **T: FromParam**\n///\n///     _This implementation always returns successfully._\n///\n///     The path segment is parsed by `T`'s `FromParam` implementation. The\n///     returned `Result` value is returned.\n///\n/// # Example\n///\n/// Say you want to parse a segment of the form:\n///\n/// ```text\n/// [a-zA-Z]+:[0-9]+\n/// ```\n///\n/// into the following structure, where the string before the `:` is stored in\n/// `key` and the number after the colon is stored in `value`:\n///\n/// ```rust\n/// struct MyParam<'r> {\n///     key: &'r str,\n///     value: usize\n/// }\n/// ```\n///\n/// The following implementation accomplishes this:\n///\n/// ```rust\n/// use rocket::request::FromParam;\n/// # #[allow(dead_code)]\n/// # struct MyParam<'r> { key: &'r str, value: usize }\n///\n/// impl<'r> FromParam<'r> for MyParam<'r> {\n///     type Error = &'r str;\n///\n///     fn from_param(param: &'r str) -> Result<Self, Self::Error> {\n///         // We can convert `param` into a `str` since we'll check every\n///         // character for safety later.\n///         let (key, val_str) = match param.find(':') {\n///             Some(i) if i > 0 => (&param[..i], &param[(i + 1)..]),\n///             _ => return Err(param)\n///         };\n///\n///         if !key.chars().all(|c| c.is_ascii_alphabetic()) {\n///             return Err(param);\n///         }\n///\n///         val_str.parse()\n///             .map(|value| MyParam { key, value })\n///             .map_err(|_| param)\n///     }\n/// }\n/// ```\n///\n/// With the implementation, the `MyParam` type can be used as the target of a\n/// dynamic path segment:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use rocket::request::FromParam;\n/// # #[allow(dead_code)]\n/// # struct MyParam<'r> { key: &'r str, value: usize }\n/// # impl<'r> FromParam<'r> for MyParam<'r> {\n/// #     type Error = &'r str;\n/// #     fn from_param(param: &'r str) -> Result<Self, Self::Error> {\n/// #         Err(param)\n/// #     }\n/// # }\n/// #\n/// #[get(\"/<key_val>\")]\n/// fn hello(key_val: MyParam) -> String {\n/// # let _kv = key_val;\n/// # /*\n///     ...\n/// # */\n/// # \"\".to_string()\n/// }\n/// # fn main() {  }\n/// ```\npub trait FromParam<'a>: Sized {\n    /// The associated error to be returned if parsing/validation fails.\n    type Error: std::fmt::Debug;\n\n    /// Parses and validates an instance of `Self` from a path parameter string\n    /// or returns an `Error` if parsing or validation fails.\n    fn from_param(param: &'a str) -> Result<Self, Self::Error>;\n}\n\nimpl<'a> FromParam<'a> for &'a str {\n    type Error = Empty;\n\n    #[inline(always)]\n    fn from_param(param: &'a str) -> Result<&'a str, Self::Error> {\n        if param.is_empty() {\n            return Err(Empty);\n        }\n\n        Ok(param)\n    }\n}\n\nimpl<'a> FromParam<'a> for String {\n    type Error = Empty;\n\n    #[track_caller]\n    #[inline(always)]\n    fn from_param(param: &'a str) -> Result<String, Self::Error> {\n        #[cfg(debug_assertions)] {\n            let location = std::panic::Location::caller();\n            warn!(%location, \"`String` as a parameter is inefficient. Use `&str` instead.\");\n        }\n\n        if param.is_empty() {\n            return Err(Empty);\n        }\n\n        Ok(param.to_string())\n    }\n}\n\nmacro_rules! impl_with_fromstr {\n    ($($T:ty),+) => ($(\n        impl<'a> FromParam<'a> for $T {\n            type Error = <$T as FromStr>::Err;\n\n            #[inline(always)]\n            fn from_param(param: &'a str) -> Result<Self, Self::Error> {\n                <$T as FromStr>::from_str(param)\n            }\n        }\n    )+)\n}\n\nuse std::num::{\n    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,\n    NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,\n};\nuse std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr};\n\nimpl_with_fromstr! {\n    i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64,\n    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,\n    NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,\n    bool, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6, SocketAddr\n}\n\nimpl<'a> FromParam<'a> for PathBuf {\n    type Error = PathError;\n\n    #[inline]\n    fn from_param(param: &'a str) -> Result<Self, Self::Error> {\n        use crate::http::private::Indexed;\n\n        let segments = &[Indexed::Indexed(0, param.len())];\n        Segments::new(param.into(), segments).to_path_buf(false)\n    }\n}\n\nimpl<'a, T: FromParam<'a>> FromParam<'a> for Result<T, T::Error> {\n    type Error = std::convert::Infallible;\n\n    #[inline]\n    fn from_param(param: &'a str) -> Result<Self, Self::Error> {\n        match T::from_param(param) {\n            Ok(val) => Ok(Ok(val)),\n            Err(e) => Ok(Err(e)),\n        }\n    }\n}\n\nimpl<'a, T: FromParam<'a>> FromParam<'a> for Option<T> {\n    type Error = std::convert::Infallible;\n\n    #[inline]\n    fn from_param(param: &'a str) -> Result<Self, Self::Error> {\n        match T::from_param(param) {\n            Ok(val) => Ok(Some(val)),\n            Err(_) => Ok(None)\n        }\n    }\n}\n\n/// Trait to convert _many_ dynamic path segment strings to a concrete value.\n///\n/// This is the `..` analog to [`FromParam`], and its functionality is identical\n/// to it with one exception: this trait applies to segment parameters of the\n/// form `<param..>`, where `param` is of some type `T` that implements\n/// `FromSegments`. `T::from_segments` is called to convert the matched segments\n/// (via the [`Segments`] iterator) into the implementing type.\n///\n/// # Provided Implementations\n///\n/// **`PathBuf`**\n///\n/// The `PathBuf` implementation constructs a path from the segments iterator.\n/// Each segment is percent-decoded. If a segment equals \"..\" before or after\n/// decoding, the previous segment (if any) is omitted. For security purposes,\n/// any other segments that begin with \"*\" or \".\" are ignored.  If a\n/// percent-decoded segment results in invalid UTF8, an `Err` is returned with\n/// the `Utf8Error`.\npub trait FromSegments<'r>: Sized {\n    /// The associated error to be returned when parsing fails.\n    type Error: std::fmt::Debug;\n\n    /// Parses an instance of `Self` from many dynamic path parameter strings or\n    /// returns an `Error` if one cannot be parsed.\n    fn from_segments(segments: Segments<'r, Path>) -> Result<Self, Self::Error>;\n}\n\nimpl<'r> FromSegments<'r> for Segments<'r, Path> {\n    type Error = std::convert::Infallible;\n\n    #[inline(always)]\n    fn from_segments(segments: Self) -> Result<Self, Self::Error> {\n        Ok(segments)\n    }\n}\n\n/// Creates a `PathBuf` from a `Segments` iterator. The returned `PathBuf` is\n/// percent-decoded. If a segment is equal to \"..\", the previous segment (if\n/// any) is skipped.\n///\n/// For security purposes, if a segment meets any of the following conditions,\n/// an `Err` is returned indicating the condition met:\n///\n///   * Decoded segment starts with any of: `.` (except `..`), `*`\n///   * Decoded segment ends with any of: `:`, `>`, `<`\n///   * Decoded segment contains any of: `/`\n///   * On Windows, decoded segment contains any of: `\\`\n///   * Percent-encoding results in invalid UTF8.\n///\n/// As a result of these conditions, a `PathBuf` derived via `FromSegments` is\n/// safe to interpolate within, or use as a suffix of, a path without additional\n/// checks.\nimpl FromSegments<'_> for PathBuf {\n    type Error = PathError;\n\n    fn from_segments(segments: Segments<'_, Path>) -> Result<Self, Self::Error> {\n        segments.to_path_buf(false)\n    }\n}\n\nimpl<'r, T: FromSegments<'r>> FromSegments<'r> for Result<T, T::Error> {\n    type Error = std::convert::Infallible;\n\n    #[inline]\n    fn from_segments(segments: Segments<'r, Path>) -> Result<Result<T, T::Error>, Self::Error> {\n        match T::from_segments(segments) {\n            Ok(val) => Ok(Ok(val)),\n            Err(e) => Ok(Err(e)),\n        }\n    }\n}\n\nimpl<'r, T: FromSegments<'r>> FromSegments<'r> for Option<T> {\n    type Error = std::convert::Infallible;\n\n    #[inline]\n    fn from_segments(segments: Segments<'r, Path>) -> Result<Option<T>, Self::Error> {\n        match T::from_segments(segments) {\n            Ok(val) => Ok(Some(val)),\n            Err(_) => Ok(None)\n        }\n    }\n}\n\n/// Implements `FromParam` for `Either<A, B>`, where `A` and `B` both implement\n/// `FromParam`. If `A::from_param` returns `Ok(a)`, `Either::Left(a)` is\n/// returned. If `B::from_param` returns `Ok(b)`, `Either::Right(b)` is\n/// returned. If both `A::from_param` and `B::from_param` return `Err(a)` and\n/// `Err(b)`, respectively, then `Err((a, b))` is returned.\nimpl<'v, A: FromParam<'v>, B: FromParam<'v>> FromParam<'v> for Either<A, B> {\n    type Error = (A::Error, B::Error);\n\n    #[inline(always)]\n    fn from_param(param: &'v str) -> Result<Self, Self::Error> {\n        match A::from_param(param) {\n            Ok(a) => Ok(Either::Left(a)),\n            Err(a) => match B::from_param(param) {\n                Ok(b) => Ok(Either::Right(b)),\n                Err(b) => Err((a, b)),\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/request/from_request.rs",
    "content": "use std::fmt::Debug;\nuse std::convert::Infallible;\nuse std::net::{IpAddr, SocketAddr};\n\nuse crate::{Request, Route};\nuse crate::outcome::{self, IntoOutcome, Outcome::*};\n\nuse crate::http::uri::{Host, Origin};\nuse crate::http::{Status, ContentType, Accept, Method, ProxyProto, CookieJar};\nuse crate::listener::Endpoint;\n\n/// Type alias for the `Outcome` of a `FromRequest` conversion.\npub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;\n\n/// Trait implemented by request guards to derive a value from incoming\n/// requests.\n///\n/// # Request Guards\n///\n/// A request guard is a type that represents an arbitrary validation policy.\n/// The validation policy is implemented through `FromRequest`. In other words,\n/// every type that implements `FromRequest` is a request guard.\n///\n/// Request guards appear as inputs to handlers. An arbitrary number of request\n/// guards can appear as arguments in a route handler. Rocket will automatically\n/// invoke the `FromRequest` implementation for request guards before calling\n/// the handler. Rocket only dispatches requests to a handler when all of its\n/// guards pass.\n///\n/// ## Async Trait\n///\n/// [`FromRequest`] is an _async_ trait. Implementations of `FromRequest` must\n/// be decorated with an attribute of `#[rocket::async_trait]`:\n///\n/// ```rust\n/// use rocket::request::{self, Request, FromRequest};\n/// # struct MyType;\n/// # type MyError = String;\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for MyType {\n///     type Error = MyError;\n///\n///     async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n///         /* .. */\n///         # unimplemented!()\n///     }\n/// }\n/// ```\n///\n/// ## Example\n///\n/// The following dummy handler makes use of three request guards, `A`, `B`, and\n/// `C`. An input type can be identified as a request guard if it is not named\n/// in the route attribute. This is why, for instance, `param` is not a request\n/// guard.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use rocket::http::Method;\n/// # type A = Method; type B = Method; type C = Method; type T = ();\n/// #[get(\"/<param>\")]\n/// fn index(param: isize, a: A, b: B, c: C) -> T { /* ... */ }\n/// # fn main() {}\n/// ```\n///\n/// Request guards always fire in left-to-right declaration order. In the\n/// example above, the order is `a` followed by `b` followed by `c`. Errors are\n/// short-circuiting; if one guard errors, the remaining are not attempted.\n///\n/// # Outcomes\n///\n/// The returned [`Outcome`] of a `from_request` call determines how the\n/// incoming request will be processed.\n///\n/// * **Success**(S)\n///\n///   If the `Outcome` is [`Success`], then the `Success` value will be used as\n///   the value for the corresponding parameter.  As long as all other guards\n///   succeed, the request will be handled.\n///\n/// * **Error**(Status, E)\n///\n///   If the `Outcome` is [`Error`], the request will fail with the given\n///   status code and error. The designated error [`Catcher`](crate::Catcher)\n///   will be used to respond to the request. Note that users can request types\n///   of `Result<S, E>` and `Option<S>` to catch `Error`s and retrieve the\n///   error value.\n///\n/// * **Forward**(Status)\n///\n///   If the `Outcome` is [`Forward`], the request will be forwarded to the next\n///   matching route until either one succeeds or there are no further matching\n///   routes to attempt. In the latter case, the request will be sent to the\n///   [`Catcher`](crate::Catcher) for the designated `Status`. Note that users\n///   can request an `Option<S>` to catch `Forward`s.\n///\n/// # Provided Implementations\n///\n/// Rocket implements `FromRequest` for several built-in types. Their behavior\n/// is documented here.\n///\n///   * **Method**\n///\n///     Extracts the [`Method`] from the incoming request.\n///\n///     _This implementation always returns successfully._\n///\n///   * **&Origin**\n///\n///     Extracts the [`Origin`] URI from the incoming request.\n///\n///     _This implementation always returns successfully._\n///\n///   * **&Host**\n///\n///     Extracts the [`Host`] from the incoming request, if it exists. See\n///     [`Request::host()`] for details. If it does not exist, the request is\n///     forwarded with a 500 Internal Server Error status.\n///\n///   * **&Route**\n///\n///     Extracts the [`Route`] from the request if one is available. When used\n///     as a request guard in a route handler, this will always succeed. Outside\n///     of a route handler, a route may not be available, and the request is\n///     forwarded with a 500 Internal Server Error status.\n///\n///     For more information on when an `&Route` is available, see\n///     [`Request::route()`].\n///\n///   * **&CookieJar**\n///\n///     Returns a borrow to the [`CookieJar`] in the incoming request. Note that\n///     `CookieJar` implements internal mutability, so a handle to a `CookieJar`\n///     allows you to get _and_ set cookies in the request.\n///\n///     _This implementation always returns successfully._\n///\n///   * **&[`Config`]**\n///\n///     Extracts the application [`Config`].\n///\n///     _This implementation always returns successfully._\n///\n///   * **&ContentType**\n///\n///     Extracts the [`ContentType`] header from the incoming request via\n///     [`Request::content_type()`]. If the request didn't specify a\n///     Content-Type, the request is forwarded with a 500 Internal Server Error\n///     status.\n///\n///   * **&Accept**\n///\n///     Extracts the [`Accept`] header from the incoming request via\n///     [`Request::accept()`]. If the request didn't specify an `Accept`, the\n///     request is forwarded with a 500 Internal Server Error status.\n///\n///   * ***IpAddr**\n///\n///     Extracts the client ip address of the incoming request as an [`IpAddr`]\n///     via [`Request::client_ip()`]. If the client's IP address is not known,\n///     the request is forwarded with a 500 Internal Server Error status.\n///\n///   * **ProxyProto**\n///\n///     Extracts the protocol of the incoming request as a [`ProxyProto`] via\n///     [`Request::proxy_proto()`]. If no such header is present, the request is\n///     forwarded with a 500 Internal Server Error status.\n///\n///   * **SocketAddr**\n///\n///     Extracts the remote address of the incoming request as a [`SocketAddr`]\n///     via [`Request::remote()`]. If the remote address is not known, the\n///     request is forwarded with a 500 Internal Server Error status.\n///\n///   * **Option&lt;T>** _where_ **T: FromRequest**\n///\n///     The type `T` is derived from the incoming request using `T`'s\n///     `FromRequest` implementation. If the derivation is a `Success`, the\n///     derived value is returned in `Some`. Otherwise, a `None` is returned.\n///\n///     _This implementation always returns successfully._\n///\n///   * **Result&lt;T, T::Error>** _where_ **T: FromRequest**\n///\n///     The type `T` is derived from the incoming request using `T`'s\n///     `FromRequest` implementation. If derivation is a `Success`, the value is\n///     returned in `Ok`. If the derivation is an `Error`, the error value is\n///     returned in `Err`. If the derivation is a `Forward`, the request is\n///     forwarded with the same status code as the original forward.\n///\n/// [`Config`]: crate::config::Config\n///\n/// # Example\n///\n/// Imagine you're running an authenticated API service that requires that some\n/// requests be sent along with a valid API key in a header field. You want to\n/// ensure that the handlers corresponding to these requests don't get called\n/// unless there is an API key in the request and the key is valid. The\n/// following example implements this using an `ApiKey` type and a `FromRequest`\n/// implementation for that type. The `ApiKey` type is then used in the\n/// `sensitive` handler.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// use rocket::http::Status;\n/// use rocket::request::{self, Outcome, Request, FromRequest};\n///\n/// struct ApiKey<'r>(&'r str);\n///\n/// #[derive(Debug)]\n/// enum ApiKeyError {\n///     Missing,\n///     Invalid,\n/// }\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for ApiKey<'r> {\n///     type Error = ApiKeyError;\n///\n///     async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n///         /// Returns true if `key` is a valid API key string.\n///         fn is_valid(key: &str) -> bool {\n///             key == \"valid_api_key\"\n///         }\n///\n///         match req.headers().get_one(\"x-api-key\") {\n///             None => Outcome::Error((Status::BadRequest, ApiKeyError::Missing)),\n///             Some(key) if is_valid(key) => Outcome::Success(ApiKey(key)),\n///             Some(_) => Outcome::Error((Status::BadRequest, ApiKeyError::Invalid)),\n///         }\n///     }\n/// }\n///\n/// #[get(\"/sensitive\")]\n/// fn sensitive(key: ApiKey<'_>) -> &'static str {\n///     \"Sensitive data.\"\n/// }\n/// ```\n///\n/// # Request-Local State\n///\n/// Request guards that perform expensive operations, such as those that query a\n/// database or an external service, should use the [request-local state] cache\n/// to store results if they might be invoked multiple times during the routing\n/// of a single request.\n///\n/// For example, consider a pair of `User` and `Admin` guards and a pair of\n/// routes (`admin_dashboard` and `user_dashboard`):\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[cfg(feature = \"secrets\")] mod wrapper {\n/// # use rocket::outcome::{IntoOutcome, try_outcome};\n/// # use rocket::request::{self, Outcome, FromRequest, Request};\n/// # use rocket::http::Status;\n/// # struct User { id: String, is_admin: bool }\n/// # struct Database;\n/// # impl Database {\n/// #     fn get_user(&self, id: String) -> Result<User, ()> {\n/// #         Ok(User { id, is_admin: false })\n/// #     }\n/// # }\n/// # #[rocket::async_trait]\n/// # impl<'r> FromRequest<'r> for Database {\n/// #     type Error = ();\n/// #     async fn from_request(request: &'r Request<'_>) -> Outcome<Database, ()> {\n/// #         Outcome::Success(Database)\n/// #     }\n/// # }\n/// #\n/// # struct Admin { user: User }\n/// #\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for User {\n///     type Error = ();\n///\n///     async fn from_request(request: &'r Request<'_>) -> Outcome<User, ()> {\n///         let db = try_outcome!(request.guard::<Database>().await);\n///         request.cookies()\n///             .get_private(\"user_id\")\n///             .and_then(|cookie| cookie.value().parse().ok())\n///             .and_then(|id| db.get_user(id).ok())\n///             .or_forward(Status::Unauthorized)\n///     }\n/// }\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for Admin {\n///     type Error = ();\n///\n///     async fn from_request(request: &'r Request<'_>) -> Outcome<Admin, ()> {\n///         // This will unconditionally query the database!\n///         let user = try_outcome!(request.guard::<User>().await);\n///         if user.is_admin {\n///             Outcome::Success(Admin { user })\n///         } else {\n///             Outcome::Forward(Status::Unauthorized)\n///         }\n///     }\n/// }\n///\n/// #[get(\"/dashboard\")]\n/// fn admin_dashboard(admin: Admin) { }\n///\n/// #[get(\"/dashboard\", rank = 2)]\n/// fn user_dashboard(user: User) { }\n/// # } // end of cfg wrapper\n/// ```\n///\n/// When a non-admin user is logged in, the database will be queried twice: once\n/// via the `Admin` guard invoking the `User` guard, and a second time via the\n/// `User` guard directly. For cases like these, request-local state should be\n/// used, as illustrated below:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[cfg(feature = \"secrets\")] mod wrapper {\n/// # use rocket::outcome::{IntoOutcome, try_outcome};\n/// # use rocket::request::{self, Outcome, FromRequest, Request};\n/// # use rocket::http::Status;\n/// # struct User { id: String, is_admin: bool }\n/// # struct Database;\n/// # impl Database {\n/// #     fn get_user(&self, id: String) -> Result<User, ()> {\n/// #         Ok(User { id, is_admin: false })\n/// #     }\n/// # }\n/// # #[rocket::async_trait]\n/// # impl<'r> FromRequest<'r> for Database {\n/// #     type Error = ();\n/// #     async fn from_request(request: &'r Request<'_>) -> Outcome<Database, ()> {\n/// #         Outcome::Success(Database)\n/// #     }\n/// # }\n/// #\n/// # struct Admin<'a> { user: &'a User }\n/// #\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for &'r User {\n///     type Error = std::convert::Infallible;\n///\n///     async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n///         // This closure will execute at most once per request, regardless of\n///         // the number of times the `User` guard is executed.\n///         let user_result = request.local_cache_async(async {\n///             let db = request.guard::<Database>().await.succeeded()?;\n///             request.cookies()\n///                 .get_private(\"user_id\")\n///                 .and_then(|cookie| cookie.value().parse().ok())\n///                 .and_then(|id| db.get_user(id).ok())\n///         }).await;\n///\n///         user_result.as_ref().or_forward(Status::Unauthorized)\n///     }\n/// }\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for Admin<'r> {\n///     type Error = std::convert::Infallible;\n///\n///     async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n///         let user = try_outcome!(request.guard::<&User>().await);\n///         if user.is_admin {\n///             Outcome::Success(Admin { user })\n///         } else {\n///             Outcome::Forward(Status::Unauthorized)\n///         }\n///     }\n/// }\n/// # } // end of cfg wrapper\n/// ```\n///\n/// Notice that these request guards provide access to *borrowed* data (`&'a\n/// User` and `Admin<'a>`) as the data is now owned by the request's cache.\n///\n/// [request-local state]: https://rocket.rs/master/guide/state/#request-local-state\n#[crate::async_trait]\npub trait FromRequest<'r>: Sized {\n    /// The associated error to be returned if derivation fails.\n    type Error: Debug;\n\n    /// Derives an instance of `Self` from the incoming request metadata.\n    ///\n    /// If the derivation is successful, an outcome of `Success` is returned. If\n    /// the derivation fails in an unrecoverable fashion, `Error` is returned.\n    /// `Forward` is returned to indicate that the request should be forwarded\n    /// to other matching routes, if any.\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for Method {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        Success(request.method())\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r Origin<'r> {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        Success(request.uri())\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r Host<'r> {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        match request.host() {\n            Some(host) => Success(host),\n            None => Forward(Status::InternalServerError)\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r Route {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        match request.route() {\n            Some(route) => Success(route),\n            None => Forward(Status::InternalServerError)\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r CookieJar<'r> {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        Success(request.cookies())\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r Accept {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        match request.accept() {\n            Some(accept) => Success(accept),\n            None => Forward(Status::InternalServerError)\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r ContentType {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        match request.content_type() {\n            Some(content_type) => Success(content_type),\n            None => Forward(Status::InternalServerError)\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for IpAddr {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        match request.client_ip() {\n            Some(addr) => Success(addr),\n            None => Forward(Status::InternalServerError)\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for ProxyProto<'r> {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n        request.proxy_proto().or_forward(Status::InternalServerError)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for &'r Endpoint {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        request.remote().or_forward(Status::InternalServerError)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for SocketAddr {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        request.remote()\n            .and_then(|r| r.socket_addr())\n            .or_forward(Status::InternalServerError)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        match T::from_request(request).await {\n            Success(val) => Success(Ok(val)),\n            Error((_, e)) => Success(Err(e)),\n            Forward(status) => Forward(status),\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: FromRequest<'r>> FromRequest<'r> for Option<T> {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        match T::from_request(request).await {\n            Success(val) => Success(Some(val)),\n            Error(_) | Forward(_) => Success(None),\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: FromRequest<'r>> FromRequest<'r> for Outcome<T, T::Error> {\n    type Error = Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {\n        Success(T::from_request(request).await)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/request/mod.rs",
    "content": "//! Types and traits for request parsing and handling.\n\nmod request;\nmod from_param;\nmod from_request;\nmod atomic_method;\n\n#[cfg(test)]\nmod tests;\n\npub use self::request::Request;\npub use self::from_request::{FromRequest, Outcome};\npub use self::from_param::{FromParam, FromSegments};\n\n#[doc(hidden)]\npub use rocket_codegen::FromParam;\n\n#[doc(inline)]\npub use crate::response::flash::FlashMessage;\n\npub(crate) use self::request::ConnectionMeta;\npub(crate) use self::atomic_method::AtomicMethod;\n\ncrate::export! {\n    /// Store and immediately retrieve a vector-like value `$v` (`String` or\n    /// `Vec<T>`) in `$request`'s local cache using a locally generated\n    /// anonymous type to avoid type conflicts.\n    ///\n    /// Unlike `local_cache_once`, this macro's generated code _always_ returns\n    /// a unique reference to request-local cache.\n    ///\n    /// # Note\n    ///\n    /// The value `$v` must be of type `String` or `Vec<T>`, that is, a type\n    /// that implements the sealed trait [`Shareable`](crate::form::Shareable)bb).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::request::{local_cache, local_cache_once};\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    ///\n    /// // The first store into local cache for a given type wins.\n    /// for i in 0..4 {\n    ///     assert_eq!(request.local_cache(|| i.to_string()), \"0\");\n    /// }\n    ///\n    /// // This shows that we cannot cache different values of the same type; we\n    /// // _must_ use a proxy type. To avoid the need to write these manually, use\n    /// // `local_cache!`, which generates one of the fly.\n    /// for i in 0..4 {\n    ///     assert_eq!(local_cache!(request, i.to_string()), i.to_string());\n    /// }\n    ///\n    /// // Note that while `local_cache_once!` generates a new type for the\n    /// // _macro_ invocation, that type is the same per run-time invocation, so\n    /// // all \"calls\" to `local_cache_once!` on the same line return the same\n    /// // reference for a given request.\n    /// for i in 1..4 {\n    ///     // Note that this is `1`, so _not_ the `String` from line 4.\n    ///     assert_eq!(local_cache_once!(request, i.to_string()), \"1\");\n    /// }\n    /// ```\n    macro_rules! local_cache {\n        ($request:expr, $v:expr $(,)?) => ({\n            struct Local<T: $crate::form::Shareable>($crate::form::SharedStack<T>);\n            let stack = $request.local_cache(|| Local($crate::form::SharedStack::new()));\n            stack.0.push_owned($v)\n        })\n    }\n}\n\ncrate::export! {\n    /// Store and immediately retrieve a value `$v` in `$request`'s local cache\n    /// using a locally generated anonymous type to avoid type conflicts.\n    ///\n    /// The code generated by this macro is expected to be invoked at-most once\n    /// per-request. This is because while `local_cache_once!` generates a new\n    /// type for the _macro_ invocation, that type is the same per run-time\n    /// invocation. Thus, for a given request, a `local_cache_once!` invocation\n    /// always returns the same reference.\n    ///\n    /// To get a unique request-local reference to string-like values, use\n    /// [`local_cache!`] instead.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::request::local_cache_once;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    ///\n    /// // The first store into local cache for a given type wins.\n    /// assert_eq!(request.local_cache(|| String::from(\"hello\")), \"hello\");\n    ///\n    /// // The following returns the cached, previously stored value for the type.\n    /// assert_eq!(request.local_cache(|| String::from(\"goodbye\")), \"hello\");\n    ///\n    /// // This shows that we cannot cache different values of the same type;\n    /// // we _must_ use a proxy type. To avoid the need to write these manually,\n    /// // use `local_cache_once!`, which generates one of the fly.\n    /// assert_eq!(local_cache_once!(request, String::from(\"hello\")), \"hello\");\n    /// assert_eq!(local_cache_once!(request, String::from(\"goodbye\")), \"goodbye\");\n    ///\n    /// // But a macro invocation for the same request always resolves to the\n    /// // first reference as the unique type is generated at compile-time.\n    /// for i in 1..4 {\n    ///     assert_eq!(local_cache_once!(request, i.to_string()), \"1\");\n    /// }\n    /// ```\n    macro_rules! local_cache_once {\n        ($request:expr, $v:expr $(,)?) => ({\n            struct Local<T>(T);\n            &$request.local_cache(move || Local($v)).0\n        })\n    }\n}\n"
  },
  {
    "path": "core/lib/src/request/request.rs",
    "content": "use std::{io, fmt};\nuse std::ops::RangeFrom;\nuse std::sync::{Arc, atomic::Ordering};\nuse std::borrow::Cow;\nuse std::str::FromStr;\nuse std::future::Future;\nuse std::net::IpAddr;\n\nuse http::Version;\nuse rocket_http::HttpVersion;\nuse state::{TypeMap, InitCell};\nuse futures::future::BoxFuture;\nuse ref_swap::OptionRefSwap;\n\nuse crate::{Rocket, Route, Orbit};\nuse crate::request::{FromParam, FromSegments, FromRequest, Outcome, AtomicMethod};\nuse crate::form::{self, ValueField, FromForm};\nuse crate::data::Limits;\n\nuse crate::http::ProxyProto;\nuse crate::http::{Method, Header, HeaderMap, ContentType, Accept, MediaType, CookieJar, Cookie};\nuse crate::http::uri::{fmt::Path, Origin, Segments, Host, Authority};\nuse crate::listener::{Certificates, Endpoint};\n\n/// The type of an incoming web request.\n///\n/// This should be used sparingly in Rocket applications. In particular, it\n/// should likely only be used when writing [`FromRequest`] implementations. It\n/// contains all of the information for a given web request except for the body\n/// data. This includes the HTTP method, URI, cookies, headers, and more.\n#[derive(Clone)]\npub struct Request<'r> {\n    method: AtomicMethod,\n    uri: Origin<'r>,\n    headers: HeaderMap<'r>,\n    pub(crate) version: Option<HttpVersion>,\n    pub(crate) errors: Vec<RequestError>,\n    pub(crate) connection: ConnectionMeta,\n    pub(crate) state: RequestState<'r>,\n}\n\n/// Information derived from an incoming connection, if any.\n#[derive(Clone, Default)]\npub(crate) struct ConnectionMeta {\n    pub peer_endpoint: Option<Endpoint>,\n    #[cfg_attr(not(feature = \"mtls\"), allow(dead_code))]\n    pub peer_certs: Option<Arc<Certificates<'static>>>,\n    #[cfg_attr(feature = \"tls\", allow(dead_code))]\n    pub server_name: Option<String>,\n}\n\nimpl ConnectionMeta {\n    pub fn new(\n        endpoint: io::Result<Endpoint>,\n        certs: Option<Certificates<'_>>,\n        server_name: Option<&str>) -> Self {\n        ConnectionMeta {\n            peer_endpoint: endpoint.ok(),\n            peer_certs: certs.map(|c| c.into_owned()).map(Arc::new),\n            server_name: server_name.map(|s| s.to_string()),\n        }\n    }\n}\n\n/// Information derived from the request.\npub(crate) struct RequestState<'r> {\n    pub rocket: &'r Rocket<Orbit>,\n    pub route: OptionRefSwap<'r, Route>,\n    pub cookies: CookieJar<'r>,\n    pub accept: InitCell<Option<Accept>>,\n    pub content_type: InitCell<Option<ContentType>>,\n    pub cache: Arc<TypeMap![Send + Sync]>,\n    pub host: Option<Host<'r>>,\n}\n\nimpl Clone for RequestState<'_> {\n    fn clone(&self) -> Self {\n        RequestState {\n            rocket: self.rocket,\n            route: OptionRefSwap::new(self.route.load(Ordering::Acquire)),\n            cookies: self.cookies.clone(),\n            accept: self.accept.clone(),\n            content_type: self.content_type.clone(),\n            cache: self.cache.clone(),\n            host: self.host.clone(),\n        }\n    }\n}\n\nimpl<'r> Request<'r> {\n    /// Create a new `Request` with the given `method` and `uri`.\n    #[inline(always)]\n    pub(crate) fn new<'s: 'r>(\n        rocket: &'r Rocket<Orbit>,\n        method: Method,\n        uri: Origin<'s>,\n        version: Option<HttpVersion>,\n    ) -> Request<'r> {\n        Request {\n            uri,\n            method: AtomicMethod::new(method),\n            headers: HeaderMap::new(),\n            version,\n            errors: Vec::new(),\n            connection: ConnectionMeta::default(),\n            state: RequestState {\n                rocket,\n                route: OptionRefSwap::new(None),\n                cookies: CookieJar::new(None, rocket),\n                accept: InitCell::new(),\n                content_type: InitCell::new(),\n                cache: Arc::new(<TypeMap![Send + Sync]>::new()),\n                host: None,\n            }\n        }\n    }\n\n    /// Retrieve http protocol version, when applicable.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::HttpVersion;\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # req.override_version(HttpVersion::Http11);\n    /// assert_eq!(req.version(), Some(HttpVersion::Http11));\n    /// ```\n    pub fn version(&self) -> Option<HttpVersion> {\n        self.version\n    }\n\n    /// Retrieve the method from `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::Method;\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// # let post = |uri| c.post(uri);\n    /// assert_eq!(get(\"/\").method(), Method::Get);\n    /// assert_eq!(post(\"/\").method(), Method::Post);\n    /// ```\n    #[inline(always)]\n    pub fn method(&self) -> Method {\n        self.method.load()\n    }\n\n    /// Set the method of `self` to `method`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::Method;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// assert_eq!(request.method(), Method::Get);\n    ///\n    /// request.set_method(Method::Post);\n    /// assert_eq!(request.method(), Method::Post);\n    /// ```\n    #[inline(always)]\n    pub fn set_method(&mut self, method: Method) {\n        self.method.set(method);\n    }\n\n    /// Borrow the [`Origin`] URI from `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// assert_eq!(get(\"/hello/rocketeer\").uri().path(), \"/hello/rocketeer\");\n    /// assert_eq!(get(\"/hello\").uri().query(), None);\n    /// ```\n    #[inline(always)]\n    pub fn uri(&self) -> &Origin<'r> {\n        &self.uri\n    }\n\n    /// Set the URI in `self` to `uri`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::uri::Origin;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// let uri = Origin::parse(\"/hello/Sergio?type=greeting\").unwrap();\n    /// request.set_uri(uri);\n    /// assert_eq!(request.uri().path(), \"/hello/Sergio\");\n    /// assert_eq!(request.uri().query().unwrap(), \"type=greeting\");\n    ///\n    /// let new_uri = request.uri().map_path(|p| format!(\"/foo{}\", p)).unwrap();\n    /// request.set_uri(new_uri);\n    /// assert_eq!(request.uri().path(), \"/foo/hello/Sergio\");\n    /// assert_eq!(request.uri().query().unwrap(), \"type=greeting\");\n    /// ```\n    #[inline(always)]\n    pub fn set_uri(&mut self, uri: Origin<'r>) {\n        self.uri = uri;\n    }\n\n    /// Returns the [`Host`] identified in the request, if any.\n    ///\n    /// If the request is made via HTTP/1.1 (or earlier), this method returns\n    /// the value in the `HOST` header without the deprecated `user_info`\n    /// component. Otherwise, this method returns the contents of the\n    /// `:authority` pseudo-header request field.\n    ///\n    /// Note that this method _only_ reflects the `HOST` header in the _initial_\n    /// request and not any changes made thereafter. To change the value\n    /// returned by this method, use [`Request::set_host()`].\n    ///\n    /// # ⚠️ DANGER ⚠️\n    ///\n    /// Using the user-controlled `host` to construct URLs is a security hazard!\n    /// _Never_ do so without first validating the host against a whitelist. For\n    /// this reason, Rocket disallows constructing host-prefixed URIs with\n    /// [`uri!`]. _Always_ use [`uri!`] to construct URIs.\n    ///\n    /// [`uri!`]: crate::uri!\n    ///\n    /// # Example\n    ///\n    /// Retrieve the raw host, unusable to construct safe URIs:\n    ///\n    /// ```rust\n    /// use rocket::http::uri::Host;\n    /// # use rocket::uri;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// assert_eq!(request.host(), None);\n    ///\n    /// request.set_host(Host::from(uri!(\"rocket.rs\")));\n    /// let host = request.host().unwrap();\n    /// assert_eq!(host.domain(), \"rocket.rs\");\n    /// assert_eq!(host.port(), None);\n    ///\n    /// request.set_host(Host::from(uri!(\"rocket.rs:2392\")));\n    /// let host = request.host().unwrap();\n    /// assert_eq!(host.domain(), \"rocket.rs\");\n    /// assert_eq!(host.port(), Some(2392));\n    /// ```\n    ///\n    /// Retrieve the raw host, check it against a whitelist, and construct a\n    /// URI:\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// # type Token = String;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    /// use rocket::http::uri::Host;\n    ///\n    /// // A sensitive URI we want to prefix with safe hosts.\n    /// #[get(\"/token?<secret>\")]\n    /// fn token(secret: Token) { /* .. */ }\n    ///\n    /// // Whitelist of known hosts. In a real setting, you might retrieve this\n    /// // list from config at ignite-time using tools like `AdHoc::config()`.\n    /// const WHITELIST: [Host<'static>; 3] = [\n    ///     Host::new(uri!(\"rocket.rs\")),\n    ///     Host::new(uri!(\"rocket.rs:443\")),\n    ///     Host::new(uri!(\"guide.rocket.rs:443\")),\n    /// ];\n    ///\n    /// // A request with a host of \"rocket.rs\". Note the case-insensitivity.\n    /// request.set_host(Host::from(uri!(\"ROCKET.rs\")));\n    /// let prefix = request.host().and_then(|h| h.to_absolute(\"https\", &WHITELIST));\n    ///\n    /// // `rocket.rs` is in the whitelist, so we'll get back a `Some`.\n    /// assert!(prefix.is_some());\n    /// if let Some(prefix) = prefix {\n    ///     // We can use this prefix to safely construct URIs.\n    ///     let uri = uri!(prefix, token(\"some-secret-token\"));\n    ///     assert_eq!(uri, \"https://ROCKET.rs/token?secret=some-secret-token\");\n    /// }\n    ///\n    /// // A request with a host of \"attacker-controlled.com\".\n    /// request.set_host(Host::from(uri!(\"attacker-controlled.com\")));\n    /// let prefix = request.host().and_then(|h| h.to_absolute(\"https\", &WHITELIST));\n    ///\n    /// // `attacker-controlled.come` is _not_ on the whitelist.\n    /// assert!(prefix.is_none());\n    /// assert!(request.host().is_some());\n    /// ```\n    #[inline(always)]\n    pub fn host(&self) -> Option<&Host<'r>> {\n        self.state.host.as_ref()\n    }\n\n    /// Returns the resolved SNI server name requested in the TLS handshake, if\n    /// any.\n    ///\n    /// Ideally, this will match the `Host` header in the request.\n    #[cfg(feature = \"tls\")]\n    #[inline(always)]\n    pub fn sni(&mut self) -> Option<&str> {\n        self.connection.server_name.as_deref()\n    }\n\n    /// Sets the host of `self` to `host`.\n    ///\n    /// # Example\n    ///\n    /// Set the host to `rocket.rs:443`.\n    ///\n    /// ```rust\n    /// use rocket::http::uri::Host;\n    /// # use rocket::uri;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// assert_eq!(request.host(), None);\n    ///\n    /// request.set_host(Host::from(uri!(\"rocket.rs:443\")));\n    /// let host = request.host().unwrap();\n    /// assert_eq!(host.domain(), \"rocket.rs\");\n    /// assert_eq!(host.port(), Some(443));\n    /// ```\n    #[inline(always)]\n    pub fn set_host(&mut self, host: Host<'r>) {\n        self.state.host = Some(host);\n    }\n\n    /// Returns the raw address of the remote connection that initiated this\n    /// request if the address is known. If the address is not known, `None` is\n    /// returned.\n    ///\n    /// Because it is common for proxies to forward connections for clients, the\n    /// remote address may contain information about the proxy instead of the\n    /// client. For this reason, proxies typically set a \"X-Real-IP\" header\n    /// [`ip_header`](crate::Config::ip_header) with the client's true IP. To\n    /// extract this IP from the request, use the [`real_ip()`] or\n    /// [`client_ip()`] methods.\n    ///\n    /// [`real_ip()`]: #method.real_ip\n    /// [`client_ip()`]: #method.client_ip\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};\n    /// use rocket::listener::Endpoint;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// assert_eq!(request.remote(), None);\n    ///\n    /// let localhost = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8111);\n    /// request.set_remote(Endpoint::Tcp(localhost));\n    /// assert_eq!(request.remote().unwrap().tcp().unwrap(), localhost);\n    /// ```\n    #[inline(always)]\n    pub fn remote(&self) -> Option<&Endpoint> {\n        self.connection.peer_endpoint.as_ref()\n    }\n\n    /// Sets the remote address of `self` to `address`.\n    ///\n    /// # Example\n    ///\n    /// Set the remote address to be 127.0.0.1:8111:\n    ///\n    /// ```rust\n    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};\n    /// use rocket::listener::Endpoint;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// assert_eq!(request.remote(), None);\n    ///\n    /// let localhost = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 8111);\n    /// request.set_remote(Endpoint::Tcp(localhost));\n    /// assert_eq!(request.remote().unwrap().tcp().unwrap(), localhost);\n    /// ```\n    #[inline(always)]\n    pub fn set_remote(&mut self, endpoint: Endpoint) {\n        self.connection.peer_endpoint = Some(endpoint);\n    }\n\n    /// Returns the IP address of the configured\n    /// [`ip_header`](crate::Config::ip_header) of the request if such a header\n    /// is configured, exists and contains a valid IP address.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::net::Ipv4Addr;\n    /// use rocket::http::Header;\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let req = c.get(\"/\");\n    /// assert_eq!(req.real_ip(), None);\n    ///\n    /// // `ip_header` defaults to `X-Real-IP`.\n    /// let req = req.header(Header::new(\"X-Real-IP\", \"127.0.0.1\"));\n    /// assert_eq!(req.real_ip(), Some(Ipv4Addr::LOCALHOST.into()));\n    /// ```\n    pub fn real_ip(&self) -> Option<IpAddr> {\n        let ip_header = self.rocket().config.ip_header.as_ref()?.as_str();\n        self.headers()\n            .get_one(ip_header)\n            .and_then(|ip| {\n                ip.parse()\n                    .map_err(|_| warn!(value = ip, \"'{ip_header}' header is malformed\"))\n                    .ok()\n            })\n    }\n\n    /// Returns the [`ProxyProto`] associated with the current request.\n    ///\n    /// The value is determined by inspecting the header named\n    /// [`proxy_proto_header`](crate::Config::proxy_proto_header), if\n    /// configured, and parsing it case-insensitivity. If the parameter isn't\n    /// configured or the request doesn't contain a header named as indicated,\n    /// this method returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::{Header, ProxyProto};\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let req = c.get(\"/\");\n    /// // By default, no `proxy_proto_header` is configured.\n    /// let req = req.header(Header::new(\"x-forwarded-proto\", \"https\"));\n    /// assert_eq!(req.proxy_proto(), None);\n    ///\n    /// // We can configure one by setting the `proxy_proto_header` parameter.\n    /// // Here we set it to `x-forwarded-proto`, considered de-facto standard.\n    /// # let figment = rocket::figment::Figment::from(rocket::Config::debug_default());\n    /// let figment = figment.merge((\"proxy_proto_header\", \"x-forwarded-proto\"));\n    /// # let c = rocket::local::blocking::Client::debug(rocket::custom(figment)).unwrap();\n    /// # let req = c.get(\"/\");\n    /// let req = req.header(Header::new(\"x-forwarded-proto\", \"https\"));\n    /// assert_eq!(req.proxy_proto(), Some(ProxyProto::Https));\n    ///\n    /// # let req = c.get(\"/\");\n    /// let req = req.header(Header::new(\"x-forwarded-proto\", \"HTTP\"));\n    /// assert_eq!(req.proxy_proto(), Some(ProxyProto::Http));\n    ///\n    /// # let req = c.get(\"/\");\n    /// let req = req.header(Header::new(\"x-forwarded-proto\", \"xproto\"));\n    /// assert_eq!(req.proxy_proto(), Some(ProxyProto::Unknown(\"xproto\".into())));\n    /// ```\n    pub fn proxy_proto(&self) -> Option<ProxyProto<'_>> {\n        self.rocket()\n            .config\n            .proxy_proto_header\n            .as_ref()\n            .and_then(|header| self.headers().get_one(header.as_str()))\n            .map(ProxyProto::from)\n    }\n\n    /// Returns whether we are *likely* in a secure context.\n    ///\n    /// A request is in a \"secure context\" if it was initially sent over a\n    /// secure (TLS, via HTTPS) connection. If TLS is configured and enabled,\n    /// then the request is guaranteed to be in a secure context. Otherwise, if\n    /// [`Request::proxy_proto()`] evaluates to `Https`, then we are _likely_ to\n    /// be in a secure context. We say _likely_ because it is entirely possible\n    /// for the header to indicate that the connection is being proxied via\n    /// HTTPS while reality differs. As such, this value should not be trusted\n    /// when 100% confidence is a necessity.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::{Header, ProxyProto};\n    ///\n    /// # let client = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let req = client.get(\"/\");\n    /// // If TLS and proxy_proto are disabled, we are not in a secure context.\n    /// assert_eq!(req.context_is_likely_secure(), false);\n    ///\n    /// // Configuring proxy_proto and receiving a header value of `https` is\n    /// // interpreted as likely being in a secure context.\n    /// // Here we set it to `x-forwarded-proto`, considered de-facto standard.\n    /// # let figment = rocket::figment::Figment::from(rocket::Config::debug_default());\n    /// let figment = figment.merge((\"proxy_proto_header\", \"x-forwarded-proto\"));\n    /// # let c = rocket::local::blocking::Client::debug(rocket::custom(figment)).unwrap();\n    /// # let req = c.get(\"/\");\n    /// let req = req.header(Header::new(\"x-forwarded-proto\", \"https\"));\n    /// assert_eq!(req.context_is_likely_secure(), true);\n    /// ```\n    pub fn context_is_likely_secure(&self) -> bool {\n        self.cookies().state.secure\n    }\n\n    /// Attempts to return the client's IP address by first inspecting the\n    /// [`ip_header`](crate::Config::ip_header) and then using the remote\n    /// connection's IP address. Note that the built-in `IpAddr` request guard\n    /// can be used to retrieve the same information in a handler:\n    ///\n    /// ```rust\n    /// # use rocket::get;\n    /// use std::net::IpAddr;\n    ///\n    /// #[get(\"/\")]\n    /// fn get_ip(client_ip: IpAddr) { /* ... */ }\n    ///\n    /// #[get(\"/\")]\n    /// fn try_get_ip(client_ip: Option<IpAddr>) { /* ... */ }\n    /// ````\n    ///\n    /// If the `ip_header` exists and contains a valid IP address, that address\n    /// is returned. Otherwise, if the address of the remote connection is\n    /// known, that address is returned. Otherwise, `None` is returned.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::http::Header;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    /// # use std::net::{SocketAddr, IpAddr, Ipv4Addr};\n    /// # use rocket::listener::Endpoint;\n    ///\n    /// // starting without an \"X-Real-IP\" header or remote address\n    /// assert!(request.client_ip().is_none());\n    ///\n    /// // add a remote address; this is done by Rocket automatically\n    /// let localhost_9190 = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 9190);\n    /// request.set_remote(Endpoint::Tcp(localhost_9190));\n    /// assert_eq!(request.client_ip().unwrap(), Ipv4Addr::LOCALHOST);\n    ///\n    /// // now with an X-Real-IP header, the default value for `ip_header`.\n    /// request.add_header(Header::new(\"X-Real-IP\", \"8.8.8.8\"));\n    /// assert_eq!(request.client_ip().unwrap(), Ipv4Addr::new(8, 8, 8, 8));\n    /// ```\n    #[inline]\n    pub fn client_ip(&self) -> Option<IpAddr> {\n        self.real_ip().or_else(|| self.remote()?.ip())\n    }\n\n    /// Returns a wrapped borrow to the cookies in `self`.\n    ///\n    /// [`CookieJar`] implements internal mutability, so this method allows you\n    /// to get _and_ add/remove cookies in `self`.\n    ///\n    /// # Example\n    ///\n    /// Add a new cookie to a request's cookies:\n    ///\n    /// ```rust\n    /// use rocket::http::Cookie;\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    /// # let req = request.inner();\n    /// req.cookies().add((\"key\", \"val\"));\n    /// req.cookies().add((\"ans\", format!(\"life: {}\", 38 + 4)));\n    ///\n    /// assert_eq!(req.cookies().get_pending(\"key\").unwrap().value(), \"val\");\n    /// assert_eq!(req.cookies().get_pending(\"ans\").unwrap().value(), \"life: 42\");\n    /// ```\n    #[inline(always)]\n    pub fn cookies(&self) -> &CookieJar<'r> {\n        &self.state.cookies\n    }\n\n    /// Returns a [`HeaderMap`] of all of the headers in `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::{Accept, ContentType};\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// assert!(get(\"/\").headers().is_empty());\n    ///\n    /// let req = get(\"/\").header(Accept::HTML).header(ContentType::HTML);\n    /// assert_eq!(req.headers().len(), 2);\n    /// ```\n    #[inline(always)]\n    pub fn headers(&self) -> &HeaderMap<'r> {\n        &self.headers\n    }\n\n    /// Add `header` to `self`'s headers. The type of `header` can be any type\n    /// that implements the `Into<Header>` trait. This includes common types\n    /// such as [`ContentType`] and [`Accept`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::ContentType;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// assert!(request.headers().is_empty());\n    ///\n    /// request.add_header(ContentType::HTML);\n    /// assert!(request.headers().contains(\"Content-Type\"));\n    /// assert_eq!(request.headers().len(), 1);\n    /// ```\n    #[inline]\n    pub fn add_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) {\n        let header = header.into();\n        self.bust_header_cache(&header, false);\n        self.headers.add(header);\n    }\n\n    /// Replaces the value of the header with name `header.name` with\n    /// `header.value`. If no such header exists, `header` is added as a header\n    /// to `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::ContentType;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let mut req = c.get(\"/\");\n    /// # let request = req.inner_mut();\n    ///\n    /// assert!(request.headers().is_empty());\n    ///\n    /// request.add_header(ContentType::Any);\n    /// assert_eq!(request.headers().get_one(\"Content-Type\"), Some(\"*/*\"));\n    /// assert_eq!(request.content_type(), Some(&ContentType::Any));\n    ///\n    /// request.replace_header(ContentType::PNG);\n    /// assert_eq!(request.headers().get_one(\"Content-Type\"), Some(\"image/png\"));\n    /// assert_eq!(request.content_type(), Some(&ContentType::PNG));\n    /// ```\n    #[inline]\n    pub fn replace_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) {\n        let header = header.into();\n        self.bust_header_cache(&header, true);\n        self.headers.replace(header);\n    }\n\n    /// Returns the Content-Type header of `self`. If the header is not present,\n    /// returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::ContentType;\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// assert_eq!(get(\"/\").content_type(), None);\n    ///\n    /// let req = get(\"/\").header(ContentType::JSON);\n    /// assert_eq!(req.content_type(), Some(&ContentType::JSON));\n    /// ```\n    #[inline]\n    pub fn content_type(&self) -> Option<&ContentType> {\n        self.state.content_type\n            .get_or_init(|| self.headers().get_one(\"Content-Type\").and_then(|v| v.parse().ok()))\n            .as_ref()\n    }\n\n    /// Returns the Accept header of `self`. If the header is not present,\n    /// returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::Accept;\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// assert_eq!(get(\"/\").accept(), None);\n    /// assert_eq!(get(\"/\").header(Accept::JSON).accept(), Some(&Accept::JSON));\n    /// ```\n    #[inline]\n    pub fn accept(&self) -> Option<&Accept> {\n        self.state.accept\n            .get_or_init(|| self.headers().get_one(\"Accept\").and_then(|v| v.parse().ok()))\n            .as_ref()\n    }\n\n    /// Returns the media type \"format\" of the request.\n    ///\n    /// The returned `MediaType` is derived from either the `Content-Type` or\n    /// the `Accept` header of the request, based on whether the request's\n    /// method allows a body (see [`Method::allows_request_body()`]). The table\n    /// below summarized this:\n    ///\n    /// | Method Allows Body | Returned Format                 |\n    /// |--------------------|---------------------------------|\n    /// | Always             | `Option<ContentType>`           |\n    /// | Maybe or Never     | `Some(Preferred Accept or Any)` |\n    ///\n    /// In short, if the request's method indicates support for a payload, the\n    /// request's `Content-Type` header value, if any, is returned. Otherwise\n    /// the [preferred](Accept::preferred()) `Accept` header value is returned,\n    /// or if none is present, [`Accept::Any`].\n    ///\n    /// The media type returned from this method is used to match against the\n    /// `format` route attribute.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::http::{Accept, ContentType, MediaType};\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// # let post = |uri| c.post(uri);\n    ///\n    /// // Non-payload-bearing: format is accept header.\n    /// let req = get(\"/\").header(Accept::HTML);\n    /// assert_eq!(req.format(), Some(&MediaType::HTML));\n    ///\n    /// let req = get(\"/\").header(ContentType::JSON).header(Accept::HTML);\n    /// assert_eq!(req.format(), Some(&MediaType::HTML));\n    ///\n    /// // Payload: format is content-type header.\n    /// let req = post(\"/\").header(ContentType::HTML);\n    /// assert_eq!(req.format(), Some(&MediaType::HTML));\n    ///\n    /// let req = post(\"/\").header(ContentType::JSON).header(Accept::HTML);\n    /// assert_eq!(req.format(), Some(&MediaType::JSON));\n    ///\n    /// // Non-payload-bearing method and no accept header: `Any`.\n    /// assert_eq!(get(\"/\").format(), Some(&MediaType::Any));\n    /// ```\n    pub fn format(&self) -> Option<&MediaType> {\n        static ANY: MediaType = MediaType::Any;\n        if self.method().allows_request_body().unwrap_or(false) {\n            self.content_type().map(|ct| ct.media_type())\n        } else {\n            // TODO: Should we be using `accept_first` or `preferred`? Or\n            // should we be checking neither and instead pass things through\n            // where the client accepts the thing at all?\n            self.accept()\n                .map(|accept| accept.preferred().media_type())\n                .or(Some(&ANY))\n        }\n    }\n\n    /// Returns the [`Rocket`] instance that is handling this request.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    /// # type Pool = usize;\n    /// // Retrieve the application config via `Rocket::config()`.\n    /// let config = request.rocket().config();\n    ///\n    /// // Retrieve managed state via `Rocket::state()`.\n    /// let state = request.rocket().state::<Pool>();\n    ///\n    /// // Get a list of all of the registered routes and catchers.\n    /// let routes = request.rocket().routes();\n    /// let catchers = request.rocket().catchers();\n    /// ```\n    #[inline(always)]\n    pub fn rocket(&self) -> &'r Rocket<Orbit> {\n        self.state.rocket\n    }\n\n    /// Returns the configured application data limits.\n    ///\n    /// This is convenience function equivalent to:\n    ///\n    /// ```rust\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    /// &request.rocket().config().limits\n    /// # ;\n    /// ```\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::data::ToByteUnit;\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    ///\n    /// // This is the default `form` limit.\n    /// assert_eq!(request.limits().get(\"form\"), Some(32.kibibytes()));\n    ///\n    /// // Retrieve the limit for files with extension `.pdf`; etails to 1MiB.\n    /// assert_eq!(request.limits().get(\"file/pdf\"), Some(1.mebibytes()));\n    /// ```\n    #[inline(always)]\n    pub fn limits(&self) -> &'r Limits {\n        &self.rocket().config().limits\n    }\n\n    /// Get the presently matched route, if any.\n    ///\n    /// This method returns `Some` any time a handler or its guards are being\n    /// invoked. This method returns `None` _before_ routing has commenced; this\n    /// includes during request fairing callbacks.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    /// let route = request.route();\n    /// ```\n    #[inline(always)]\n    pub fn route(&self) -> Option<&'r Route> {\n        self.state.route.load(Ordering::Acquire)\n    }\n\n    /// Invokes the request guard implementation for `T`, returning its outcome.\n    ///\n    /// # Example\n    ///\n    /// Assuming a `User` request guard exists, invoke it:\n    ///\n    /// ```rust\n    /// # type User = rocket::http::Method;\n    /// # rocket::async_test(async move {\n    /// # let c = rocket::local::asynchronous::Client::debug_with(vec![]).await.unwrap();\n    /// # let request = c.get(\"/\");\n    /// let outcome = request.guard::<User>().await;\n    /// # })\n    /// ```\n    #[inline(always)]\n    pub fn guard<'z, 'a, T>(&'a self) -> BoxFuture<'z, Outcome<T, T::Error>>\n        where T: FromRequest<'a> + 'z, 'a: 'z, 'r: 'z\n    {\n        T::from_request(self)\n    }\n\n    /// Retrieves the cached value for type `T` from the request-local cached\n    /// state of `self`. If no such value has previously been cached for this\n    /// request, `f` is called to produce the value which is subsequently\n    /// returned.\n    ///\n    /// Different values of the same type _cannot_ be cached without using a\n    /// proxy, wrapper type. To avoid the need to write these manually, or for\n    /// libraries wishing to store values of public types, use the\n    /// [`local_cache!`](crate::request::local_cache) or\n    /// [`local_cache_once!`](crate::request::local_cache_once) macros to\n    /// generate a locally anonymous wrapper type, store, and retrieve the\n    /// wrapped value from request-local cache.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let request = c.get(\"/\");\n    /// // The first store into local cache for a given type wins.\n    /// let value = request.local_cache(|| \"hello\");\n    /// assert_eq!(*request.local_cache(|| \"hello\"), \"hello\");\n    ///\n    /// // The following return the cached, previously stored value for the type.\n    /// assert_eq!(*request.local_cache(|| \"goodbye\"), \"hello\");\n    /// ```\n    #[inline]\n    pub fn local_cache<T, F>(&self, f: F) -> &T\n        where F: FnOnce() -> T,\n              T: Send + Sync + 'static\n    {\n        self.state.cache.try_get()\n            .unwrap_or_else(|| {\n                self.state.cache.set(f());\n                self.state.cache.get()\n            })\n    }\n\n    /// Retrieves the cached value for type `T` from the request-local cached\n    /// state of `self`. If no such value has previously been cached for this\n    /// request, `fut` is `await`ed to produce the value which is subsequently\n    /// returned.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::Request;\n    /// # type User = ();\n    /// async fn current_user<'r>(request: &Request<'r>) -> User {\n    ///     // validate request for a given user, load from database, etc\n    /// }\n    ///\n    /// # rocket::async_test(async move {\n    /// # let c = rocket::local::asynchronous::Client::debug_with(vec![]).await.unwrap();\n    /// # let request = c.get(\"/\");\n    /// let current_user = request.local_cache_async(async {\n    ///     current_user(&request).await\n    /// }).await;\n    /// # })\n    /// ```\n    #[inline]\n    pub async fn local_cache_async<'a, T, F>(&'a self, fut: F) -> &'a T\n        where F: Future<Output = T>,\n              T: Send + Sync + 'static\n    {\n        match self.state.cache.try_get() {\n            Some(s) => s,\n            None => {\n                self.state.cache.set(fut.await);\n                self.state.cache.get()\n            }\n        }\n    }\n\n    /// Retrieves and parses into `T` the 0-indexed `n`th non-empty segment from\n    /// the _routed_ request, that is, the `n`th segment _after_ the mount\n    /// point. If the request has not been routed, then this is simply the `n`th\n    /// non-empty request URI segment.\n    ///\n    /// Returns `None` if `n` is greater than the number of non-empty segments.\n    /// Returns `Some(Err(T::Error))` if the parameter type `T` failed to be\n    /// parsed from the `n`th dynamic parameter.\n    ///\n    /// This method exists only to be used by manual routing. To retrieve\n    /// parameters from a request, use Rocket's code generation facilities.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// use rocket::error::Empty;\n    ///\n    /// assert_eq!(get(\"/a/b/c\").param(0), Some(Ok(\"a\")));\n    /// assert_eq!(get(\"/a/b/c\").param(1), Some(Ok(\"b\")));\n    /// assert_eq!(get(\"/a/b/c\").param(2), Some(Ok(\"c\")));\n    /// assert_eq!(get(\"/a/b/c\").param::<&str>(3), None);\n    ///\n    /// assert_eq!(get(\"/1/b/3\").param(0), Some(Ok(1)));\n    /// assert!(get(\"/1/b/3\").param::<usize>(1).unwrap().is_err());\n    /// assert_eq!(get(\"/1/b/3\").param(2), Some(Ok(3)));\n    ///\n    /// assert_eq!(get(\"/\").param::<&str>(0), Some(Err(Empty)));\n    /// ```\n    #[inline]\n    pub fn param<'a, T>(&'a self, n: usize) -> Option<Result<T, T::Error>>\n        where T: FromParam<'a>\n    {\n        self.routed_segment(n).map(T::from_param)\n    }\n\n    /// Retrieves and parses into `T` all of the path segments in the request\n    /// URI beginning and including the 0-indexed `n`th non-empty segment\n    /// _after_ the mount point.,that is, the `n`th segment _after_ the mount\n    /// point. If the request has not been routed, then this is simply the `n`th\n    /// non-empty request URI segment.\n    ///\n    /// `T` must implement [`FromSegments`], which is used to parse the\n    /// segments. If there are no non-empty segments, the `Segments` iterator\n    /// will be empty.\n    ///\n    /// This method exists only to be used by manual routing. To retrieve\n    /// segments from a request, use Rocket's code generation facilities.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::path::PathBuf;\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// assert_eq!(get(\"/\").segments(0..), Ok(PathBuf::new()));\n    /// assert_eq!(get(\"/\").segments(2..), Ok(PathBuf::new()));\n    ///\n    /// // Empty segments are skipped.\n    /// assert_eq!(get(\"///\").segments(2..), Ok(PathBuf::new()));\n    /// assert_eq!(get(\"/a/b/c\").segments(0..), Ok(PathBuf::from(\"a/b/c\")));\n    /// assert_eq!(get(\"/a/b/c\").segments(1..), Ok(PathBuf::from(\"b/c\")));\n    /// assert_eq!(get(\"/a/b/c\").segments(2..), Ok(PathBuf::from(\"c\")));\n    /// assert_eq!(get(\"/a/b/c\").segments(3..), Ok(PathBuf::new()));\n    /// assert_eq!(get(\"/a/b/c\").segments(4..), Ok(PathBuf::new()));\n    /// ```\n    #[inline]\n    pub fn segments<'a, T>(&'a self, n: RangeFrom<usize>) -> Result<T, T::Error>\n        where T: FromSegments<'a>\n    {\n        T::from_segments(self.routed_segments(n))\n    }\n\n    /// Retrieves and parses into `T` the query value with field name `name`.\n    /// `T` must implement [`FromForm`], which is used to parse the query's\n    /// value. Key matching is performed case-sensitively.\n    ///\n    /// # Warning\n    ///\n    /// This method exists _only_ to be used by manual routing and should\n    /// _never_ be used in a regular Rocket application. It is much more\n    /// expensive to use this method than to retrieve query parameters via\n    /// Rocket's codegen. To retrieve query values from a request, _always_\n    /// prefer to use Rocket's code generation facilities.\n    ///\n    /// # Error\n    ///\n    /// If a query segment with name `name` isn't present, returns `None`. If\n    /// parsing the value fails, returns `Some(Err(_))`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::form::FromForm;\n    ///\n    /// #[derive(Debug, PartialEq, FromForm)]\n    /// struct Dog<'r> {\n    ///     name: &'r str,\n    ///     age: usize\n    /// }\n    ///\n    /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap();\n    /// # let get = |uri| c.get(uri);\n    /// let req = get(\"/?a=apple&z=zebra&a=aardvark\");\n    /// assert_eq!(req.query_value::<&str>(\"a\").unwrap(), Ok(\"apple\"));\n    /// assert_eq!(req.query_value::<&str>(\"z\").unwrap(), Ok(\"zebra\"));\n    /// assert_eq!(req.query_value::<&str>(\"b\"), None);\n    ///\n    /// let a_seq = req.query_value::<Vec<&str>>(\"a\");\n    /// assert_eq!(a_seq.unwrap().unwrap(), [\"apple\", \"aardvark\"]);\n    ///\n    /// let req = get(\"/?dog.name=Max+Fido&dog.age=3\");\n    /// let dog = req.query_value::<Dog>(\"dog\");\n    /// assert_eq!(dog.unwrap().unwrap(), Dog { name: \"Max Fido\", age: 3 });\n    /// ```\n    #[inline]\n    pub fn query_value<'a, T>(&'a self, name: &str) -> Option<form::Result<'a, T>>\n        where T: FromForm<'a>\n    {\n        if !self.query_fields().any(|f| f.name == name) {\n            return None;\n        }\n\n        let mut ctxt = T::init(form::Options::Lenient);\n\n        self.query_fields()\n            .filter(|f| f.name == name)\n            .for_each(|f| T::push_value(&mut ctxt, f.shift()));\n\n        Some(T::finalize(ctxt))\n    }\n}\n\n// All of these methods only exist for internal, including codegen, purposes.\n// They _are not_ part of the stable API. Please, don't use these.\n#[doc(hidden)]\nimpl<'r> Request<'r> {\n    /// Resets the cached value (if any) for the header with name `name`.\n    fn bust_header_cache(&mut self, header: &Header<'_>, replace: bool) {\n        if header.name() == \"Content-Type\" {\n            if self.content_type().is_none() || replace {\n                self.state.content_type = InitCell::new();\n            }\n        } else if header.name() == \"Accept\" {\n            if self.accept().is_none() || replace {\n                self.state.accept = InitCell::new();\n            }\n        } else if Some(header.name()) == self.rocket().config.proxy_proto_header.as_deref() {\n            if !self.cookies().state.secure || replace {\n                self.cookies_mut().state.secure |= ProxyProto::from(header.value()).is_https();\n            }\n        }\n    }\n\n    /// Get the `n`th non-empty path segment, 0-indexed, after the mount point\n    /// for the currently matched route, as a string, if it exists. Used by\n    /// codegen.\n    #[inline]\n    pub fn routed_segment(&self, n: usize) -> Option<&str> {\n        self.routed_segments(0..).get(n)\n    }\n\n    /// Get the segments beginning at the `range`, 0-indexed, after the mount\n    /// point for the currently matched route, if they exist. Used by codegen.\n    #[inline]\n    pub fn routed_segments(&self, range: RangeFrom<usize>) -> Segments<'_, Path> {\n        let mount_segments = self.route()\n            .map(|r| r.uri.metadata.base_len)\n            .unwrap_or(0);\n\n        trace!(name: \"segments\", mount_segments, range.start);\n        self.uri().path().segments().skip(mount_segments + range.start)\n    }\n\n    // Retrieves the pre-parsed query items. Used by matching and codegen.\n    #[inline]\n    pub fn query_fields(&self) -> impl Iterator<Item = ValueField<'_>> {\n        self.uri().query()\n            .map(|q| q.segments().map(ValueField::from))\n            .into_iter()\n            .flatten()\n    }\n\n    /// Set `self`'s parameters given that the route used to reach this request\n    /// was `route`. Use during routing when attempting a given route.\n    #[inline(always)]\n    pub(crate) fn set_route(&self, route: &'r Route) {\n        self.state.route.store(Some(route), Ordering::Release)\n    }\n\n    #[inline(always)]\n    pub(crate) fn _set_method(&self, method: Method) {\n        self.method.store(method)\n    }\n\n    pub(crate) fn cookies_mut(&mut self) -> &mut CookieJar<'r> {\n        &mut self.state.cookies\n    }\n\n    /// Convert from Hyper types into a Rocket Request.\n    pub(crate) fn from_hyp(\n        rocket: &'r Rocket<Orbit>,\n        hyper: &'r hyper::http::request::Parts,\n        connection: ConnectionMeta,\n    ) -> Result<Request<'r>, Request<'r>> {\n        // Keep track of parsing errors; emit a `BadRequest` if any exist.\n        let mut errors = vec![];\n\n        // Ensure that the method is known.\n        let method = match hyper.method {\n            hyper::Method::GET => Method::Get,\n            hyper::Method::PUT => Method::Put,\n            hyper::Method::POST => Method::Post,\n            hyper::Method::DELETE => Method::Delete,\n            hyper::Method::OPTIONS => Method::Options,\n            hyper::Method::HEAD => Method::Head,\n            hyper::Method::TRACE => Method::Trace,\n            hyper::Method::CONNECT => Method::Connect,\n            hyper::Method::PATCH => Method::Patch,\n            ref ext => Method::from_str(ext.as_str()).unwrap_or_else(|_| {\n                errors.push(RequestError::BadMethod(hyper.method.clone()));\n                Method::Get\n            }),\n        };\n\n        // TODO: Keep around not just the path/query, but the rest, if there?\n        let uri = hyper.uri.path_and_query()\n            .map(|uri| {\n                // In debug, make sure we agree with Hyper about URI validity.\n                // If we disagree, log a warning but continue anyway; if this is\n                // a security issue with Hyper, there isn't much we can do.\n                #[cfg(debug_assertions)]\n                if Origin::parse(uri.as_str()).is_err() {\n                    warn!(\n                        name: \"uri_discord\",\n                        %uri,\n                        \"Hyper/Rocket URI validity discord: {uri}\\n\\\n                        Hyper believes the URI is valid while Rocket disagrees.\\n\\\n                        This is likely a Hyper bug with potential security implications.\\n\\\n                        Please report this warning to Rocket's GitHub issue tracker.\"\n                    )\n                }\n\n                Origin::new(uri.path(), uri.query().map(Cow::Borrowed))\n            })\n            .unwrap_or_else(|| {\n                errors.push(RequestError::InvalidUri(hyper.uri.clone()));\n                Origin::root().clone()\n            });\n\n        // Construct the request object; fill in metadata and headers next.\n        let mut request = Request::new(rocket, method, uri, match hyper.version {\n            Version::HTTP_09 => Some(HttpVersion::Http09),\n            Version::HTTP_10 => Some(HttpVersion::Http10),\n            Version::HTTP_11 => Some(HttpVersion::Http11),\n            Version::HTTP_2 => Some(HttpVersion::Http2),\n            Version::HTTP_3 => Some(HttpVersion::Http3),\n            _ => None,\n        });\n        request.errors = errors;\n\n        // Set the passed in connection metadata.\n        request.connection = connection;\n\n        // Determine + set host. On HTTP < 2, use the `HOST` header. Otherwise,\n        // use the `:authority` pseudo-header which hyper makes part of the URI.\n        // TODO: Use an `InitCell` to compute this later.\n        request.state.host = if hyper.version < hyper::Version::HTTP_2 {\n            hyper.headers.get(\"host\").and_then(|h| Host::parse_bytes(h.as_bytes()).ok())\n        } else {\n            hyper.uri.host().map(|h| Host::new(Authority::new(None, h, hyper.uri.port_u16())))\n        };\n\n        // Set the request cookies, if they exist.\n        for header in hyper.headers.get_all(\"Cookie\") {\n            let Ok(raw_str) = std::str::from_utf8(header.as_bytes()) else {\n                continue\n            };\n\n            for cookie_str in raw_str.split(';').map(|s| s.trim()) {\n                if let Ok(cookie) = Cookie::parse_encoded(cookie_str) {\n                    request.state.cookies.add_original(cookie.into_owned());\n                }\n            }\n        }\n\n        // Set the rest of the headers. This is rather unfortunate and slow.\n        for (header, value) in hyper.headers.iter() {\n            // FIXME: This is rather unfortunate. Header values needn't be UTF8.\n            let Ok(value) = std::str::from_utf8(value.as_bytes()) else {\n                warn!(%header, \"dropping header with invalid UTF-8\");\n                continue;\n            };\n\n            request.add_header(Header::new(header.as_str(), value));\n        }\n\n        match request.errors.is_empty() {\n            true => Ok(request),\n            false => Err(request),\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub(crate) enum RequestError {\n    InvalidUri(hyper::Uri),\n    BadMethod(hyper::Method),\n}\n\nimpl fmt::Display for RequestError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            RequestError::InvalidUri(u) => write!(f, \"invalid origin URI: {}\", u),\n            RequestError::BadMethod(m) => write!(f, \"invalid or unrecognized method: {}\", m),\n        }\n    }\n}\n\nimpl fmt::Debug for Request<'_> {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"Request\")\n            .field(\"method\", &self.method())\n            .field(\"uri\", &self.uri())\n            .field(\"headers\", &self.headers())\n            .field(\"remote\", &self.remote())\n            .field(\"cookies\", &self.cookies())\n            .finish()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/request/tests.rs",
    "content": "use std::collections::HashMap;\n\nuse crate::request::{Request, ConnectionMeta};\nuse crate::local::blocking::Client;\n\nmacro_rules! assert_headers {\n    ($($key:expr => [$($value:expr),+]),+) => ({\n        // Create a new Hyper request. Add all of the passed in headers.\n        let mut req = hyper::Request::get(\"/test\").body(()).unwrap();\n        $($(\n            req.headers_mut()\n                .append($key, hyper::header::HeaderValue::from_str($value).unwrap());\n        )+)+\n\n        // Build up what we expect the headers to actually be.\n        let mut expected = HashMap::new();\n        $(expected.entry($key).or_insert(vec![]).append(&mut vec![$($value),+]);)+\n\n        // Create a valid `Rocket` and convert the hyper req to a Rocket one.\n        let client = Client::debug_with(vec![]).unwrap();\n        let hyper = req.into_parts().0;\n        let meta = ConnectionMeta::default();\n        let req = Request::from_hyp(client.rocket(), &hyper, meta).unwrap();\n\n        // Dispatch the request and check that the headers match.\n        let actual_headers = req.headers();\n        for (key, values) in expected.iter() {\n            let actual: Vec<_> = actual_headers.get(key).collect();\n            assert_eq!(*values, actual);\n        }\n    })\n}\n\n#[test]\nfn test_multiple_headers_from_hyp() {\n    assert_headers!(\"friends\" => [\"alice\"]);\n    assert_headers!(\"friends\" => [\"alice\", \"bob\"]);\n    assert_headers!(\"friends\" => [\"alice\", \"bob, carol\"]);\n    assert_headers!(\"friends\" => [\"alice, david\", \"bob, carol\", \"eric, frank\"]);\n    assert_headers!(\"friends\" => [\"alice\"], \"enemies\" => [\"victor\"]);\n    assert_headers!(\"friends\" => [\"alice\", \"bob\"], \"enemies\" => [\"david\", \"emily\"]);\n}\n\n#[test]\nfn test_multiple_headers_merge_into_one_from_hyp() {\n    assert_headers!(\"friend\" => [\"alice\"], \"friend\" => [\"bob\"]);\n    assert_headers!(\"friend\" => [\"alice\"], \"friend\" => [\"bob\"], \"friend\" => [\"carol\"]);\n    assert_headers!(\"friend\" => [\"alice\"], \"friend\" => [\"bob\"], \"enemy\" => [\"carol\"]);\n}\n"
  },
  {
    "path": "core/lib/src/response/body.rs",
    "content": "use std::{io, fmt};\nuse std::task::{Context, Poll};\nuse std::pin::Pin;\n\nuse tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, ReadBuf};\n\n/// The body of a [`Response`].\n///\n/// A `Body` is never created directly, but instead, through the following\n/// methods on `Response` and `Builder`:\n///\n///   * [`Builder::sized_body()`]\n///   * [`Response::set_sized_body()`]\n///   * [`Builder::streamed_body()`]\n///   * [`Response::set_streamed_body()`]\n///\n/// [`Response`]: crate::Response\n/// [`Builder`]: crate::response::Builder\n/// [`Response::set_sized_body()`]: crate::Response::set_sized_body\n/// [`Response::set_streamed_body()`]: crate::Response::set_streamed_body\n/// [`Builder::sized_body()`]: crate::response::Builder::sized_body\n/// [`Builder::streamed_body()`]: crate::response::Builder::streamed_body\n///\n/// An unset body in a `Response` begins as a [`Body::default()`], a `None`\n/// body with a preset size of `0`.\n///\n/// # Sizing\n///\n/// A response body may be sized or unsized (\"streamed\"). A \"sized\" body is\n/// transferred with a `Content-Length` equal to its size while an \"unsized\"\n/// body is chunk-encoded. The body data is streamed in _all_ cases and is never\n/// buffered in memory beyond a minimal amount for efficient transmission.\n///\n/// ## Sized\n///\n/// A sized body may have a _preset_ size ([`Body::preset_size()`]) or may have\n/// its size computed on the fly by seeking ([`Body::size()`]). As such, sized\n/// bodies must implement [`AsyncSeek`]. If a body does not have a preset size\n/// and the fails to be computed dynamically, a sized body is treated as an\n/// unsized body when written out to the network.\n///\n/// ## Unsized\n///\n/// An unsized body's data is streamed as it arrives. In other words, as soon as\n/// the body's [`AsyncRead`] implementation returns bytes, the bytes are written\n/// to the network. Individual unsized bodies may use an internal buffer to\n/// curtail writes to the network.\n///\n/// The maximum number of bytes written to the network at once is controlled via\n/// the [`Body::max_chunk_size()`] parameter which can be set via\n/// [`Response::set_max_chunk_size()`] and [`Builder::max_chunk_size()`].\n///\n/// [`Response::set_max_chunk_size()`]: crate::Response::set_max_chunk_size\n/// [`Builder::max_chunk_size()`]: crate::response::Builder::max_chunk_size\n///\n/// # Reading\n///\n/// The contents of a body, decoded, can be read through [`Body::to_bytes()`],\n/// [`Body::to_string()`], or directly though `Body`'s [`AsyncRead`]\n/// implementation.\n#[derive(Debug)]\npub struct Body<'r> {\n    /// The size of the body, if it is known.\n    size: Option<usize>,\n    /// The body itself.\n    inner: Inner<'r>,\n    /// The maximum chunk size.\n    max_chunk: usize,\n}\n\n/// A \"trait alias\" of sorts so we can use `AsyncRead + AsyncSeek` in `dyn`.\npub trait AsyncReadSeek: AsyncRead + AsyncSeek { }\n\n/// Implemented for all `AsyncRead + AsyncSeek`, of course.\nimpl<T: AsyncRead + AsyncSeek> AsyncReadSeek for T {  }\n\n/// A pinned `AsyncRead + AsyncSeek` body type.\ntype SizedBody<'r> = Pin<Box<dyn AsyncReadSeek + Send + 'r>>;\n\n/// A pinned `AsyncRead` (not `AsyncSeek`) body type.\ntype UnsizedBody<'r> = Pin<Box<dyn AsyncRead + Send + 'r>>;\n\nenum Inner<'r> {\n    /// A body that can be `seek()`ed to determine its size.\n    Seekable(SizedBody<'r>),\n    /// A body that has no known size.\n    Unsized(UnsizedBody<'r>),\n    /// A body that \"exists\" but only for metadata calculations.\n    Phantom(SizedBody<'r>),\n    /// An empty body: no body at all.\n    None,\n}\n\nimpl Default for Body<'_> {\n    fn default() -> Self {\n        Body {\n            size: Some(0),\n            inner: Inner::None,\n            max_chunk: Body::DEFAULT_MAX_CHUNK,\n        }\n    }\n}\n\nimpl<'r> Body<'r> {\n    /// The default max size, in bytes, of chunks for streamed responses.\n    ///\n    /// The present value is `4096`.\n    pub const DEFAULT_MAX_CHUNK: usize = 4096;\n\n    pub(crate) fn unsized_none() -> Self {\n        Body {\n            size: None,\n            inner: Inner::None,\n            max_chunk: Body::DEFAULT_MAX_CHUNK,\n        }\n    }\n\n    pub(crate) fn with_sized<T>(body: T, preset_size: Option<usize>) -> Self\n        where T: AsyncReadSeek + Send + 'r\n    {\n        Body {\n            size: preset_size,\n            inner: Inner::Seekable(Box::pin(body)),\n            max_chunk: Body::DEFAULT_MAX_CHUNK,\n        }\n    }\n\n    pub(crate) fn with_unsized<T>(body: T) -> Self\n        where T: AsyncRead + Send + 'r\n    {\n        Body {\n            size: None,\n            inner: Inner::Unsized(Box::pin(body)),\n            max_chunk: Body::DEFAULT_MAX_CHUNK,\n        }\n    }\n\n    pub(crate) fn set_max_chunk_size(&mut self, max_chunk: usize) {\n        self.max_chunk = max_chunk;\n    }\n\n    pub(crate) fn strip(&mut self) {\n        let body = std::mem::take(self);\n        *self = match body.inner {\n            Inner::Seekable(b) | Inner::Phantom(b) => Body {\n                size: body.size,\n                inner: Inner::Phantom(b),\n                max_chunk: body.max_chunk,\n            },\n            Inner::Unsized(_) | Inner::None => Body::default()\n        };\n    }\n\n    /// Returns `true` if the body is `None` or unset, the default.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::Response;\n    ///\n    /// let r = Response::build().finalize();\n    /// assert!(r.body().is_none());\n    /// ```\n    #[inline(always)]\n    pub fn is_none(&self) -> bool {\n        matches!(self.inner, Inner::None)\n    }\n\n    /// Returns `true` if the body is _not_ `None`, anything other than the\n    /// default.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::response::Response;\n    ///\n    /// let body = \"Brewing the best coffee!\";\n    /// let r = Response::build()\n    ///     .sized_body(body.len(), Cursor::new(body))\n    ///     .finalize();\n    ///\n    /// assert!(r.body().is_some());\n    /// ```\n    #[inline(always)]\n    pub fn is_some(&self) -> bool {\n        !self.is_none()\n    }\n\n    /// A body's preset size, which may have been computed by a previous call to\n    /// [`Body::size()`].\n    ///\n    /// Unsized bodies _always_ return `None`, while sized bodies return `Some`\n    /// if the body size was supplied directly on creation or a call to\n    /// [`Body::size()`] successfully computed the size and `None` otherwise.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::response::Response;\n    ///\n    /// # rocket::async_test(async {\n    /// let body = \"Brewing the best coffee!\";\n    /// let r = Response::build()\n    ///     .sized_body(body.len(), Cursor::new(body))\n    ///     .finalize();\n    ///\n    /// // This will _always_ return `Some`.\n    /// assert_eq!(r.body().preset_size(), Some(body.len()));\n    ///\n    /// let r = Response::build()\n    ///     .streamed_body(Cursor::new(body))\n    ///     .finalize();\n    ///\n    /// // This will _never_ return `Some`.\n    /// assert_eq!(r.body().preset_size(), None);\n    ///\n    /// let mut r = Response::build()\n    ///     .sized_body(None, Cursor::new(body))\n    ///     .finalize();\n    ///\n    /// // This returns `Some` only after a call to `size()`.\n    /// assert_eq!(r.body().preset_size(), None);\n    /// assert_eq!(r.body_mut().size().await, Some(body.len()));\n    /// assert_eq!(r.body().preset_size(), Some(body.len()));\n    /// # });\n    /// ```\n    pub fn preset_size(&self) -> Option<usize> {\n        self.size\n    }\n\n    /// Returns the maximum chunk size for chunked transfers.\n    ///\n    /// If none is explicitly set, defaults to [`Body::DEFAULT_MAX_CHUNK`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::response::{Response, Body};\n    ///\n    /// let body = \"Brewing the best coffee!\";\n    /// let r = Response::build()\n    ///     .sized_body(body.len(), Cursor::new(body))\n    ///     .finalize();\n    ///\n    /// assert_eq!(r.body().max_chunk_size(), Body::DEFAULT_MAX_CHUNK);\n    ///\n    /// let r = Response::build()\n    ///     .sized_body(body.len(), Cursor::new(body))\n    ///     .max_chunk_size(1024)\n    ///     .finalize();\n    ///\n    /// assert_eq!(r.body().max_chunk_size(), 1024);\n    /// ```\n    pub fn max_chunk_size(&self) -> usize {\n        self.max_chunk\n    }\n\n    /// Attempts to compute the body's size and returns it if the body is sized.\n    ///\n    /// If the size was preset (see [`Body::preset_size()`]), the value is\n    /// returned immediately as `Some`. If the body is unsized or computing the\n    /// size fails, returns `None`. Otherwise, the size is computed by seeking,\n    /// and the `preset_size` is updated to reflect the known value.\n    ///\n    /// **Note:** the number of bytes read from the reader and/or written to the\n    /// network may differ from the value returned by this method. Some examples\n    /// include:\n    ///\n    ///   * bodies in response to `HEAD` requests are never read or written\n    ///   * the client may close the connection before the body is read fully\n    ///   * reading the body may fail midway\n    ///   * a preset size may differ from the actual body size\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::response::Response;\n    ///\n    /// # rocket::async_test(async {\n    /// let body = \"Hello, Rocketeers!\";\n    /// let mut r = Response::build()\n    ///     .sized_body(None, Cursor::new(body))\n    ///     .finalize();\n    ///\n    /// assert_eq!(r.body().preset_size(), None);\n    /// assert_eq!(r.body_mut().size().await, Some(body.len()));\n    /// assert_eq!(r.body().preset_size(), Some(body.len()));\n    /// # });\n    /// ```\n    pub async fn size(&mut self) -> Option<usize> {\n        if let Some(size) = self.size {\n            return Some(size);\n        }\n\n        if let Inner::Seekable(ref mut body) | Inner::Phantom(ref mut body) = self.inner {\n            let pos = body.seek(io::SeekFrom::Current(0)).await.ok()?;\n            let end = body.seek(io::SeekFrom::End(0)).await.ok()?;\n            body.seek(io::SeekFrom::Start(pos)).await.ok()?;\n\n            let size = end as usize - pos as usize;\n            self.size = Some(size);\n            return Some(size);\n        }\n\n        None\n    }\n\n    /// Moves the body out of `self` and returns it, leaving a\n    /// [`Body::default()`] in its place.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::response::Response;\n    ///\n    /// let mut r = Response::build()\n    ///     .sized_body(None, Cursor::new(\"Hi\"))\n    ///     .finalize();\n    ///\n    /// assert!(r.body().is_some());\n    ///\n    /// let body = r.body_mut().take();\n    /// assert!(body.is_some());\n    /// assert!(r.body().is_none());\n    /// ```\n    #[inline(always)]\n    pub fn take(&mut self) -> Self {\n        std::mem::take(self)\n    }\n\n    /// Reads all of `self` into a vector of bytes, consuming the contents.\n    ///\n    /// If reading fails, returns `Err`. Otherwise, returns `Ok`. Calling this\n    /// method may partially or fully consume the body's content. As such,\n    /// subsequent calls to `to_bytes()` will likely return different result.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::response::Response;\n    ///\n    /// # let ok: io::Result<()> = rocket::async_test(async {\n    /// let mut r = Response::build()\n    ///     .streamed_body(io::Cursor::new(&[1, 2, 3, 11, 13, 17]))\n    ///     .finalize();\n    ///\n    /// assert_eq!(r.body_mut().to_bytes().await?, &[1, 2, 3, 11, 13, 17]);\n    /// # Ok(())\n    /// # });\n    /// # assert!(ok.is_ok());\n    /// ```\n    pub async fn to_bytes(&mut self) -> io::Result<Vec<u8>> {\n        let mut vec = Vec::new();\n        let n = match self.read_to_end(&mut vec).await {\n            Ok(n) => n,\n            Err(e) => {\n                error!(\"i/o error reading body: {:?}\", e);\n                return Err(e);\n            }\n        };\n\n        if let Some(ref mut size) = self.size {\n            *size = size.checked_sub(n).unwrap_or(0);\n        }\n\n        Ok(vec)\n    }\n\n    /// Reads all of `self` into a string, consuming the contents.\n    ///\n    /// If reading fails, or the body contains invalid UTF-8 characters, returns\n    /// `Err`. Otherwise, returns `Ok`. Calling this method may partially or\n    /// fully consume the body's content. As such, subsequent calls to\n    /// `to_string()` will likely return different result.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::response::Response;\n    ///\n    /// # let ok: io::Result<()> = rocket::async_test(async {\n    /// let mut r = Response::build()\n    ///     .streamed_body(io::Cursor::new(\"Hello, Rocketeers!\"))\n    ///     .finalize();\n    ///\n    /// assert_eq!(r.body_mut().to_string().await?, \"Hello, Rocketeers!\");\n    /// # Ok(())\n    /// # });\n    /// # assert!(ok.is_ok());\n    /// ```\n    pub async fn to_string(&mut self) -> io::Result<String> {\n        String::from_utf8(self.to_bytes().await?).map_err(|e| {\n            error!(\"invalid body UTF-8: {}\", e);\n            io::Error::new(io::ErrorKind::InvalidData, e)\n        })\n    }\n}\n\nimpl AsyncRead for Body<'_> {\n    fn poll_read(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        let reader = match self.inner {\n            Inner::Seekable(ref mut b) => b as &mut (dyn AsyncRead + Unpin),\n            Inner::Unsized(ref mut b) => b as &mut (dyn AsyncRead + Unpin),\n            Inner::Phantom(_) | Inner::None => return Poll::Ready(Ok(())),\n        };\n\n        Pin::new(reader).poll_read(cx, buf)\n    }\n}\n\nimpl fmt::Debug for Inner<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Inner::Seekable(_) => \"seekable\".fmt(f),\n            Inner::Unsized(_) => \"unsized\".fmt(f),\n            Inner::Phantom(_) => \"phantom\".fmt(f),\n            Inner::None => \"none\".fmt(f),\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/content.rs",
    "content": "//! Contains types that set the Content-Type of a response.\n//!\n//! # Usage\n//!\n//! Each type in this module is a `Responder` that wraps an existing\n//! `Responder`, overwriting the `Content-Type` of the response but otherwise\n//! delegating the response to the wrapped responder. As a convenience,\n//! `(ContentType, R)` where `R: Responder` is _also_ a `Responder` that\n//! overrides the `Content-Type` to the value in `.0`:\n//!\n//! ```rust\n//! # use rocket::get;\n//! use rocket::http::ContentType;\n//!\n//! #[get(\"/\")]\n//! fn index() -> (ContentType, &'static str) {\n//!     (ContentType::HTML, \"Is this HTML? <p>Sure, why not!</p>\")\n//! }\n//! ```\n//!\n//! # Example\n//!\n//! The following snippet creates a `RawHtml` response from a string. Normally,\n//! raw strings set their response Content-Type to `text/plain`. By using the\n//! `RawHtml` content response, the Content-Type will be set to `text/html`\n//! instead:\n//!\n//! ```rust\n//! use rocket::response::content;\n//!\n//! let response = content::RawHtml(\"<h1>Hello, world!</h1>\");\n//! ```\n\nuse crate::request::Request;\nuse crate::response::{self, Response, Responder};\nuse crate::http::ContentType;\n\nmacro_rules! ctrs {\n    ($($name:ident: $ct:ident, $name_str:expr, $ct_str:expr),+) => {\n        $(\n            #[doc=\"Override the `Content-Type` of the response to <b>\"]\n            #[doc=$name_str]\n            #[doc=\"</b>, or <i>\"]\n            #[doc=$ct_str]\n            #[doc=\"</i>.\"]\n            ///\n            /// Delegates the remainder of the response to the wrapped responder.\n            ///\n            /// **Note:** Unlike types like [`Json`](crate::serde::json::Json)\n            /// and [`MsgPack`](crate::serde::msgpack::MsgPack), this type _does\n            /// not_ serialize data in any way. You should _always_ use those\n            /// types to respond with serializable data. Additionally, you\n            /// should _always_ use [`NamedFile`](crate::fs::NamedFile), which\n            /// automatically sets a `Content-Type`, to respond with file data.\n            #[derive(Debug, Clone, PartialEq)]\n            pub struct $name<R>(pub R);\n\n            /// Sets the Content-Type of the response then delegates the\n            /// remainder of the response to the wrapped responder.\n            impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for $name<R> {\n                fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n                    (ContentType::$ct, self.0).respond_to(req)\n                }\n            }\n        )+\n    }\n}\n\nctrs! {\n    // FIXME: Add a note that this is _not_ `serde::Json`.\n    RawJson: JSON, \"JSON\", \"application/json\",\n    RawXml: XML, \"XML\", \"text/xml\",\n    RawMsgPack: MsgPack, \"MessagePack\", \"application/msgpack\",\n    RawHtml: HTML, \"HTML\", \"text/html\",\n    RawText: Text, \"plain text\", \"text/plain\",\n    RawCss: CSS, \"CSS\", \"text/css\",\n    RawJavaScript: JavaScript, \"JavaScript\", \"application/javascript\"\n}\n\nimpl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (ContentType, R) {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        Response::build()\n            .merge(self.1.respond_to(req)?)\n            .header(self.0)\n            .ok()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/debug.rs",
    "content": "use crate::request::Request;\nuse crate::response::{self, Responder};\nuse crate::http::Status;\n\n/// Debug prints the internal value before forwarding to the 500 error catcher.\n///\n/// This value exists primarily to allow handler return types that would not\n/// otherwise implement [`Responder`]. It is typically used in conjunction with\n/// `Result<T, E>` where `E` implements `Debug` but not `Responder`.\n///\n/// Note that because of it's common use as an error value, `std::io::Error`\n/// _does_ implement `Responder`. As a result, a `std::io::Result<T>` can be\n/// returned directly without the need for `Debug`:\n///\n/// ```rust\n/// use std::io;\n///\n/// # use rocket::get;\n/// use rocket::fs::NamedFile;\n///\n/// #[get(\"/\")]\n/// async fn index() -> io::Result<NamedFile> {\n///     NamedFile::open(\"index.html\").await\n/// }\n/// ```\n///\n/// # Example\n///\n/// Because of the generic `From<E>` implementation for `Debug<E>`, conversions\n/// from `Result<T, E>` to `Result<T, Debug<E>>` through `?` occur\n/// automatically:\n///\n/// ```rust\n/// use std::string::FromUtf8Error;\n///\n/// # use rocket::get;\n/// use rocket::response::Debug;\n///\n/// #[get(\"/\")]\n/// fn rand_str() -> Result<String, Debug<FromUtf8Error>> {\n///     # /*\n///     let bytes: Vec<u8> = random_bytes();\n///     # */\n///     # let bytes: Vec<u8> = vec![];\n///     Ok(String::from_utf8(bytes)?)\n/// }\n/// ```\n///\n/// It is also possible to map the error directly to `Debug` via\n/// [`Result::map_err()`]:\n///\n/// ```rust\n/// use std::string::FromUtf8Error;\n///\n/// # use rocket::get;\n/// use rocket::response::Debug;\n///\n/// #[get(\"/\")]\n/// fn rand_str() -> Result<String, Debug<FromUtf8Error>> {\n///     # /*\n///     let bytes: Vec<u8> = random_bytes();\n///     # */\n///     # let bytes: Vec<u8> = vec![];\n///     String::from_utf8(bytes).map_err(Debug)\n/// }\n/// ```\n#[derive(Debug)]\npub struct Debug<E>(pub E);\n\nimpl<E> From<E> for Debug<E> {\n    #[inline(always)]\n    fn from(e: E) -> Self {\n        Debug(e)\n    }\n}\n\nimpl<'r, E: std::fmt::Debug> Responder<'r, 'static> for Debug<E> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        let type_name = std::any::type_name::<E>();\n        info!(type_name, value = ?self.0, \"debug response (500)\");\n        Err(Status::InternalServerError)\n    }\n}\n\n/// Prints a warning with the error and forwards to the `500` error catcher.\nimpl<'r> Responder<'r, 'static> for std::io::Error {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        warn!(\"i/o error response: {self}\");\n        Err(Status::InternalServerError)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/flash.rs",
    "content": "use time::Duration;\nuse serde::ser::{Serialize, Serializer, SerializeStruct};\n\nuse crate::outcome::IntoOutcome;\nuse crate::response::{self, Responder};\nuse crate::request::{self, Request, FromRequest};\nuse crate::http::{Status, Cookie, CookieJar};\nuse std::sync::atomic::{AtomicBool, Ordering};\n\n// The name of the actual flash cookie.\nconst FLASH_COOKIE_NAME: &str = \"_flash\";\n\n// Character to use as a delimiter after the cookie's name's length.\nconst FLASH_COOKIE_DELIM: char = ':';\n\n/// Sets a \"flash\" cookie that will be removed when it is accessed. The\n/// analogous request type is [`FlashMessage`].\n///\n/// This type makes it easy to send messages across requests. It is typically\n/// used for \"status\" messages after redirects. For instance, if a user attempts\n/// to visit a page he/she does not have access to, you may want to redirect the\n/// user to a safe place and show a message indicating what happened on the\n/// redirected page. The message should only persist for a single request. This\n/// can be accomplished with this type.\n///\n/// # Usage\n///\n/// Each `Flash` message consists of a `kind` and `message`. A generic\n/// constructor ([new](#method.new)) can be used to construct a message of any\n/// kind, while the [warning](#method.warning), [success](#method.success), and\n/// [error](#method.error) constructors create messages with the corresponding\n/// kinds.\n///\n/// Messages can be retrieved on the request side via the [`FlashMessage`] type\n/// and the [kind](#method.kind) and [message](#method.message) methods.\n///\n/// # Response\n///\n/// The `Responder` implementation for `Flash` sets the message cookie and then\n/// uses the passed in responder `res` to complete the response. In other words,\n/// it simply sets a cookie and delegates the rest of the response handling to\n/// the wrapped responder.\n///\n/// # Example\n///\n/// The following routes illustrate the use of a `Flash` message on both the\n/// request and response sides.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::response::{Flash, Redirect};\n/// use rocket::request::FlashMessage;\n///\n/// #[post(\"/login/<name>\")]\n/// fn login(name: &str) -> Result<&'static str, Flash<Redirect>> {\n///     if name == \"special_user\" {\n///         Ok(\"Hello, special user!\")\n///     } else {\n///         Err(Flash::error(Redirect::to(uri!(index)), \"Invalid username.\"))\n///     }\n/// }\n///\n/// #[get(\"/\")]\n/// fn index(flash: Option<FlashMessage<'_>>) -> String {\n///     flash.map(|flash| format!(\"{}: {}\", flash.kind(), flash.message()))\n///          .unwrap_or_else(|| \"Welcome!\".to_string())\n/// }\n/// ```\n///\n/// On the response side (in `login`), a `Flash` error message is set if some\n/// fictional authentication failed, and the user is redirected to `\"/\"`. On the\n/// request side (in `index`), the handler emits the flash message if there is\n/// one and otherwise emits a standard welcome message. Note that if the user\n/// were to refresh the index page after viewing a flash message, the user would\n/// receive the standard welcome message.\n#[derive(Debug)]\npub struct Flash<R> {\n    kind: String,\n    message: String,\n    consumed: AtomicBool,\n    inner: R,\n}\n\n/// Type alias to retrieve [`Flash`] messages from a request.\n///\n/// # Flash Cookie\n///\n/// A `FlashMessage` holds the parsed contents of the flash cookie. As long as\n/// there is a flash cookie present (set by the `Flash` `Responder`), a\n/// `FlashMessage` request guard will succeed.\n///\n/// The flash cookie is cleared if either the [`kind()`] or [`message()`] method is\n/// called. If neither method is called, the flash cookie is not cleared.\n///\n/// [`kind()`]: Flash::kind()\n/// [`message()`]: Flash::message()\npub type FlashMessage<'a> = crate::response::Flash<&'a CookieJar<'a>>;\n\nimpl<R> Flash<R> {\n    /// Constructs a new `Flash` message with the given `kind`, `message`, and\n    /// underlying `responder`.\n    ///\n    /// # Examples\n    ///\n    /// Construct a \"suggestion\" message with contents \"Try this out!\" that\n    /// redirects to \"/\".\n    ///\n    /// ```rust\n    /// use rocket::response::{Redirect, Flash};\n    ///\n    /// # #[allow(unused_variables)]\n    /// let message = Flash::new(Redirect::to(\"/\"), \"suggestion\", \"Try this out!\");\n    /// ```\n    pub fn new<K: Into<String>, M: Into<String>>(res: R, kind: K, message: M) -> Flash<R> {\n        Flash {\n            kind: kind.into(),\n            message: message.into(),\n            consumed: AtomicBool::default(),\n            inner: res,\n        }\n    }\n\n    /// Constructs a \"success\" `Flash` message with the given `responder` and\n    /// `message`.\n    ///\n    /// # Examples\n    ///\n    /// Construct a \"success\" message with contents \"It worked!\" that redirects\n    /// to \"/\".\n    ///\n    /// ```rust\n    /// use rocket::response::{Redirect, Flash};\n    ///\n    /// # #[allow(unused_variables)]\n    /// let message = Flash::success(Redirect::to(\"/\"), \"It worked!\");\n    /// ```\n    pub fn success<S: Into<String>>(responder: R, message: S) -> Flash<R> {\n        Flash::new(responder, \"success\", message.into())\n    }\n\n    /// Constructs a \"warning\" `Flash` message with the given `responder` and\n    /// `message`.\n    ///\n    /// # Examples\n    ///\n    /// Construct a \"warning\" message with contents \"Watch out!\" that redirects\n    /// to \"/\".\n    ///\n    /// ```rust\n    /// use rocket::response::{Redirect, Flash};\n    ///\n    /// # #[allow(unused_variables)]\n    /// let message = Flash::warning(Redirect::to(\"/\"), \"Watch out!\");\n    /// ```\n    pub fn warning<S: Into<String>>(responder: R, message: S) -> Flash<R> {\n        Flash::new(responder, \"warning\", message.into())\n    }\n\n    /// Constructs an \"error\" `Flash` message with the given `responder` and\n    /// `message`.\n    ///\n    /// # Examples\n    ///\n    /// Construct an \"error\" message with contents \"Whoops!\" that redirects\n    /// to \"/\".\n    ///\n    /// ```rust\n    /// use rocket::response::{Redirect, Flash};\n    ///\n    /// # #[allow(unused_variables)]\n    /// let message = Flash::error(Redirect::to(\"/\"), \"Whoops!\");\n    /// ```\n    pub fn error<S: Into<String>>(responder: R, message: S) -> Flash<R> {\n        Flash::new(responder, \"error\", message.into())\n    }\n\n    fn cookie(&self) -> Cookie<'static> {\n        let content = format!(\"{}{}{}{}\",\n            self.kind.len(), FLASH_COOKIE_DELIM, self.kind, self.message);\n\n        Cookie::build((FLASH_COOKIE_NAME, content))\n            .max_age(Duration::minutes(5))\n            .build()\n    }\n}\n\n/// Sets the message cookie and then uses the wrapped responder to complete the\n/// response. In other words, simply sets a cookie and delegates the rest of the\n/// response handling to the wrapped responder. As a result, the `Outcome` of\n/// the response is the `Outcome` of the wrapped `Responder`.\nimpl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Flash<R> {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        req.cookies().add(self.cookie());\n        self.inner.respond_to(req)\n    }\n}\n\nimpl<'r> FlashMessage<'r> {\n    /// Constructs a new message with the given name and message for the given\n    /// request.\n    fn named<S: Into<String>>(kind: S, message: S, req: &'r Request<'_>) -> Self {\n        Flash {\n            kind: kind.into(),\n            message: message.into(),\n            consumed: AtomicBool::new(false),\n            inner: req.cookies(),\n        }\n    }\n\n    // Clears the request cookie if it hasn't already been cleared.\n    fn clear_cookie_if_needed(&self) {\n        // Remove the cookie if it hasn't already been removed.\n        if !self.consumed.swap(true, Ordering::Relaxed) {\n            self.inner.remove(FLASH_COOKIE_NAME);\n        }\n    }\n\n    /// Returns a tuple of `(kind, message)`, consuming `self`.\n    pub fn into_inner(self) -> (String, String) {\n        self.clear_cookie_if_needed();\n        (self.kind, self.message)\n    }\n\n    /// Returns the `kind` of this message.\n    pub fn kind(&self) -> &str {\n        self.clear_cookie_if_needed();\n        &self.kind\n    }\n\n    /// Returns the `message` contents of this message.\n    pub fn message(&self) -> &str {\n        self.clear_cookie_if_needed();\n        &self.message\n    }\n}\n\n/// Retrieves a flash message from a flash cookie. If there is no flash cookie,\n/// or if the flash cookie is malformed, an empty `Err` is returned.\n///\n/// The suggested use is through an `Option` and the `FlashMessage` type alias\n/// in `request`: `Option<FlashMessage>`.\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for FlashMessage<'r> {\n    type Error = ();\n\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n        req.cookies().get(FLASH_COOKIE_NAME).ok_or(()).and_then(|cookie| {\n            // Parse the flash message.\n            let content = cookie.value();\n            let (len_str, kv) = match content.find(FLASH_COOKIE_DELIM) {\n                Some(i) => (&content[..i], &content[(i + 1)..]),\n                None => return Err(()),\n            };\n\n            match len_str.parse::<usize>() {\n                Ok(i) if i <= kv.len() => Ok(Flash::named(&kv[..i], &kv[i..], req)),\n                _ => Err(())\n            }\n        }).or_error(Status::BadRequest)\n    }\n}\n\nimpl Serialize for FlashMessage<'_> {\n    fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {\n        let mut flash = ser.serialize_struct(\"Flash\", 2)?;\n        flash.serialize_field(\"kind\", self.kind())?;\n        flash.serialize_field(\"message\", self.message())?;\n        flash.end()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/mod.rs",
    "content": "//! Types and traits to build and send responses.\n//!\n//! The return type of a Rocket handler can be any type that implements the\n//! [`Responder`] trait, which means that the type knows how to generate a\n//! [`Response`]. Among other things, this module contains several such types.\n//!\n//! # Composing\n//!\n//! Many of the built-in `Responder` types _chain_ responses: they take in\n//! another `Responder` and add, remove, or change information in the response.\n//! In other words, many `Responder` types are built to compose well. As a\n//! result, you'll often have types of the form `A<B<C>>` consisting of three\n//! `Responder`s `A`, `B`, and `C`. This is normal and encouraged as the type\n//! names typically illustrate the intended response.\n\nmod responder;\nmod redirect;\nmod response;\nmod debug;\nmod body;\n\npub(crate) mod flash;\n\npub mod content;\npub mod status;\npub mod stream;\n\n#[doc(hidden)]\npub use rocket_codegen::Responder;\n\npub use self::response::{Response, Builder};\npub use self::body::Body;\npub use self::responder::Responder;\npub use self::redirect::Redirect;\npub use self::flash::Flash;\npub use self::debug::Debug;\n\n/// Type alias for the `Result` of a [`Responder::respond_to()`] call.\npub type Result<'r> = std::result::Result<Response<'r>, crate::http::Status>;\n"
  },
  {
    "path": "core/lib/src/response/redirect.rs",
    "content": "use crate::request::Request;\nuse crate::response::{self, Response, Responder};\nuse crate::http::uri::Reference;\nuse crate::http::Status;\n\n/// An empty redirect response to a given URL.\n///\n/// This type simplifies returning a redirect response to the client.\n///\n/// # Usage\n///\n/// All constructors accept a generic type of `T: TryInto<Reference<'static>>`.\n/// Among the candidate types are:\n///\n///   * `String`, `&'static str`\n///   * [`Origin`](crate::http::uri::Origin)\n///   * [`Authority`](crate::http::uri::Authority)\n///   * [`Absolute`](crate::http::uri::Absolute)\n///   * [`Reference`](crate::http::uri::Reference)\n///\n/// Any non-`'static` strings must first be allocated using `.to_string()` or\n/// similar before being passed to a `Redirect` constructor. When redirecting to\n/// a route, or any URI containing a route, _always_ use [`uri!`] to construct a\n/// valid URI:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::response::Redirect;\n///\n/// #[get(\"/hello/<name>/<age>\")]\n/// fn hello(name: String, age: u8) -> String {\n///     format!(\"Hello, {} year old named {}!\", age, name)\n/// }\n///\n/// #[get(\"/hi/<name>/<age>\")]\n/// fn hi(name: String, age: u8) -> Redirect {\n///     Redirect::to(uri!(hello(name, age)))\n/// }\n///\n/// #[get(\"/bye/<name>/<age>\")]\n/// fn bye(name: String, age: u8) -> Redirect {\n///     Redirect::to(uri!(\"https://rocket.rs/bye\", hello(name, age), \"?bye#now\"))\n/// }\n/// ```\n///\n/// [`Origin`]: crate::http::uri::Origin\n/// [`uri!`]: ../macro.uri.html\n#[derive(Debug, Clone)]\npub struct Redirect(Status, Option<Reference<'static>>);\n\nimpl Redirect {\n    /// Construct a temporary \"see other\" (303) redirect response. This is the\n    /// typical response when redirecting a user to another page. This type of\n    /// redirect indicates that the client should look elsewhere, but always via\n    /// a `GET` request, for a given resource.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::response::Redirect;\n    ///\n    /// let redirect = Redirect::to(uri!(\"/foo/bar\"));\n    /// let redirect = Redirect::to(uri!(\"https://domain.com#foo\"));\n    /// ```\n    pub fn to<U: TryInto<Reference<'static>>>(uri: U) -> Redirect {\n        Redirect(Status::SeeOther, uri.try_into().ok())\n    }\n\n    /// Construct a \"temporary\" (307) redirect response. This response instructs\n    /// the client to reissue the current request to a different URL,\n    /// maintaining the contents of the request identically. This means that,\n    /// for example, a `POST` request will be resent, contents included, to the\n    /// requested URL.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::response::Redirect;\n    ///\n    /// let redirect = Redirect::temporary(uri!(\"some/other/path\"));\n    /// let redirect = Redirect::temporary(uri!(\"https://rocket.rs?foo\"));\n    /// let redirect = Redirect::temporary(format!(\"some-{}-thing\", \"crazy\"));\n    /// ```\n    pub fn temporary<U: TryInto<Reference<'static>>>(uri: U) -> Redirect {\n        Redirect(Status::TemporaryRedirect, uri.try_into().ok())\n    }\n\n   /// Construct a \"permanent\" (308) redirect response. This redirect must only\n   /// be used for permanent redirects as it is cached by clients. This\n   /// response instructs the client to reissue requests for the current URL to\n   /// a different URL, now and in the future, maintaining the contents of the\n   /// request identically. This means that, for example, a `POST` request will\n   /// be resent, contents included, to the requested URL.\n   ///\n   /// # Examples\n   ///\n   /// ```rust\n   /// # #[macro_use] extern crate rocket;\n   /// use rocket::response::Redirect;\n   ///\n   /// let redirect = Redirect::permanent(uri!(\"/other_url\"));\n   /// let redirect = Redirect::permanent(format!(\"some-{}-thing\", \"crazy\"));\n   /// ```\n   pub fn permanent<U: TryInto<Reference<'static>>>(uri: U) -> Redirect {\n       Redirect(Status::PermanentRedirect, uri.try_into().ok())\n   }\n\n   /// Construct a temporary \"found\" (302) redirect response. This response\n   /// instructs the client to reissue the current request to a different URL,\n   /// ideally maintaining the contents of the request identically.\n   /// Unfortunately, different clients may respond differently to this type of\n   /// redirect, so `303` or `307` redirects, which disambiguate, are\n   /// preferred.\n   ///\n   /// # Examples\n   ///\n   /// ```rust\n   /// # #[macro_use] extern crate rocket;\n   /// use rocket::response::Redirect;\n   ///\n   /// let redirect = Redirect::found(uri!(\"/other_url\"));\n   /// let redirect = Redirect::found(format!(\"some-{}-thing\", \"crazy\"));\n   /// ```\n   pub fn found<U: TryInto<Reference<'static>>>(uri: U) -> Redirect {\n       Redirect(Status::Found, uri.try_into().ok())\n   }\n\n   /// Construct a permanent \"moved\" (301) redirect response. This response\n   /// should only be used for permanent redirects as it can be cached by\n   /// browsers. Because different clients may respond differently to this type\n   /// of redirect, a `308` redirect, which disambiguates, is preferred.\n   ///\n   /// # Examples\n   ///\n   /// ```rust\n   /// # #[macro_use] extern crate rocket;\n   /// use rocket::response::Redirect;\n   ///\n   /// let redirect = Redirect::moved(uri!(\"here\"));\n   /// let redirect = Redirect::moved(format!(\"some-{}-thing\", \"crazy\"));\n   /// ```\n   pub fn moved<U: TryInto<Reference<'static>>>(uri: U) -> Redirect {\n       Redirect(Status::MovedPermanently, uri.try_into().ok())\n   }\n\n    pub fn map_uri<U: TryInto<Reference<'static>>>(self, f: impl FnOnce(Reference<'static>) -> U)\n        -> Redirect\n    {\n        Redirect(self.0, self.1.and_then(|p| f(p).try_into().ok()))\n    }\n}\n\n/// Constructs a response with the appropriate status code and the given URL in\n/// the `Location` header field. The body of the response is empty. If the URI\n/// value used to create the `Responder` is an invalid URI, an error of\n/// `Status::InternalServerError` is returned.\nimpl<'r> Responder<'r, 'static> for Redirect {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        if let Some(uri) = self.1 {\n            Response::build()\n                .status(self.0)\n                .raw_header(\"Location\", uri.to_string())\n                .ok()\n        } else {\n            error!(\"Invalid URI used for redirect.\");\n            Err(Status::InternalServerError)\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/responder.rs",
    "content": "use std::fs::File;\nuse std::io::Cursor;\nuse std::sync::Arc;\n\nuse crate::http::{Status, ContentType, StatusClass};\nuse crate::response::{self, Response};\nuse crate::request::Request;\n\n/// Trait implemented by types that generate responses for clients.\n///\n/// Any type that implements `Responder` can be used as the return type of a\n/// handler:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type T = ();\n/// #\n/// // This works for any `T` that implements `Responder`.\n/// #[get(\"/\")]\n/// fn index() -> T { /* ... */ }\n/// ```\n///\n/// # Deriving\n///\n/// This trait can, and largely _should_, be automatically derived. The derive\n/// can handle all simple cases and most complex cases, too. When deriving\n/// `Responder`, the first field of the annotated structure (or of each variant\n/// if an `enum`) is used to generate a response while the remaining fields are\n/// used as response headers:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # #[cfg(feature = \"json\")] mod _main {\n/// # type Template = String;\n/// use rocket::http::ContentType;\n/// use rocket::serde::{Serialize, json::Json};\n///\n/// #[derive(Responder)]\n/// enum Error<T> {\n///     #[response(status = 400)]\n///     Unauthorized(Json<T>),\n///     #[response(status = 404)]\n///     NotFound(Template, ContentType),\n/// }\n/// # }\n/// ```\n///\n/// For full details on deriving `Responder`, see the [`Responder` derive].\n///\n/// [`Responder` derive]: derive@crate::Responder\n///\n/// # Provided Implementations\n///\n/// Rocket implements `Responder` for several standard library types. Their\n/// behavior is documented here. Note that the `Result` implementation is\n/// overloaded, allowing for two `Responder`s to be used at once, depending on\n/// the variant.\n///\n///   * **&str**\n///\n///     Sets the `Content-Type` to `text/plain`. The string is used as the body\n///     of the response, which is fixed size and not streamed. To stream a raw\n///     string, use `Stream::from(Cursor::new(string))`.\n///\n///   * **String**\n///\n///     Sets the `Content-Type` to `text/plain`. The string is used as the body\n///     of the response, which is fixed size and not streamed. To stream a\n///     string, use `Stream::from(Cursor::new(string))`.\n///\n///   * **&\\[u8\\]**\n///\n///     Sets the `Content-Type` to `application/octet-stream`. The slice\n///     is used as the body of the response, which is fixed size and not\n///     streamed. To stream a slice of bytes, use\n///     `Stream::from(Cursor::new(data))`.\n///\n///   * **Vec&lt;u8>**\n///\n///     Sets the `Content-Type` to `application/octet-stream`. The vector's data\n///     is used as the body of the response, which is fixed size and not\n///     streamed. To stream a vector of bytes, use\n///     `Stream::from(Cursor::new(vec))`.\n///\n///   * **File**\n///\n///     Responds with a streamed body containing the data in the `File`. No\n///     `Content-Type` is set. To automatically have a `Content-Type` set based\n///     on the file's extension, use [`NamedFile`](crate::fs::NamedFile).\n///\n///   * **()**\n///\n///     Responds with an empty body. No `Content-Type` is set.\n///\n///   * **Option&lt;T>**\n///\n///     If the `Option` is `Some`, the wrapped responder is used to respond to\n///     the client. Otherwise, an `Err` with status **404 Not Found** is\n///     returned and a warning is printed to the console.\n///\n///   * **Result&lt;T, E>**\n///\n///     If the `Result` is `Ok`, the wrapped `Ok` responder is used to respond\n///     to the client. If the `Result` is `Err`, the wrapped `Err` responder is\n///     used to respond to the client.\n///\n/// # Return Value\n///\n/// A `Responder` returns a `Result<Response, Status>`.\n///\n///   * An `Ok(Response)` indicates success. The `Response` will be written out\n///     to the client.\n///\n///   * An `Err(Status)` indicates an error. The error catcher for `Status` will\n///     be invoked to generate a response.\n///\n/// # Implementation Tips\n///\n/// This section describes a few best practices to take into account when\n/// implementing `Responder`.\n///\n/// 1. Avoid Manual Implementations\n///\n///    The [`Responder` derive] is a powerful mechanism that eliminates the need\n///    to implement `Responder` in almost all cases. We encourage you to explore\n///    using the derive _before_ attempting to implement `Responder` directly.\n///    It allows you to leverage existing `Responder` implementations through\n///    composition, decreasing the opportunity for mistakes or performance\n///    degradation.\n///\n/// 2. Joining and Merging\n///\n///    When chaining/wrapping other `Responder`s, start with\n///    [`Response::build_from()`] and/or use the [`merge()`](Response::merge())\n///    or [`join()`](Response::join()) methods on the `Response` or\n///    `ResponseBuilder` struct. Ensure that you document merging or joining\n///    behavior appropriately.\n///\n/// 3. Inspecting Requests\n///\n///    While tempting, a `Responder` that varies its functionality based on the\n///    incoming request sacrifices its functionality being understood based\n///    purely on its type. By implication, gleaning the functionality of a\n///    _handler_ from its type signature also becomes more difficult. You should\n///    avoid varying responses based on the `Request` value as much as possible.\n///\n/// 4. Perform `async` I/O in Constructors\n///\n///    The `Responder` trait is not an `async` trait. This is not an oversight.\n///    Instead of performing `async` operations in what would be the\n///    `respond_to` method, perform them in a constructor for the responder. As\n///    an example, see [`NamedFile::open()`](crate::fs::NamedFile::open()),\n///    which performs the requisite I/O for `NamedFile`'s responder.\n///\n/// ## Lifetimes\n///\n/// `Responder` has two lifetimes: `Responder<'r, 'o: 'r>`.\n///\n///   * `'r` bounds the reference to the `&'r Request`.\n///\n///   * `'o` bounds the returned `Response<'o>` to values that live at least as\n///     long as the request.\n///\n///     This includes borrows from the `Request` itself (where `'o` would be\n///     `'r` as in `impl<'r> Responder<'r, 'r>`) as well as `'static` data\n///     (where `'o` would be `'static` as in `impl<'r> Responder<'r, 'static>`).\n///\n/// In practice, you are likely choosing between four signatures:\n///\n/// ```rust\n/// # use rocket::request::Request;\n/// # use rocket::response::{self, Responder};\n/// # struct A;\n/// // If the response contains no borrowed data.\n/// impl<'r> Responder<'r, 'static> for A {\n///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n///         todo!()\n///     }\n/// }\n///\n/// # struct B<'r>(&'r str);\n/// // If the response borrows from the request.\n/// impl<'r> Responder<'r, 'r> for B<'r> {\n///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {\n///         todo!()\n///     }\n/// }\n///\n/// # struct C;\n/// // If the response is or wraps a borrow that may outlive the request.\n/// impl<'r, 'o: 'r> Responder<'r, 'o> for &'o C {\n///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {\n///         todo!()\n///     }\n/// }\n///\n/// # struct D<R>(R);\n/// // If the response wraps an existing responder.\n/// impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for D<R> {\n///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {\n///         todo!()\n///     }\n/// }\n/// ```\n///\n/// # Example\n///\n/// Say that you have a custom type, `Person`:\n///\n/// ```rust\n/// struct Person {\n///     name: String,\n///     age: u16\n/// }\n/// ```\n///\n/// You'd like to use `Person` as a `Responder` so that you can return a\n/// `Person` directly from a handler:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type Person = String;\n/// #[get(\"/person/<id>\")]\n/// fn person(id: usize) -> Option<Person> {\n///     # /*\n///     Person::from_id(id)\n///     # */ None\n/// }\n/// # fn main() {}\n/// ```\n///\n/// You want the `Person` responder to set two header fields: `X-Person-Name`\n/// and `X-Person-Age` as well as supply a custom representation of the object\n/// (`Content-Type: application/x-person`) in the body of the response. The\n/// following `Responder` implementation accomplishes this:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// #\n/// # #[derive(Debug)]\n/// # struct Person { name: String, age: u16 }\n/// #\n/// use std::io::Cursor;\n///\n/// use rocket::request::Request;\n/// use rocket::response::{self, Response, Responder};\n/// use rocket::http::ContentType;\n///\n/// impl<'r> Responder<'r, 'static> for Person {\n///     fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n///         let string = format!(\"{}:{}\", self.name, self.age);\n///         Response::build_from(string.respond_to(req)?)\n///             .raw_header(\"X-Person-Name\", self.name)\n///             .raw_header(\"X-Person-Age\", self.age.to_string())\n///             .header(ContentType::new(\"application\", \"x-person\"))\n///             .ok()\n///     }\n/// }\n/// #\n/// # #[get(\"/person\")]\n/// # fn person() -> Person { Person { name: \"a\".to_string(), age: 20 } }\n/// # fn main() {  }\n/// ```\n///\n/// Note that the implementation could have instead been derived if structured\n/// in a slightly different manner:\n///\n/// ```rust\n/// use rocket::http::Header;\n/// use rocket::response::Responder;\n///\n/// #[derive(Responder)]\n/// #[response(content_type = \"application/x-person\")]\n/// struct Person {\n///     text: String,\n///     name: Header<'static>,\n///     age: Header<'static>,\n/// }\n///\n/// impl Person {\n///     fn new(name: &str, age: usize) -> Person {\n///         Person {\n///             text: format!(\"{}:{}\", name, age),\n///             name: Header::new(\"X-Person-Name\", name.to_string()),\n///             age: Header::new(\"X-Person-Age\", age.to_string())\n///         }\n///     }\n/// }\n/// #\n/// # #[rocket::get(\"/person\")]\n/// # fn person() -> Person { Person::new(\"Bob\", 29) }\n/// ```\npub trait Responder<'r, 'o: 'r> {\n    /// Returns `Ok` if a `Response` could be generated successfully. Otherwise,\n    /// returns an `Err` with a failing `Status`.\n    ///\n    /// The `request` parameter is the `Request` that this `Responder` is\n    /// responding to.\n    ///\n    /// When using Rocket's code generation, if an `Ok(Response)` is returned,\n    /// the response will be written out to the client. If an `Err(Status)` is\n    /// returned, the error catcher for the given status is retrieved and called\n    /// to generate a final error response, which is then written out to the\n    /// client.\n    fn respond_to(self, request: &'r Request<'_>) -> response::Result<'o>;\n}\n\n/// Returns a response with Content-Type `text/plain` and a fixed-size body\n/// containing the string `self`. Always returns `Ok`.\nimpl<'r, 'o: 'r> Responder<'r, 'o> for &'o str {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {\n        Response::build()\n            .header(ContentType::Plain)\n            .sized_body(self.len(), Cursor::new(self))\n            .ok()\n    }\n}\n\n/// Returns a response with Content-Type `text/plain` and a fixed-size body\n/// containing the string `self`. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for String {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build()\n            .header(ContentType::Plain)\n            .sized_body(self.len(), Cursor::new(self))\n            .ok()\n    }\n}\n\n#[repr(transparent)]\nstruct DerefRef<T>(T);\n\nimpl<T: std::ops::Deref> AsRef<[u8]> for DerefRef<T> where T::Target: AsRef<[u8]> {\n    fn as_ref(&self) -> &[u8] {\n        self.0.deref().as_ref()\n    }\n}\n\n/// Returns a response with Content-Type `text/plain` and a fixed-size body\n/// containing the string `self`. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for Arc<str> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build()\n            .header(ContentType::Plain)\n            .sized_body(self.len(), Cursor::new(DerefRef(self)))\n            .ok()\n    }\n}\n\n/// Returns a response with Content-Type `text/plain` and a fixed-size body\n/// containing the string `self`. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for Box<str> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build()\n            .header(ContentType::Plain)\n            .sized_body(self.len(), Cursor::new(DerefRef(self)))\n            .ok()\n    }\n}\n\n/// Returns a response with Content-Type `application/octet-stream` and a\n/// fixed-size body containing the data in `self`. Always returns `Ok`.\nimpl<'r, 'o: 'r> Responder<'r, 'o> for &'o [u8] {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {\n        Response::build()\n            .header(ContentType::Binary)\n            .sized_body(self.len(), Cursor::new(self))\n            .ok()\n    }\n}\n\n/// Returns a response with Content-Type `application/octet-stream` and a\n/// fixed-size body containing the data in `self`. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for Vec<u8> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build()\n            .header(ContentType::Binary)\n            .sized_body(self.len(), Cursor::new(self))\n            .ok()\n    }\n}\n\n/// Returns a response with Content-Type `application/octet-stream` and a\n/// fixed-size body containing the data in `self`. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for Arc<[u8]> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build()\n            .header(ContentType::Binary)\n            .sized_body(self.len(), Cursor::new(self))\n            .ok()\n    }\n}\n\n/// Returns a response with Content-Type `application/octet-stream` and a\n/// fixed-size body containing the data in `self`. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for Box<[u8]> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build()\n            .header(ContentType::Binary)\n            .sized_body(self.len(), Cursor::new(self))\n            .ok()\n    }\n}\n\n/// Returns the response generated by the inner `T`. Note that this explicitly\n/// does not support `Box<dyn Responder>`.\n///\n/// ```rust,compile_fail\n/// #[macro_use] extern crate rocket;\n///\n/// use rocket::response::Responder;\n///\n/// #[get(\"/\")]\n/// fn f() -> Box<dyn Responder<'static,'static>> {\n///     Box::new(())\n/// }\n/// ```\n///\n/// However, this `impl` allows boxing sized responders:\n///\n/// ```rust\n/// #[macro_use] extern crate rocket;\n///\n/// #[derive(Responder)]\n/// enum Content {\n///     Redirect(Box<rocket::response::Redirect>),\n///     Text(String),\n/// }\n///\n/// #[get(\"/\")]\n/// fn f() -> Option<Box<String>> {\n///     None\n/// }\n///\n/// #[get(\"/\")]\n/// fn g() -> Content {\n///     Content::Text(\"hello\".to_string())\n/// }\n/// ```\nimpl<'r, 'o: 'r, T: Responder<'r, 'o> + Sized> Responder<'r, 'o> for Box<T> {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        let inner = *self;\n        inner.respond_to(req)\n    }\n}\n\n/// Returns a response with a sized body for the file. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for File {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n        tokio::fs::File::from(self).respond_to(req)\n    }\n}\n\n/// Returns a response with a sized body for the file. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for tokio::fs::File {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build().sized_body(None, self).ok()\n    }\n}\n\n/// Returns an empty, default `Response`. Always returns `Ok`.\nimpl<'r> Responder<'r, 'static> for () {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Ok(Response::new())\n    }\n}\n\n/// Responds with the inner `Responder` in `Cow`.\nimpl<'r, 'o: 'r, R: ?Sized + ToOwned> Responder<'r, 'o> for std::borrow::Cow<'o, R>\n    where &'o R: Responder<'r, 'o> + 'o, <R as ToOwned>::Owned: Responder<'r, 'o> + 'r\n{\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        match self {\n            std::borrow::Cow::Borrowed(b) => b.respond_to(req),\n            std::borrow::Cow::Owned(o) => o.respond_to(req),\n        }\n    }\n}\n\n/// If `self` is `Some`, responds with the wrapped `Responder`. Otherwise prints\n/// a warning message and returns an `Err` of `Status::NotFound`.\nimpl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Option<R> {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        match self {\n            Some(r) => r.respond_to(req),\n            None => {\n                let type_name = std::any::type_name::<Self>();\n                debug!(type_name, \"`Option` responder returned `None`\");\n                Err(Status::NotFound)\n            },\n        }\n    }\n}\n\n/// Responds with the wrapped `Responder` in `self`, whether it is `Ok` or\n/// `Err`.\nimpl<'r, 'o: 'r, 't: 'o, 'e: 'o, T, E> Responder<'r, 'o> for Result<T, E>\n    where T: Responder<'r, 't>, E: Responder<'r, 'e>\n{\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        match self {\n            Ok(responder) => responder.respond_to(req),\n            Err(responder) => responder.respond_to(req),\n        }\n    }\n}\n\n/// Responds with the wrapped `Responder` in `self`, whether it is `Left` or\n/// `Right`.\nimpl<'r, 'o: 'r, 't: 'o, 'e: 'o, T, E> Responder<'r, 'o> for either::Either<T, E>\n    where T: Responder<'r, 't>, E: Responder<'r, 'e>\n{\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        match self {\n            either::Either::Left(r) => r.respond_to(req),\n            either::Either::Right(r) => r.respond_to(req),\n        }\n    }\n}\n\n/// The response generated by `Status` depends on the status code itself. The\n/// table below summarizes the functionality:\n///\n/// | Status Code Range | Response                              |\n/// |-------------------|---------------------------------------|\n/// | [400, 599]        | Forwards to catcher for given status. |\n/// | 100, [200, 205]   | Empty with status of `self`.          |\n/// | All others.       | Invalid. Errors to `500` catcher.     |\n///\n/// In short, a client or server error status codes will forward to the\n/// corresponding error catcher, a successful status code less than `206` or\n/// `100` responds with any empty body and the given status code, and all other\n/// status code emit an error message and forward to the `500` (internal server\n/// error) catcher.\nimpl<'r> Responder<'r, 'static> for Status {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        match self.class() {\n            StatusClass::ClientError | StatusClass::ServerError => Err(self),\n            StatusClass::Success if self.code < 206 => {\n                Response::build().status(self).ok()\n            }\n            StatusClass::Informational if self.code == 100 => {\n                Response::build().status(self).ok()\n            }\n            _ => {\n                error!(status = self.code,\n                    \"invalid status used as responder\\n\\\n                    status must be one of 100, 200..=205, 400..=599\");\n\n                Err(Status::InternalServerError)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/response.rs",
    "content": "use std::{fmt, str};\nuse std::borrow::Cow;\nuse std::collections::HashMap;\n\nuse tokio::io::{AsyncRead, AsyncSeek};\n\nuse crate::http::{Header, HeaderMap, Status, ContentType, Cookie};\nuse crate::http::uncased::{Uncased, AsUncased};\nuse crate::data::IoHandler;\nuse crate::response::Body;\n\n/// Builder for the [`Response`] type.\n///\n/// Building a [`Response`] can be a low-level ordeal; this structure presents a\n/// higher-level API that simplifies building `Response`s.\n///\n/// # Usage\n///\n/// `Builder` follows the builder pattern and is usually obtained by calling\n/// [`Response::build()`] on `Response`. Almost all methods take the current\n/// builder as a mutable reference and return the same mutable reference with\n/// field(s) modified in the `Response` being built. These method calls can be\n/// chained: `build.a().b()`.\n///\n/// To finish building and retrieve the built `Response`, use the\n/// [`finalize()`](#method.finalize) or [`ok()`](#method.ok) methods.\n///\n/// ## Headers\n///\n/// When building a `Response`, headers can either be _replaced_ or _adjoined_;\n/// the default behavior (using `header(..)`) is to _replace_. When a header is\n/// _replaced_, any existing values for headers with the same name are removed,\n/// and the new value is set. If no header exists, the header is simply added.\n/// On the other hand, when a header is _adjoined_, all existing values will\n/// remain, and the `value` of the adjoined header will be added to the set of\n/// existing values, if any. Adjoining maintains order: headers adjoined first\n/// will appear first in the `Response`.\n///\n/// ## Joining and Merging\n///\n/// It is often necessary to combine multiple `Response`s in some way. The\n/// [merge](#method.merge) and [join](#method.join) methods facilitate this. The\n/// `merge` method replaces all of the fields in `self` with those present in\n/// `other`. The `join` method sets any fields not set in `self` to the value in\n/// `other`. See their documentation for more details.\n/// ## Example\n///\n/// The following example builds a `Response` with:\n///\n///   * **Status**: `418 I'm a teapot`\n///   * **Content-Type** header: `text/plain; charset=utf-8`\n///   * **X-Teapot-Make** header: `Rocket`\n///   * **X-Teapot-Model** headers: `Utopia`, `Series 1`\n///   * **Body**: fixed-size string `\"Brewing the best coffee!\"`\n///\n/// ```rust\n/// use std::io::Cursor;\n/// use rocket::response::Response;\n/// use rocket::http::{Status, ContentType};\n///\n/// let body = \"Brewing the best coffee!\";\n/// let response = Response::build()\n///     .status(Status::ImATeapot)\n///     .header(ContentType::Plain)\n///     .raw_header(\"X-Teapot-Make\", \"Rocket\")\n///     .raw_header(\"X-Teapot-Model\", \"Utopia\")\n///     .raw_header_adjoin(\"X-Teapot-Model\", \"Series 1\")\n///     .sized_body(body.len(), Cursor::new(body))\n///     .finalize();\n/// ```\npub struct Builder<'r> {\n    response: Response<'r>,\n}\n\nimpl<'r> Builder<'r> {\n    /// Creates a new `Builder` that will build on top of the `base`\n    /// `Response`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::{Builder, Response};\n    ///\n    /// # #[allow(unused_variables)]\n    /// let builder = Builder::new(Response::new());\n    /// ```\n    #[inline(always)]\n    pub fn new(base: Response<'r>) -> Builder<'r> {\n        Builder {\n            response: base,\n        }\n    }\n\n    /// Sets the status of the `Response` being built to `status`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Status;\n    ///\n    /// let response = Response::build()\n    ///     .status(Status::NotFound)\n    ///     .finalize();\n    /// ```\n    #[inline(always)]\n    pub fn status(&mut self, status: Status) -> &mut Builder<'r> {\n        self.response.set_status(status);\n        self\n    }\n\n    /// Adds `header` to the `Response`, replacing any header with the same name\n    /// that already exists in the response. If multiple headers with\n    /// the same name exist, they are all removed, and only the new header and\n    /// value will remain.\n    ///\n    /// The type of `header` can be any type that implements `Into<Header>`. See\n    /// [trait implementations](Header#trait-implementations).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::ContentType;\n    ///\n    /// let response = Response::build()\n    ///     .header(ContentType::JSON)\n    ///     .header(ContentType::HTML)\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.headers().get(\"Content-Type\").count(), 1);\n    /// ```\n    #[inline(always)]\n    pub fn header<'h: 'r, H>(&mut self, header: H) -> &mut Builder<'r>\n        where H: Into<Header<'h>>\n    {\n        self.response.set_header(header);\n        self\n    }\n\n    /// Adds `header` to the `Response` by adjoining the header with any\n    /// existing headers with the same name that already exist in the\n    /// `Response`. This allows for multiple headers with the same name and\n    /// potentially different values to be present in the `Response`.\n    ///\n    /// The type of `header` can be any type that implements `Into<Header>`. See\n    /// [trait implementations](Header#trait-implementations).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::{Header, Accept};\n    ///\n    /// let response = Response::build()\n    ///     .header_adjoin(Header::new(\"Accept\", \"application/json\"))\n    ///     .header_adjoin(Accept::XML)\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.headers().get(\"Accept\").count(), 2);\n    /// ```\n    #[inline(always)]\n    pub fn header_adjoin<'h: 'r, H>(&mut self, header: H) -> &mut Builder<'r>\n        where H: Into<Header<'h>>\n    {\n        self.response.adjoin_header(header);\n        self\n    }\n\n    /// Adds a custom header to the `Response` with the given name and value,\n    /// replacing any header with the same name that already exists in the\n    /// response. If multiple headers with the same name exist, they are all\n    /// removed, and only the new header and value will remain.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    ///\n    /// let response = Response::build()\n    ///     .raw_header(\"X-Custom\", \"first\")\n    ///     .raw_header(\"X-Custom\", \"second\")\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.headers().get(\"X-Custom\").count(), 1);\n    /// ```\n    #[inline(always)]\n    pub fn raw_header<'a, 'b, N, V>(&mut self, name: N, value: V) -> &mut Builder<'r>\n        where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>, 'a: 'r, 'b: 'r\n    {\n        self.response.set_raw_header(name, value);\n        self\n    }\n\n    /// Adds custom header to the `Response` with the given name and value,\n    /// adjoining the header with any existing headers with the same name that\n    /// already exist in the `Response`. This allows for multiple headers with\n    /// the same name and potentially different values to be present in the\n    /// `Response`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    ///\n    /// let response = Response::build()\n    ///     .raw_header_adjoin(\"X-Custom\", \"first\")\n    ///     .raw_header_adjoin(\"X-Custom\", \"second\")\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.headers().get(\"X-Custom\").count(), 2);\n    /// ```\n    #[inline(always)]\n    pub fn raw_header_adjoin<'a, 'b, N, V>(&mut self, name: N, value: V) -> &mut Builder<'r>\n        where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>, 'a: 'r, 'b: 'r\n    {\n        self.response.adjoin_raw_header(name, value);\n        self\n    }\n\n    /// Sets the body of the `Response` to be the fixed-sized `body` with size\n    /// `size`, which may be `None`. If `size` is `None`, the body's size will\n    /// be computed with calls to `seek` when the response is written out.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::Response;\n    ///\n    /// let body = \"Hello, world!\";\n    /// let response = Response::build()\n    ///     .sized_body(body.len(), Cursor::new(body))\n    ///     .finalize();\n    /// ```\n    pub fn sized_body<B, S>(&mut self, size: S, body: B) -> &mut Builder<'r>\n        where B: AsyncRead + AsyncSeek + Send + 'r,\n              S: Into<Option<usize>>\n    {\n        self.response.set_sized_body(size, body);\n        self\n    }\n\n    /// Sets the body of the `Response` to be the streamed `body`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::Response;\n    ///\n    /// let response = Response::build()\n    ///     .streamed_body(Cursor::new(\"Hello, world!\"))\n    ///     .finalize();\n    /// ```\n    #[inline(always)]\n    pub fn streamed_body<B>(&mut self, body: B) -> &mut Builder<'r>\n        where B: AsyncRead + Send + 'r\n    {\n        self.response.set_streamed_body(body);\n        self\n    }\n\n    /// Registers `handler` as the I/O handler for upgrade protocol `protocol`.\n    ///\n    /// This is equivalent to [`Response::add_upgrade()`].\n    ///\n    /// **NOTE**: Responses registering I/O handlers for upgraded protocols\n    /// **should not** set the response status to `101 Switching Protocols`, nor set the\n    /// `Connection` or `Upgrade` headers. Rocket automatically sets these\n    /// headers as needed. See [`Response`#upgrading] for details.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::pin::Pin;\n    ///\n    /// use rocket::Response;\n    /// use rocket::data::{IoHandler, IoStream};\n    /// use rocket::tokio::io;\n    ///\n    /// struct EchoHandler;\n    ///\n    /// #[rocket::async_trait]\n    /// impl IoHandler for EchoHandler {\n    ///     async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {\n    ///         let (mut reader, mut writer) = io::split(io);\n    ///         io::copy(&mut reader, &mut writer).await?;\n    ///         Ok(())\n    ///     }\n    /// }\n    ///\n    /// let response = Response::build()\n    ///     .upgrade(\"raw-echo\", EchoHandler)\n    ///     .streamed_body(std::io::Cursor::new(\"We didn't upgrade!\"))\n    ///     .finalize();\n    /// ```\n    #[inline(always)]\n    pub fn upgrade<P, H>(&mut self, protocol: P, handler: H) -> &mut Builder<'r>\n        where P: Into<Uncased<'r>>, H: IoHandler + 'r\n    {\n        self.response.add_upgrade(protocol.into(), handler);\n        self\n    }\n\n    /// Sets the max chunk size of a body, if any, to `size`.\n    ///\n    /// See [`Response::set_max_chunk_size()`] for notes.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::Response;\n    ///\n    /// let response = Response::build()\n    ///     .streamed_body(Cursor::new(\"Hello, world!\"))\n    ///     .max_chunk_size(3072)\n    ///     .finalize();\n    /// ```\n    #[inline(always)]\n    pub fn max_chunk_size(&mut self, size: usize) -> &mut Builder<'r> {\n        self.response.set_max_chunk_size(size);\n        self\n    }\n\n    /// Merges the `other` `Response` into `self` by setting any fields in\n    /// `self` to the corresponding value in `other` if they are set in `other`.\n    /// Fields in `self` are unchanged if they are not set in `other`. If a\n    /// header is set in both `self` and `other`, the values in `other` are\n    /// kept. Headers set only in `self` remain.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::{Status, ContentType};\n    ///\n    /// let base = Response::build()\n    ///     .status(Status::NotFound)\n    ///     .header(ContentType::HTML)\n    ///     .raw_header(\"X-Custom\", \"value 1\")\n    ///     .finalize();\n    ///\n    /// let response = Response::build()\n    ///     .status(Status::ImATeapot)\n    ///     .raw_header(\"X-Custom\", \"value 2\")\n    ///     .raw_header_adjoin(\"X-Custom\", \"value 3\")\n    ///     .merge(base)\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.status(), Status::NotFound);\n    ///\n    /// let ctype: Vec<_> = response.headers().get(\"Content-Type\").collect();\n    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);\n    ///\n    /// let custom_values: Vec<_> = response.headers().get(\"X-Custom\").collect();\n    /// assert_eq!(custom_values, vec![\"value 1\"]);\n    /// ```\n    #[inline(always)]\n    pub fn merge(&mut self, other: Response<'r>) -> &mut Builder<'r> {\n        self.response.merge(other);\n        self\n    }\n\n    /// Joins the `other` `Response` into `self` by setting any fields in `self`\n    /// to the corresponding value in `other` if they are set in `self`. Fields\n    /// in `self` are unchanged if they are already set. If a header is set in\n    /// both `self` and `other`, the values are adjoined, with the values in\n    /// `self` coming first. Headers only in `self` or `other` are set in\n    /// `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::{Status, ContentType};\n    ///\n    /// let other = Response::build()\n    ///     .status(Status::NotFound)\n    ///     .header(ContentType::HTML)\n    ///     .raw_header(\"X-Custom\", \"value 1\")\n    ///     .finalize();\n    ///\n    /// let response = Response::build()\n    ///     .status(Status::ImATeapot)\n    ///     .raw_header(\"X-Custom\", \"value 2\")\n    ///     .raw_header_adjoin(\"X-Custom\", \"value 3\")\n    ///     .join(other)\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.status(), Status::ImATeapot);\n    ///\n    /// let ctype: Vec<_> = response.headers().get(\"Content-Type\").collect();\n    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);\n    ///\n    /// let custom_values: Vec<_> = response.headers().get(\"X-Custom\").collect();\n    /// assert_eq!(custom_values, vec![\"value 2\", \"value 3\", \"value 1\"]);\n    /// ```\n    #[inline(always)]\n    pub fn join(&mut self, other: Response<'r>) -> &mut Builder<'r> {\n        self.response.join(other);\n        self\n    }\n\n    /// Return the `Response` structure that was being built by this builder.\n    /// After calling this method, `self` is cleared and must be rebuilt as if\n    /// from `new()`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    ///\n    /// use rocket::Response;\n    /// use rocket::http::Status;\n    ///\n    /// let body = \"Brewing the best coffee!\";\n    /// let response = Response::build()\n    ///     .status(Status::ImATeapot)\n    ///     .sized_body(body.len(), Cursor::new(body))\n    ///     .raw_header(\"X-Custom\", \"value 2\")\n    ///     .finalize();\n    /// ```\n    pub fn finalize(&mut self) -> Response<'r> {\n        std::mem::replace(&mut self.response, Response::new())\n    }\n\n    /// Retrieve the built `Response` wrapped in `Ok`. After calling this\n    /// method, `self` is cleared and must be rebuilt as if from `new()`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    ///\n    /// let response: Result<Response, ()> = Response::build()\n    ///     // build the response\n    ///     .ok();\n    ///\n    /// assert!(response.is_ok());\n    /// ```\n    #[inline(always)]\n    pub fn ok<E>(&mut self) -> Result<Response<'r>, E> {\n        Ok(self.finalize())\n    }\n}\n\n/// A response, as returned by types implementing\n/// [`Responder`](crate::response::Responder).\n///\n/// See [`Builder`] for docs on how a `Response` is typically created and the\n/// [module docs](crate::response) for notes on composing responses\n///\n/// ## Upgrading\n///\n/// A response may optionally register [`IoHandler`]s for upgraded requests via\n/// [`Response::add_upgrade()`] or the corresponding builder method\n/// [`Builder::upgrade()`]. If the incoming request 1) requests an upgrade via a\n/// `Connection: Upgrade` header _and_ 2) includes a protocol in its `Upgrade`\n/// header that is registered by the returned `Response`, the connection will be\n/// upgraded. An upgrade response is sent to the client, and the registered\n/// `IoHandler` for the client's preferred protocol is invoked with an\n/// [`IoStream`](crate::data::IoStream) representing a raw byte stream to the\n/// client. Note that protocol names are treated case-insensitively during\n/// matching.\n///\n/// If a connection is upgraded, Rocket automatically set the following in the\n/// upgrade response:\n///   * The response status to `101 Switching Protocols`.\n///   * The `Connection: Upgrade` header.\n///   * The `Upgrade` header's value to the selected protocol.\n///\n/// As such, a response **should never** set a `101` status nor the `Connection`\n/// or `Upgrade` headers: Rocket handles this automatically. Instead, it should\n/// set a status and headers to use in case the connection is not upgraded,\n/// either due to an error or because the client did not request an upgrade.\n///\n/// If a connection _is not_ upgraded due to an error, even though there was a\n/// matching, registered protocol, the `IoHandler` is not invoked, and the\n/// original response is sent to the client without alteration.\n#[derive(Default)]\npub struct Response<'r> {\n    status: Option<Status>,\n    headers: HeaderMap<'r>,\n    body: Body<'r>,\n    upgrade: HashMap<Uncased<'r>, Box<dyn IoHandler + 'r>>,\n}\n\nimpl<'r> Response<'r> {\n    /// Creates a new, empty `Response` without a status, body, or headers.\n    /// Because all HTTP responses must have a status, if a default `Response`\n    /// is written to the client without a status, the status defaults to `200\n    /// Ok`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Status;\n    ///\n    /// let mut response = Response::new();\n    ///\n    /// assert_eq!(response.status(), Status::Ok);\n    /// assert_eq!(response.headers().len(), 0);\n    /// assert!(response.body().is_none());\n    /// ```\n    #[inline(always)]\n    pub fn new() -> Response<'r> {\n        Response::default()\n    }\n\n    /// Returns a `Builder` with a base of `Response::new()`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    ///\n    /// # #[allow(unused_variables)]\n    /// let builder = Response::build();\n    /// ```\n    #[inline(always)]\n    pub fn build() -> Builder<'r> {\n        Response::build_from(Response::new())\n    }\n\n    /// Returns a `Builder` with a base of `other`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #![allow(unused_variables)]\n    /// use rocket::Response;\n    ///\n    /// let other = Response::new();\n    /// let builder = Response::build_from(other);\n    /// ```\n    #[inline(always)]\n    pub fn build_from(other: Response<'r>) -> Builder<'r> {\n        Builder::new(other)\n    }\n\n    /// Returns the status of `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Status;\n    ///\n    /// let mut response = Response::new();\n    /// assert_eq!(response.status(), Status::Ok);\n    ///\n    /// response.set_status(Status::NotFound);\n    /// assert_eq!(response.status(), Status::NotFound);\n    /// ```\n    #[inline(always)]\n    pub fn status(&self) -> Status {\n        self.status.unwrap_or(Status::Ok)\n    }\n\n    /// Sets the status of `self` to `status`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Status;\n    ///\n    /// let mut response = Response::new();\n    /// response.set_status(Status::ImATeapot);\n    /// assert_eq!(response.status(), Status::ImATeapot);\n    /// ```\n    #[inline(always)]\n    pub fn set_status(&mut self, status: Status) {\n        self.status = Some(status);\n    }\n\n    /// Returns the Content-Type header of `self`. If the header is not present\n    /// or is malformed, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::ContentType;\n    ///\n    /// let mut response = Response::new();\n    /// response.set_header(ContentType::HTML);\n    /// assert_eq!(response.content_type(), Some(ContentType::HTML));\n    /// ```\n    #[inline(always)]\n    pub fn content_type(&self) -> Option<ContentType> {\n        self.headers().get_one(\"Content-Type\").and_then(|v| v.parse().ok())\n    }\n\n    /// Returns an iterator over the cookies in `self` as identified by the\n    /// `Set-Cookie` header. Malformed cookies are skipped.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Cookie;\n    ///\n    /// let mut response = Response::new();\n    /// response.set_header(Cookie::new(\"hello\", \"world!\"));\n    /// let cookies: Vec<_> = response.cookies().collect();\n    /// assert_eq!(cookies, vec![Cookie::new(\"hello\", \"world!\")]);\n    /// ```\n    pub fn cookies(&self) -> impl Iterator<Item = Cookie<'_>> {\n        self.headers()\n            .get(\"Set-Cookie\")\n            .filter_map(|header| Cookie::parse_encoded(header).ok())\n    }\n\n    /// Returns a [`HeaderMap`] of all of the headers in `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Header;\n    ///\n    /// let mut response = Response::new();\n    /// response.adjoin_raw_header(\"X-Custom\", \"1\");\n    /// response.adjoin_raw_header(\"X-Custom\", \"2\");\n    ///\n    /// let mut custom_headers = response.headers().iter();\n    /// assert_eq!(custom_headers.next(), Some(Header::new(\"X-Custom\", \"1\")));\n    /// assert_eq!(custom_headers.next(), Some(Header::new(\"X-Custom\", \"2\")));\n    /// assert_eq!(custom_headers.next(), None);\n    /// ```\n    #[inline(always)]\n    pub fn headers(&self) -> &HeaderMap<'r> {\n        &self.headers\n    }\n\n    pub fn set_header_map<'h: 'r>(&mut self, headers: HeaderMap<'h>) {\n        self.headers = headers;\n    }\n\n    /// Sets the header `header` in `self`. Any existing headers with the name\n    /// `header.name` will be lost, and only `header` will remain. The type of\n    /// `header` can be any type that implements `Into<Header>`. See [trait\n    /// implementations](Header#trait-implementations).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::ContentType;\n    ///\n    /// let mut response = Response::new();\n    ///\n    /// response.set_header(ContentType::HTML);\n    /// assert_eq!(response.headers().iter().next(), Some(ContentType::HTML.into()));\n    /// assert_eq!(response.headers().len(), 1);\n    ///\n    /// response.set_header(ContentType::JSON);\n    /// assert_eq!(response.headers().iter().next(), Some(ContentType::JSON.into()));\n    /// assert_eq!(response.headers().len(), 1);\n    /// ```\n    #[inline(always)]\n    pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {\n        self.headers.replace(header)\n    }\n\n    /// Sets the custom header with name `name` and value `value` in `self`. Any\n    /// existing headers with the same `name` will be lost, and the new custom\n    /// header will remain. This method should be used sparingly; prefer to use\n    /// [set_header](#method.set_header) instead.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Header;\n    ///\n    /// let mut response = Response::new();\n    ///\n    /// response.set_raw_header(\"X-Custom\", \"1\");\n    /// assert_eq!(response.headers().get_one(\"X-Custom\"), Some(\"1\"));\n    /// assert_eq!(response.headers().len(), 1);\n    ///\n    /// response.set_raw_header(\"X-Custom\", \"2\");\n    /// assert_eq!(response.headers().get_one(\"X-Custom\"), Some(\"2\"));\n    /// assert_eq!(response.headers().len(), 1);\n    /// ```\n    #[inline(always)]\n    pub fn set_raw_header<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V) -> bool\n        where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>\n    {\n        self.set_header(Header::new(name, value))\n    }\n\n    /// Adds the header `header` to `self`. If `self` contains headers with the\n    /// name `header.name`, another header with the same name and value\n    /// `header.value` is added. The type of `header` can be any type that\n    /// implements `Into<Header>`. This includes `Header` itself,\n    /// [`ContentType`](crate::http::ContentType),\n    /// [`Accept`](crate::http::Accept).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::{Header, Accept};\n    ///\n    /// let mut response = Response::new();\n    /// response.adjoin_header(Accept::JSON);\n    /// response.adjoin_header(Header::new(\"Accept\", \"text/plain\"));\n    ///\n    /// let mut accept_headers = response.headers().iter();\n    /// assert_eq!(accept_headers.next(), Some(Header::new(\"Accept\", \"application/json\")));\n    /// assert_eq!(accept_headers.next(), Some(Header::new(\"Accept\", \"text/plain\")));\n    /// assert_eq!(accept_headers.next(), None);\n    /// ```\n    #[inline(always)]\n    pub fn adjoin_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) {\n        self.headers.add(header)\n    }\n\n    /// Adds a custom header with name `name` and value `value` to `self`. If\n    /// `self` already contains headers with the name `name`, another header\n    /// with the same `name` and `value` is added.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::Header;\n    ///\n    /// let mut response = Response::new();\n    /// response.adjoin_raw_header(\"X-Custom\", \"one\");\n    /// response.adjoin_raw_header(\"X-Custom\", \"two\");\n    ///\n    /// let mut custom_headers = response.headers().iter();\n    /// assert_eq!(custom_headers.next(), Some(Header::new(\"X-Custom\", \"one\")));\n    /// assert_eq!(custom_headers.next(), Some(Header::new(\"X-Custom\", \"two\")));\n    /// assert_eq!(custom_headers.next(), None);\n    /// ```\n    #[inline(always)]\n    pub fn adjoin_raw_header<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V)\n        where N: Into<Cow<'a, str>>, V: Into<Cow<'b, str>>\n    {\n        self.adjoin_header(Header::new(name, value));\n    }\n\n    /// Removes all headers with the name `name`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    ///\n    /// let mut response = Response::new();\n    ///\n    /// response.adjoin_raw_header(\"X-Custom\", \"one\");\n    /// response.adjoin_raw_header(\"X-Custom\", \"two\");\n    /// response.adjoin_raw_header(\"X-Other\", \"hi\");\n    /// assert_eq!(response.headers().len(), 3);\n    ///\n    /// response.remove_header(\"X-Custom\");\n    /// assert_eq!(response.headers().len(), 1);\n    /// ```\n    #[inline(always)]\n    pub fn remove_header(&mut self, name: &str) {\n        self.headers.remove(name);\n    }\n\n    /// Returns an immutable borrow of the body of `self`, if there is one.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::Response;\n    ///\n    /// # rocket::async_test(async {\n    /// let mut response = Response::new();\n    /// assert!(response.body().is_none());\n    ///\n    /// let string = \"Hello, world!\";\n    /// response.set_sized_body(string.len(), Cursor::new(string));\n    /// assert!(response.body().is_some());\n    /// # })\n    /// ```\n    #[inline(always)]\n    pub fn body(&self) -> &Body<'r> {\n        &self.body\n    }\n\n    /// Returns `Ok(Some(_))` if `self` contains a suitable handler for any of\n    /// the comma-separated protocol strings in `I`. Returns `Err(_)` if\n    /// `protocols` is non-empty but no match was found in `self`. If `self`\n    /// doesn't support any kind of upgrade, return `Ok(None)`.\n    pub(crate) fn search_upgrades<'a, I: Iterator<Item = &'a str>>(\n        &mut self,\n        protocols: I\n    ) -> Result<Option<(Uncased<'r>, Box<dyn IoHandler + 'r>)>, ()> {\n        if self.upgrade.is_empty() {\n            return Ok(None);\n        }\n\n        let mut protocols = protocols.peekable();\n        let have_protocols = protocols.peek().is_some();\n        let found = protocols\n            .flat_map(|v| v.split(',').map(str::trim))\n            .find_map(|p| self.upgrade.remove_entry(p.as_uncased()));\n\n        match found {\n            Some(handler) => Ok(Some(handler)),\n            None if have_protocols => Err(()),\n            None => Ok(None)\n        }\n    }\n\n    /// Returns the [`IoHandler`] for the protocol `proto`.\n    ///\n    /// Returns `Some` if such a handler was registered via\n    /// [`Response::add_upgrade()`] or the corresponding builder method\n    /// [`upgrade()`](Builder::upgrade()). Otherwise returns `None`.\n    ///\n    /// ```rust\n    /// use std::pin::Pin;\n    ///\n    /// use rocket::Response;\n    /// use rocket::data::{IoHandler, IoStream};\n    /// use rocket::tokio::io;\n    ///\n    /// struct EchoHandler;\n    ///\n    /// #[rocket::async_trait]\n    /// impl IoHandler for EchoHandler {\n    ///     async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {\n    ///         let (mut reader, mut writer) = io::split(io);\n    ///         io::copy(&mut reader, &mut writer).await?;\n    ///         Ok(())\n    ///     }\n    /// }\n    ///\n    /// # rocket::async_test(async {\n    /// let mut response = Response::new();\n    /// assert!(response.upgrade(\"raw-echo\").is_none());\n    ///\n    /// response.add_upgrade(\"raw-echo\", EchoHandler);\n    /// assert!(response.upgrade(\"raw-echo\").is_some());\n    /// # })\n    /// ```\n    pub fn upgrade(&mut self, proto: &str) -> Option<&mut (dyn IoHandler + 'r)> {\n        self.upgrade.get_mut(proto.as_uncased()).map(|h| h.as_mut())\n    }\n\n    /// Returns a mutable borrow of the body of `self`, if there is one. A\n    /// mutable borrow allows for reading the body.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    /// use rocket::Response;\n    ///\n    /// # rocket::async_test(async {\n    /// let mut response = Response::new();\n    /// assert!(response.body().is_none());\n    ///\n    /// let string = \"Hello, world!\";\n    /// response.set_sized_body(string.len(), Cursor::new(string));\n    /// let string = response.body_mut().to_string().await;\n    /// assert_eq!(string.unwrap(), \"Hello, world!\");\n    /// # })\n    /// ```\n    #[inline(always)]\n    pub fn body_mut(&mut self) -> &mut Body<'r> {\n        &mut self.body\n    }\n\n    // Makes the `AsyncRead`er in the body empty but leaves the size of the body\n    // if it exists. Meant to be used during HEAD handling.\n    #[inline(always)]\n    pub(crate) fn strip_body(&mut self) {\n        self.body.strip();\n    }\n\n    /// Sets the body of `self` to be the fixed-sized `body` with size\n    /// `size`, which may be `None`. If `size` is `None`, the body's size will\n    /// be computing with calls to `seek` just before being written out in a\n    /// response.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::io;\n    /// use rocket::Response;\n    ///\n    /// # let o: io::Result<()> = rocket::async_test(async {\n    /// let string = \"Hello, world!\";\n    ///\n    /// let mut response = Response::new();\n    /// response.set_sized_body(string.len(), io::Cursor::new(string));\n    /// assert_eq!(response.body_mut().to_string().await?, \"Hello, world!\");\n    /// # Ok(())\n    /// # });\n    /// # assert!(o.is_ok());\n    /// ```\n    pub fn set_sized_body<B, S>(&mut self, size: S, body: B)\n        where B: AsyncRead + AsyncSeek + Send + 'r,\n              S: Into<Option<usize>>\n    {\n        self.body = Body::with_sized(body, size.into());\n    }\n\n    /// Sets the body of `self` to `body`, which will be streamed.\n    ///\n    /// The max chunk size is configured via [`Response::set_max_chunk_size()`]\n    /// and defaults to [`Body::DEFAULT_MAX_CHUNK`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use std::io;\n    /// use tokio::io::{repeat, AsyncReadExt};\n    /// use rocket::Response;\n    ///\n    /// # let o: io::Result<()> = rocket::async_test(async {\n    /// let mut response = Response::new();\n    /// response.set_streamed_body(repeat(97).take(5));\n    /// assert_eq!(response.body_mut().to_string().await?, \"aaaaa\");\n    /// # Ok(())\n    /// # });\n    /// # assert!(o.is_ok());\n    /// ```\n    #[inline(always)]\n    pub fn set_streamed_body<B>(&mut self, body: B)\n        where B: AsyncRead + Send + 'r\n    {\n        self.body = Body::with_unsized(body);\n    }\n\n    /// Registers `handler` as the I/O handler for upgrade protocol `protocol`.\n    ///\n    /// Responses registering I/O handlers for upgraded protocols **should not**\n    /// set the response status to `101`, nor set the `Connection` or `Upgrade`\n    /// headers. Rocket automatically sets these headers as needed. See\n    /// [`Response`#upgrading] for details.\n    ///\n    /// If a handler was previously registered for `protocol`, this `handler`\n    /// replaces it. If the connection is upgraded to `protocol`, the last\n    /// `handler` registered for the protocol is used to handle the connection.\n    /// See [`IoHandler`] for details on implementing an I/O handler. For\n    /// details on connection upgrading, see [`Response`#upgrading].\n    ///\n    /// [`Response`#upgrading]: Response#upgrading\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::pin::Pin;\n    ///\n    /// use rocket::Response;\n    /// use rocket::data::{IoHandler, IoStream};\n    /// use rocket::tokio::io;\n    ///\n    /// struct EchoHandler;\n    ///\n    /// #[rocket::async_trait]\n    /// impl IoHandler for EchoHandler {\n    ///     async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {\n    ///         let (mut reader, mut writer) = io::split(io);\n    ///         io::copy(&mut reader, &mut writer).await?;\n    ///         Ok(())\n    ///     }\n    /// }\n    ///\n    /// # rocket::async_test(async {\n    /// let mut response = Response::new();\n    /// assert!(response.upgrade(\"raw-echo\").is_none());\n    ///\n    /// response.add_upgrade(\"raw-echo\", EchoHandler);\n    /// assert!(response.upgrade(\"raw-echo\").is_some());\n    /// # })\n    /// ```\n    pub fn add_upgrade<N, H>(&mut self, protocol: N, handler: H)\n        where N: Into<Uncased<'r>>, H: IoHandler + 'r\n    {\n        self.upgrade.insert(protocol.into(), Box::new(handler));\n    }\n\n    /// Sets the body's maximum chunk size to `size` bytes.\n    ///\n    /// The default max chunk size is [`Body::DEFAULT_MAX_CHUNK`]. The max chunk\n    /// size is a property of the body and is thus reset whenever a body is set\n    /// via [`Response::set_streamed_body()`], [`Response::set_sized_body()`],\n    /// or the corresponding builder methods.\n    ///\n    /// This setting does not typically need to be changed. Configuring a high\n    /// value can result in high memory usage. Similarly, configuring a low\n    /// value can result in excessive network writes. When unsure, leave the\n    /// value unchanged.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use tokio::io::{repeat, AsyncReadExt};\n    /// use rocket::Response;\n    ///\n    /// # let o: Option<()> = rocket::async_test(async {\n    /// let mut response = Response::new();\n    /// response.set_streamed_body(repeat(97).take(5));\n    /// response.set_max_chunk_size(3072);\n    /// # Some(())\n    /// # });\n    /// # assert!(o.is_some());\n    #[inline(always)]\n    pub fn set_max_chunk_size(&mut self, size: usize) {\n        self.body_mut().set_max_chunk_size(size);\n    }\n\n    /// Replaces this response's status and body with that of `other`, if they\n    /// exist in `other`. Any headers that exist in `other` replace the ones in\n    /// `self`. Any in `self` that aren't in `other` remain in `self`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::{Status, ContentType};\n    ///\n    /// let base = Response::build()\n    ///     .status(Status::NotFound)\n    ///     .header(ContentType::HTML)\n    ///     .raw_header(\"X-Custom\", \"value 1\")\n    ///     .finalize();\n    ///\n    /// let response = Response::build()\n    ///     .status(Status::ImATeapot)\n    ///     .raw_header(\"X-Custom\", \"value 2\")\n    ///     .raw_header_adjoin(\"X-Custom\", \"value 3\")\n    ///     .merge(base)\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.status(), Status::NotFound);\n    ///\n    /// let ctype: Vec<_> = response.headers().get(\"Content-Type\").collect();\n    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);\n    ///\n    /// let custom_values: Vec<_> = response.headers().get(\"X-Custom\").collect();\n    /// assert_eq!(custom_values, vec![\"value 1\"]);\n    /// ```\n    pub fn merge(&mut self, other: Response<'r>) {\n        if let Some(status) = other.status {\n            self.status = Some(status);\n        }\n\n        if other.body().is_some() {\n            self.body = other.body;\n        }\n\n        for (name, values) in other.headers.into_iter_raw() {\n            self.headers.replace_all(name.into_cow(), values);\n        }\n    }\n\n    /// Sets `self`'s status and body to that of `other` if they are not already\n    /// set in `self`. Any headers present in both `other` and `self` are\n    /// adjoined.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Response;\n    /// use rocket::http::{Status, ContentType};\n    ///\n    /// let other = Response::build()\n    ///     .status(Status::NotFound)\n    ///     .header(ContentType::HTML)\n    ///     .raw_header(\"X-Custom\", \"value 1\")\n    ///     .finalize();\n    ///\n    /// let response = Response::build()\n    ///     .status(Status::ImATeapot)\n    ///     .raw_header(\"X-Custom\", \"value 2\")\n    ///     .raw_header_adjoin(\"X-Custom\", \"value 3\")\n    ///     .join(other)\n    ///     .finalize();\n    ///\n    /// assert_eq!(response.status(), Status::ImATeapot);\n    ///\n    /// let ctype: Vec<_> = response.headers().get(\"Content-Type\").collect();\n    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);\n    ///\n    /// let custom_values: Vec<_> = response.headers().get(\"X-Custom\").collect();\n    /// assert_eq!(custom_values, vec![\"value 2\", \"value 3\", \"value 1\"]);\n    /// ```\n    pub fn join(&mut self, other: Response<'r>) {\n        if self.status.is_none() {\n            self.status = other.status;\n        }\n\n        if self.body.is_none() {\n            self.body = other.body;\n        }\n\n        for (name, mut values) in other.headers.into_iter_raw() {\n            self.headers.add_all(name.into_cow(), &mut values);\n        }\n    }\n}\n\nimpl fmt::Debug for Response<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        writeln!(f, \"{}\", self.status())?;\n\n        for header in self.headers().iter() {\n            writeln!(f, \"{}\", header)?;\n        }\n\n        self.body.fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/status.rs",
    "content": "//! Contains types that set the status code and corresponding headers of a\n//! response.\n//!\n//! # Responding\n//!\n//! Types in this module designed to make it easier to construct correct\n//! responses with a given status code. Each type takes in the minimum number of\n//! parameters required to construct a correct response. Some types take in\n//! responders; when they do, the responder finalizes the response by writing\n//! out additional headers and, importantly, the body of the response.\n//!\n//! The [`Custom`] type allows responding with _any_ `Status` but _does not_\n//! ensure that all of the required headers are present. As a convenience,\n//! `(Status, R)` where `R: Responder` is _also_ a `Responder`, identical to\n//! `Custom`.\n//!\n//! ```rust\n//! # extern crate rocket;\n//! # use rocket::get;\n//! use rocket::http::Status;\n//!\n//! #[get(\"/\")]\n//! fn index() -> (Status, &'static str) {\n//!     (Status::NotFound, \"Hey, there's no index!\")\n//! }\n//! ```\n\nuse std::hash::{Hash, Hasher};\nuse std::collections::hash_map::DefaultHasher;\nuse std::borrow::Cow;\n\nuse crate::request::Request;\nuse crate::response::{self, Responder, Response};\nuse crate::http::Status;\n\n/// Sets the status of the response to 201 Created.\n///\n/// Sets the `Location` header and optionally the `ETag` header in the response.\n/// The body of the response, which identifies the created resource, can be set\n/// via the builder methods [`Created::body()`] and [`Created::tagged_body()`].\n/// While both builder methods set the responder, the [`Created::tagged_body()`]\n/// additionally computes a hash for the responder which is used as the value of\n/// the `ETag` header when responding.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::response::status;\n///\n/// let response = status::Created::new(\"http://myservice.com/resource.json\")\n///     .tagged_body(\"{ 'resource': 'Hello, world!' }\");\n/// ```\n#[derive(Debug, Clone, PartialEq)]\npub struct Created<R>(Cow<'static, str>, Option<R>, Option<u64>);\n\nimpl<R> Created<R> {\n    /// Constructs a `Created` response with a `location` and no body.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::{get, routes, local::blocking::Client};\n    /// use rocket::response::status;\n    ///\n    /// #[get(\"/\")]\n    /// fn create() -> status::Created<&'static str> {\n    ///     status::Created::new(\"http://myservice.com/resource.json\")\n    /// }\n    ///\n    /// # let client = Client::debug_with(routes![create]).unwrap();\n    /// let response = client.get(\"/\").dispatch();\n    ///\n    /// let loc = response.headers().get_one(\"Location\");\n    /// assert_eq!(loc, Some(\"http://myservice.com/resource.json\"));\n    /// assert!(response.body().is_none());\n    /// ```\n    pub fn new<L: Into<Cow<'static, str>>>(location: L) -> Self {\n        Created(location.into(), None, None)\n    }\n\n    /// Adds `responder` as the body of `self`.\n    ///\n    /// Unlike [`tagged_body()`](self::Created::tagged_body()), this method\n    /// _does not_ result in an `ETag` header being set in the response.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::{get, routes, local::blocking::Client};\n    /// use rocket::response::status;\n    ///\n    /// #[get(\"/\")]\n    /// fn create() -> status::Created<&'static str> {\n    ///     status::Created::new(\"http://myservice.com/resource.json\")\n    ///         .body(\"{ 'resource': 'Hello, world!' }\")\n    /// }\n    ///\n    /// # let client = Client::debug_with(routes![create]).unwrap();\n    /// let response = client.get(\"/\").dispatch();\n    ///\n    /// let loc = response.headers().get_one(\"Location\");\n    /// assert_eq!(loc, Some(\"http://myservice.com/resource.json\"));\n    ///\n    /// let etag = response.headers().get_one(\"ETag\");\n    /// assert_eq!(etag, None);\n    ///\n    /// let body = response.into_string();\n    /// assert_eq!(body.unwrap(), \"{ 'resource': 'Hello, world!' }\");\n    /// ```\n    pub fn body(mut self, responder: R) -> Self {\n        self.1 = Some(responder);\n        self\n    }\n\n    /// Adds `responder` as the body of `self`. Computes a hash of the\n    /// `responder` to be used as the value of the `ETag` header.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::{get, routes, local::blocking::Client};\n    /// use rocket::response::status;\n    ///\n    /// #[get(\"/\")]\n    /// fn create() -> status::Created<&'static str> {\n    ///     status::Created::new(\"http://myservice.com/resource.json\")\n    ///         .tagged_body(\"{ 'resource': 'Hello, world!' }\")\n    /// }\n    ///\n    /// # let client = Client::debug_with(routes![create]).unwrap();\n    /// let response = client.get(\"/\").dispatch();\n    ///\n    /// let loc = response.headers().get_one(\"Location\");\n    /// assert_eq!(loc, Some(\"http://myservice.com/resource.json\"));\n    ///\n    /// let etag = response.headers().get_one(\"ETag\");\n    /// assert_eq!(etag, Some(r#\"\"13046220615156895040\"\"#));\n    ///\n    /// let body = response.into_string();\n    /// assert_eq!(body.unwrap(), \"{ 'resource': 'Hello, world!' }\");\n    /// ```\n    pub fn tagged_body(mut self, responder: R) -> Self where R: Hash {\n        let mut hasher = &mut DefaultHasher::default();\n        responder.hash(&mut hasher);\n        let hash = hasher.finish();\n        self.1 = Some(responder);\n        self.2 = Some(hash);\n        self\n    }\n}\n\n/// Sets the status code of the response to 201 Created. Sets the `Location`\n/// header to the parameter in the [`Created::new()`] constructor.\n///\n/// The optional responder, set via [`Created::body()`] or\n/// [`Created::tagged_body()`] finalizes the response if it exists. The wrapped\n/// responder should write the body of the response so that it contains\n/// information about the created resource. If no responder is provided, the\n/// response body will be empty.\n///\n/// In addition to setting the status code, `Location` header, and finalizing\n/// the response with the `Responder`, the `ETag` header is set conditionally if\n/// a hashable `Responder` is provided via [`Created::tagged_body()`]. The `ETag`\n/// header is set to a hash value of the responder.\nimpl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Created<R> {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        let mut response = Response::build();\n        if let Some(responder) = self.1 {\n            response.merge(responder.respond_to(req)?);\n        }\n\n        if let Some(hash) = self.2 {\n            response.raw_header(\"ETag\", format!(r#\"\"{}\"\"#, hash));\n        }\n\n        response.status(Status::Created)\n            .raw_header(\"Location\", self.0)\n            .ok()\n    }\n}\n\n/// Sets the status of the response to 204 No Content.\n///\n/// The response body will be empty.\n///\n/// # Example\n///\n/// A 204 No Content response:\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket::response::status;\n///\n/// #[get(\"/\")]\n/// fn foo() -> status::NoContent {\n///     status::NoContent\n/// }\n/// ```\n#[derive(Debug, Clone, PartialEq)]\npub struct NoContent;\n\n/// Sets the status code of the response to 204 No Content.\nimpl<'r> Responder<'r, 'static> for NoContent {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build().status(Status::NoContent).ok()\n    }\n}\n\n/// Creates a response with a status code and underlying responder.\n///\n/// Note that this is equivalent to `(Status, R)`.\n///\n/// # Example\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket::response::status;\n/// use rocket::http::Status;\n///\n/// #[get(\"/\")]\n/// fn handler() -> status::Custom<&'static str> {\n///     status::Custom(Status::ImATeapot, \"Hi!\")\n/// }\n///\n/// // This is equivalent to the above.\n/// #[get(\"/\")]\n/// fn handler2() -> (Status, &'static str) {\n///     (Status::ImATeapot, \"Hi!\")\n/// }\n/// ```\n#[derive(Debug, Clone, PartialEq)]\npub struct Custom<R>(pub Status, pub R);\n\n/// Sets the status code of the response and then delegates the remainder of the\n/// response to the wrapped responder.\nimpl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for Custom<R> {\n    #[inline]\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n        Response::build_from(self.1.respond_to(req)?)\n            .status(self.0)\n            .ok()\n    }\n}\n\nimpl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for (Status, R) {\n    #[inline(always)]\n    fn respond_to(self, request: &'r Request<'_>) -> response::Result<'o> {\n        Custom(self.0, self.1).respond_to(request)\n    }\n}\n\nmacro_rules! status_response {\n    ($T:ident $kind:expr) => {\n        /// Sets the status of the response to\n        #[doc = concat!($kind, concat!(\" ([`Status::\", stringify!($T), \"`]).\"))]\n        ///\n        /// The remainder of the response is delegated to `self.0`.\n        /// # Examples\n        ///\n        /// A\n        #[doc = $kind]\n        /// response without a body:\n        ///\n        /// ```rust\n        /// # use rocket::get;\n        /// use rocket::response::status;\n        ///\n        /// #[get(\"/\")]\n        #[doc = concat!(\"fn handler() -> status::\", stringify!($T), \"<()> {\")]\n        #[doc = concat!(\"    status::\", stringify!($T), \"(())\")]\n        /// }\n        /// ```\n        ///\n        /// A\n        #[doc = $kind]\n        /// response _with_ a body:\n        ///\n        /// ```rust\n        /// # use rocket::get;\n        /// use rocket::response::status;\n        ///\n        /// #[get(\"/\")]\n        #[doc = concat!(\"fn handler() -> status::\", stringify!($T), \"<&'static str> {\")]\n        #[doc = concat!(\"    status::\", stringify!($T), \"(\\\"body\\\")\")]\n        /// }\n        /// ```\n        #[derive(Debug, Clone, PartialEq)]\n        pub struct $T<R>(pub R);\n\n        impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for $T<R> {\n            #[inline(always)]\n            fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {\n                Custom(Status::$T, self.0).respond_to(req)\n            }\n        }\n    }\n}\n\nstatus_response!(Accepted \"202 Accepted\");\nstatus_response!(BadRequest \"400 Bad Request\");\nstatus_response!(Unauthorized \"401 Unauthorized\");\nstatus_response!(Forbidden \"403 Forbidden\");\nstatus_response!(NotFound \"404 NotFound\");\nstatus_response!(Conflict \"409 Conflict\");\n\n// The following are unimplemented.\n// 206 Partial Content (variant), 203 Non-Authoritative Information (headers).\n"
  },
  {
    "path": "core/lib/src/response/stream/bytes.rs",
    "content": "use futures::stream::{Stream, StreamExt};\n\nuse crate::request::Request;\nuse crate::response::{self, Response, Responder};\nuse crate::http::ContentType;\nuse crate::response::stream::ReaderStream;\n\n/// A potentially infinite stream of bytes: any `T: AsRef<[u8]>`.\n///\n/// A `ByteStream` can be constructed from any [`Stream`] of items of type `T`\n/// where `T: AsRef<[u8]>`. This includes `Vec<u8>`, `&[u8]`, `&str`, `&RawStr`,\n/// and more. The stream can be constructed directly, via `ByteStream(..)` or\n/// [`ByteStream::from()`], or through generator syntax via [`ByteStream!`].\n///\n/// [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n///\n/// # Responder\n///\n/// `ByteStream` is a (potentially infinite) responder. The response\n/// `Content-Type` is set to [`Binary`](ContentType::Binary). The body is\n/// [unsized](crate::response::Body#unsized), and values are sent as soon as\n/// they are yielded by the internal iterator.\n///\n/// # Example\n///\n/// Use [`ByteStream!`] to yield 10 3-byte vectors, one every second, of the\n/// form `vec![i, i + 1, i + 2]` for `i` from `0` to `10` exclusive:\n///\n/// ```rust\n/// # use rocket::*;\n/// use rocket::response::stream::ByteStream;\n/// use rocket::futures::stream::{repeat, StreamExt};\n/// use rocket::tokio::time::{self, Duration};\n///\n/// #[get(\"/bytes\")]\n/// fn bytes() -> ByteStream![&'static [u8]] {\n///     ByteStream(repeat(&[1, 2, 3][..]))\n/// }\n///\n/// #[get(\"/byte/stream\")]\n/// fn stream() -> ByteStream![Vec<u8>] {\n///     ByteStream! {\n///         let mut interval = time::interval(Duration::from_secs(1));\n///         for i in 0..10u8 {\n///             yield vec![i, i + 1, i + 2];\n///             interval.tick().await;\n///         }\n///     }\n/// }\n/// ```\n///\n/// The syntax of `ByteStream!` as an expression is identical to that of\n/// [`stream!`](crate::response::stream::stream).\n#[derive(Debug, Clone)]\npub struct ByteStream<S>(pub S);\n\nimpl<S> From<S> for ByteStream<S> {\n    /// Creates a `ByteStream` from any `S: Stream`.\n    fn from(stream: S) -> Self {\n        ByteStream(stream)\n    }\n}\n\nimpl<'r, S: Stream> Responder<'r, 'r> for ByteStream<S>\n    where S: Send + 'r, S::Item: AsRef<[u8]> + Send + Unpin + 'r\n{\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {\n        Response::build()\n            .header(ContentType::Binary)\n            .streamed_body(ReaderStream::from(self.0.map(std::io::Cursor::new)))\n            .ok()\n    }\n}\n\ncrate::export! {\n    /// Type and stream expression macro for [`struct@ByteStream`].\n    ///\n    /// See [`stream!`](crate::response::stream::stream) for the syntax\n    /// supported by this macro.\n    ///\n    /// See [`struct@ByteStream`] and the [module level\n    /// docs](crate::response::stream#typed-streams) for usage details.\n    macro_rules! ByteStream {\n        ($($s:tt)*) => ($crate::_typed_stream!(ByteStream, $($s)*));\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/stream/mod.rs",
    "content": "//! Potentially infinite async [`Stream`] response types.\n//!\n//! A [`Stream<Item = T>`] is the async analog of an `Iterator<Item = T>`: it\n//! generates a sequence of values asynchronously, otherwise known as an async\n//! _generator_. Types in this module allow for returning responses that are\n//! streams.\n//!\n//! [`Stream<Item = T>`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n//! [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n//!\n//! # Raw Streams\n//!\n//! Rust does not yet natively support syntax for creating arbitrary generators,\n//! and as such, for creating streams. To ameliorate this, Rocket exports\n//! [`stream!`], which retrofit generator syntax, allowing raw `impl Stream`s to\n//! be defined using `yield` and `for await` syntax:\n//!\n//! ```rust\n//! use rocket::futures::stream::Stream;\n//! use rocket::response::stream::stream;\n//!\n//! fn make_stream() -> impl Stream<Item = u8> {\n//!     stream! {\n//!         for i in 0..3 {\n//!             yield i;\n//!         }\n//!     }\n//! }\n//! ```\n//!\n//! See [`stream!`] for full usage details.\n//!\n//! # Typed Streams\n//!\n//! A raw stream is not a `Responder`, so it cannot be directly returned from a\n//! route handler. Instead, one of three _typed_ streams may be used. Each typed\n//! stream places type bounds on the `Item` of the stream, allowing for\n//! `Responder` implementation on the stream itself.\n//!\n//! Each typed stream exists both as a type and as a macro. They are:\n//!\n//!   * [`struct@ReaderStream`] ([`ReaderStream!`]) - streams of `T: AsyncRead`\n//!   * [`struct@ByteStream`] ([`ByteStream!`]) - streams of `T: AsRef<[u8]>`\n//!   * [`struct@TextStream`] ([`TextStream!`]) - streams of `T: AsRef<str>`\n//!   * [`struct@EventStream`] ([`EventStream!`]) - Server-Sent [`Event`] stream\n//!\n//! Each type implements `Responder`; each macro can be invoked to generate a\n//! typed stream, exactly like [`stream!`] above. Additionally, each macro is\n//! also a _type_ macro, expanding to a wrapped `impl Stream<Item = $T>`, where\n//! `$T` is the input to the macro.\n//!\n//! As a concrete example, the route below produces an infinite series of\n//! `\"hello\"`s, one per second:\n//!\n//! ```rust\n//! # use rocket::get;\n//! use rocket::tokio::time::{self, Duration};\n//! use rocket::response::stream::TextStream;\n//!\n//! /// Produce an infinite series of `\"hello\"`s, one per second.\n//! #[get(\"/infinite-hellos\")]\n//! fn hello() -> TextStream![&'static str] {\n//!     TextStream! {\n//!         let mut interval = time::interval(Duration::from_secs(1));\n//!         loop {\n//!             yield \"hello\";\n//!             interval.tick().await;\n//!         }\n//!     }\n//! }\n//! ```\n//!\n//! The `TextStream![&'static str]` invocation expands to:\n//!\n//! ```rust\n//! # use rocket::response::stream::TextStream;\n//! # use rocket::futures::stream::Stream;\n//! # use rocket::response::stream::stream;\n//! # fn f() ->\n//! TextStream<impl Stream<Item = &'static str>>\n//! # { TextStream::from(stream! { yield \"hi\" }) }\n//! ```\n//!\n//! While the inner `TextStream! { .. }` invocation expands to:\n//!\n//! ```rust\n//! # use rocket::response::stream::{TextStream, stream};\n//! TextStream::from(stream! { /* .. */ })\n//! # ;\n//! ```\n//!\n//! The expansions are identical for `ReaderStream` and `ByteStream`, with\n//! `TextStream` replaced with `ReaderStream` and `ByteStream`, respectively.\n//!\n//! ## Borrowing\n//!\n//! A stream can _yield_ borrowed values with no extra effort:\n//!\n//! ```rust\n//! # use rocket::get;\n//! use rocket::State;\n//! use rocket::response::stream::TextStream;\n//!\n//! /// Produce a single string borrowed from the request.\n//! #[get(\"/infinite-hellos\")]\n//! fn hello(string: &State<String>) -> TextStream![&str] {\n//!     TextStream! {\n//!         yield string.as_str();\n//!     }\n//! }\n//! ```\n//!\n//! If the stream _contains_ a borrowed value or uses one internally, Rust\n//! requires this fact be explicit with a lifetime annotation:\n//!\n//! ```rust\n//! # use rocket::get;\n//! use rocket::State;\n//! use rocket::response::stream::TextStream;\n//!\n//! #[get(\"/\")]\n//! fn borrow1(ctxt: &State<bool>) -> TextStream![&'static str + '_] {\n//!     TextStream! {\n//!         // By using `ctxt` in the stream, the borrow is moved into it. Thus,\n//!         // the stream object contains a borrow, prompting the '_ annotation.\n//!         if *ctxt.inner() {\n//!             yield \"hello\";\n//!         }\n//!     }\n//! }\n//!\n//! // Just as before but yielding an owned yield value.\n//! #[get(\"/\")]\n//! fn borrow2(ctxt: &State<bool>) -> TextStream![String + '_] {\n//!     TextStream! {\n//!         if *ctxt.inner() {\n//!             yield \"hello\".to_string();\n//!         }\n//!     }\n//! }\n//!\n//! // As before but _also_ return a borrowed value. Without it, Rust gives:\n//! // - lifetime `'r` is missing in item created through this procedural macro\n//! #[get(\"/\")]\n//! fn borrow3<'r>(ctxt: &'r State<bool>, s: &'r State<String>) -> TextStream![&'r str + 'r] {\n//!     TextStream! {\n//!         if *ctxt.inner() {\n//!             yield s.as_str();\n//!         }\n//!     }\n//! }\n//! ```\n//!\n//! # Graceful Shutdown\n//!\n//! Infinite responders, like the one defined in `hello` above, will prolong\n//! shutdown initiated via [`Shutdown::notify()`](crate::Shutdown::notify()) for\n//! the defined grace period. After the grace period has elapsed, Rocket will\n//! abruptly terminate the responder.\n//!\n//! To avoid abrupt termination, graceful shutdown can be detected via the\n//! [`Shutdown`](crate::Shutdown) future, allowing the infinite responder to\n//! gracefully shut itself down. The following example modifies the previous\n//! `hello` with shutdown detection:\n//!\n//! ```rust\n//! # use rocket::get;\n//! use rocket::Shutdown;\n//! use rocket::response::stream::TextStream;\n//! use rocket::tokio::select;\n//! use rocket::tokio::time::{self, Duration};\n//!\n//! /// Produce an infinite series of `\"hello\"`s, 1/second, until shutdown.\n//! #[get(\"/infinite-hellos\")]\n//! fn hello(mut shutdown: Shutdown) -> TextStream![&'static str] {\n//!     TextStream! {\n//!         let mut interval = time::interval(Duration::from_secs(1));\n//!         loop {\n//!             select! {\n//!                 _ = interval.tick() => yield \"hello\",\n//!                 _ = &mut shutdown => {\n//!                     yield \"goodbye\";\n//!                     break;\n//!                 }\n//!             };\n//!         }\n//!     }\n//! }\n//! ```\n\nmod reader;\nmod bytes;\nmod text;\nmod one;\nmod sse;\nmod raw_sse;\n\npub(crate) use self::raw_sse::*;\n\npub use self::one::One;\npub use self::text::TextStream;\npub use self::bytes::ByteStream;\npub use self::reader::ReaderStream;\npub use self::sse::{Event, EventStream};\n\ncrate::export! {\n    /// Retrofitted support for [`Stream`]s with `yield`, `for await` syntax.\n    ///\n    /// [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n    ///\n    /// This macro takes any series of statements and expands them into an\n    /// expression of type `impl Stream<Item = T>`, a stream that `yield`s\n    /// elements of type `T`. It supports any Rust statement syntax with the\n    /// following extensions:\n    ///\n    ///   * `yield expr`\n    ///\n    ///      Yields the result of evaluating `expr` to the caller (the stream\n    ///      consumer). `expr` must be of type `T`.\n    ///\n    ///   * `for await x in stream { .. }`\n    ///\n    ///      `await`s the next element in `stream`, binds it to `x`, and\n    ///      executes the block with the binding. `stream` must implement\n    ///      `Stream<Item = T>`; the type of `x` is `T`.\n    ///\n    ///   * `?` short-circuits stream termination on `Err`\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use rocket::response::stream::stream;\n    /// use rocket::futures::stream::Stream;\n    ///\n    /// fn f(stream: impl Stream<Item = u8>) -> impl Stream<Item = String> {\n    ///     stream! {\n    ///         for s in &[\"hi\", \"there\"]{\n    ///             yield s.to_string();\n    ///         }\n    ///\n    ///         for await n in stream {\n    ///             yield format!(\"n: {}\", n);\n    ///         }\n    ///     }\n    /// }\n    ///\n    /// # rocket::async_test(async {\n    /// use rocket::futures::stream::{self, StreamExt};\n    ///\n    /// let stream = f(stream::iter(vec![3, 7, 11]));\n    /// let strings: Vec<_> = stream.collect().await;\n    /// assert_eq!(strings, [\"hi\", \"there\", \"n: 3\", \"n: 7\", \"n: 11\"]);\n    /// # });\n    /// ```\n    ///\n    /// Using `?` on an `Err` short-circuits stream termination:\n    ///\n    /// ```rust\n    /// use std::io;\n    ///\n    /// use rocket::response::stream::stream;\n    /// use rocket::futures::stream::Stream;\n    ///\n    /// fn g<S>(stream: S) -> impl Stream<Item = io::Result<u8>>\n    ///     where S: Stream<Item = io::Result<&'static str>>\n    /// {\n    ///     stream! {\n    ///         for await s in stream {\n    ///             let num = s?.parse();\n    ///             let num = num.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;\n    ///             yield Ok(num);\n    ///         }\n    ///     }\n    /// }\n    ///\n    /// # rocket::async_test(async {\n    /// use rocket::futures::stream::{self, StreamExt};\n    ///\n    /// let e = io::Error::last_os_error();\n    /// let stream = g(stream::iter(vec![Ok(\"3\"), Ok(\"four\"), Err(e), Ok(\"2\")]));\n    /// let results: Vec<_> = stream.collect().await;\n    /// assert!(matches!(results.as_slice(), &[Ok(3), Err(_)]));\n    /// # });\n    /// ```\n    macro_rules! stream {\n        ($($t:tt)*) => ($crate::async_stream::stream!($($t)*));\n    }\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! _typed_stream {\n    ($S:ident, $($t:tt)*) => (\n        $crate::__typed_stream! {\n            $crate::response::stream::$S,\n            $crate::response::stream::stream,\n            $crate::futures::stream::Stream,\n            $($t)*\n        }\n    )\n}\n"
  },
  {
    "path": "core/lib/src/response/stream/one.rs",
    "content": "use std::pin::Pin;\nuse std::task::{Context, Poll};\n\nuse futures::stream::Stream;\n\n/// A stream that yields exactly one value.\n///\n/// A `ReaderStream` which wraps this type and yields one `AsyncRead` is\n/// returned by [`ReaderStream::one()`]. A `One` can also be constructed via\n/// [`One::from()`].\n///\n/// [`ReaderStream::one()`]: crate::response::stream::ReaderStream::one()\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::response::stream::One;\n/// use rocket::futures::stream::StreamExt;\n///\n/// # rocket::async_test(async {\n/// let mut stream = One::from(\"hello!\");\n/// let values: Vec<_> = stream.collect().await;\n/// assert_eq!(values, [\"hello!\"]);\n/// # });\n/// ```\npub struct One<T: Unpin>(Option<T>);\n\n/// Returns a `One` stream that will yield `value` exactly once.\n///\n/// # Example\n///\n/// ```rust\n/// use rocket::response::stream::One;\n///\n/// let mut stream = One::from(\"hello!\");\n/// ```\nimpl<T: Unpin> From<T> for One<T> {\n    fn from(value: T) -> Self {\n        One(Some(value))\n    }\n}\n\nimpl<T: Unpin> Stream for One<T> {\n    type Item = T;\n\n    fn poll_next(\n        mut self: Pin<&mut Self>,\n        _: &mut Context<'_>,\n    ) -> Poll<Option<Self::Item>> {\n        Poll::Ready(self.0.take())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/stream/raw_sse.rs",
    "content": "use std::borrow::Cow;\nuse std::io::{self, Cursor};\nuse std::task::{Context, Poll};\nuse std::pin::Pin;\nuse std::cmp::min;\n\nuse tokio::io::{AsyncRead, AsyncReadExt, ReadBuf, Take};\n\n/// Low-level serialization of fields in text/event-stream format.\n///\n/// Based on https://html.spec.whatwg.org/multipage/server-sent-events.html,\n/// reproduced here for quick reference. Retrieved 2021-04-17.\n///\n/// ```text\n/// stream        = [ bom ] *event\n/// event         = *( comment / field ) end-of-line\n/// comment       = colon *any-char end-of-line\n/// field         = 1*name-char [ colon [ space ] *any-char ] end-of-line\n/// end-of-line   = ( cr lf / cr / lf )\n///\n/// ; characters\n/// lf            = %x000A ; U+000A LINE FEED (LF)\n/// cr            = %x000D ; U+000D CARRIAGE RETURN (CR)\n/// space         = %x0020 ; U+0020 SPACE\n/// colon         = %x003A ; U+003A COLON (:)\n/// bom           = %xFEFF ; U+FEFF BYTE ORDER MARK\n/// name-char     = %x0000-0009 / %x000B-000C / %x000E-0039 / %x003B-10FFFF\n///                 ; a scalar value other than:\n///                 ; U+000A LINE FEED (LF), U+000D CARRIAGE RETURN (CR), or U+003A COLON (:)\n/// any-char      = %x0000-0009 / %x000B-000C / %x000E-10FFFF\n///                 ; a scalar value other than:\n///                 ; U+000A LINE FEED (LF) or U+000D CARRIAGE RETURN (CR)/\n/// ```\n///\n/// Notice that Multiple encodings are possible for the same data, especially in\n/// the choice of newline. This implementation always uses only \"\\n\" (LF).\n///\n/// Serializes (via `AsyncRead`) as a series of \"${name}:${value}\\n\" events.\n/// Either or both `name` and `value` may be empty. When the name is empty, this\n/// is a comment. Otherwise, this is a field.\n#[derive(Debug)]\npub struct RawLinedEvent {\n    name: Cursor<Cow<'static, [u8]>>,\n    value: Take<Cursor<Cow<'static, [u8]>>>,\n    state: State,\n}\n\n/// Converts a `Cow<str>` to a `Cow<[u8]>`.\nfn farm(cow: Cow<'_, str>) -> Cow<'_, [u8]> {\n    match cow {\n        Cow::Borrowed(slice) => Cow::Borrowed(slice.as_bytes()),\n        Cow::Owned(vec) => Cow::Owned(vec.into_bytes())\n    }\n}\n\n/// Farms `cow`, replacing `\\r`, `\\n`, and `:` with ` ` in the process.\n///\n/// This converts any string into a valid event `name`.\nfn farm_name(cow: Cow<'_, str>) -> Cow<'_, [u8]> {\n    let mut i = 0;\n    let mut cow = farm(cow);\n    while i < cow.len() {\n        if let Some(k) = memchr::memchr3(b'\\r', b'\\n', b':', &cow[i..]) {\n            cow.to_mut()[i + k] = b' ';\n            // This can't overflow as i + k + 1 <= len, since we found a char.\n            i += k + 1;\n        } else {\n            break;\n        }\n    }\n\n    cow\n}\n\n/// Farms `cow`, replacing `\\r` and `\\n` with ` ` in the process.\n///\n/// This converts any string into a valid event `value`.\nfn farm_value(cow: Cow<'_, str>) -> Cow<'_, [u8]> {\n    let mut i = 0;\n    let mut cow = farm(cow);\n    while i < cow.len() {\n        if let Some(k) = memchr::memchr2(b'\\r', b'\\n', &cow[i..]) {\n            cow.to_mut()[i + k] = b' ';\n            // This can't overflow as i + k + 1 <= len, since we found a char.\n            i += k + 1;\n        } else {\n            break;\n        }\n    }\n\n    cow\n}\n\nimpl RawLinedEvent {\n    /// Create a `RawLinedEvent` from a valid, prefarmed `name` and `value`.\n    fn prefarmed(name: Cow<'static, [u8]>, value: Cow<'static, [u8]>) -> RawLinedEvent {\n        let name = Cursor::new(name);\n        let mut value = Cursor::new(value).take(0);\n        advance(&mut value);\n        RawLinedEvent { name, value, state: State::Name }\n    }\n\n    /// Create a `RawLinedEvent` from potentially invalid `name` and `value`\n    /// where `value` is not allowed to be multiple lines.\n    ///\n    /// Characters `\\n`, `\\r`, and ':' in `name` and characters `\\r` \\`n` in\n    /// `value` `are replaced with a space ` `.\n    pub fn one<N, V>(name: N, value: V) -> RawLinedEvent\n        where N: Into<Cow<'static, str>>, V: Into<Cow<'static, str>>\n    {\n        RawLinedEvent::prefarmed(farm_name(name.into()), farm_value(value.into()))\n    }\n\n    /// Create a `RawLinedEvent` from potentially invalid `name` and `value`\n    /// where `value` is allowed to be multiple lines.\n    ///\n    /// Characters `\\n`, `\\r`, and ':' in `name` are replaced with a space ` `.\n    /// `value` is allowed to contain any character. New lines (`\\r\\n` or `\\n`)\n    /// and carriage returns `\\r` result in a new event being emitted.\n    pub fn many<N, V>(name: N, value: V) -> RawLinedEvent\n        where N: Into<Cow<'static, str>>, V: Into<Cow<'static, str>>\n    {\n        RawLinedEvent::prefarmed(farm_name(name.into()), farm(value.into()))\n    }\n\n    /// Create a `RawLinedEvent` from known value `value`. The value is emitted\n    /// directly with _no_ name and suffixed with a `\\n`.\n    pub fn raw<V: Into<Cow<'static, str>>>(value: V) -> RawLinedEvent {\n        let value = value.into();\n        let len = value.len();\n        RawLinedEvent {\n            name: Cursor::new(Cow::Borrowed(&[])),\n            value: Cursor::new(farm(value)).take(len as u64),\n            state: State::Value\n        }\n    }\n}\n\n/// The `AsyncRead`er state.\n#[derive(Debug, PartialEq, Copy, Clone)]\nenum State {\n    Name,\n    Colon,\n    Value,\n    NewLine,\n    Done\n}\n\n/// Find the next new-line (`\\n` or `\\r`) character in `buf` beginning at the\n/// current cursor position and sets the limit to be at that position.\nfn advance<T: AsRef<[u8]> + Unpin>(buf: &mut Take<Cursor<T>>) {\n    // Technically, the position need not be <= len, so we right it.\n    let pos = min(buf.get_ref().get_ref().as_ref().len() as u64, buf.get_ref().position());\n    let inner = buf.get_ref().get_ref().as_ref();\n    let next = memchr::memchr2(b'\\n', b'\\r', &inner[(pos as usize)..])\n        .map(|i| pos + i as u64)\n        .unwrap_or_else(|| inner.len() as u64);\n\n    let limit = next - pos;\n    buf.set_limit(limit);\n}\n\n/// If the cursor in `buf` is currently at an `\\r`, `\\r\\n` or `\\n`, sets the\n/// cursor position to be _after_ the characters.\nfn skip<T: AsRef<[u8]> + Unpin>(buf: &mut Take<Cursor<T>>) {\n    let pos = min(buf.get_ref().get_ref().as_ref().len() as u64, buf.get_ref().position());\n    match buf.get_ref().get_ref().as_ref().get(pos as usize) {\n        // This cannot overflow as clearly `buf.len() >= pos + 1`.\n        Some(b'\\n') => buf.get_mut().set_position(pos + 1),\n        Some(b'\\r') => {\n            let next = (pos as usize).saturating_add(1);\n            if buf.get_ref().get_ref().as_ref().get(next) == Some(&b'\\n') {\n                // This cannot overflow as clearly `buf.len() >= pos + 2`.\n                buf.get_mut().set_position(pos + 2);\n            } else {\n                // This cannot overflow as clearly `buf.len() >= pos + 1`.\n                buf.get_mut().set_position(pos + 1);\n            }\n        }\n        _ => (),\n    }\n}\n\nmacro_rules! dbg_assert_ready {\n    ($e:expr) => ({\n        let poll = $e;\n        debug_assert!(poll.is_ready());\n        ::futures::ready!(poll)\n    })\n}\n\n// NOTE: The correctness of this implementation depends on the types of `name`\n// and `value` having `AsyncRead` implementations that always return `Ready`.\n// Otherwise, we may return `Pending` after having written data to `buf` which\n// violates the contract. This can happen because even after a successful\n// partial or full read of `name`, we loop back to a `ready!(name.poll())` if\n// `buf` was not completely filled. So, we return `Pending` if that poll does.\nimpl AsyncRead for RawLinedEvent {\n    fn poll_read(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        use bytes::Buf;\n\n        loop {\n            if buf.remaining() == 0 {\n                return Poll::Ready(Ok(()));\n            }\n\n            match self.state {\n                State::Name => {\n                    dbg_assert_ready!(Pin::new(&mut self.name).poll_read(cx, buf))?;\n                    if !self.name.has_remaining() {\n                        self.name.set_position(0);\n                        self.state = State::Colon;\n                    }\n                }\n                State::Colon => {\n                    // Note that we've checked `buf.remaining() != 0`.\n                    buf.put_slice(&[b':']);\n                    self.state = State::Value;\n                }\n                State::Value => {\n                    dbg_assert_ready!(Pin::new(&mut self.value).poll_read(cx, buf))?;\n                    if self.value.limit() == 0 {\n                        self.state = State::NewLine;\n                    }\n                }\n                State::NewLine => {\n                    // Note that we've checked `buf.remaining() != 0`.\n                    buf.put_slice(&[b'\\n']);\n                    if self.value.get_ref().has_remaining() {\n                        skip(&mut self.value);\n                        advance(&mut self.value);\n                        self.state = State::Name;\n                    } else {\n                        self.state = State::Done;\n                    }\n                }\n                State::Done => return Poll::Ready(Ok(()))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/stream/reader.rs",
    "content": "use std::{fmt, io};\nuse std::task::{Context, Poll};\nuse std::pin::Pin;\n\nuse futures::stream::Stream;\nuse tokio::io::{AsyncRead, ReadBuf};\nuse pin_project_lite::pin_project;\n\nuse crate::request::Request;\nuse crate::response::{self, Response, Responder};\nuse crate::response::stream::One;\n\npin_project! {\n    /// An async reader that reads from a stream of async readers.\n    ///\n    /// A `ReaderStream` can be constructed from any [`Stream`] of items of type\n    /// `T` where `T: AsyncRead`, or from a single `AsyncRead` type using\n    /// [`ReaderStream::one()`]. The `AsyncRead` implementation of\n    /// `ReaderStream` progresses the stream forward, returning the contents of\n    /// the inner readers. Thus, a `ReaderStream` can be thought of as a\n    /// _flattening_ of async readers.\n    ///\n    /// `ReaderStream` is designed to be used as a building-block for\n    /// stream-based responders by acting as the `streamed_body` of a\n    /// `Response`, though it may also be used as a responder itself.\n    ///\n    /// [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n    ///\n    /// ```rust\n    /// use std::io::Cursor;\n    ///\n    /// use rocket::{Request, Response};\n    /// use rocket::futures::stream::{Stream, StreamExt};\n    /// use rocket::response::{self, Responder, stream::ReaderStream};\n    /// use rocket::http::ContentType;\n    ///\n    /// struct MyStream<S>(S);\n    ///\n    /// impl<'r, S: Stream<Item = String>> Responder<'r, 'r> for MyStream<S>\n    ///     where S: Send + 'r\n    /// {\n    ///     fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {\n    ///         Response::build()\n    ///             .header(ContentType::Text)\n    ///             .streamed_body(ReaderStream::from(self.0.map(Cursor::new)))\n    ///             .ok()\n    ///     }\n    /// }\n    /// ```\n    ///\n    /// # Responder\n    ///\n    /// `ReaderStream` is a (potentially infinite) responder. No `Content-Type`\n    /// is set. The body is [unsized](crate::response::Body#unsized), and values\n    /// are sent as soon as they are yielded by the internal stream.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use rocket::response::stream::ReaderStream;\n    /// use rocket::futures::stream::{repeat, StreamExt};\n    /// use rocket::tokio::time::{self, Duration};\n    /// use rocket::tokio::fs::File;\n    ///\n    /// // Stream the contents of `safe/path` followed by `another/safe/path`.\n    /// #[get(\"/reader/stream\")]\n    /// fn stream() -> ReaderStream![File] {\n    ///     ReaderStream! {\n    ///         let paths = &[\"safe/path\", \"another/safe/path\"];\n    ///         for path in paths {\n    ///             if let Ok(file) = File::open(path).await {\n    ///                 yield file;\n    ///             }\n    ///         }\n    ///     }\n    /// }\n    ///\n    /// // Stream the contents of the file `safe/path`. This is identical to\n    /// // returning `File` directly; Rocket responders stream and never buffer.\n    /// #[get(\"/reader/stream/one\")]\n    /// async fn stream_one() -> std::io::Result<ReaderStream![File]> {\n    ///     let file = File::open(\"safe/path\").await?;\n    ///     Ok(ReaderStream::one(file))\n    /// }\n    /// ```\n    ///\n    /// The syntax of [`ReaderStream!`] as an expression is identical to that of\n    /// [`stream!`](crate::response::stream::stream).\n    pub struct ReaderStream<S: Stream> {\n        #[pin]\n        stream: S,\n        #[pin]\n        state: State<S::Item>,\n    }\n}\n\npin_project! {\n    #[project = StateProjection]\n    #[derive(Debug)]\n    enum State<R> {\n        Pending,\n        Reading { #[pin] reader: R },\n        Done,\n    }\n}\n\nimpl<R: Unpin> ReaderStream<One<R>> {\n    /// Create a `ReaderStream` that yields exactly one reader, streaming the\n    /// contents of the reader itself.\n    ///\n    /// # Example\n    ///\n    /// Stream the bytes from a remote TCP connection:\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use std::io;\n    /// use std::net::SocketAddr;\n    ///\n    /// use rocket::tokio::net::TcpStream;\n    /// use rocket::response::stream::ReaderStream;\n    ///\n    /// #[get(\"/stream\")]\n    /// async fn stream() -> io::Result<ReaderStream![TcpStream]> {\n    ///     let addr = SocketAddr::from(([127, 0, 0, 1], 9999));\n    ///     let stream = TcpStream::connect(addr).await?;\n    ///     Ok(ReaderStream::one(stream))\n    /// }\n    /// ```\n    pub fn one(reader: R) -> Self {\n        ReaderStream::from(One::from(reader))\n    }\n}\n\nimpl<S: Stream> From<S> for ReaderStream<S> {\n    fn from(stream: S) -> Self {\n        ReaderStream { stream, state: State::Pending }\n    }\n}\n\nimpl<'r, S: Stream> Responder<'r, 'r> for ReaderStream<S>\n    where S: Send + 'r, S::Item: AsyncRead + Send,\n{\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {\n        Response::build()\n            .streamed_body(self)\n            .ok()\n    }\n}\n\nimpl<S: Stream> AsyncRead for ReaderStream<S>\n    where S::Item: AsyncRead + Send\n{\n    fn poll_read(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>\n    ) -> Poll<io::Result<()>> {\n        let mut me = self.project();\n        loop {\n            match me.state.as_mut().project() {\n                StateProjection::Pending => match me.stream.as_mut().poll_next(cx) {\n                    Poll::Pending => return Poll::Pending,\n                    Poll::Ready(None) => me.state.set(State::Done),\n                    Poll::Ready(Some(reader)) => me.state.set(State::Reading { reader }),\n                },\n                StateProjection::Reading { reader } => {\n                    let init = buf.filled().len();\n                    match reader.poll_read(cx, buf) {\n                        Poll::Ready(Ok(())) if buf.filled().len() == init => {\n                            me.state.set(State::Pending);\n                        },\n                        Poll::Ready(Ok(())) => return Poll::Ready(Ok(())),\n                        Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),\n                        Poll::Pending => return Poll::Pending,\n                    }\n                },\n                StateProjection::Done => return Poll::Ready(Ok(())),\n            }\n        }\n    }\n}\n\nimpl<S: Stream + fmt::Debug> fmt::Debug for ReaderStream<S>\n    where S::Item: fmt::Debug\n{\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"ReaderStream\")\n            .field(\"stream\", &self.stream)\n            .field(\"state\", &self.state)\n            .finish()\n    }\n}\n\ncrate::export! {\n    /// Type and stream expression macro for [`struct@ReaderStream`].\n    ///\n    /// See [`stream!`](crate::response::stream::stream) for the syntax\n    /// supported by this macro.\n    ///\n    /// See [`struct@ReaderStream`] and the [module level\n    /// docs](crate::response::stream#typed-streams) for usage details.\n    macro_rules! ReaderStream {\n        ($($s:tt)*) => ($crate::_typed_stream!(ReaderStream, $($s)*));\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/stream/sse.rs",
    "content": "use std::borrow::Cow;\n\nuse tokio::io::AsyncRead;\nuse tokio::time::{interval, Duration};\nuse futures::{stream::{self, Stream}, future::Either};\nuse tokio_stream::{StreamExt, wrappers::IntervalStream};\n\nuse crate::request::Request;\nuse crate::response::{self, Response, Responder, stream::{ReaderStream, RawLinedEvent}};\nuse crate::http::ContentType;\n\n/// A Server-Sent `Event` (SSE) in a Server-Sent [`struct@EventStream`].\n///\n/// A server-sent event is either a _field_ or a _comment_. Comments can be\n/// constructed via [`Event::comment()`] while fields can be constructed via\n/// [`Event::data()`], [`Event::json()`], and [`Event::retry()`].\n///\n/// ```rust\n/// use rocket::tokio::time::Duration;\n/// use rocket::response::stream::Event;\n///\n/// // A `data` event with message \"Hello, SSE!\".\n/// let event = Event::data(\"Hello, SSE!\");\n///\n/// // The same event but with event name of `hello`.\n/// let event = Event::data(\"Hello, SSE!\").event(\"hello\");\n///\n/// // A `retry` event to set the client-side reconnection time.\n/// let event = Event::retry(Duration::from_secs(5));\n///\n/// // An event with an attached comment, event name, and ID.\n/// let event = Event::data(\"Hello, SSE!\")\n///     .with_comment(\"just a hello message\")\n///     .event(\"hello\")\n///     .id(\"1\");\n/// ```\n///\n/// We largely defer to [MDN's using server-sent events] documentation for\n/// client-side details but reproduce, in our words, relevant server-side\n/// documentation here.\n///\n/// [MDN's using server-sent events]:\n/// https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events\n///\n/// # Pitfalls\n///\n/// Server-Sent Events suffer from certain pitfalls. We encourage readers to\n/// read through [pitfalls](struct@EventStream#pitfalls) before making use of\n/// Rocket's SSE support.\n///\n/// # Comments\n///\n/// A server-sent _comment_, created via [`Event::comment()`], is an event that\n/// appears only in the raw server-sent event data stream and is inaccessible by\n/// most clients. This includes JavaScript's `EventSource`. As such, they serve\n/// little utility beyond debugging a raw data stream and keeping a connection\n/// alive. See [heartbeat](struct@EventStream#heartbeat) for information on\n/// Rocket's `EventStream` keep-alive.\n///\n/// # Fields\n///\n/// A server-sent field can be one of four kinds:\n///\n///   * `retry`\n///\n///     A `retry` event, created via [`Event::retry()`], sets the reconnection\n///     time on the client side. It is the duration the client will wait before\n///     attempting to reconnect when a connection is lost. Most applications\n///     will not need to set a `retry`, opting instead to use the\n///     implementation's default or to reconnect manually on error.\n///\n///   * `id`\n///\n///     Sets the event id to associate all subsequent fields with. This value\n///     cannot be retrieved directly via most clients, including JavaScript\n///     `EventSource`. Instead, it is sent by the implementation on reconnection\n///     via the `Last-Event-ID` header. An `id` can be attached to other fields\n///     via the [`Event::id()`] builder method.\n///\n///   * `event`\n///\n///     Sets the event name to associate the next `data` field with. In\n///     JavaScript's `EventSource`, this is the event to be listened for, which\n///     defaults to `message`. An `event` can be attached to other fields via\n///     the [`Event::event()`] builder method.\n///\n///   * `data`\n///\n///     Sends data to dispatch as an event at the client. In JavaScript's\n///     `EventSource`, this (and only this) results in an event handler for\n///     `event`, specified just prior, being triggered. A data field can be\n///     created via the [`Event::data()`] or [`Event::json()`] constructors.\n///\n/// # Implementation Notes\n///\n/// A constructed `Event` _always_ emits its fields in the following order:\n///\n///   1. `comment`\n///   2. `retry`\n///   3. `id`\n///   4. `event`\n///   5. `data`\n///\n/// The `event` and `id` fields _cannot_ contain new lines or carriage returns.\n/// Rocket's default implementation automatically converts new lines and\n/// carriage returns in `event` and `id` fields to spaces.\n///\n/// The `data` and `comment` fields _cannot_ contain carriage returns. Rocket\n/// converts the unencoded sequence `\\r\\n` and the isolated `\\r` into a\n/// protocol-level `\\n`, that is, in such a way that they are interpreted as\n/// `\\n` at the client. For example, the raw message `foo\\r\\nbar\\rbaz` is\n/// received as `foo\\nbar\\nbaz` at the client-side. Encoded sequences, such as\n/// those emitted by [`Event::json()`], have no such restrictions.\n#[derive(Clone, Eq, PartialEq, Hash, Debug)]\npub struct Event {\n    comment: Option<Cow<'static, str>>,\n    retry: Option<Duration>,\n    id: Option<Cow<'static, str>>,\n    event: Option<Cow<'static, str>>,\n    data: Option<Cow<'static, str>>,\n}\n\nimpl Event {\n    // We hide this since we never want to construct an `Event` with nothing.\n    fn new() -> Self {\n        Event { comment: None, retry: None, id: None, event: None, data: None, }\n    }\n\n    /// Creates a new `Event` with an empty data field.\n    ///\n    /// This is exactly equivalent to `Event::data(\"\")`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    ///\n    /// let event = Event::empty();\n    /// ```\n    pub fn empty() -> Self {\n        Event::data(\"\")\n    }\n\n    /// Creates a new `Event` with a data field of `data` serialized as JSON.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::serde::Serialize;\n    /// use rocket::response::stream::Event;\n    ///\n    /// #[derive(Serialize)]\n    /// #[serde(crate = \"rocket::serde\")]\n    /// struct MyData<'r> {\n    ///     string: &'r str,\n    ///     number: usize,\n    /// }\n    ///\n    /// let data = MyData { string: \"hello!\", number: 10 };\n    /// let event = Event::json(&data);\n    /// ```\n    #[cfg(feature = \"json\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"json\")))]\n    pub fn json<T: serde::Serialize>(data: &T) -> Self {\n        let string = serde_json::to_string(data).unwrap_or_default();\n        Self::data(string)\n    }\n\n    /// Creates a new `Event` with a data field containing the raw `data`.\n    ///\n    /// # Raw SSE is Lossy\n    ///\n    /// Unencoded carriage returns cannot be expressed in the protocol. Thus,\n    /// any carriage returns in `data` will not appear at the client-side.\n    /// Instead, the sequence `\\r\\n` and the isolated `\\r` will each appear as\n    /// `\\n` at the client-side. For example, the message `foo\\r\\nbar\\rbaz` is\n    /// received as `foo\\nbar\\nbaz` at the client-side.\n    ///\n    /// See [pitfalls](struct@EventStream#pitfalls) for more details.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    ///\n    /// // A `data` event with message \"Hello, SSE!\".\n    /// let event = Event::data(\"Hello, SSE!\");\n    /// ```\n    pub fn data<T: Into<Cow<'static, str>>>(data: T) -> Self {\n        Self { data: Some(data.into()), ..Event::new() }\n    }\n\n    /// Creates a new comment `Event`.\n    ///\n    /// As with [`Event::data()`], unencoded carriage returns cannot be\n    /// expressed in the protocol. Thus, any carriage returns in `data` will\n    /// not appear at the client-side. For comments, this is generally not a\n    /// concern as comments are discarded by client-side libraries.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    ///\n    /// let event = Event::comment(\"bet you'll never see me!\");\n    /// ```\n    pub fn comment<T: Into<Cow<'static, str>>>(data: T) -> Self {\n        Self { comment: Some(data.into()), ..Event::new() }\n    }\n\n    /// Creates a new retry `Event`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    /// use rocket::tokio::time::Duration;\n    ///\n    /// let event = Event::retry(Duration::from_millis(250));\n    /// ```\n    pub fn retry(period: Duration) -> Self {\n        Self { retry: Some(period), ..Event::new() }\n    }\n\n    /// Sets the value of the 'event' (event type) field.\n    ///\n    /// Event names may not contain new lines `\\n` or carriage returns `\\r`. If\n    /// `event` _does_ contain new lines or carriage returns, they are replaced\n    /// with spaces (` `) before being sent to the client.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    ///\n    /// // The event name is \"start\".\n    /// let event = Event::data(\"hi\").event(\"start\");\n    ///\n    /// // The event name is \"then end\", with `\\n` replaced with ` `.\n    /// let event = Event::data(\"bye\").event(\"then\\nend\");\n    /// ```\n    pub fn event<T: Into<Cow<'static, str>>>(mut self, event: T) -> Self {\n        self.event = Some(event.into());\n        self\n    }\n\n    /// Sets the value of the 'id' (last event ID) field.\n    ///\n    /// Event IDs may not contain new lines `\\n` or carriage returns `\\r`. If\n    /// `id` _does_ contain new lines or carriage returns, they are replaced\n    /// with spaces (` `) before being sent to the client.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    ///\n    /// // The event ID is \"start\".\n    /// let event = Event::data(\"hi\").id(\"start\");\n    ///\n    /// // The event ID is \"then end\", with `\\n` replaced with ` `.\n    /// let event = Event::data(\"bye\").id(\"then\\nend\");\n    /// ```\n    /// Sets the value of the 'id' field. It may not contain newlines.\n    pub fn id<T: Into<Cow<'static, str>>>(mut self, id: T) -> Self {\n        self.id = Some(id.into());\n        self\n    }\n\n    /// Sets or replaces the value of the `data` field.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    ///\n    /// // The data \"hello\" will be sent.\n    /// let event = Event::data(\"hi\").with_data(\"hello\");\n    ///\n    /// // The two below are equivalent.\n    /// let event = Event::comment(\"bye\").with_data(\"goodbye\");\n    /// let event = Event::data(\"goodbye\").with_comment(\"bye\");\n    /// ```\n    pub fn with_data<T: Into<Cow<'static, str>>>(mut self, data: T) -> Self {\n        self.data = Some(data.into());\n        self\n    }\n\n    /// Sets or replaces the value of the `comment` field.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    ///\n    /// // The comment \"🚀\" will be sent.\n    /// let event = Event::comment(\"Rocket is great!\").with_comment(\"🚀\");\n    ///\n    /// // The two below are equivalent.\n    /// let event = Event::comment(\"bye\").with_data(\"goodbye\");\n    /// let event = Event::data(\"goodbye\").with_comment(\"bye\");\n    /// ```\n    pub fn with_comment<T: Into<Cow<'static, str>>>(mut self, data: T) -> Self {\n        self.comment = Some(data.into());\n        self\n    }\n\n    /// Sets or replaces the value of the `retry` field.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::Event;\n    /// use rocket::tokio::time::Duration;\n    ///\n    /// // The reconnection will be set to 10 seconds.\n    /// let event = Event::retry(Duration::from_millis(500))\n    ///     .with_retry(Duration::from_secs(10));\n    ///\n    /// // The two below are equivalent.\n    /// let event = Event::comment(\"bye\").with_retry(Duration::from_millis(500));\n    /// let event = Event::retry(Duration::from_millis(500)).with_comment(\"bye\");\n    /// ```\n    pub fn with_retry(mut self, period: Duration) -> Self {\n        self.retry = Some(period);\n        self\n    }\n\n    fn into_stream(self) -> impl Stream<Item = RawLinedEvent> {\n        let events = [\n            self.comment.map(|v| RawLinedEvent::many(\"\", v)),\n            self.retry.map(|r| RawLinedEvent::one(\"retry\", format!(\"{}\", r.as_millis()))),\n            self.id.map(|v| RawLinedEvent::one(\"id\", v)),\n            self.event.map(|v| RawLinedEvent::one(\"event\", v)),\n            self.data.map(|v| RawLinedEvent::many(\"data\", v)),\n            Some(RawLinedEvent::raw(\"\")),\n        ];\n\n        stream::iter(events).filter_map(|x| x)\n    }\n}\n\n/// A potentially infinite stream of Server-Sent [`Event`]s (SSE).\n///\n/// An `EventStream` can be constructed from any [`Stream`] of items of type\n/// `Event`. The stream can be constructed directly via [`EventStream::from()`]\n/// or through generator syntax via [`EventStream!`].\n///\n/// [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n///\n/// # Responder\n///\n/// `EventStream` is a (potentially infinite) responder. The response\n/// `Content-Type` is set to [`EventStream`](const@ContentType::EventStream).\n/// The body is [unsized](crate::response::Body#unsized), and values are sent as\n/// soon as they are yielded by the internal iterator.\n///\n/// ## Heartbeat\n///\n/// A heartbeat comment is injected into the internal stream and sent at a fixed\n/// interval. The comment is discarded by clients and serves only to keep the\n/// connection alive; it does not interfere with application data. The interval\n/// defaults to 30 seconds but can be adjusted with\n/// [`EventStream::heartbeat()`].\n///\n/// # Examples\n///\n/// Use [`EventStream!`] to yield an infinite series of \"ping\" SSE messages to\n/// the client, one per second:\n///\n/// ```rust\n/// # use rocket::*;\n/// use rocket::response::stream::{Event, EventStream};\n/// use rocket::tokio::time::{self, Duration};\n///\n/// #[get(\"/events\")]\n/// fn stream() -> EventStream![] {\n///     EventStream! {\n///         let mut interval = time::interval(Duration::from_secs(1));\n///         loop {\n///             yield Event::data(\"ping\");\n///             interval.tick().await;\n///         }\n///     }\n/// }\n/// ```\n///\n/// Yield 9 events: 3 triplets of `retry`, `data`, and `comment` events:\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket::response::stream::{Event, EventStream};\n/// use rocket::tokio::time::Duration;\n///\n/// #[get(\"/events\")]\n/// fn events() -> EventStream![] {\n///     EventStream! {\n///         for i in 0..3 {\n///             yield Event::retry(Duration::from_secs(10));\n///             yield Event::data(format!(\"{}\", i)).id(\"cat\").event(\"bar\");\n///             yield Event::comment(\"silly boy\");\n///         }\n///     }\n/// }\n/// ```\n///\n/// The syntax of `EventStream!` as an expression is identical to that of\n/// [`stream!`](crate::response::stream::stream). For how to gracefully\n/// terminate an otherwise infinite stream, see [graceful\n/// shutdown](crate::response::stream#graceful-shutdown).\n///\n/// # Borrowing\n///\n/// If an `EventStream` contains a borrow, the extended type syntax\n/// `EventStream![Event + '_]` must be used:\n///\n/// ```rust\n/// # use rocket::get;\n/// use rocket::State;\n/// use rocket::response::stream::{Event, EventStream};\n///\n/// #[get(\"/events\")]\n/// fn events(ctxt: &State<bool>) -> EventStream![Event + '_] {\n///     EventStream! {\n///         // By using `ctxt` in the stream, the borrow is moved into it. Thus,\n///         // the stream object contains a borrow, prompting the '_ annotation.\n///         if *ctxt.inner() {\n///             yield Event::data(\"hi\");\n///         }\n///     }\n/// }\n/// ```\n///\n/// See [`stream#borrowing`](crate::response::stream#borrowing) for further\n/// details on borrowing in streams.\n///\n/// # Pitfalls\n///\n/// Server-Sent Events are a rather simple mechanism, though there are some\n/// pitfalls to be aware of.\n///\n///  * **Buffering**\n///\n///    Protocol restrictions complicate implementing an API that does not\n///    buffer. As such, if you are sending _lots_ of data, consider sending the\n///    data via multiple data fields (with events to signal start and end).\n///    Alternatively, send _one_ event which instructs the client to fetch the\n///    data from another endpoint which in-turn streams the data.\n///\n///  * **Raw SSE requires UTF-8 data**\n///\n///    Only UTF-8 data can be sent via SSE. If you need to send arbitrary bytes,\n///    consider encoding it, for instance, as JSON using [`Event::json()`].\n///    Alternatively, as described before, use SSE as a notifier which alerts\n///    the client to fetch the data from elsewhere.\n///\n///  * **Raw SSE is Lossy**\n///\n///    Data sent via SSE cannot contain new lines `\\n` or carriage returns `\\r`\n///    due to interference with the line protocol.\n///\n///    The protocol allows expressing new lines as multiple messages, however,\n///    and Rocket automatically transforms a message of `foo\\nbar` into two\n///    messages, `foo` and `bar`, so that they are reconstructed (automatically)\n///    as `foo\\nbar` on the client-side. For messages that only contain new\n///    lines `\\n`, the conversion is lossless.\n///\n///    However, the protocol has no mechanism for expressing carriage returns\n///    and thus it is not possible to send unencoded carriage returns via SSE.\n///    Rocket handles carriage returns like it handles new lines: it splits the\n///    data into multiple messages. Thus, a sequence of `\\r\\n` becomes `\\n` at\n///    the client side. A single `\\r` that is not part of an `\\r\\n` sequence\n///    also becomes `\\n` at the client side. As a result, the message\n///    `foo\\r\\nbar\\rbaz` is read as `foo\\nbar\\nbaz` at the client-side.\n///\n///    To send messages losslessly, they must be encoded first, for instance, by\n///    using [`Event::json()`].\n///\n///  * **Clients reconnect ad-infinitum**\n///\n///    The [SSE standard] stipulates: _\"Clients will reconnect if the connection\n///    is closed; a client can be told to stop reconnecting using the HTTP 204\n///    No Content response code.\"_ As a result, clients will typically reconnect\n///    exhaustively until either they choose to disconnect or they receive a\n///    `204 No Content` response.\n///\n///    [SSE standard]: https://html.spec.whatwg.org/multipage/server-sent-events.html\npub struct EventStream<S> {\n    stream: S,\n    heartbeat: Option<Duration>,\n}\n\nimpl<S: Stream<Item = Event>> EventStream<S> {\n    /// Sets a \"ping\" interval for this `EventStream` to avoid connection\n    /// timeouts when no data is being transferred. The default `interval` is 30\n    /// seconds.\n    ///\n    /// The ping is implemented by sending an empty comment to the client every\n    /// `interval` seconds.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::get;\n    /// use rocket::response::stream::{Event, EventStream};\n    /// use rocket::tokio::time::Duration;\n    ///\n    /// #[get(\"/events\")]\n    /// fn events() -> EventStream![] {\n    ///     // Remove the default heartbeat.\n    ///     # let event_stream = rocket::futures::stream::pending();\n    ///     EventStream::from(event_stream).heartbeat(None);\n    ///\n    ///     // Set the heartbeat interval to 15 seconds.\n    ///     # let event_stream = rocket::futures::stream::pending();\n    ///     EventStream::from(event_stream).heartbeat(Duration::from_secs(15));\n    ///\n    ///     // Do the same but for a generated `EventStream`:\n    ///     let stream = EventStream! {\n    ///         yield Event::data(\"hello\");\n    ///     };\n    ///\n    ///     stream.heartbeat(Duration::from_secs(15))\n    /// }\n    /// ```\n    pub fn heartbeat<H: Into<Option<Duration>>>(mut self, heartbeat: H) -> Self {\n        self.heartbeat = heartbeat.into();\n        self\n    }\n\n    fn heartbeat_stream(&self) -> impl Stream<Item = RawLinedEvent> {\n        self.heartbeat\n            .map(|beat| IntervalStream::new(interval(beat)))\n            .map(|stream| stream.map(|_| RawLinedEvent::raw(\":\")))\n            .map_or_else(|| Either::Right(stream::empty()), Either::Left)\n    }\n\n    fn into_stream(self) -> impl Stream<Item = RawLinedEvent> {\n        use futures::StreamExt;\n\n        let heartbeats = self.heartbeat_stream();\n        let events = StreamExt::map(self.stream, |e| e.into_stream()).flatten();\n        crate::util::join(events, heartbeats)\n    }\n\n    fn into_reader(self) -> impl AsyncRead {\n        ReaderStream::from(self.into_stream())\n    }\n}\n\nimpl<S: Stream<Item = Event>> From<S> for EventStream<S> {\n    /// Creates an `EventStream` from a [`Stream`] of [`Event`]s.\n    ///\n    /// Use `EventStream::from()` to construct an `EventStream` from an already\n    /// existing stream. Otherwise, prefer to use [`EventStream!`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::response::stream::{Event, EventStream};\n    /// use rocket::futures::stream;\n    ///\n    /// let raw = stream::iter(vec![Event::data(\"a\"), Event::data(\"b\")]);\n    /// let stream = EventStream::from(raw);\n    /// ```\n    fn from(stream: S) -> Self {\n        EventStream { stream, heartbeat: Some(Duration::from_secs(30)), }\n    }\n}\n\nimpl<'r, S: Stream<Item = Event> + Send + 'r> Responder<'r, 'r> for EventStream<S> {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {\n        Response::build()\n            .header(ContentType::EventStream)\n            .raw_header(\"Cache-Control\", \"no-cache\")\n            .raw_header(\"Expires\", \"0\")\n            .streamed_body(self.into_reader())\n            .ok()\n    }\n}\n\ncrate::export! {\n    /// Type and stream expression macro for [`struct@EventStream`].\n    ///\n    /// See [`stream!`](crate::response::stream::stream) for the syntax\n    /// supported by this macro. In addition to that syntax, this macro can also\n    /// be called with no arguments, `EventStream![]`, as shorthand for\n    /// `EventStream![Event]`.\n    ///\n    /// See [`struct@EventStream`] and the [module level\n    /// docs](crate::response::stream#typed-streams) for usage details.\n    macro_rules! EventStream {\n        () => ($crate::_typed_stream!(EventStream, $crate::response::stream::Event));\n        ($($s:tt)*) => ($crate::_typed_stream!(EventStream, $($s)*));\n    }\n}\n\n#[cfg(test)]\nmod sse_tests {\n    use tokio::io::AsyncReadExt;\n    use tokio::time::{self, Duration};\n    use futures::stream::Stream;\n    use crate::response::stream::{stream, Event, EventStream, ReaderStream};\n\n    impl Event {\n        fn into_string(self) -> String {\n            crate::async_test(async move {\n                let mut string = String::new();\n                let mut reader = ReaderStream::from(self.into_stream());\n                reader.read_to_string(&mut string).await.expect(\"event -> string\");\n                string\n            })\n        }\n    }\n\n    impl<S: Stream<Item = Event>> EventStream<S> {\n        fn into_string(self) -> String {\n            use std::pin::pin;\n\n            crate::async_test(async move {\n                let mut string = String::new();\n                let mut reader = pin!(self.into_reader());\n                reader.read_to_string(&mut string).await.expect(\"event stream -> string\");\n                string\n            })\n        }\n    }\n\n    #[test]\n    fn test_event_data() {\n        let event = Event::data(\"a\\nb\");\n        assert_eq!(event.into_string(), \"data:a\\ndata:b\\n\\n\");\n\n        let event = Event::data(\"a\\n\");\n        assert_eq!(event.into_string(), \"data:a\\ndata:\\n\\n\");\n\n        let event = Event::data(\"cats make me happy!\");\n        assert_eq!(event.into_string(), \"data:cats make me happy!\\n\\n\");\n\n        let event = Event::data(\"in the\\njungle\\nthe mighty\\njungle\");\n        assert_eq!(event.into_string(),\n            \"data:in the\\ndata:jungle\\ndata:the mighty\\ndata:jungle\\n\\n\");\n\n        let event = Event::data(\"in the\\njungle\\r\\nthe mighty\\rjungle\");\n        assert_eq!(event.into_string(),\n            \"data:in the\\ndata:jungle\\ndata:the mighty\\ndata:jungle\\n\\n\");\n\n        let event = Event::data(\"\\nb\\n\");\n        assert_eq!(event.into_string(), \"data:\\ndata:b\\ndata:\\n\\n\");\n\n        let event = Event::data(\"\\r\\nb\\n\");\n        assert_eq!(event.into_string(), \"data:\\ndata:b\\ndata:\\n\\n\");\n\n        let event = Event::data(\"\\r\\nb\\r\\n\");\n        assert_eq!(event.into_string(), \"data:\\ndata:b\\ndata:\\n\\n\");\n\n        let event = Event::data(\"\\n\\nb\\n\");\n        assert_eq!(event.into_string(), \"data:\\ndata:\\ndata:b\\ndata:\\n\\n\");\n\n        let event = Event::data(\"\\n\\rb\\n\");\n        assert_eq!(event.into_string(), \"data:\\ndata:\\ndata:b\\ndata:\\n\\n\");\n\n        let event = Event::data(\"\\n\\rb\\r\");\n        assert_eq!(event.into_string(), \"data:\\ndata:\\ndata:b\\ndata:\\n\\n\");\n\n        let event = Event::comment(\"\\n\\rb\\r\");\n        assert_eq!(event.into_string(), \":\\n:\\n:b\\n:\\n\\n\");\n\n        let event = Event::data(\"\\n\\n\\n\");\n        assert_eq!(event.into_string(), \"data:\\ndata:\\ndata:\\ndata:\\n\\n\");\n\n        let event = Event::data(\"\\n\");\n        assert_eq!(event.into_string(), \"data:\\ndata:\\n\\n\");\n\n        let event = Event::data(\"\");\n        assert_eq!(event.into_string(), \"data:\\n\\n\");\n    }\n\n    #[test]\n    fn test_event_fields() {\n        let event = Event::data(\"foo\").id(\"moo\");\n        assert_eq!(event.into_string(), \"id:moo\\ndata:foo\\n\\n\");\n\n        let event = Event::data(\"foo\").id(\"moo\").with_retry(Duration::from_secs(45));\n        assert_eq!(event.into_string(), \"retry:45000\\nid:moo\\ndata:foo\\n\\n\");\n\n        let event = Event::data(\"foo\\nbar\").id(\"moo\").with_retry(Duration::from_secs(45));\n        assert_eq!(event.into_string(), \"retry:45000\\nid:moo\\ndata:foo\\ndata:bar\\n\\n\");\n\n        let event = Event::retry(Duration::from_secs(45));\n        assert_eq!(event.into_string(), \"retry:45000\\n\\n\");\n\n        let event = Event::comment(\"incoming data...\");\n        assert_eq!(event.into_string(), \":incoming data...\\n\\n\");\n\n        let event = Event::data(\"foo\").id(\"moo\").with_comment(\"cows, ey?\");\n        assert_eq!(event.into_string(), \":cows, ey?\\nid:moo\\ndata:foo\\n\\n\");\n\n        let event = Event::data(\"foo\\nbar\")\n            .id(\"moo\")\n            .event(\"milk\")\n            .with_retry(Duration::from_secs(3));\n\n        assert_eq!(event.into_string(), \"retry:3000\\nid:moo\\nevent:milk\\ndata:foo\\ndata:bar\\n\\n\");\n\n        let event = Event::data(\"foo\")\n            .id(\"moo\")\n            .event(\"milk\")\n            .with_comment(\"??\")\n            .with_retry(Duration::from_secs(3));\n\n        assert_eq!(event.into_string(), \":??\\nretry:3000\\nid:moo\\nevent:milk\\ndata:foo\\n\\n\");\n\n        let event = Event::data(\"foo\")\n            .id(\"moo\")\n            .event(\"milk\")\n            .with_comment(\"?\\n?\")\n            .with_retry(Duration::from_secs(3));\n\n        assert_eq!(event.into_string(), \":?\\n:?\\nretry:3000\\nid:moo\\nevent:milk\\ndata:foo\\n\\n\");\n\n        let event = Event::data(\"foo\\r\\nbar\\nbaz\")\n            .id(\"moo\")\n            .event(\"milk\")\n            .with_comment(\"?\\n?\")\n            .with_retry(Duration::from_secs(3));\n\n        assert_eq!(event.into_string(),\n            \":?\\n:?\\nretry:3000\\nid:moo\\nevent:milk\\ndata:foo\\ndata:bar\\ndata:baz\\n\\n\");\n    }\n\n    #[test]\n    fn test_bad_chars() {\n        let event = Event::data(\"foo\").id(\"dead\\nbeef\").event(\"m\\noo\");\n        assert_eq!(event.into_string(), \"id:dead beef\\nevent:m oo\\ndata:foo\\n\\n\");\n\n        let event = Event::data(\"f\\no\").id(\"d\\r\\nbe\\rf\").event(\"m\\n\\r\");\n        assert_eq!(event.into_string(), \"id:d  be f\\nevent:m  \\ndata:f\\ndata:o\\n\\n\");\n\n        let event = Event::data(\"f\\no\").id(\"\\r\\n\\n\\r\\n\\r\\r\").event(\"\\n\\rb\");\n        assert_eq!(event.into_string(), \"id:       \\nevent:  b\\ndata:f\\ndata:o\\n\\n\");\n    }\n\n    #[test]\n    fn test_event_stream() {\n        use futures::stream::iter;\n\n        let stream = EventStream::from(iter(vec![Event::data(\"foo\")]));\n        assert_eq!(stream.into_string().replace(\":\\n\\n\", \"\"), \"data:foo\\n\\n\");\n\n        let stream = EventStream::from(iter(vec![Event::data(\"a\"), Event::data(\"b\")]));\n        assert_eq!(stream.into_string().replace(\":\\n\\n\", \"\"), \"data:a\\n\\ndata:b\\n\\n\");\n\n        let stream = EventStream::from(iter(vec![\n                Event::data(\"a\\nb\"),\n                Event::data(\"b\"),\n                Event::data(\"c\\n\\nd\"),\n                Event::data(\"e\"),\n        ]));\n\n        assert_eq!(stream.into_string().replace(\":\\n\\n\", \"\"),\n            \"data:a\\ndata:b\\n\\ndata:b\\n\\ndata:c\\ndata:\\ndata:d\\n\\ndata:e\\n\\n\");\n    }\n\n    #[test]\n    fn test_heartbeat() {\n        use futures::future::ready;\n        use futures::stream::{once, iter, StreamExt};\n\n        const HEARTBEAT: &str = \":\\n\";\n\n        // Set a heartbeat interval of 250ms. Send nothing for 600ms. We should\n        // get 2 or 3 heartbeats, the latter if one is sent eagerly. Maybe 4.\n        let raw = stream!(time::sleep(Duration::from_millis(600)).await;)\n            .map(|_| unreachable!());\n\n        let string = EventStream::from(raw)\n            .heartbeat(Duration::from_millis(250))\n            .into_string();\n\n        let heartbeats = string.matches(HEARTBEAT).count();\n        assert!(heartbeats >= 2 && heartbeats <= 4, \"got {} beat(s)\", heartbeats);\n\n        let stream = EventStream! {\n            time::sleep(Duration::from_millis(250)).await;\n            yield Event::data(\"foo\");\n            time::sleep(Duration::from_millis(250)).await;\n            yield Event::data(\"bar\");\n        };\n\n        // We expect: foo\\n\\n [heartbeat] bar\\n\\n [maybe heartbeat].\n        let string = stream.heartbeat(Duration::from_millis(350)).into_string();\n        let heartbeats = string.matches(HEARTBEAT).count();\n        assert!(heartbeats >= 1 && heartbeats <= 3, \"got {} beat(s)\", heartbeats);\n        assert!(string.contains(\"data:foo\\n\\n\"), \"string = {:?}\", string);\n        assert!(string.contains(\"data:bar\\n\\n\"), \"string = {:?}\", string);\n\n        // We shouldn't send a heartbeat if a message is immediately available.\n        let stream = EventStream::from(once(ready(Event::data(\"hello\"))));\n        let string = stream.heartbeat(Duration::from_secs(1)).into_string();\n        assert_eq!(string, \"data:hello\\n\\n\", \"string = {:?}\", string);\n\n        // It's okay if we do it with two, though.\n        let stream = EventStream::from(iter(vec![Event::data(\"a\"), Event::data(\"b\")]));\n        let string = stream.heartbeat(Duration::from_secs(1)).into_string();\n        let heartbeats = string.matches(HEARTBEAT).count();\n        assert!(heartbeats <= 1);\n        assert!(string.contains(\"data:a\\n\\n\"), \"string = {:?}\", string);\n        assert!(string.contains(\"data:b\\n\\n\"), \"string = {:?}\", string);\n    }\n}\n"
  },
  {
    "path": "core/lib/src/response/stream/text.rs",
    "content": "use futures::stream::{Stream, StreamExt};\n\nuse crate::request::Request;\nuse crate::response::{self, Response, Responder};\nuse crate::http::ContentType;\nuse crate::response::stream::ReaderStream;\n\n/// A potentially infinite stream of text: `T: AsRef<str>`.\n///\n/// A `TextStream` can be constructed from any [`Stream`] of items of type `T`\n/// where `T: AsRef<str>`. This includes `&str`, `String`, `Cow<str>`,\n/// `&RawStr`, and more. The stream can be constructed directly, via\n/// `TextStream(..)` or [`TextStream::from()`], or through generator syntax via\n/// [`TextStream!`].\n///\n/// [`Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n///\n/// # Responder\n///\n/// `TextStream` is a (potentially infinite) responder. The response\n/// `Content-Type` is set to [`Text`](ContentType::Text). The body is\n/// [unsized](crate::response::Body#unsized), and values are sent as soon as\n/// they are yielded by the internal iterator.\n///\n/// # Example\n///\n/// Use [`TextStream!`] to yield 10 strings, one every second, of the form `\"n:\n/// $k\"` for `$k` from `0` to `10` exclusive:\n///\n/// ```rust\n/// # use rocket::*;\n/// use rocket::response::stream::TextStream;\n/// use rocket::futures::stream::{repeat, StreamExt};\n/// use rocket::tokio::time::{self, Duration};\n///\n/// #[get(\"/text\")]\n/// fn text() -> TextStream![&'static str] {\n///     TextStream(repeat(\"hi\"))\n/// }\n///\n/// #[get(\"/text/stream\")]\n/// fn stream() -> TextStream![String] {\n///     TextStream! {\n///         let mut interval = time::interval(Duration::from_secs(1));\n///         for i in 0..10 {\n///             yield format!(\"n: {}\", i);\n///             interval.tick().await;\n///         }\n///     }\n/// }\n/// ```\n///\n/// The syntax of [`TextStream!`] as an expression is identical to that of\n/// [`stream!`](crate::response::stream::stream).\n#[derive(Debug, Clone)]\npub struct TextStream<S>(pub S);\n\nimpl<S> From<S> for TextStream<S> {\n    /// Creates a `TextStream` from any `S: Stream`.\n    fn from(stream: S) -> Self {\n        TextStream(stream)\n    }\n}\n\nimpl<'r, S: Stream> Responder<'r, 'r> for TextStream<S>\n    where S: Send + 'r, S::Item: AsRef<str> + Send + Unpin + 'r\n{\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> {\n        struct ByteStr<T>(T);\n\n        impl<T: AsRef<str>> AsRef<[u8]> for ByteStr<T> {\n            fn as_ref(&self) -> &[u8] {\n                self.0.as_ref().as_bytes()\n            }\n        }\n\n        let inner = self.0.map(ByteStr).map(std::io::Cursor::new);\n        Response::build()\n            .header(ContentType::Text)\n            .streamed_body(ReaderStream::from(inner))\n            .ok()\n    }\n}\n\ncrate::export! {\n    /// Type and stream expression macro for [`struct@TextStream`].\n    ///\n    /// See [`stream!`](crate::response::stream::stream) for the syntax\n    /// supported by this macro.\n    ///\n    /// See [`struct@TextStream`] and the [module level\n    /// docs](crate::response::stream#typed-streams) for usage details.\n    macro_rules! TextStream {\n        ($($s:tt)*) => ($crate::_typed_stream!(TextStream, $($s)*));\n    }\n}\n"
  },
  {
    "path": "core/lib/src/rocket.rs",
    "content": "use std::fmt;\nuse std::ops::{Deref, DerefMut};\nuse std::sync::Arc;\nuse std::time::Duration;\nuse std::any::Any;\nuse std::future::Future;\nuse std::panic::Location;\n\nuse either::Either;\nuse figment::{Figment, Provider};\nuse futures::TryFutureExt;\n\nuse crate::shutdown::{Stages, Shutdown};\nuse crate::trace::{Trace, TraceAll};\nuse crate::{sentinel, shield::Shield, Catcher, Config, Route};\nuse crate::listener::{Bind, DefaultListener, Endpoint, Listener};\nuse crate::router::Router;\nuse crate::fairing::{Fairing, Fairings};\nuse crate::phase::{Phase, Build, Building, Ignite, Igniting, Orbit, Orbiting};\nuse crate::phase::{Stateful, StateRef, StateRefMut, State};\nuse crate::http::uri::Origin;\nuse crate::http::ext::IntoOwned;\nuse crate::error::{Error, ErrorKind};\n\n/// The application server itself.\n///\n/// # Phases\n///\n/// A `Rocket` instance represents a web server and its state. It progresses\n/// through three statically-enforced phases: build, ignite, orbit.\n///\n/// * **Build**: _application and server configuration_\n///\n///   This phase enables:\n///\n///     * setting configuration options\n///     * mounting/registering routes/catchers\n///     * managing state\n///     * attaching fairings\n///\n///   This is the _only_ phase in which an instance can be modified. To finalize\n///   changes, an instance is ignited via [`Rocket::ignite()`], progressing it\n///   into the _ignite_ phase, or directly launched into orbit with\n///   [`Rocket::launch()`] which progress the instance through ignite into\n///   orbit.\n///\n/// * **Ignite**: _verification and finalization of configuration_\n///\n///   An instance in the [`Ignite`] phase is in its final configuration,\n///   available via [`Rocket::config()`]. Barring user-supplied interior\n///   mutation, application state is guaranteed to remain unchanged beyond this\n///   point. An instance in the ignite phase can be launched into orbit to serve\n///   requests via [`Rocket::launch()`].\n///\n/// * **Orbit**: _a running web server_\n///\n///   An instance in the [`Orbit`] phase represents a _running_ application,\n///   actively serving requests.\n///\n/// # Launching\n///\n/// To launch a `Rocket` application, the suggested approach is to return an\n/// instance of `Rocket<Build>` from a function named `rocket` marked with the\n/// [`#[launch]`](crate::launch) attribute:\n///\n///   ```rust,no_run\n///   # use rocket::launch;\n///   #[launch]\n///   fn rocket() -> _ {\n///       rocket::build()\n///   }\n///   ```\n///\n/// This generates a `main` function with an `async` runtime that runs the\n/// returned `Rocket` instance.\n///\n/// * **Manual Launching**\n///\n///   To launch an instance of `Rocket`, it _must_ progress through all three\n///   phases. To progress into the ignite or launch phases, a tokio `async`\n///   runtime is required. The [`#[main]`](crate::main) attribute initializes a\n///   Rocket-specific tokio runtime and runs the attributed `async fn` inside of\n///   it:\n///\n///   ```rust,no_run\n///   #[rocket::main]\n///   async fn main() -> Result<(), rocket::Error> {\n///       let _rocket = rocket::build()\n///           .ignite().await?\n///           .launch().await?;\n///\n///       Ok(())\n///   }\n///   ```\n///\n///   Note that [`Rocket::launch()`] automatically progresses an instance of\n///   `Rocket` from any phase into orbit:\n///\n///   ```rust,no_run\n///   #[rocket::main]\n///   async fn main() -> Result<(), rocket::Error> {\n///       let _rocket = rocket::build().launch().await?;\n///       Ok(())\n///   }\n///   ```\n///\n///   For extreme and rare cases in which [`#[main]`](crate::main) imposes\n///   obstinate restrictions, use [`rocket::execute()`](crate::execute()) to\n///   execute Rocket's `launch()` future.\n///\n/// * **Automatic Launching**\n///\n///   Manually progressing an instance of Rocket though its phases is only\n///   necessary when either an instance's finalized state is to be inspected (in\n///   the _ignite_ phase) or the instance is expected to deorbit due to\n///   [`Rocket::shutdown()`]. In the more common case when neither is required,\n///   the [`#[launch]`](crate::launch) attribute can be used. When applied to a\n///   function that returns a `Rocket<Build>`, it automatically initializes an\n///   `async` runtime and launches the function's returned instance:\n///\n///   ```rust,no_run\n///   # use rocket::launch;\n///   use rocket::{Rocket, Build};\n///\n///   #[launch]\n///   fn rocket() -> Rocket<Build> {\n///       rocket::build()\n///   }\n///   ```\n///\n///   To avoid needing to import _any_ items in the common case, the `launch`\n///   attribute will infer a return type written as `_` as `Rocket<Build>`:\n///\n///   ```rust,no_run\n///   # use rocket::launch;\n///   #[launch]\n///   fn rocket() -> _ {\n///       rocket::build()\n///   }\n///   ```\npub struct Rocket<P: Phase>(pub(crate) P::State);\n\nimpl Rocket<Build> {\n    /// Create a new `Rocket` application using the default configuration\n    /// provider, [`Config::figment()`].\n    ///\n    /// This method is typically called through the\n    /// [`rocket::build()`](crate::build) alias.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use rocket::launch;\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    /// }\n    /// ```\n    #[must_use]\n    #[inline(always)]\n    pub fn build() -> Self {\n        Rocket::custom(Config::figment())\n    }\n\n    /// Creates a new `Rocket` application using the supplied configuration\n    /// provider.\n    ///\n    /// This method is typically called through the\n    /// [`rocket::custom()`](crate::custom()) alias.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::launch;\n    /// use rocket::figment::{Figment, providers::{Toml, Env, Format}};\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     let figment = Figment::from(rocket::Config::default())\n    ///         .merge(Toml::file(\"MyApp.toml\").nested())\n    ///         .merge(Env::prefixed(\"MY_APP_\").global());\n    ///\n    ///     rocket::custom(figment)\n    /// }\n    /// ```\n    #[must_use]\n    pub fn custom<T: Provider>(provider: T) -> Self {\n        Rocket::<Build>(Building::default())\n            .reconfigure(provider)\n            .attach(Shield::default())\n    }\n\n    /// Overrides the current configuration provider with `provider`.\n    ///\n    /// The default provider, or a provider previously set with\n    /// [`Rocket::custom()`] or [`Rocket::reconfigure()`], is overridden by\n    /// `provider`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::config::{Config, Ident};\n    /// # use std::net::Ipv4Addr;\n    /// # use std::path::{Path, PathBuf};\n    /// # type Result = std::result::Result<(), rocket::Error>;\n    ///\n    /// let config = Config {\n    ///     ident: Ident::try_new(\"MyServer\").expect(\"valid ident\"),\n    ///     temp_dir: \"/tmp/config-example\".into(),\n    ///     ..Config::debug_default()\n    /// };\n    ///\n    /// # let _: Result = rocket::async_test(async move {\n    /// let rocket = rocket::custom(&config).ignite().await?;\n    /// assert_eq!(rocket.config().ident.as_str(), Some(\"MyServer\"));\n    /// assert_eq!(rocket.config().temp_dir.relative(), Path::new(\"/tmp/config-example\"));\n    ///\n    /// // Create a new figment which modifies _some_ keys the existing figment:\n    /// let figment = rocket.figment().clone()\n    ///     .merge((Config::IDENT, \"Example\"));\n    ///\n    /// let rocket = rocket::custom(&config)\n    ///     .reconfigure(figment)\n    ///     .ignite().await?;\n    ///\n    /// assert_eq!(rocket.config().ident.as_str(), Some(\"Example\"));\n    /// assert_eq!(rocket.config().temp_dir.relative(), Path::new(\"/tmp/config-example\"));\n    /// # Ok(())\n    /// # });\n    /// ```\n    #[must_use]\n    pub fn reconfigure<T: Provider>(mut self, provider: T) -> Self {\n        // We initialize the logger here so that logging from fairings and so on\n        // are visible; we use the final config to set a max log-level in ignite\n        self.figment = Figment::from(provider);\n        crate::trace::init(Config::try_from(&self.figment).ok().as_ref());\n        span_trace!(\"reconfigure\" => self.figment().trace_trace());\n\n        self\n    }\n\n    #[track_caller]\n    fn load<'a, B, T, F, M>(mut self, kind: &str, base: B, items: Vec<T>, m: M, f: F) -> Self\n        where B: TryInto<Origin<'a>> + Clone + fmt::Display,\n              B::Error: fmt::Display,\n              M: Fn(&Origin<'a>, T) -> T,\n              F: Fn(&mut Self, T),\n              T: Clone + Trace,\n    {\n        let mut base = match base.clone().try_into() {\n            Ok(origin) => origin.into_owned(),\n            Err(e) => {\n                error!(%base, location = %Location::caller(), \"invalid {kind} base uri: {e}\");\n                panic!(\"aborting due to {} base error\", kind);\n            }\n        };\n\n        if base.query().is_some() {\n            warn!(%base, location = %Location::caller(), \"query in {kind} base is ignored\");\n            base.clear_query();\n        }\n\n        for unmounted_item in items {\n            f(&mut self, m(&base, unmounted_item.clone()))\n        }\n\n        self\n    }\n\n    /// Mounts all of the `routes` at the given `base` mount point.\n    ///\n    /// A route _mounted_ at `base` has an effective URI of `base/route`, where\n    /// `route` is the route URI. In other words, `base` is added as a prefix to\n    /// the route's URI. The URI resulting from joining the `base` URI and the\n    /// route URI is called the route's _effective URI_, as this is the URI used\n    /// for request matching during routing.\n    ///\n    /// A `base` URI is not allowed to have a query part. If a `base` _does_\n    /// have a query part, it is ignored when producing the effective URI.\n    ///\n    /// A `base` may have an optional trailing slash. A route with a URI path of\n    /// `/` (and any optional query) mounted at a `base` has an effective URI\n    /// equal to the `base` (plus any optional query). That is, if the base has\n    /// a trailing slash, the effective URI path has a trailing slash, and\n    /// otherwise it does not. Routes with URI paths other than `/` are not\n    /// effected by trailing slashes in their corresponding mount point.\n    ///\n    /// As concrete examples, consider the following table:\n    ///\n    /// | mount point | route URI | effective URI |\n    /// |-------------|-----------|---------------|\n    /// | `/`         | `/foo`    | `/foo`        |\n    /// | `/`         | `/foo/`   | `/foo/`       |\n    /// | `/foo`      | `/`       | `/foo`        |\n    /// | `/foo`      | `/?bar`   | `/foo?bar`    |\n    /// | `/foo`      | `/bar`    | `/foo/bar`    |\n    /// | `/foo`      | `/bar/`   | `/foo/bar/`   |\n    /// | `/foo/`     | `/`       | `/foo/`       |\n    /// | `/foo/`     | `/bar`    | `/foo/bar`    |\n    /// | `/foo/`     | `/?bar`   | `/foo/?bar`   |\n    /// | `/foo/bar`  | `/`       | `/foo/bar`    |\n    /// | `/foo/bar/` | `/`       | `/foo/bar/`   |\n    /// | `/foo/?bar` | `/`       | `/foo/`       |\n    /// | `/foo/?bar` | `/baz`    | `/foo/baz`    |\n    /// | `/foo/?bar` | `/baz/`   | `/foo/baz/`   |\n    ///\n    /// # Panics\n    ///\n    /// Panics if either:\n    ///\n    ///   * the `base` mount point is not a valid origin URI without dynamic\n    ///     parameters\n    ///\n    ///   * any route URI is not a valid origin URI. (**Note:** _This kind of\n    ///     panic is guaranteed not to occur if the routes were generated using\n    ///     Rocket's code generation._)\n    ///\n    /// # Examples\n    ///\n    /// Use the `routes!` macro to mount routes created using the code\n    /// generation facilities. Requests to both `/world` and `/hello/world` URI\n    /// will be dispatched to the `hi` route.\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// #\n    /// #[get(\"/world\")]\n    /// fn hi() -> &'static str {\n    ///     \"Hello!\"\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .mount(\"/\", routes![hi])\n    ///         .mount(\"/hello\", routes![hi])\n    /// }\n    /// ```\n    ///\n    /// Manually create a route named `hi` at path `\"/world\"` mounted at base\n    /// `\"/hello\"`. Requests to the `/hello/world` URI will be dispatched to the\n    /// `hi` route.\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::{Request, Route, Data, route};\n    /// use rocket::http::Method;\n    ///\n    /// fn hi<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {\n    ///     route::Outcome::from(req, \"Hello!\").pin()\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     let hi_route = Route::new(Method::Get, \"/world\", hi);\n    ///     rocket::build().mount(\"/hello\", vec![hi_route])\n    /// }\n    /// ```\n    #[must_use]\n    #[track_caller]\n    pub fn mount<'a, B, R>(self, base: B, routes: R) -> Self\n        where B: TryInto<Origin<'a>> + Clone + fmt::Display,\n              B::Error: fmt::Display,\n              R: Into<Vec<Route>>\n    {\n        self.load(\"route\", base, routes.into(),\n            |base, route| route.rebase(base.clone()),\n            |r, route| r.0.routes.push(route))\n    }\n\n    /// Registers all of the catchers in the supplied vector, scoped to `base`.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `base` is not a valid static path: a valid origin URI without\n    /// dynamic parameters.\n    ///\n    /// # Examples\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::Request;\n    ///\n    /// #[catch(500)]\n    /// fn internal_error() -> &'static str {\n    ///     \"Whoops! Looks like we messed up.\"\n    /// }\n    ///\n    /// #[catch(404)]\n    /// fn not_found(req: &Request) -> String {\n    ///     format!(\"I couldn't find '{}'. Try something else?\", req.uri())\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build().register(\"/\", catchers![internal_error, not_found])\n    /// }\n    /// ```\n    #[must_use]\n    pub fn register<'a, B, C>(self, base: B, catchers: C) -> Self\n        where B: TryInto<Origin<'a>> + Clone + fmt::Display,\n              B::Error: fmt::Display,\n              C: Into<Vec<Catcher>>\n    {\n        self.load(\"catcher\", base, catchers.into(),\n            |base, catcher| catcher.rebase(base.clone()),\n            |r, catcher| r.0.catchers.push(catcher))\n    }\n\n    /// Add `state` to the state managed by this instance of Rocket.\n    ///\n    /// This method can be called any number of times as long as each call\n    /// refers to a different `T`.\n    ///\n    /// Managed state can be retrieved by any request handler via the\n    /// [`State`](crate::State) request guard. In particular, if a value of type `T`\n    /// is managed by Rocket, adding `State<T>` to the list of arguments in a\n    /// request handler instructs Rocket to retrieve the managed value.\n    ///\n    /// # Panics\n    ///\n    /// Panics if state of type `T` is already being managed.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::State;\n    ///\n    /// struct MyInt(isize);\n    /// struct MyString(String);\n    ///\n    /// #[get(\"/int\")]\n    /// fn int(state: &State<MyInt>) -> String {\n    ///     format!(\"The stateful int is: {}\", state.0)\n    /// }\n    ///\n    /// #[get(\"/string\")]\n    /// fn string(state: &State<MyString>) -> &str {\n    ///     &state.0\n    /// }\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .manage(MyInt(10))\n    ///         .manage(MyString(\"Hello, managed state!\".to_string()))\n    ///         .mount(\"/\", routes![int, string])\n    /// }\n    /// ```\n    #[must_use]\n    pub fn manage<T>(self, state: T) -> Self\n        where T: Send + Sync + 'static\n    {\n        let type_name = std::any::type_name::<T>();\n        if !self.state.set(state) {\n            error!(\"state for type '{}' is already being managed\", type_name);\n            panic!(\"aborting due to duplicated managed state\");\n        }\n\n        self\n    }\n\n    /// Attaches a fairing to this instance of Rocket. No fairings are eagerly\n    /// executed; fairings are executed at their appropriate time.\n    ///\n    /// If the attached fairing is a [singleton] and a fairing of the same type\n    /// has already been attached, this fairing replaces it. Otherwise the\n    /// fairing gets attached without replacing any existing fairing.\n    ///\n    /// [singleton]: crate::fairing::Fairing#singletons\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::Rocket;\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .attach(AdHoc::on_liftoff(\"Liftoff Message\", |_| Box::pin(async {\n    ///             println!(\"We have liftoff!\");\n    ///         })))\n    /// }\n    /// ```\n    #[must_use]\n    pub fn attach<F: Fairing>(mut self, fairing: F) -> Self {\n        self.fairings.add(Box::new(fairing));\n        self\n    }\n\n    /// Returns a `Future` that transitions this instance of `Rocket` into the\n    /// _ignite_ phase.\n    ///\n    /// When `await`ed, the future runs all _ignite_ fairings in serial,\n    /// [attach](Rocket::attach()) order, and verifies that `self` represents a\n    /// valid instance of `Rocket` ready for launch. This means that:\n    ///\n    ///   * All ignite fairings succeeded.\n    ///   * A valid [`Config`] was extracted from [`Rocket::figment()`].\n    ///   * If `secrets` are enabled, the extracted `Config` contains a safe\n    ///     secret key.\n    ///   * There are no [`Route#collisions`] or [`Catcher#collisions`]\n    ///     collisions.\n    ///   * No [`Sentinel`](crate::Sentinel) triggered an abort.\n    ///\n    /// If any of these conditions fail to be met, a respective [`Error`] is\n    /// returned.\n    ///\n    /// [configured]: Rocket::figment()\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[rocket::main]\n    /// async fn main() -> Result<(), rocket::Error> {\n    ///     let rocket = rocket::build()\n    ///         # .reconfigure(rocket::Config::debug_default())\n    ///         .attach(AdHoc::on_ignite(\"Manage State\", |rocket| async move {\n    ///             rocket.manage(String::from(\"managed string\"))\n    ///         }));\n    ///\n    ///     // No fairings are run until ignition occurs.\n    ///     assert!(rocket.state::<String>().is_none());\n    ///\n    ///     let rocket = rocket.ignite().await?;\n    ///     assert_eq!(rocket.state::<String>().unwrap(), \"managed string\");\n    ///\n    ///     Ok(())\n    /// }\n    /// ```\n    pub async fn ignite(mut self) -> Result<Rocket<Ignite>, Error> {\n        self = Fairings::handle_ignite(self).await;\n        self.fairings.audit().map_err(|f| ErrorKind::FailedFairings(f.to_vec()))?;\n\n        // Extract the configuration; initialize default trace subscriber.\n        #[allow(unused_mut)]\n        let mut config = Config::try_from(&self.figment).map_err(ErrorKind::Config)?;\n        crate::trace::init(&config);\n\n        // Check for safely configured secrets.\n        #[cfg(feature = \"secrets\")]\n        if !config.secret_key.is_provided() {\n            if config.profile != Config::DEBUG_PROFILE {\n                return Err(Error::new(ErrorKind::InsecureSecretKey(config.profile.clone())));\n            }\n\n            if config.secret_key.is_zero() {\n                config.secret_key = crate::config::SecretKey::generate()\n                    .unwrap_or_else(crate::config::SecretKey::zero);\n            }\n        }\n\n        // Initialize the router; check for collisions.\n        let mut router = Router::new();\n        self.routes.clone().into_iter().for_each(|r| router.routes.push(r));\n        self.catchers.clone().into_iter().for_each(|c| router.catchers.push(c));\n        let router = router.finalize()\n            .map_err(|(r, c)| ErrorKind::Collisions { routes: r, catchers: c, })?;\n\n        // Finally, freeze managed state for faster access later.\n        self.state.freeze();\n\n        // Log everything we know: config, routes, catchers, fairings.\n        // TODO: Store/print managed state type names?\n        let fairings = self.fairings.unique_set();\n        span_info!(\"config\", profile = %self.figment().profile() => {\n            config.trace_info();\n            self.figment().trace_debug();\n        });\n\n        span_info!(\"routes\", count = self.routes.len() => self.routes().trace_all_info());\n        span_info!(\"catchers\", count = self.catchers.len() => self.catchers().trace_all_info());\n        span_info!(\"fairings\", count = fairings.len() => fairings.trace_all_info());\n\n        // Ignite the rocket.\n        let rocket: Rocket<Ignite> = Rocket(Igniting {\n            shutdown: Stages::new(),\n            figment: self.0.figment,\n            fairings: self.0.fairings,\n            state: self.0.state,\n            router, config,\n        });\n\n        // Query the sentinels, abort if requested.\n        let sentinels = rocket.routes().flat_map(|r| r.sentinels.iter());\n        sentinel::query(sentinels, &rocket).map_err(ErrorKind::SentinelAborts)?;\n\n        Ok(rocket)\n    }\n}\n\nimpl Rocket<Ignite> {\n    /// Returns the finalized, active configuration. This is guaranteed to\n    /// remain stable through ignition and into orbit.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// #[rocket::main]\n    /// async fn main() -> Result<(), rocket::Error> {\n    ///     let rocket = rocket::build().ignite().await?;\n    ///     let config = rocket.config();\n    ///     Ok(())\n    /// }\n    /// ```\n    pub fn config(&self) -> &Config {\n        &self.config\n    }\n\n    /// Returns a handle which can be used to trigger a shutdown and detect a\n    /// triggered shutdown.\n    ///\n    /// A completed graceful shutdown resolves the future returned by\n    /// [`Rocket::launch()`]. If [`Shutdown::notify()`] is called _before_ an\n    /// instance is launched, it will be immediately shutdown after liftoff. See\n    /// [`Shutdown`] and [`ShutdownConfig`](crate::config::ShutdownConfig) for\n    /// details on graceful shutdown.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # use std::time::Duration;\n    /// use rocket::tokio::{self, time};\n    ///\n    /// #[rocket::main]\n    /// async fn main() -> Result<(), rocket::Error> {\n    ///     let rocket = rocket::build().ignite().await?;\n    ///\n    ///     let shutdown = rocket.shutdown();\n    ///     tokio::spawn(async move {\n    ///         time::sleep(time::Duration::from_secs(5)).await;\n    ///         shutdown.notify();\n    ///     });\n    ///\n    ///     // The `launch()` future resolves after ~5 seconds.\n    ///     let result = rocket.launch().await;\n    ///     assert!(result.is_ok());\n    ///\n    ///     Ok(())\n    /// }\n    /// ```\n    pub fn shutdown(&self) -> Shutdown {\n        self.shutdown.start.clone()\n    }\n\n    pub(crate) fn into_orbit(self, endpoints: Vec<Endpoint>) -> Rocket<Orbit> {\n        Rocket(Orbiting {\n            endpoints,\n            router: self.0.router,\n            fairings: self.0.fairings,\n            figment: self.0.figment,\n            config: self.0.config,\n            state: self.0.state,\n            shutdown: self.0.shutdown,\n        })\n    }\n\n    async fn _local_launch(self, endpoint: Endpoint) -> Rocket<Orbit> {\n        let rocket = self.into_orbit(vec![endpoint]);\n        Rocket::liftoff(&rocket).await;\n        rocket\n    }\n\n    async fn _launch<L: Listener + 'static>(self, listener: L) -> Result<Rocket<Ignite>, Error> {\n        let rocket = self.listen_and_serve(listener, |rocket| async move {\n            let rocket = Arc::new(rocket);\n\n            rocket.shutdown.spawn_listener(&rocket.config.shutdown);\n            if let Err(e) = tokio::spawn(Rocket::liftoff(rocket.clone())).await {\n                let rocket = rocket.try_wait_shutdown().await.map(Box::new);\n                return Err(ErrorKind::Liftoff(rocket, e).into());\n            }\n\n            Ok(rocket)\n        }).await?;\n\n        Ok(rocket.try_wait_shutdown().await.map_err(ErrorKind::Shutdown)?)\n    }\n}\n\nimpl Rocket<Orbit> {\n    /// Rocket wraps all connections in a `CancellableIo` struct, an internal\n    /// structure that gracefully closes I/O when it receives a signal. That\n    /// signal is the `shutdown` future. When the future resolves,\n    /// `CancellableIo` begins to terminate in grace, mercy, and finally force\n    /// close phases. Since all connections are wrapped in `CancellableIo`, this\n    /// eventually ends all I/O.\n    ///\n    /// At that point, unless a user spawned an infinite, stand-alone task that\n    /// isn't monitoring `Shutdown`, all tasks should resolve. This means that\n    /// all instances of the shared `Arc<Rocket>` are dropped and we can return\n    /// the owned instance of `Rocket`.\n    ///\n    /// Unfortunately, the Hyper `server` future resolves as soon as it has\n    /// finished processing requests without respect for ongoing responses. That\n    /// is, `server` resolves even when there are running tasks that are\n    /// generating a response. So, `server` resolving implies little to nothing\n    /// about the state of connections. As a result, we depend on the timing of\n    /// grace + mercy + some buffer to determine when all connections should be\n    /// closed, thus all tasks should be complete, thus all references to\n    /// `Arc<Rocket>` should be dropped and we can get back a unique reference.\n    async fn try_wait_shutdown(self: Arc<Self>) -> Result<Rocket<Ignite>, Arc<Self>> {\n        info!(\"Shutting down. Waiting for shutdown fairings and pending I/O...\");\n        tokio::spawn({\n            let rocket = self.clone();\n            async move { rocket.fairings.handle_shutdown(&rocket).await }\n        });\n\n        let config = &self.config.shutdown;\n        let wait = Duration::from_micros(250);\n        for period in [wait, config.grace(), wait, config.mercy(), wait * 4] {\n            if Arc::strong_count(&self) == 1 { break }\n            tokio::time::sleep(period).await;\n        }\n\n        match Arc::try_unwrap(self) {\n            Ok(rocket) => {\n                info!(\"Graceful shutdown completed successfully.\");\n                Ok(rocket.deorbit())\n            }\n            Err(rocket) => {\n                warn!(\"Shutdown failed: outstanding background I/O.\");\n                Err(rocket)\n            }\n        }\n    }\n\n    pub(crate) fn deorbit(self) -> Rocket<Ignite> {\n        Rocket(Igniting {\n            router: self.0.router,\n            fairings: self.0.fairings,\n            figment: self.0.figment,\n            config: self.0.config,\n            state: self.0.state,\n            shutdown: self.0.shutdown,\n        })\n    }\n\n    pub(crate) async fn liftoff<R: Deref<Target = Self>>(rocket: R) {\n        let rocket = rocket.deref();\n        rocket.fairings.handle_liftoff(rocket).await;\n\n        if !crate::running_within_rocket_async_rt().await {\n            warn!(\n                \"Rocket is executing inside of a custom runtime.\\n\\\n                Rocket's runtime is enabled via `#[rocket::main]` or `#[launch]`\\n\\\n                Forced shutdown is disabled. Runtime settings may be suboptimal.\"\n            );\n        }\n\n        tracing::info!(name: \"liftoff\", endpoint = %rocket.endpoints[0]);\n    }\n\n    /// Returns the finalized, active configuration. This is guaranteed to\n    /// remain stable after [`Rocket::ignite()`], through ignition and into\n    /// orbit.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .attach(AdHoc::on_liftoff(\"Config\", |rocket| Box::pin(async move {\n    ///             println!(\"Rocket launch config: {:?}\", rocket.config());\n    ///         })))\n    /// }\n    /// ```\n    pub fn config(&self) -> &Config {\n        &self.config\n    }\n\n    pub fn endpoints(&self) -> impl Iterator<Item = &Endpoint> {\n        self.endpoints.iter()\n    }\n\n    /// Returns a handle which can be used to trigger a shutdown and detect a\n    /// triggered shutdown.\n    ///\n    /// A completed graceful shutdown resolves the future returned by\n    /// [`Rocket::launch()`]. See [`Shutdown`] and\n    /// [`ShutdownConfig`](crate::config::ShutdownConfig) for details on\n    /// graceful shutdown.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::tokio::{self, time};\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[launch]\n    /// fn rocket() -> _ {\n    ///     rocket::build()\n    ///         .attach(AdHoc::on_liftoff(\"Shutdown\", |rocket| Box::pin(async move {\n    ///             let shutdown = rocket.shutdown();\n    ///             tokio::spawn(async move {\n    ///                 time::sleep(time::Duration::from_secs(5)).await;\n    ///                 shutdown.notify();\n    ///             });\n    ///         })))\n    /// }\n    /// ```\n    pub fn shutdown(&self) -> Shutdown {\n        self.shutdown.start.clone()\n    }\n}\n\nimpl<P: Phase> Rocket<P> {\n    /// Returns an iterator over all of the routes mounted on this instance of\n    /// Rocket. The order is unspecified.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use rocket::Rocket;\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[get(\"/hello\")]\n    /// fn hello() -> &'static str {\n    ///     \"Hello, world!\"\n    /// }\n    ///\n    /// let rocket = rocket::build()\n    ///     .mount(\"/\", routes![hello])\n    ///     .mount(\"/hi\", routes![hello]);\n    ///\n    /// assert_eq!(rocket.routes().count(), 2);\n    /// assert!(rocket.routes().any(|r| r.uri == \"/hello\"));\n    /// assert!(rocket.routes().any(|r| r.uri == \"/hi/hello\"));\n    /// ```\n    pub fn routes(&self) -> impl Iterator<Item = &Route> {\n        match self.0.as_ref() {\n            StateRef::Build(p) => Either::Left(p.routes.iter()),\n            StateRef::Ignite(p) => Either::Right(p.router.routes.iter()),\n            StateRef::Orbit(p) => Either::Right(p.router.routes.iter()),\n        }\n    }\n\n    /// Returns an iterator over all of the catchers registered on this instance\n    /// of Rocket. The order is unspecified.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use rocket::Rocket;\n    /// use rocket::fairing::AdHoc;\n    ///\n    /// #[catch(404)] fn not_found() -> &'static str { \"Nothing here, sorry!\" }\n    /// #[catch(500)] fn just_500() -> &'static str { \"Whoops!?\" }\n    /// #[catch(default)] fn some_default() -> &'static str { \"Everything else.\" }\n    ///\n    /// let rocket = rocket::build()\n    ///     .register(\"/foo\", catchers![not_found])\n    ///     .register(\"/\", catchers![just_500, some_default]);\n    ///\n    /// assert_eq!(rocket.catchers().count(), 3);\n    /// assert!(rocket.catchers().any(|c| c.code == Some(404) && c.base() == \"/foo\"));\n    /// assert!(rocket.catchers().any(|c| c.code == Some(500) && c.base() == \"/\"));\n    /// assert!(rocket.catchers().any(|c| c.code == None && c.base() == \"/\"));\n    /// ```\n    pub fn catchers(&self) -> impl Iterator<Item = &Catcher> {\n        match self.0.as_ref() {\n            StateRef::Build(p) => Either::Left(p.catchers.iter()),\n            StateRef::Ignite(p) => Either::Right(p.router.catchers.iter()),\n            StateRef::Orbit(p) => Either::Right(p.router.catchers.iter()),\n        }\n    }\n\n    /// Returns `Some` of the managed state value for the type `T` if it is\n    /// being managed by `self`. Otherwise, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// #[derive(PartialEq, Debug)]\n    /// struct MyState(&'static str);\n    ///\n    /// let rocket = rocket::build().manage(MyState(\"hello!\"));\n    /// assert_eq!(rocket.state::<MyState>().unwrap(), &MyState(\"hello!\"));\n    /// ```\n    pub fn state<T: Send + Sync + 'static>(&self) -> Option<&T> {\n        match self.0.as_ref() {\n            StateRef::Build(p) => p.state.try_get(),\n            StateRef::Ignite(p) => p.state.try_get(),\n            StateRef::Orbit(p) => p.state.try_get(),\n        }\n    }\n\n    /// Returns a reference to the first fairing of type `F` if it is attached.\n    /// Otherwise, returns `None`.\n    ///\n    /// To retrieve a _mutable_ reference to fairing `F`, use\n    /// [`Rocket::fairing_mut()`] instead.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};\n    /// # use rocket::fairing::{self, Fairing, Info, Kind};\n    /// #\n    /// # #[rocket::async_trait]\n    /// # impl Fairing for MyFairing {\n    /// #     fn info(&self) -> Info {\n    /// #       Info { name: \"\", kind: Kind::Ignite  }\n    /// #     }\n    /// # }\n    /// #\n    /// # #[rocket::async_trait]\n    /// # impl Fairing for MySingletonFairing {\n    /// #     fn info(&self) -> Info {\n    /// #       Info { name: \"\", kind: Kind::Ignite | Kind::Singleton }\n    /// #     }\n    /// # }\n    /// // A regular, non-singleton fairing.\n    /// struct MyFairing(&'static str);\n    ///\n    /// // A singleton fairing.\n    /// struct MySingletonFairing(&'static str);\n    ///\n    /// // fairing is not attached, returns `None`\n    /// let rocket = rocket::build();\n    /// assert!(rocket.fairing::<MyFairing>().is_none());\n    /// assert!(rocket.fairing::<MySingletonFairing>().is_none());\n    ///\n    /// // attach fairing, now returns `Some`\n    /// let rocket = rocket.attach(MyFairing(\"some state\"));\n    /// assert!(rocket.fairing::<MyFairing>().is_some());\n    /// assert_eq!(rocket.fairing::<MyFairing>().unwrap().0, \"some state\");\n    ///\n    /// // it returns the first fairing of a given type only\n    /// let rocket = rocket.attach(MyFairing(\"other state\"));\n    /// assert_eq!(rocket.fairing::<MyFairing>().unwrap().0, \"some state\");\n    ///\n    /// // attach fairing, now returns `Some`\n    /// let rocket = rocket.attach(MySingletonFairing(\"first\"));\n    /// assert_eq!(rocket.fairing::<MySingletonFairing>().unwrap().0, \"first\");\n    ///\n    /// // recall that new singletons replace existing attached singletons\n    /// let rocket = rocket.attach(MySingletonFairing(\"second\"));\n    /// assert_eq!(rocket.fairing::<MySingletonFairing>().unwrap().0, \"second\");\n    /// ```\n    pub fn fairing<F: Fairing>(&self) -> Option<&F> {\n        match self.0.as_ref() {\n            StateRef::Build(p) => p.fairings.filter::<F>().next(),\n            StateRef::Ignite(p) => p.fairings.filter::<F>().next(),\n            StateRef::Orbit(p) => p.fairings.filter::<F>().next(),\n        }\n    }\n\n    /// Returns an iterator over all attached fairings of type `F`, if any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};\n    /// # use rocket::fairing::{self, Fairing, Info, Kind};\n    /// #\n    /// # #[rocket::async_trait]\n    /// # impl Fairing for MyFairing {\n    /// #     fn info(&self) -> Info {\n    /// #         Info { name: \"\", kind: Kind::Ignite  }\n    /// #     }\n    /// # }\n    /// #\n    /// # #[rocket::async_trait]\n    /// # impl Fairing for MySingletonFairing {\n    /// #     fn info(&self) -> Info {\n    /// #         Info { name: \"\", kind: Kind::Ignite | Kind::Singleton }\n    /// #     }\n    /// # }\n    /// // A regular, non-singleton fairing.\n    /// struct MyFairing(&'static str);\n    ///\n    /// // A singleton fairing.\n    /// struct MySingletonFairing(&'static str);\n    ///\n    /// let rocket = rocket::build();\n    /// assert_eq!(rocket.fairings::<MyFairing>().count(), 0);\n    /// assert_eq!(rocket.fairings::<MySingletonFairing>().count(), 0);\n    ///\n    /// let rocket = rocket.attach(MyFairing(\"some state\"))\n    ///     .attach(MySingletonFairing(\"first\"))\n    ///     .attach(MySingletonFairing(\"second\"))\n    ///     .attach(MyFairing(\"other state\"))\n    ///     .attach(MySingletonFairing(\"third\"));\n    ///\n    /// let my_fairings: Vec<_> = rocket.fairings::<MyFairing>().collect();\n    /// assert_eq!(my_fairings.len(), 2);\n    /// assert_eq!(my_fairings[0].0, \"some state\");\n    /// assert_eq!(my_fairings[1].0, \"other state\");\n    ///\n    /// let my_singleton: Vec<_> = rocket.fairings::<MySingletonFairing>().collect();\n    /// assert_eq!(my_singleton.len(), 1);\n    /// assert_eq!(my_singleton[0].0, \"third\");\n    /// ```\n    pub fn fairings<F: Fairing>(&self) -> impl Iterator<Item = &F> {\n        match self.0.as_ref() {\n            StateRef::Build(p) => Either::Left(p.fairings.filter::<F>()),\n            StateRef::Ignite(p) => Either::Right(p.fairings.filter::<F>()),\n            StateRef::Orbit(p) => Either::Right(p.fairings.filter::<F>()),\n        }\n    }\n\n    /// Returns a mutable reference to the first fairing of type `F` if it is\n    /// attached. Otherwise, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};\n    /// # use rocket::fairing::{self, Fairing, Info, Kind};\n    /// #\n    /// # #[rocket::async_trait]\n    /// # impl Fairing for MyFairing {\n    /// #     fn info(&self) -> Info {\n    /// #       Info { name: \"\", kind: Kind::Ignite  }\n    /// #     }\n    /// # }\n    /// // A regular, non-singleton fairing.\n    /// struct MyFairing(&'static str);\n    ///\n    /// // fairing is not attached, returns `None`\n    /// let mut rocket = rocket::build();\n    /// assert!(rocket.fairing_mut::<MyFairing>().is_none());\n    ///\n    /// // attach fairing, now returns `Some`\n    /// let mut rocket = rocket.attach(MyFairing(\"some state\"));\n    /// assert!(rocket.fairing_mut::<MyFairing>().is_some());\n    /// assert_eq!(rocket.fairing_mut::<MyFairing>().unwrap().0, \"some state\");\n    ///\n    /// // we can modify the fairing\n    /// rocket.fairing_mut::<MyFairing>().unwrap().0 = \"other state\";\n    /// assert_eq!(rocket.fairing_mut::<MyFairing>().unwrap().0, \"other state\");\n    ///\n    /// // it returns the first fairing of a given type only\n    /// let mut rocket = rocket.attach(MyFairing(\"yet more state\"));\n    /// assert_eq!(rocket.fairing_mut::<MyFairing>().unwrap().0, \"other state\");\n    /// ```\n    pub fn fairing_mut<F: Fairing>(&mut self) -> Option<&mut F> {\n        match self.0.as_mut() {\n            StateRefMut::Build(p) => p.fairings.filter_mut::<F>().next(),\n            StateRefMut::Ignite(p) => p.fairings.filter_mut::<F>().next(),\n            StateRefMut::Orbit(p) => p.fairings.filter_mut::<F>().next(),\n        }\n    }\n\n    /// Returns an iterator of mutable references to all attached fairings of\n    /// type `F`, if any.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};\n    /// # use rocket::fairing::{self, Fairing, Info, Kind};\n    /// #\n    /// # #[rocket::async_trait]\n    /// # impl Fairing for MyFairing {\n    /// #     fn info(&self) -> Info {\n    /// #         Info { name: \"\", kind: Kind::Ignite  }\n    /// #     }\n    /// # }\n    /// // A regular, non-singleton fairing.\n    /// struct MyFairing(&'static str);\n    ///\n    /// let mut rocket = rocket::build()\n    ///     .attach(MyFairing(\"some state\"))\n    ///     .attach(MyFairing(\"other state\"))\n    ///     .attach(MyFairing(\"yet more state\"));\n    ///\n    /// let mut fairings: Vec<_> = rocket.fairings_mut::<MyFairing>().collect();\n    /// assert_eq!(fairings.len(), 3);\n    /// assert_eq!(fairings[0].0, \"some state\");\n    /// assert_eq!(fairings[1].0, \"other state\");\n    /// assert_eq!(fairings[2].0, \"yet more state\");\n    ///\n    /// // we can modify the fairings\n    /// fairings[1].0 = \"modified state\";\n    ///\n    /// let fairings: Vec<_> = rocket.fairings::<MyFairing>().collect();\n    /// assert_eq!(fairings.len(), 3);\n    /// assert_eq!(fairings[0].0, \"some state\");\n    /// assert_eq!(fairings[1].0, \"modified state\");\n    /// assert_eq!(fairings[2].0, \"yet more state\");\n    /// ```\n    pub fn fairings_mut<F: Fairing>(&mut self) -> impl Iterator<Item = &mut F> {\n        match self.0.as_mut() {\n            StateRefMut::Build(p) => Either::Left(p.fairings.filter_mut::<F>()),\n            StateRefMut::Ignite(p) => Either::Right(p.fairings.filter_mut::<F>()),\n            StateRefMut::Orbit(p) => Either::Right(p.fairings.filter_mut::<F>()),\n        }\n    }\n\n    /// Returns the figment derived from the configuration provider set for\n    /// `self`. To extract a typed config, prefer to use\n    /// [`AdHoc::config()`](crate::fairing::AdHoc::config()).\n    ///\n    /// Note; A [`Figment`] generated from the current `provider` can _always_\n    /// be retrieved via this method. However, because the provider can be\n    /// changed at any point prior to ignition, a [`Config`] can only be\n    /// retrieved in the ignite or orbit phases, or by manually extracting one\n    /// from a particular figment.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// let rocket = rocket::build();\n    /// let figment = rocket.figment();\n    /// ```\n    pub fn figment(&self) -> &Figment {\n        match self.0.as_ref() {\n            StateRef::Build(p) => &p.figment,\n            StateRef::Ignite(p) => &p.figment,\n            StateRef::Orbit(p) => &p.figment,\n        }\n    }\n\n    async fn into_ignite(self) -> Result<Rocket<Ignite>, Error> {\n        match self.0.into_state() {\n            State::Build(s) => Rocket::from(s).ignite().await,\n            State::Ignite(s) => Ok(Rocket::from(s)),\n            State::Orbit(s) => Ok(Rocket::from(s).deorbit()),\n        }\n    }\n\n    pub(crate) async fn local_launch(self, e: Endpoint) -> Result<Rocket<Orbit>, Error> {\n        Ok(self.into_ignite().await?._local_launch(e).await)\n    }\n\n    /// Returns a `Future` that transitions this instance of `Rocket` from any\n    /// phase into the _orbit_ phase. When `await`ed, the future drives the\n    /// server forward, listening for and dispatching requests to mounted routes\n    /// and catchers.\n    ///\n    /// In addition to all of the processes that occur during\n    /// [ignition](Rocket::ignite()), a successful launch results in _liftoff_\n    /// fairings being executed _after_ binding to any respective network\n    /// interfaces but before serving the first request. Liftoff fairings are\n    /// run concurrently; resolution of all fairings is `await`ed before\n    /// resuming request serving.\n    ///\n    /// The `Future` resolves as an `Err` if any of the following occur:\n    ///\n    ///   * there is an error igniting; see [`Rocket::ignite()`].\n    ///   * there is an I/O error starting the server.\n    ///   * an unrecoverable, system-level error occurs while running.\n    ///\n    /// The `Future` resolves as an `Ok` if any of the following occur:\n    ///\n    ///   * graceful shutdown via [`Shutdown::notify()`] completes.\n    ///\n    /// The returned value on `Ok(())` is previously running instance.\n    ///\n    /// The `Future` does not resolve otherwise.\n    ///\n    /// # Error\n    ///\n    /// If there is a problem starting the application or the application fails\n    /// unexpectedly while running, an [`Error`] is returned. Note that a value\n    /// of type `Error` panics if dropped without first being inspected. See the\n    /// [`Error`] documentation for more information.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// #[rocket::main]\n    /// async fn main() {\n    ///     let result = rocket::build().launch().await;\n    ///\n    ///     // this is reachable only after `Shutdown::notify()` or `Ctrl+C`.\n    ///     println!(\"Rocket: deorbit.\");\n    /// }\n    /// ```\n    pub async fn launch(self) -> Result<Rocket<Ignite>, Error> {\n        self.launch_with::<DefaultListener>().await\n    }\n\n    pub async fn launch_with<B: Bind>(self) -> Result<Rocket<Ignite>, Error> {\n        let rocket = self.into_ignite().await?;\n        let bind_endpoint = B::bind_endpoint(&rocket).ok();\n        let listener: B = B::bind(&rocket).await\n            .map_err(|e| ErrorKind::Bind(bind_endpoint, Box::new(e)))?;\n\n        let any: Box<dyn Any + Send + Sync> = Box::new(listener);\n        match any.downcast::<DefaultListener>() {\n            Ok(listener) => {\n                let listener = *listener;\n                crate::util::for_both!(listener, listener => {\n                    crate::util::for_both!(listener, listener => {\n                        rocket._launch(listener).await\n                    })\n                })\n            }\n            Err(any) => {\n                let listener = *any.downcast::<B>().unwrap();\n                rocket._launch(listener).await\n            }\n        }\n    }\n\n    pub async fn try_launch_on<L, F, E>(self, listener: F) -> Result<Rocket<Ignite>, Error>\n        where L: Listener + 'static,\n              F: Future<Output = Result<L, E>>,\n              E: std::error::Error + Send + 'static\n    {\n        let listener = listener.map_err(|e| ErrorKind::Bind(None, Box::new(e))).await?;\n        self.into_ignite().await?._launch(listener).await\n    }\n\n    pub async fn launch_on<L>(self, listener: L) -> Result<Rocket<Ignite>, Error>\n        where L: Listener + 'static,\n    {\n        self.into_ignite().await?._launch(listener).await\n    }\n}\n\n#[doc(hidden)]\nimpl<P: Phase> Deref for Rocket<P> {\n    type Target = P::State;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\n#[doc(hidden)]\nimpl<P: Phase> DerefMut for Rocket<P> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n\nimpl<P: Phase> fmt::Debug for Rocket<P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/route/handler.rs",
    "content": "use crate::{Request, Data};\nuse crate::response::{Response, Responder};\nuse crate::http::Status;\n\n/// Type alias for the return type of a [`Route`](crate::Route)'s\n/// [`Handler::handle()`].\npub type Outcome<'r> = crate::outcome::Outcome<Response<'r>, Status, (Data<'r>, Status)>;\n\n/// Type alias for the return type of a _raw_ [`Route`](crate::Route)'s\n/// [`Handler`].\npub type BoxFuture<'r, T = Outcome<'r>> = futures::future::BoxFuture<'r, T>;\n\n/// Trait implemented by [`Route`](crate::Route) request handlers.\n///\n/// In general, you will never need to implement `Handler` manually or be\n/// concerned about the `Handler` trait; Rocket's code generation handles\n/// everything for you. You only need to learn about this trait if you want to\n/// provide an external, library-based mechanism to handle requests where\n/// request handling depends on input from the user. In other words, if you want\n/// to write a plugin for Rocket that looks mostly like a static route but need\n/// user provided state to make a request handling decision, you should consider\n/// implementing a custom `Handler`.\n///\n/// ## Async Trait\n///\n/// This is an _async_ trait. Implementations must be decorated\n/// [`#[rocket::async_trait]`](crate::async_trait).\n///\n/// # Example\n///\n/// Say you'd like to write a handler that changes its functionality based on an\n/// enum value that the user provides:\n///\n/// ```rust\n/// #[derive(Copy, Clone)]\n/// enum Kind {\n///     Simple,\n///     Intermediate,\n///     Complex,\n/// }\n/// ```\n///\n/// Such a handler might be written and used as follows:\n///\n/// ```rust,no_run\n/// # #[derive(Copy, Clone)] enum Kind { Simple, Intermediate, Complex, }\n/// use rocket::{Request, Data};\n/// use rocket::route::{Handler, Route, Outcome};\n/// use rocket::http::Method;\n///\n/// #[derive(Clone)]\n/// struct CustomHandler(Kind);\n///\n/// #[rocket::async_trait]\n/// impl Handler for CustomHandler {\n///     async fn handle<'r>(&self, req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r> {\n///         match self.0 {\n///             Kind::Simple => Outcome::from(req, \"simple\"),\n///             Kind::Intermediate => Outcome::from(req, \"intermediate\"),\n///             Kind::Complex => Outcome::from(req, \"complex\"),\n///         }\n///     }\n/// }\n///\n/// impl Into<Vec<Route>> for CustomHandler {\n///     fn into(self) -> Vec<Route> {\n///         vec![Route::new(Method::Get, \"/\", self)]\n///     }\n/// }\n///\n/// #[rocket::launch]\n/// fn rocket() -> _ {\n///     rocket::build().mount(\"/\", CustomHandler(Kind::Simple))\n/// }\n/// ```\n///\n/// Note the following:\n///\n///   1. `CustomHandler` implements `Clone`. This is required so that\n///      `CustomHandler` implements `Cloneable` automatically. The `Cloneable`\n///      trait serves no other purpose but to ensure that every `Handler` can be\n///      cloned, allowing `Route`s to be cloned.\n///   2. `CustomHandler` implements `Into<Vec<Route>>`, allowing an instance to\n///      be used directly as the second parameter to `rocket.mount()`.\n///   3. Unlike static-function-based handlers, this custom handler can make use\n///      of any internal state.\n///\n/// # Alternatives\n///\n/// The previous example could have been implemented using a combination of\n/// managed state and a static route, as follows:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate rocket;\n/// #\n/// # #[derive(Copy, Clone)]\n/// # enum Kind {\n/// #     Simple,\n/// #     Intermediate,\n/// #     Complex,\n/// # }\n/// #\n/// use rocket::State;\n///\n/// #[get(\"/\")]\n/// fn custom_handler(state: &State<Kind>) -> &'static str {\n///     match state.inner() {\n///         Kind::Simple => \"simple\",\n///         Kind::Intermediate => \"intermediate\",\n///         Kind::Complex => \"complex\",\n///     }\n/// }\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build()\n///         .mount(\"/\", routes![custom_handler])\n///         .manage(Kind::Simple)\n/// }\n/// ```\n///\n/// Pros:\n///\n///   * The handler is easier to implement since Rocket's code generation\n///     ensures type-safety at all levels.\n///\n/// Cons:\n///\n///   * Only one `Kind` can be stored in managed state. As such, only one\n///     variant of the custom handler can be used.\n///   * The user must remember to manually call `rocket.manage(state)`.\n///\n/// Use this alternative when a single configuration is desired and your custom\n/// handler is private to your application. For all other cases, a custom\n/// `Handler` implementation is preferred.\n#[crate::async_trait]\npub trait Handler: Cloneable + Send + Sync + 'static {\n    /// Called by Rocket when a `Request` with its associated `Data` should be\n    /// handled by this handler.\n    ///\n    /// The variant of `Outcome` returned by the returned `Future` determines\n    /// what Rocket does next. If the return value is a `Success(Response)`, the\n    /// wrapped `Response` is used to respond to the client. If the return value\n    /// is an `Error(Status)`, the error catcher for `Status` is invoked to\n    /// generate a response. Otherwise, if the return value is `Forward(Data)`,\n    /// the next matching route is attempted. If there are no other matching\n    /// routes, the `404` error catcher is invoked.\n    async fn handle<'r>(&self, request: &'r Request<'_>, data: Data<'r>) -> Outcome<'r>;\n}\n\n// We write this manually to avoid double-boxing.\nimpl<F: Clone + Sync + Send + 'static> Handler for F\n    where for<'x> F: Fn(&'x Request<'_>, Data<'x>) -> BoxFuture<'x>,\n{\n    #[inline(always)]\n    fn handle<'r, 'life0, 'life1, 'async_trait>(\n        &'life0 self,\n        req: &'r Request<'life1>,\n        data: Data<'r>,\n    ) -> BoxFuture<'r>\n        where 'r: 'async_trait,\n              'life0: 'async_trait,\n              'life1: 'async_trait,\n              Self: 'async_trait,\n    {\n        self(req, data)\n    }\n}\n\nimpl<'r, 'o: 'r> Outcome<'o> {\n    /// Return the `Outcome` of response to `req` from `responder`.\n    ///\n    /// If the responder returns `Ok`, an outcome of `Success` is returned with\n    /// the response. If the responder returns `Err`, an outcome of `Error` is\n    /// returned with the status code.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::{Request, Data, route};\n    ///\n    /// fn str_responder<'r>(req: &'r Request, _: Data<'r>) -> route::Outcome<'r> {\n    ///     route::Outcome::from(req, \"Hello, world!\")\n    /// }\n    /// ```\n    #[inline]\n    pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {\n        match responder.respond_to(req) {\n            Ok(response) => Outcome::Success(response),\n            Err(status) => Outcome::Error(status)\n        }\n    }\n\n    /// Return the `Outcome` of response to `req` from `responder`.\n    ///\n    /// If the responder returns `Ok`, an outcome of `Success` is returned with\n    /// the response. If the responder returns `Err`, an outcome of `Error` is\n    /// returned with the status code.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::{Request, Data, route};\n    ///\n    /// fn str_responder<'r>(req: &'r Request, _: Data<'r>) -> route::Outcome<'r> {\n    ///     route::Outcome::from(req, \"Hello, world!\")\n    /// }\n    /// ```\n    #[inline]\n    pub fn try_from<R, E>(req: &'r Request<'_>, result: Result<R, E>) -> Outcome<'r>\n        where R: Responder<'r, 'o>, E: std::fmt::Debug\n    {\n        let responder = result.map_err(crate::response::Debug);\n        match responder.respond_to(req) {\n            Ok(response) => Outcome::Success(response),\n            Err(status) => Outcome::Error(status)\n        }\n    }\n\n    /// Return an `Outcome` of `Error` with the status code `code`. This is\n    /// equivalent to `Outcome::Error(code)`.\n    ///\n    /// This method exists to be used during manual routing.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::{Request, Data, route};\n    /// use rocket::http::Status;\n    ///\n    /// fn bad_req_route<'r>(_: &'r Request, _: Data<'r>) -> route::Outcome<'r> {\n    ///     route::Outcome::error(Status::BadRequest)\n    /// }\n    /// ```\n    #[inline(always)]\n    pub fn error(code: Status) -> Outcome<'r> {\n        Outcome::Error(code)\n    }\n\n    /// Return an `Outcome` of `Forward` with the data `data` and status\n    /// `status`. This is equivalent to `Outcome::Forward((data, status))`.\n    ///\n    /// This method exists to be used during manual routing.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::{Request, Data, route};\n    /// use rocket::http::Status;\n    ///\n    /// fn always_forward<'r>(_: &'r Request, data: Data<'r>) -> route::Outcome<'r> {\n    ///     route::Outcome::forward(data, Status::InternalServerError)\n    /// }\n    /// ```\n    #[inline(always)]\n    pub fn forward(data: Data<'r>, status: Status) -> Outcome<'r> {\n        Outcome::Forward((data, status))\n    }\n}\n\n// INTERNAL: A handler to use when one is needed temporarily.\n#[doc(hidden)]\npub fn dummy_handler<'r>(r: &'r Request<'_>, _: Data<'r>) -> BoxFuture<'r> {\n    Outcome::from(r, ()).pin()\n}\n\nmod private {\n    pub trait Sealed {}\n    impl<T: super::Handler + Clone> Sealed for T {}\n}\n\n/// Helper trait to make a [`Route`](crate::Route)'s `Box<dyn Handler>`\n/// `Clone`.\n///\n/// This trait cannot be implemented directly. Instead, implement `Clone` and\n/// [`Handler`]; all types that implement `Clone` and `Handler` automatically\n/// implement `Cloneable`.\npub trait Cloneable: private::Sealed {\n    #[doc(hidden)]\n    fn clone_handler(&self) -> Box<dyn Handler>;\n}\n\nimpl<T: Handler + Clone> Cloneable for T {\n    fn clone_handler(&self) -> Box<dyn Handler> {\n        Box::new(self.clone())\n    }\n}\n\nimpl Clone for Box<dyn Handler> {\n    fn clone(&self) -> Box<dyn Handler> {\n        self.clone_handler()\n    }\n}\n"
  },
  {
    "path": "core/lib/src/route/mod.rs",
    "content": "//! Types and traits for routes and their request handlers and return types.\n\nmod route;\nmod handler;\nmod uri;\nmod segment;\n\npub use route::*;\npub use handler::*;\npub use uri::*;\n\npub(crate) use segment::Segment;\n"
  },
  {
    "path": "core/lib/src/route/route.rs",
    "content": "use std::fmt;\nuse std::borrow::Cow;\n\nuse crate::http::{uri, Method, MediaType};\nuse crate::route::{Handler, RouteUri, BoxFuture};\nuse crate::sentinel::Sentry;\n\n/// A request handling route.\n///\n/// A route consists of exactly the information in its fields. While a `Route`\n/// can be instantiated directly, doing so should be a rare or nonexistent\n/// event. Instead, a Rocket application should use Rocket's\n/// [`#[route]`](macro@crate::route) series of attributes to generate a `Route`.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # use std::path::PathBuf;\n/// #[get(\"/route/<path..>?query\", rank = 2, format = \"json\")]\n/// fn route_name(path: PathBuf) { /* handler procedure */ }\n///\n/// use rocket::http::{Method, MediaType};\n///\n/// let route = routes![route_name].remove(0);\n/// assert_eq!(route.name.unwrap(), \"route_name\");\n/// assert_eq!(route.method, Some(Method::Get));\n/// assert_eq!(route.uri, \"/route/<path..>?query\");\n/// assert_eq!(route.rank, 2);\n/// assert_eq!(route.format.unwrap(), MediaType::JSON);\n/// ```\n///\n/// Note that the `rank` and `format` attribute parameters are optional. See\n/// [`#[route]`](macro@crate::route) for details on macro usage. Note also that\n/// a route's mounted _base_ becomes part of its URI; see [`RouteUri`] for\n/// details.\n///\n/// # Routing\n///\n/// A request is _routed_ to a route if it has the highest precedence (lowest\n/// rank) among all routes that [match](Route::matches()) the request. See\n/// [`Route::matches()`] for details on what it means for a request to match.\n///\n/// Note that a single request _may_ be routed to multiple routes if a route\n/// forwards. If a route fails, the request is instead routed to the highest\n/// precedence [`Catcher`](crate::Catcher).\n///\n/// ## Collisions\n///\n/// Two routes are said to [collide](Route::collides_with()) if there exists a\n/// request that matches both routes. Colliding routes present a routing\n/// ambiguity and are thus disallowed by Rocket. Because routes can be\n/// constructed dynamically, collision checking is done at\n/// [`ignite`](crate::Rocket::ignite()) time, after it becomes statically\n/// impossible to add any more routes to an instance of `Rocket`.\n///\n/// Note that because query parsing is always lenient -- extra and missing query\n/// parameters are allowed -- queries do not directly impact whether two routes\n/// collide.\n///\n/// ## Resolving Collisions\n///\n/// Collisions are resolved through _ranking_. Routes with lower ranks have\n/// higher precedence during routing than routes with higher ranks. Thus, routes\n/// are attempted in ascending rank order. If a higher precedence route returns\n/// an `Outcome` of `Forward`, the next highest precedence route is attempted,\n/// and so on, until a route returns `Success` or `Error`, or there are no\n/// more routes to try. When all routes have been attempted, Rocket issues a\n/// `404` error, handled by the appropriate [`Catcher`](crate::Catcher).\n///\n/// ## Default Ranking\n///\n/// Most collisions are automatically resolved by Rocket's _default rank_. The\n/// default rank prefers static components over dynamic components in both paths\n/// and queries: the _more_ static a route's path and query are, the lower its\n/// rank and thus the higher its precedence.\n///\n/// There are three \"colors\" to paths and queries:\n///   1. `static` - all components are static\n///   2. `partial` - at least one, but not all, components are dynamic\n///   3. `wild` - all components are dynamic\n///\n/// Static paths carry more weight than static queries. The same is true for\n/// partial and wild paths. This results in the following default ranking\n/// table:\n///\n/// | path    | query   | rank |\n/// |---------|---------|------|\n/// | static  | static  | -12  |\n/// | static  | partial | -11  |\n/// | static  | wild    | -10  |\n/// | static  | none    | -9   |\n/// | partial | static  | -8   |\n/// | partial | partial | -7   |\n/// | partial | wild    | -6   |\n/// | partial | none    | -5   |\n/// | wild    | static  | -4   |\n/// | wild    | partial | -3   |\n/// | wild    | wild    | -2   |\n/// | wild    | none    | -1   |\n///\n/// Recall that _lower_ ranks have _higher_ precedence.\n///\n/// ### Example\n///\n/// ```rust\n/// use rocket::Route;\n/// use rocket::http::Method;\n///\n/// macro_rules! assert_rank {\n///     ($($uri:expr => $rank:expr,)*) => {$(\n///         let route = Route::new(Method::Get, $uri, rocket::route::dummy_handler);\n///         assert_eq!(route.rank, $rank);\n///     )*}\n/// }\n///\n/// assert_rank! {\n///     \"/?foo\" => -12,                 // static path, static query\n///     \"/foo/bar?a=b&bob\" => -12,      // static path, static query\n///     \"/?a=b&bob\" => -12,             // static path, static query\n///\n///     \"/?a&<zoo..>\" => -11,           // static path, partial query\n///     \"/foo?a&<zoo..>\" => -11,        // static path, partial query\n///     \"/?a&<zoo>\" => -11,             // static path, partial query\n///\n///     \"/?<zoo..>\" => -10,             // static path, wild query\n///     \"/foo?<zoo..>\" => -10,          // static path, wild query\n///     \"/foo?<a>&<b>\" => -10,          // static path, wild query\n///\n///     \"/\" => -9,                      // static path, no query\n///     \"/foo/bar\" => -9,               // static path, no query\n///\n///     \"/a/<b>?foo\" => -8,             // partial path, static query\n///     \"/a/<b..>?foo\" => -8,           // partial path, static query\n///     \"/<a>/b?foo\" => -8,             // partial path, static query\n///\n///     \"/a/<b>?<b>&c\" => -7,           // partial path, partial query\n///     \"/a/<b..>?a&<c..>\" => -7,       // partial path, partial query\n///\n///     \"/a/<b>?<c..>\" => -6,           // partial path, wild query\n///     \"/a/<b..>?<c>&<d>\" => -6,       // partial path, wild query\n///     \"/a/<b..>?<c>\" => -6,           // partial path, wild query\n///\n///     \"/a/<b>\" => -5,                 // partial path, no query\n///     \"/<a>/b\" => -5,                 // partial path, no query\n///     \"/a/<b..>\" => -5,               // partial path, no query\n///\n///     \"/<b>/<c>?foo&bar\" => -4,       // wild path, static query\n///     \"/<a>/<b..>?foo\" => -4,         // wild path, static query\n///     \"/<b..>?cat\" => -4,             // wild path, static query\n///\n///     \"/<b>/<c>?<foo>&bar\" => -3,     // wild path, partial query\n///     \"/<a>/<b..>?a&<b..>\" => -3,     // wild path, partial query\n///     \"/<b..>?cat&<dog>\" => -3,       // wild path, partial query\n///\n///     \"/<b>/<c>?<foo>\" => -2,         // wild path, wild query\n///     \"/<a>/<b..>?<b..>\" => -2,       // wild path, wild query\n///     \"/<b..>?<c>&<dog>\" => -2,       // wild path, wild query\n///\n///     \"/<b>/<c>\" => -1,               // wild path, no query\n///     \"/<a>/<b..>\" => -1,             // wild path, no query\n///     \"/<b..>\" => -1,                 // wild path, no query\n/// }\n/// ```\n#[derive(Clone)]\npub struct Route {\n    /// The name of this route, if one was given.\n    pub name: Option<Cow<'static, str>>,\n    /// The method this route matches, or `None` to match any method.\n    pub method: Option<Method>,\n    /// The function that should be called when the route matches.\n    pub handler: Box<dyn Handler>,\n    /// The route URI.\n    pub uri: RouteUri<'static>,\n    /// The rank of this route. Lower ranks have higher priorities.\n    pub rank: isize,\n    /// The media type this route matches against, if any.\n    pub format: Option<MediaType>,\n    /// The discovered sentinels.\n    pub(crate) sentinels: Vec<Sentry>,\n    /// The file, line, and column where the route was defined, if known.\n    pub(crate) location: Option<(&'static str, u32, u32)>,\n}\n\nimpl Route {\n    /// Creates a new route with the given method, path, and handler with a base\n    /// of `/` and a computed [default rank](#default-ranking).\n    ///\n    /// # Panics\n    ///\n    /// Panics if `path` is not a valid Rocket route URI.\n    ///\n    /// A valid route URI is any valid [`Origin`](uri::Origin) URI that is\n    /// normalized, that is, does not contain any empty segments except for an\n    /// optional trailing slash. Unlike a strict `Origin`, route URIs are also\n    /// allowed to contain any UTF-8 characters.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::route::dummy_handler as handler;\n    ///\n    /// // this is a route matching requests to `GET /`\n    /// let index = Route::new(Method::Get, \"/\", handler);\n    /// assert_eq!(index.rank, -9);\n    /// assert_eq!(index.method, Some(Method::Get));\n    /// assert_eq!(index.uri, \"/\");\n    /// ```\n    #[track_caller]\n    pub fn new<M: Into<Option<Method>>, H: Handler>(method: M, uri: &str, handler: H) -> Route {\n        Route::ranked(None, method.into(), uri, handler)\n    }\n\n    /// Creates a new route with the given rank, method, path, and handler with\n    /// a base of `/`. If `rank` is `None`, the computed [default\n    /// rank](#default-ranking) is used.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `path` is not a valid Rocket route URI.\n    ///\n    /// A valid route URI is any valid [`Origin`](uri::Origin) URI that is\n    /// normalized, that is, does not contain any empty segments except for an\n    /// optional trailing slash. Unlike a strict `Origin`, route URIs are also\n    /// allowed to contain any UTF-8 characters.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::route::dummy_handler as handler;\n    ///\n    /// let foo = Route::ranked(1, Method::Post, \"/foo?bar\", handler);\n    /// assert_eq!(foo.rank, 1);\n    /// assert_eq!(foo.method, Some(Method::Post));\n    /// assert_eq!(foo.uri, \"/foo?bar\");\n    ///\n    /// let foo = Route::ranked(None, Method::Post, \"/foo?bar\", handler);\n    /// assert_eq!(foo.rank, -12);\n    /// assert_eq!(foo.method, Some(Method::Post));\n    /// assert_eq!(foo.uri, \"/foo?bar\");\n    /// ```\n    #[track_caller]\n    pub fn ranked<M, H, R>(rank: R, method: M, uri: &str, handler: H) -> Route\n        where M: Into<Option<Method>>,\n              H: Handler + 'static,\n              R: Into<Option<isize>>,\n    {\n        let uri = RouteUri::new(\"/\", uri);\n        let rank = rank.into().unwrap_or_else(|| uri.default_rank());\n        Route {\n            name: None,\n            format: None,\n            sentinels: Vec::new(),\n            handler: Box::new(handler),\n            location: None,\n            method: method.into(),\n            rank,\n            uri,\n        }\n    }\n\n    /// Prefix `base` to any existing mount point base in `self`.\n    ///\n    /// If the the current mount point base is `/`, then the base is replaced by\n    /// `base`. Otherwise, `base` is prefixed to the existing `base`.\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::route::dummy_handler as handler;\n    /// # use rocket::uri;\n    ///\n    /// // The default base is `/`.\n    /// let index = Route::new(Method::Get, \"/foo/bar\", handler);\n    ///\n    /// // Since the base is `/`, rebasing replaces the base.\n    /// let rebased = index.rebase(uri!(\"/boo\"));\n    /// assert_eq!(rebased.uri.base(), \"/boo\");\n    ///\n    /// // Now every rebase prefixes.\n    /// let rebased = rebased.rebase(uri!(\"/base\"));\n    /// assert_eq!(rebased.uri.base(), \"/base/boo\");\n    ///\n    /// // Rebasing to `/` does nothing.\n    /// let rebased = rebased.rebase(uri!(\"/\"));\n    /// assert_eq!(rebased.uri.base(), \"/base/boo\");\n    ///\n    /// // Note that trailing slashes are preserved:\n    /// let index = Route::new(Method::Get, \"/foo\", handler);\n    /// let rebased = index.rebase(uri!(\"/boo/\"));\n    /// assert_eq!(rebased.uri.base(), \"/boo/\");\n    /// ```\n    pub fn rebase(mut self, base: uri::Origin<'_>) -> Self {\n        let new_base = match self.uri.base().as_str() {\n            \"/\" => base.path().to_string(),\n            _ => format!(\"{}{}\", base.path(), self.uri.base()),\n        };\n\n        self.uri = RouteUri::new(&new_base, &self.uri.unmounted_origin.to_string());\n        self\n    }\n\n    /// Maps the `base` of this route using `mapper`, returning a new `Route`\n    /// with the returned base.\n    ///\n    /// **Note:** Prefer to use [`Route::rebase()`] whenever possible!\n    ///\n    /// `mapper` is called with the current base. The returned `String` is used\n    /// as the new base if it is a valid URI. If the returned base URI contains\n    /// a query, it is ignored. Returns an error if the base produced by\n    /// `mapper` is not a valid origin URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::route::dummy_handler as handler;\n    /// # use rocket::uri;\n    ///\n    /// let index = Route::new(Method::Get, \"/foo/bar\", handler);\n    /// assert_eq!(index.uri.base(), \"/\");\n    /// assert_eq!(index.uri.unmounted().path(), \"/foo/bar\");\n    /// assert_eq!(index.uri.path(), \"/foo/bar\");\n    ///\n    /// # let old_index = index;\n    /// # let index = old_index.clone();\n    /// let mapped = index.map_base(|base| format!(\"{}{}\", \"/boo\", base)).unwrap();\n    /// assert_eq!(mapped.uri.base(), \"/boo/\");\n    /// assert_eq!(mapped.uri.unmounted().path(), \"/foo/bar\");\n    /// assert_eq!(mapped.uri.path(), \"/boo/foo/bar\");\n    ///\n    /// // Note that this produces different `base` results than `rebase`!\n    /// # let index = old_index.clone();\n    /// let rebased = index.rebase(uri!(\"/boo\"));\n    /// assert_eq!(rebased.uri.base(), \"/boo\");\n    /// assert_eq!(rebased.uri.unmounted().path(), \"/foo/bar\");\n    /// assert_eq!(rebased.uri.path(), \"/boo/foo/bar\");\n    /// ```\n    pub fn map_base<'a, F>(mut self, mapper: F) -> Result<Self, uri::Error<'static>>\n        where F: FnOnce(uri::Origin<'a>) -> String\n    {\n        let base = mapper(self.uri.base);\n        self.uri = RouteUri::try_new(&base, &self.uri.unmounted_origin.to_string())?;\n        Ok(self)\n    }\n}\n\nimpl fmt::Debug for Route {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Route\")\n            .field(\"name\", &self.name)\n            .field(\"method\", &self.method)\n            .field(\"uri\", &self.uri)\n            .field(\"rank\", &self.rank)\n            .field(\"format\", &self.format)\n            .finish()\n    }\n}\n\n/// Information generated by the `route` attribute during codegen.\n#[doc(hidden)]\npub struct StaticInfo {\n    /// The route's name, i.e, the name of the function.\n    pub name: &'static str,\n    /// The route's method.\n    pub method: Option<Method>,\n    /// The route's URi, without the base mount point.\n    pub uri: &'static str,\n    /// The route's format, if any.\n    pub format: Option<MediaType>,\n    /// The route's handler, i.e, the annotated function.\n    pub handler: for<'r> fn(&'r crate::Request<'_>, crate::Data<'r>) -> BoxFuture<'r>,\n    /// The route's rank, if any.\n    pub rank: Option<isize>,\n    /// Route-derived sentinels, if any.\n    /// This isn't `&'static [SentryInfo]` because `type_name()` isn't `const`.\n    pub sentinels: Vec<Sentry>,\n    /// The file, line, and column where the route was defined.\n    pub location: (&'static str, u32, u32),\n}\n\n#[doc(hidden)]\nimpl From<StaticInfo> for Route {\n    fn from(info: StaticInfo) -> Route {\n        // This should never panic since `info.path` is statically checked.\n        let uri = RouteUri::new(\"/\", info.uri);\n\n        Route {\n            name: Some(info.name.into()),\n            method: info.method,\n            handler: Box::new(info.handler),\n            rank: info.rank.unwrap_or_else(|| uri.default_rank()),\n            format: info.format,\n            sentinels: info.sentinels.into_iter().collect(),\n            location: Some(info.location),\n            uri,\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/route/segment.rs",
    "content": "#[derive(Debug, Clone)]\npub struct Segment {\n    /// The name of the parameter or just the static string.\n    pub value: String,\n    /// This is a `<a>`.\n    pub dynamic: bool,\n    /// This is a `<a..>`.\n    pub dynamic_trail: bool,\n}\n\nimpl Segment {\n    pub fn from(segment: &crate::http::RawStr) -> Self {\n        let mut value = segment;\n        let mut dynamic = false;\n        let mut dynamic_trail = false;\n\n        if segment.starts_with('<') && segment.ends_with('>') {\n            dynamic = true;\n            value = &segment[1..(segment.len() - 1)];\n\n            if value.ends_with(\"..\") {\n                dynamic_trail = true;\n                value = &value[..(value.len() - 2)];\n            }\n        }\n\n        Segment { value: value.to_string(), dynamic, dynamic_trail }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/route/uri.rs",
    "content": "use std::fmt;\n\nuse crate::http::uri::{self, Origin, Path};\nuse crate::http::ext::IntoOwned;\nuse crate::form::ValueField;\nuse crate::route::Segment;\n\n/// A route URI which is matched against requests.\n///\n/// A route URI is composed of two components:\n///\n///   * `base`\n///\n///     Otherwise known as the route's \"mount point\", the `base` is a static\n///     [`Origin`] that prefixes the route URI. All route URIs have a `base`.\n///     When routes are created manually with [`Route::new()`], the base\n///     defaults to `/`. When mounted via [`Rocket::mount()`], the base is\n///     explicitly specified as the first argument.\n///\n///     ```rust\n///     use rocket::Route;\n///     use rocket::http::Method;\n///     # use rocket::route::dummy_handler as handler;\n///\n///     let route = Route::new(Method::Get, \"/foo/<bar>\", handler);\n///     assert_eq!(route.uri.base(), \"/\");\n///\n///     let rocket = rocket::build().mount(\"/base\", vec![route]);\n///     let routes: Vec<_> = rocket.routes().collect();\n///     assert_eq!(routes[0].uri.base(), \"/base\");\n///     ```\n///\n///   * `origin`\n///\n///     Otherwise known as the \"route URI\", the `origin` is an [`Origin`] with\n///     potentially dynamic (`<dyn>` or `<dyn..>`) segments. It is prefixed with\n///     the `base`. This is the URI which is matched against incoming requests\n///     for routing.\n///\n///     ```rust\n///     use rocket::Route;\n///     use rocket::http::Method;\n///     # use rocket::route::dummy_handler as handler;\n///\n///     let route = Route::new(Method::Get, \"/foo/<bar>\", handler);\n///     assert_eq!(route.uri, \"/foo/<bar>\");\n///\n///     let rocket = rocket::build().mount(\"/base\", vec![route]);\n///     let routes: Vec<_> = rocket.routes().collect();\n///     assert_eq!(routes[0].uri, \"/base/foo/<bar>\");\n///     ```\n///\n/// [`Rocket::mount()`]: crate::Rocket::mount()\n/// [`Route::new()`]: crate::Route::new()\n#[derive(Debug, Clone)]\npub struct RouteUri<'a> {\n    /// The mount point.\n    pub(crate) base: Origin<'a>,\n    /// The URI _without_ the `base` mount point.\n    pub(crate) unmounted_origin: Origin<'a>,\n    /// The URI _with_ the base mount point. This is the canonical route URI.\n    pub(crate) uri: Origin<'a>,\n    /// Cached metadata about this URI.\n    pub(crate) metadata: Metadata,\n}\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\npub(crate) enum Color {\n    /// Fully static: no dynamic components.\n    Static = 3,\n    /// Partially static/dynamic: some, but not all, dynamic components.\n    Partial = 2,\n    /// Fully dynamic: no static components.\n    Wild = 1,\n}\n\n#[derive(Debug, Clone)]\npub(crate) struct Metadata {\n    /// Segments in the route URI, including base.\n    pub uri_segments: Vec<Segment>,\n    /// Numbers of segments in `uri_segments` that belong to the base.\n    pub base_len: usize,\n    /// `(name, value)` of the query segments that are static.\n    pub static_query_fields: Vec<(String, String)>,\n    /// The \"color\" of the route path.\n    pub path_color: Color,\n    /// The \"color\" of the route query, if there is query.\n    pub query_color: Option<Color>,\n    /// Whether the path has a `<trailing..>` parameter.\n    pub dynamic_trail: bool,\n}\n\ntype Result<T, E = uri::Error<'static>> = std::result::Result<T, E>;\n\nimpl<'a> RouteUri<'a> {\n    /// Create a new `RouteUri`.\n    ///\n    /// Panics if  `base` or `uri` cannot be parsed as `Origin`s.\n    #[track_caller]\n    pub(crate) fn new(base: &str, uri: &str) -> RouteUri<'static> {\n        Self::try_new(base, uri).expect(\"expected valid route URIs\")\n    }\n\n    /// Creates a new `RouteUri` from a `base` mount point and a route `uri`.\n    ///\n    /// This is a fallible variant of [`RouteUri::new`] which returns an `Err`\n    /// if `base` or `uri` cannot be parsed as [`Origin`]s.\n    /// INTERNAL!\n    #[doc(hidden)]\n    pub fn try_new(base: &str, uri: &str) -> Result<RouteUri<'static>> {\n        let mut base = Origin::parse(base)\n            .map_err(|e| e.into_owned())?\n            .into_normalized()\n            .into_owned();\n\n        base.clear_query();\n\n        let origin = Origin::parse_route(uri)\n            .map_err(|e| e.into_owned())?\n            .into_normalized()\n            .into_owned();\n\n        // Distinguish for routes `/` with bases of `/foo/` and `/foo`. The\n        // latter base, without a trailing slash, should combine as `/foo`.\n        let route_uri = match origin.path().as_str() {\n            \"/\" if !base.has_trailing_slash() => match origin.query() {\n                Some(query) => format!(\"{}?{}\", base, query),\n                None => base.to_string(),\n            }\n            _ => format!(\"{}{}\", base, origin),\n        };\n\n        let uri = Origin::parse_route(&route_uri)\n            .map_err(|e| e.into_owned())?\n            .into_normalized()\n            .into_owned();\n\n        let metadata = Metadata::from(&base, &uri);\n\n        Ok(RouteUri { base, unmounted_origin: origin, uri, metadata })\n    }\n\n    /// Returns the complete route URI.\n    ///\n    /// **Note:** `RouteURI` derefs to the `Origin` returned by this method, so\n    /// this method should rarely be called directly.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::route::dummy_handler as handler;\n    ///\n    /// let route = Route::new(Method::Get, \"/foo/bar?a=1\", handler);\n    ///\n    /// // Use `inner()` directly:\n    /// assert_eq!(route.uri.inner().query().unwrap(), \"a=1\");\n    ///\n    /// // Use the deref implementation. This is preferred:\n    /// assert_eq!(route.uri.query().unwrap(), \"a=1\");\n    /// ```\n    pub fn inner(&self) -> &Origin<'a> {\n        &self.uri\n    }\n\n    /// The base mount point of this route URI.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::route::dummy_handler as handler;\n    /// # use rocket::uri;\n    ///\n    /// let route = Route::new(Method::Get, \"/foo/bar?a=1\", handler);\n    /// assert_eq!(route.uri.base(), \"/\");\n    ///\n    /// let route = route.rebase(uri!(\"/boo\"));\n    /// assert_eq!(route.uri.base(), \"/boo\");\n    ///\n    /// let route = route.rebase(uri!(\"/foo\"));\n    /// assert_eq!(route.uri.base(), \"/foo/boo\");\n    /// ```\n    #[inline(always)]\n    pub fn base(&self) -> Path<'_> {\n        self.base.path()\n    }\n\n    /// The route URI _without_ the base mount point.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::route::dummy_handler as handler;\n    /// # use rocket::uri;\n    ///\n    /// let route = Route::new(Method::Get, \"/foo/bar?a=1\", handler);\n    /// let route = route.rebase(uri!(\"/boo\"));\n    ///\n    /// assert_eq!(route.uri, \"/boo/foo/bar?a=1\");\n    /// assert_eq!(route.uri.base(), \"/boo\");\n    /// assert_eq!(route.uri.unmounted(), \"/foo/bar?a=1\");\n    /// ```\n    #[inline(always)]\n    pub fn unmounted(&self) -> &Origin<'a> {\n        &self.unmounted_origin\n    }\n\n    /// Get the default rank of a route with this URI.\n    ///\n    /// The route's default rank is determined based on the presence or absence\n    /// of static and dynamic paths and queries. See the documentation for\n    /// [`Route::new`][`crate::Route::new`] for a table summarizing the exact default ranks.\n    ///\n    /// | path    | query   | rank |\n    /// |---------|---------|------|\n    /// | static  | static  | -12  |\n    /// | static  | partial | -11  |\n    /// | static  | wild    | -10  |\n    /// | static  | none    | -9   |\n    /// | partial | static  | -8   |\n    /// | partial | partial | -7   |\n    /// | partial | wild    | -6   |\n    /// | partial | none    | -5   |\n    /// | wild    | static  | -4   |\n    /// | wild    | partial | -3   |\n    /// | wild    | wild    | -2   |\n    /// | wild    | none    | -1   |\n    pub(crate) fn default_rank(&self) -> isize {\n        let raw_path_weight = self.metadata.path_color as u8;\n        let raw_query_weight = self.metadata.query_color.map_or(0, |c| c as u8);\n        let raw_weight = (raw_path_weight << 2) | raw_query_weight;\n\n        // We subtract `3` because `raw_path` is never `0`: 0b0100 = 4 - 3 = 1.\n        -((raw_weight as isize) - 3)\n    }\n}\n\nimpl Metadata {\n    fn from(base: &Origin<'_>, uri: &Origin<'_>) -> Self {\n        let uri_segments = uri.path()\n            .raw_segments()\n            .map(Segment::from)\n            .collect::<Vec<_>>();\n\n        let query_segs = uri.query()\n            .map(|q| q.raw_segments().map(Segment::from).collect::<Vec<_>>())\n            .unwrap_or_default();\n\n        let static_query_fields = query_segs.iter().filter(|s| !s.dynamic)\n            .map(|s| ValueField::parse(&s.value))\n            .map(|f| (f.name.source().to_string(), f.value.to_string()))\n            .collect();\n\n        let static_path = uri_segments.iter().all(|s| !s.dynamic);\n        let wild_path = !uri_segments.is_empty() && uri_segments.iter().all(|s| s.dynamic);\n        let path_color = match (static_path, wild_path) {\n            (true, _) => Color::Static,\n            (_, true) => Color::Wild,\n            (_, _) => Color::Partial\n        };\n\n        let query_color = (!query_segs.is_empty()).then(|| {\n            let static_query = query_segs.iter().all(|s| !s.dynamic);\n            let wild_query = query_segs.iter().all(|s| s.dynamic);\n            match (static_query, wild_query) {\n                (true, _) => Color::Static,\n                (_, true) => Color::Wild,\n                (_, _) => Color::Partial\n            }\n        });\n\n        let dynamic_trail = uri_segments.last().map_or(false, |p| p.dynamic_trail);\n        let segments = base.path().segments();\n        let num_empty = segments.clone().filter(|s| s.is_empty()).count();\n        let base_len = segments.num() - num_empty;\n\n        Metadata {\n            uri_segments, base_len, static_query_fields, path_color, query_color, dynamic_trail\n        }\n    }\n}\n\nimpl<'a> std::ops::Deref for RouteUri<'a> {\n    type Target = Origin<'a>;\n\n    fn deref(&self) -> &Self::Target {\n        self.inner()\n    }\n}\n\nimpl fmt::Display for RouteUri<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.uri.fmt(f)\n    }\n}\n\nimpl<'a, 'b> PartialEq<Origin<'b>> for RouteUri<'a> {\n    fn eq(&self, other: &Origin<'b>) -> bool { self.inner() == other }\n}\n\nimpl PartialEq<str> for RouteUri<'_> {\n    fn eq(&self, other: &str) -> bool { self.inner() == other }\n}\n\nimpl PartialEq<&str> for RouteUri<'_> {\n    fn eq(&self, other: &&str) -> bool { self.inner() == *other }\n}\n\n#[cfg(test)]\nmod tests {\n    macro_rules! assert_uri_equality {\n        ($base:expr, $path:expr => $ebase:expr, $epath:expr, $efull:expr) => {\n            let uri = super::RouteUri::new($base, $path);\n            assert_eq!(uri, $efull, \"complete URI mismatch. expected {}, got {}\", $efull, uri);\n            assert_eq!(uri.base(), $ebase, \"expected base {}, got {}\", $ebase, uri.base());\n            assert_eq!(uri.unmounted(), $epath, \"expected unmounted {}, got {}\", $epath,\n                uri.unmounted());\n        };\n    }\n\n    #[test]\n    fn test_route_uri_composition() {\n        assert_uri_equality!(\"/\", \"/\" => \"/\", \"/\", \"/\");\n        assert_uri_equality!(\"/\", \"/foo\" => \"/\", \"/foo\", \"/foo\");\n        assert_uri_equality!(\"/\", \"/foo/bar\" => \"/\", \"/foo/bar\", \"/foo/bar\");\n        assert_uri_equality!(\"/\", \"/foo/\" => \"/\", \"/foo/\", \"/foo/\");\n        assert_uri_equality!(\"/\", \"/foo/bar/\" => \"/\", \"/foo/bar/\", \"/foo/bar/\");\n\n        assert_uri_equality!(\"/foo\", \"/\" => \"/foo\", \"/\", \"/foo\");\n        assert_uri_equality!(\"/foo\", \"/bar\" => \"/foo\", \"/bar\", \"/foo/bar\");\n        assert_uri_equality!(\"/foo\", \"/bar/\" => \"/foo\", \"/bar/\", \"/foo/bar/\");\n        assert_uri_equality!(\"/foo\", \"/?baz\" => \"/foo\", \"/?baz\", \"/foo?baz\");\n        assert_uri_equality!(\"/foo\", \"/bar?baz\" => \"/foo\", \"/bar?baz\", \"/foo/bar?baz\");\n        assert_uri_equality!(\"/foo\", \"/bar/?baz\" => \"/foo\", \"/bar/?baz\", \"/foo/bar/?baz\");\n\n        assert_uri_equality!(\"/foo/\", \"/\" => \"/foo/\", \"/\", \"/foo/\");\n        assert_uri_equality!(\"/foo/\", \"/bar\" => \"/foo/\", \"/bar\", \"/foo/bar\");\n        assert_uri_equality!(\"/foo/\", \"/bar/\" => \"/foo/\", \"/bar/\", \"/foo/bar/\");\n        assert_uri_equality!(\"/foo/\", \"/?baz\" => \"/foo/\", \"/?baz\", \"/foo/?baz\");\n        assert_uri_equality!(\"/foo/\", \"/bar?baz\" => \"/foo/\", \"/bar?baz\", \"/foo/bar?baz\");\n        assert_uri_equality!(\"/foo/\", \"/bar/?baz\" => \"/foo/\", \"/bar/?baz\", \"/foo/bar/?baz\");\n\n        assert_uri_equality!(\"/foo?baz\", \"/\" => \"/foo\", \"/\", \"/foo\");\n        assert_uri_equality!(\"/foo?baz\", \"/bar\" => \"/foo\", \"/bar\", \"/foo/bar\");\n        assert_uri_equality!(\"/foo?baz\", \"/bar/\" => \"/foo\", \"/bar/\", \"/foo/bar/\");\n        assert_uri_equality!(\"/foo/?baz\", \"/\" => \"/foo/\", \"/\", \"/foo/\");\n        assert_uri_equality!(\"/foo/?baz\", \"/bar\" => \"/foo/\", \"/bar\", \"/foo/bar\");\n        assert_uri_equality!(\"/foo/?baz\", \"/bar/\" => \"/foo/\", \"/bar/\", \"/foo/bar/\");\n    }\n}\n"
  },
  {
    "path": "core/lib/src/router/collider.rs",
    "content": "use crate::catcher::Catcher;\nuse crate::route::{Route, Segment, RouteUri};\n\nuse crate::http::{MediaType, Method};\n\npub trait Collide<T = Self> {\n    fn collides_with(&self, other: &T) -> bool;\n}\n\nimpl Route {\n    /// Returns `true` if `self` collides with `other`.\n    ///\n    /// A [_collision_](Route#collisions) between two routes occurs when there\n    /// exists a request that could [match](Route::matches()) either route. That\n    /// is, a routing ambiguity would ensue if both routes were made available\n    /// to the router.\n    ///\n    /// Specifically, a collision occurs when two routes `a` and `b`:\n    ///\n    ///  * Have the same [method](Route::method).\n    ///  * Have the same [rank](Route#default-ranking).\n    ///  * The routes' methods don't support a payload _or_ the routes'\n    ///    methods support a payload and the formats overlap. Formats overlap\n    ///    when:\n    ///    - The top-level type of either is `*` or the top-level types are\n    ///      equivalent.\n    ///    - The sub-level type of either is `*` or the sub-level types are\n    ///      equivalent.\n    ///  * Have overlapping route URIs. This means that either:\n    ///    - The URIs have the same number of segments `n`, and for `i` in\n    ///      `0..n`, either `a.uri[i]` is dynamic _or_ `b.uri[i]` is dynamic\n    ///      _or_ they're both static with the same value.\n    ///    - One URI has fewer segments _and_ ends with a trailing dynamic\n    ///      parameter _and_ the preceding segments in both routes match the\n    ///      conditions above.\n    ///\n    /// Collisions are symmetric: for any routes `a` and `b`,\n    /// `a.collides_with(b) => b.collides_with(a)`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::{Method, MediaType};\n    /// # use rocket::route::dummy_handler as handler;\n    ///\n    /// // Two routes with the same method, rank, URI, and formats collide.\n    /// let a = Route::new(Method::Get, \"/\", handler);\n    /// let b = Route::new(Method::Get, \"/\", handler);\n    /// assert!(a.collides_with(&b));\n    ///\n    /// // Two routes with the same method, rank, URI, and overlapping formats.\n    /// let mut a = Route::new(Method::Post, \"/\", handler);\n    /// a.format = Some(MediaType::new(\"*\", \"custom\"));\n    /// let mut b = Route::new(Method::Post, \"/\", handler);\n    /// b.format = Some(MediaType::new(\"text\", \"*\"));\n    /// assert!(a.collides_with(&b));\n    ///\n    /// // Two routes with different ranks don't collide.\n    /// let a = Route::ranked(1, Method::Get, \"/\", handler);\n    /// let b = Route::ranked(2, Method::Get, \"/\", handler);\n    /// assert!(!a.collides_with(&b));\n    ///\n    /// // Two routes with different methods don't collide.\n    /// let a = Route::new(Method::Put, \"/\", handler);\n    /// let b = Route::new(Method::Post, \"/\", handler);\n    /// assert!(!a.collides_with(&b));\n    ///\n    /// // Two routes with non-overlapping URIs do not collide.\n    /// let a = Route::new(Method::Get, \"/foo\", handler);\n    /// let b = Route::new(Method::Get, \"/bar/<baz>\", handler);\n    /// assert!(!a.collides_with(&b));\n    ///\n    /// // Two payload-supporting routes with non-overlapping formats.\n    /// let mut a = Route::new(Method::Post, \"/\", handler);\n    /// a.format = Some(MediaType::HTML);\n    /// let mut b = Route::new(Method::Post, \"/\", handler);\n    /// b.format = Some(MediaType::JSON);\n    /// assert!(!a.collides_with(&b));\n    ///\n    /// // Two non payload-supporting routes with non-overlapping formats\n    /// // collide. A request with `Accept: */*` matches both.\n    /// let mut a = Route::new(Method::Get, \"/\", handler);\n    /// a.format = Some(MediaType::HTML);\n    /// let mut b = Route::new(Method::Get, \"/\", handler);\n    /// b.format = Some(MediaType::JSON);\n    /// assert!(a.collides_with(&b));\n    /// ```\n    pub fn collides_with(&self, other: &Route) -> bool {\n        methods_collide(self, other)\n            && self.rank == other.rank\n            && self.uri.collides_with(&other.uri)\n            && formats_collide(self, other)\n    }\n}\n\nimpl Catcher {\n    /// Returns `true` if `self` collides with `other`.\n    ///\n    /// A [_collision_](Catcher#collisions) between two catchers occurs when\n    /// there exists a request and ensuing error that could\n    /// [match](Catcher::matches()) both catchers. That is, a routing ambiguity\n    /// would ensue if both catchers were made available to the router.\n    ///\n    /// Specifically, a collision occurs when two catchers:\n    ///\n    ///  * Have the same [base](Catcher::base()).\n    ///  * Have the same status [code](Catcher::code) or are both `default`.\n    ///\n    /// Collisions are symmetric: for any catchers `a` and `b`,\n    /// `a.collides_with(b) => b.collides_with(a)`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Catcher;\n    /// # use rocket::catcher::dummy_handler as handler;\n    ///\n    /// // Two catchers with the same status code and base collide.\n    /// let a = Catcher::new(404, handler).map_base(|_| format!(\"/foo\")).unwrap();\n    /// let b = Catcher::new(404, handler).map_base(|_| format!(\"/foo\")).unwrap();\n    /// assert!(a.collides_with(&b));\n    ///\n    /// // Two catchers with a different base _do not_ collide.\n    /// let a = Catcher::new(404, handler);\n    /// let b = a.clone().map_base(|_| format!(\"/bar\")).unwrap();\n    /// assert_eq!(a.base(), \"/\");\n    /// assert_eq!(b.base(), \"/bar\");\n    /// assert!(!a.collides_with(&b));\n    ///\n    /// // Two catchers with a different codes _do not_ collide.\n    /// let a = Catcher::new(404, handler);\n    /// let b = Catcher::new(500, handler);\n    /// assert_eq!(a.base(), \"/\");\n    /// assert_eq!(b.base(), \"/\");\n    /// assert!(!a.collides_with(&b));\n    ///\n    /// // A catcher _with_ a status code and one _without_ do not collide.\n    /// let a = Catcher::new(404, handler);\n    /// let b = Catcher::new(None, handler);\n    /// assert!(!a.collides_with(&b));\n    /// ```\n    pub fn collides_with(&self, other: &Self) -> bool {\n        self.code == other.code && self.base().segments().eq(other.base().segments())\n    }\n}\n\nimpl Collide for Route {\n    #[inline(always)]\n    fn collides_with(&self, other: &Route) -> bool {\n        Route::collides_with(self, other)\n    }\n}\n\nimpl Collide for Catcher {\n    #[inline(always)]\n    fn collides_with(&self, other: &Self) -> bool {\n        Catcher::collides_with(self, other)\n    }\n}\n\nimpl Collide for RouteUri<'_> {\n    fn collides_with(&self, other: &Self) -> bool {\n        let a_segments = &self.metadata.uri_segments;\n        let b_segments = &other.metadata.uri_segments;\n        for (seg_a, seg_b) in a_segments.iter().zip(b_segments.iter()) {\n            if seg_a.dynamic_trail || seg_b.dynamic_trail {\n                return true;\n            }\n\n            if !seg_a.collides_with(seg_b) {\n                return false;\n            }\n        }\n\n        a_segments.len() == b_segments.len()\n    }\n}\n\nimpl Collide for Segment {\n    fn collides_with(&self, other: &Self) -> bool {\n        self.dynamic || other.dynamic || self.value == other.value\n    }\n}\n\nimpl Collide for MediaType {\n    fn collides_with(&self, other: &Self) -> bool {\n        let collide = |a, b| a == \"*\" || b == \"*\" || a == b;\n        collide(self.top(), other.top()) && collide(self.sub(), other.sub())\n    }\n}\n\nfn methods_collide(route: &Route, other: &Route) -> bool {\n    match (route.method, other.method) {\n        (Some(a), Some(b)) => a == b,\n        (None, _) | (_, None) => true,\n    }\n}\n\nfn formats_collide(route: &Route, other: &Route) -> bool {\n    let payload_support = |m: &Option<Method>| m.and_then(|m| m.allows_request_body());\n    match (payload_support(&route.method), payload_support(&other.method)) {\n        // Payload supporting methods match against `Content-Type` which must be\n        // fully specified, so the request cannot contain a format that matches\n        // more than one route format as long as those formats don't collide.\n        (Some(true), Some(true)) => match (route.format.as_ref(), other.format.as_ref()) {\n            (Some(a), Some(b)) => a.collides_with(b),\n            // A route without a `format` accepts all `Content-Type`s.\n            _ => true\n        },\n        // When a request method may not support a payload, the `Accept` header\n        // is considered during matching. The header can always be `*/*`, which\n        // would match any format. Thus two such routes would always collide.\n        _ => true,\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::str::FromStr;\n\n    use super::*;\n    use crate::route::dummy_handler;\n    use crate::http::{Method, Method::*};\n\n    fn dummy_route(ranked: bool, method: impl Into<Option<Method>>, uri: &'static str) -> Route {\n        let method = method.into().unwrap_or(Get);\n        Route::ranked((!ranked).then(|| 0), method, uri, dummy_handler)\n    }\n\n    macro_rules! assert_collision {\n        ($ranked:expr, $p1:expr, $p2:expr) => (assert_collision!($ranked, None $p1, None $p2));\n        ($ranked:expr, $m1:ident $p1:expr, $m2:ident $p2:expr) => {\n            let (a, b) = (dummy_route($ranked, $m1, $p1), dummy_route($ranked, $m2, $p2));\n            assert! {\n                a.collides_with(&b),\n                \"\\nroutes failed to collide:\\n{:?} does not collide with {:?}\\n\", a, b\n            }\n        };\n        (ranked $($t:tt)+) => (assert_collision!(true, $($t)+));\n        ($($t:tt)+) => (assert_collision!(false, $($t)+));\n    }\n\n    macro_rules! assert_no_collision {\n        ($ranked:expr, $p1:expr, $p2:expr) => (assert_no_collision!($ranked, None $p1, None $p2));\n        ($ranked:expr, $m1:ident $p1:expr, $m2:ident $p2:expr) => {\n            let (a, b) = (dummy_route($ranked, $m1, $p1), dummy_route($ranked, $m2, $p2));\n            assert! {\n                !a.collides_with(&b),\n                \"\\nunexpected collision:\\n{:?} collides with {:?}\\n\", a, b\n            }\n        };\n        (ranked $($t:tt)+) => (assert_no_collision!(true, $($t)+));\n        ($($t:tt)+) => (assert_no_collision!(false, $($t)+));\n    }\n\n    #[test]\n    fn non_collisions() {\n        assert_no_collision!(\"/a\", \"/b\");\n        assert_no_collision!(\"/a/b\", \"/a\");\n        assert_no_collision!(\"/a/b\", \"/a/c\");\n        assert_no_collision!(\"/a/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello/there\", \"/hello/there/guy\");\n        assert_no_collision!(\"/a/<b>\", \"/b/<b>\");\n        assert_no_collision!(\"/<a>/b\", \"/<b>/a\");\n        assert_no_collision!(\"/t\", \"/test\");\n        assert_no_collision!(\"/a\", \"/aa\");\n        assert_no_collision!(\"/a\", \"/aaa\");\n        assert_no_collision!(\"/\", \"/a\");\n\n        assert_no_collision!(\"/hello\", \"/hello/\");\n        assert_no_collision!(\"/hello/there\", \"/hello/there/\");\n\n        assert_no_collision!(\"/a?<b>\", \"/b\");\n        assert_no_collision!(\"/a/b\", \"/a?<b>\");\n        assert_no_collision!(\"/a/b/c?<d>\", \"/a/b/c/d\");\n        assert_no_collision!(\"/a/hello\", \"/a/?<hello>\");\n        assert_no_collision!(\"/?<a>\", \"/hi\");\n\n        assert_no_collision!(Get \"/\", Post \"/\");\n        assert_no_collision!(Post \"/\", Put \"/\");\n        assert_no_collision!(Put \"/a\", Put \"/\");\n        assert_no_collision!(Post \"/a\", Put \"/\");\n        assert_no_collision!(Get \"/a\", Put \"/\");\n        assert_no_collision!(Get \"/hello\", Put \"/hello\");\n        assert_no_collision!(Get \"/<foo..>\", Post \"/\");\n\n        assert_no_collision!(\"/a\", \"/b\");\n        assert_no_collision!(\"/a/b\", \"/a\");\n        assert_no_collision!(\"/a/b\", \"/a/c\");\n        assert_no_collision!(\"/a/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello/there\", \"/hello/there/guy\");\n        assert_no_collision!(\"/a/<b>\", \"/b/<b>\");\n        assert_no_collision!(\"/a\", \"/b\");\n        assert_no_collision!(\"/a/b\", \"/a\");\n        assert_no_collision!(\"/a/b\", \"/a/c\");\n        assert_no_collision!(\"/a/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello/there\", \"/hello/there/guy\");\n        assert_no_collision!(\"/a/<b>\", \"/b/<b>\");\n        assert_no_collision!(\"/a\", \"/b\");\n        assert_no_collision!(\"/a/b\", \"/a\");\n        assert_no_collision!(\"/a/b\", \"/a/c\");\n        assert_no_collision!(\"/a/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello\", \"/a/c\");\n        assert_no_collision!(\"/hello/there\", \"/hello/there/guy\");\n        assert_no_collision!(\"/a/<b>\", \"/b/<b>\");\n        assert_no_collision!(\"/t\", \"/test\");\n        assert_no_collision!(\"/a\", \"/aa\");\n        assert_no_collision!(\"/a\", \"/aaa\");\n        assert_no_collision!(\"/\", \"/a\");\n\n        assert_no_collision!(\"/foo\", \"/foo/\");\n        assert_no_collision!(\"/foo/bar\", \"/foo/\");\n        assert_no_collision!(\"/foo/bar\", \"/foo/bar/\");\n        assert_no_collision!(\"/foo/<a>\", \"/foo/<a>/\");\n        assert_no_collision!(\"/foo/<a>\", \"/<b>/<a>/\");\n        assert_no_collision!(\"/<b>/<a>\", \"/<b>/<a>/\");\n        assert_no_collision!(\"/a/\", \"/<a>/<b>/<c..>\");\n\n        assert_no_collision!(\"/a\", \"/a/<a..>\");\n        assert_no_collision!(\"/<a>\", \"/a/<a..>\");\n        assert_no_collision!(\"/a/b\", \"/<a>/<b>/<c..>\");\n        assert_no_collision!(\"/a/<b>\", \"/<a>/<b>/<c..>\");\n        assert_no_collision!(\"/<a>/b\", \"/<a>/<b>/<c..>\");\n        assert_no_collision!(\"/hi/<a..>\", \"/hi\");\n\n        assert_no_collision!(ranked \"/<a>\", \"/\");\n        assert_no_collision!(ranked \"/a/\", \"/<a>/\");\n        assert_no_collision!(ranked \"/hello/<a>\", \"/hello/\");\n        assert_no_collision!(ranked \"/\", \"/?a\");\n        assert_no_collision!(ranked \"/\", \"/?<a>\");\n        assert_no_collision!(ranked \"/a/<b>\", \"/a/<b>?d\");\n    }\n\n    #[test]\n    fn collisions() {\n        assert_collision!(\"/<a>\", \"/\");\n        assert_collision!(\"/a\", \"/a\");\n        assert_collision!(\"/hello\", \"/hello\");\n        assert_collision!(\"/hello/there/how/ar\", \"/hello/there/how/ar\");\n        assert_collision!(\"/hello/<a>\", \"/hello/\");\n\n        assert_collision!(\"/<a>\", \"/<b>\");\n        assert_collision!(\"/<a>\", \"/b\");\n        assert_collision!(\"/hello/<name>\", \"/hello/<person>\");\n        assert_collision!(\"/hello/<name>/hi\", \"/hello/<person>/hi\");\n        assert_collision!(\"/hello/<name>/hi/there\", \"/hello/<person>/hi/there\");\n        assert_collision!(\"/<name>/hi/there\", \"/<person>/hi/there\");\n        assert_collision!(\"/<name>/hi/there\", \"/dude/<name>/there\");\n        assert_collision!(\"/<name>/<a>/<b>\", \"/<a>/<b>/<c>\");\n        assert_collision!(\"/<name>/<a>/<b>/\", \"/<a>/<b>/<c>/\");\n        assert_collision!(\"/<a..>\", \"/hi\");\n        assert_collision!(\"/<a..>\", \"/hi/hey\");\n        assert_collision!(\"/<a..>\", \"/hi/hey/hayo\");\n        assert_collision!(\"/a/<a..>\", \"/a/hi/hey/hayo\");\n        assert_collision!(\"/a/<b>/<a..>\", \"/a/hi/hey/hayo\");\n        assert_collision!(\"/a/<b>/<c>/<a..>\", \"/a/hi/hey/hayo\");\n        assert_collision!(\"/<b>/<c>/<a..>\", \"/a/hi/hey/hayo\");\n        assert_collision!(\"/<b>/<c>/hey/hayo\", \"/a/hi/hey/hayo\");\n        assert_collision!(\"/<a..>\", \"/foo\");\n\n        assert_collision!(\"/\", \"/<a..>\");\n        assert_collision!(\"/a/\", \"/a/<a..>\");\n        assert_collision!(\"/<a>/\", \"/a/<a..>\");\n        assert_collision!(\"/<a>/bar/\", \"/a/<a..>\");\n\n        assert_collision!(\"/<a>\", \"/b\");\n        assert_collision!(\"/hello/<name>\", \"/hello/bob\");\n        assert_collision!(\"/<name>\", \"//bob\");\n\n        assert_collision!(\"/<a..>\", \"///a///\");\n        assert_collision!(\"/<a..>\", \"//a/bcjdklfj//<c>\");\n        assert_collision!(\"/a/<a..>\", \"//a/bcjdklfj//<c>\");\n        assert_collision!(\"/a/<b>/<c..>\", \"//a/bcjdklfj//<c>\");\n        assert_collision!(\"/<a..>\", \"/\");\n        assert_collision!(\"/\", \"/<_..>\");\n        assert_collision!(\"/a/b/<a..>\", \"/a/<b..>\");\n        assert_collision!(\"/a/b/<a..>\", \"/a/<b>/<b..>\");\n        assert_collision!(\"/hi/<a..>\", \"/hi/\");\n        assert_collision!(\"/<a..>\", \"//////\");\n\n        assert_collision!(\"/?<a>\", \"/?<a>\");\n        assert_collision!(\"/a/?<a>\", \"/a/?<a>\");\n        assert_collision!(\"/a?<a>\", \"/a?<a>\");\n        assert_collision!(\"/<r>?<a>\", \"/<r>?<a>\");\n        assert_collision!(\"/a/b/c?<a>\", \"/a/b/c?<a>\");\n        assert_collision!(\"/<a>/b/c?<d>\", \"/a/b/<c>?<d>\");\n        assert_collision!(\"/?<a>\", \"/\");\n        assert_collision!(\"/a?<a>\", \"/a\");\n        assert_collision!(\"/a?<a>\", \"/a\");\n        assert_collision!(\"/a/b?<a>\", \"/a/b\");\n        assert_collision!(\"/a/b\", \"/a/b?<c>\");\n\n        assert_collision!(\"/a/hi/<a..>\", \"/a/hi/\");\n        assert_collision!(\"/hi/<a..>\", \"/hi/\");\n        assert_collision!(\"/<a..>\", \"/\");\n    }\n\n    fn mt_mt_collide(mt1: &str, mt2: &str) -> bool {\n        let mt_a = MediaType::from_str(mt1).expect(mt1);\n        let mt_b = MediaType::from_str(mt2).expect(mt2);\n        mt_a.collides_with(&mt_b)\n    }\n\n    #[test]\n    fn test_content_type_collisions() {\n        assert!(mt_mt_collide(\"application/json\", \"application/json\"));\n        assert!(mt_mt_collide(\"*/json\", \"application/json\"));\n        assert!(mt_mt_collide(\"*/*\", \"application/json\"));\n        assert!(mt_mt_collide(\"application/*\", \"application/json\"));\n        assert!(mt_mt_collide(\"application/*\", \"*/json\"));\n        assert!(mt_mt_collide(\"something/random\", \"something/random\"));\n\n        assert!(!mt_mt_collide(\"text/*\", \"application/*\"));\n        assert!(!mt_mt_collide(\"*/text\", \"*/json\"));\n        assert!(!mt_mt_collide(\"*/text\", \"application/test\"));\n        assert!(!mt_mt_collide(\"something/random\", \"something_else/random\"));\n        assert!(!mt_mt_collide(\"something/random\", \"*/else\"));\n        assert!(!mt_mt_collide(\"*/random\", \"*/else\"));\n        assert!(!mt_mt_collide(\"something/*\", \"random/else\"));\n    }\n\n    fn r_mt_mt_collide<S1, S2>(m: Method, mt1: S1, mt2: S2) -> bool\n        where S1: Into<Option<&'static str>>, S2: Into<Option<&'static str>>\n    {\n        let mut route_a = Route::new(m, \"/\", dummy_handler);\n        if let Some(mt_str) = mt1.into() {\n            route_a.format = Some(mt_str.parse::<MediaType>().unwrap());\n        }\n\n        let mut route_b = Route::new(m, \"/\", dummy_handler);\n        if let Some(mt_str) = mt2.into() {\n            route_b.format = Some(mt_str.parse::<MediaType>().unwrap());\n        }\n\n        route_a.collides_with(&route_b)\n    }\n\n    #[test]\n    fn test_route_content_type_collisions() {\n        // non-payload bearing routes always collide\n        assert!(r_mt_mt_collide(Get, \"application/json\", \"application/json\"));\n        assert!(r_mt_mt_collide(Get, \"*/json\", \"application/json\"));\n        assert!(r_mt_mt_collide(Get, \"*/json\", \"application/*\"));\n        assert!(r_mt_mt_collide(Get, \"text/html\", \"text/*\"));\n        assert!(r_mt_mt_collide(Get, \"any/thing\", \"*/*\"));\n\n        assert!(r_mt_mt_collide(Get, None, \"text/*\"));\n        assert!(r_mt_mt_collide(Get, None, \"text/html\"));\n        assert!(r_mt_mt_collide(Get, None, \"*/*\"));\n        assert!(r_mt_mt_collide(Get, \"text/html\", None));\n        assert!(r_mt_mt_collide(Get, \"*/*\", None));\n        assert!(r_mt_mt_collide(Get, \"application/json\", None));\n\n        assert!(r_mt_mt_collide(Get, \"application/*\", \"text/*\"));\n        assert!(r_mt_mt_collide(Get, \"application/json\", \"text/*\"));\n        assert!(r_mt_mt_collide(Get, \"application/json\", \"text/html\"));\n        assert!(r_mt_mt_collide(Get, \"text/html\", \"text/html\"));\n\n        // payload bearing routes collide if the media types collide\n        assert!(r_mt_mt_collide(Post, \"application/json\", \"application/json\"));\n        assert!(r_mt_mt_collide(Post, \"*/json\", \"application/json\"));\n        assert!(r_mt_mt_collide(Post, \"*/json\", \"application/*\"));\n        assert!(r_mt_mt_collide(Post, \"text/html\", \"text/*\"));\n        assert!(r_mt_mt_collide(Post, \"any/thing\", \"*/*\"));\n\n        assert!(r_mt_mt_collide(Post, None, \"text/*\"));\n        assert!(r_mt_mt_collide(Post, None, \"text/html\"));\n        assert!(r_mt_mt_collide(Post, None, \"*/*\"));\n        assert!(r_mt_mt_collide(Post, \"text/html\", None));\n        assert!(r_mt_mt_collide(Post, \"*/*\", None));\n        assert!(r_mt_mt_collide(Post, \"application/json\", None));\n\n        assert!(!r_mt_mt_collide(Post, \"text/html\", \"application/*\"));\n        assert!(!r_mt_mt_collide(Post, \"application/html\", \"text/*\"));\n        assert!(!r_mt_mt_collide(Post, \"*/json\", \"text/html\"));\n        assert!(!r_mt_mt_collide(Post, \"text/html\", \"text/css\"));\n        assert!(!r_mt_mt_collide(Post, \"other/html\", \"text/html\"));\n    }\n\n    fn catchers_collide<A, B>(a: A, ap: &str, b: B, bp: &str) -> bool\n        where A: Into<Option<u16>>, B: Into<Option<u16>>\n    {\n        use crate::catcher::dummy_handler as handler;\n\n        let a = Catcher::new(a, handler).map_base(|_| ap.into()).unwrap();\n        let b = Catcher::new(b, handler).map_base(|_| bp.into()).unwrap();\n        a.collides_with(&b)\n    }\n\n    #[test]\n    fn catcher_collisions() {\n        for path in &[\"/a\", \"/foo\", \"/a/b/c\", \"/a/b/c/d/e\"] {\n            assert!(catchers_collide(404, path, 404, path));\n            assert!(catchers_collide(500, path, 500, path));\n            assert!(catchers_collide(None, path, None, path));\n        }\n    }\n\n    #[test]\n    fn catcher_non_collisions() {\n        assert!(!catchers_collide(404, \"/foo\", 405, \"/foo\"));\n        assert!(!catchers_collide(404, \"/\", None, \"/foo\"));\n        assert!(!catchers_collide(404, \"/\", None, \"/\"));\n        assert!(!catchers_collide(404, \"/a/b\", None, \"/a/b\"));\n        assert!(!catchers_collide(404, \"/a/b\", 404, \"/a/b/c\"));\n\n        assert!(!catchers_collide(None, \"/a/b\", None, \"/a/b/c\"));\n        assert!(!catchers_collide(None, \"/b\", None, \"/a/b/c\"));\n        assert!(!catchers_collide(None, \"/\", None, \"/a/b/c\"));\n    }\n}\n"
  },
  {
    "path": "core/lib/src/router/matcher.rs",
    "content": "use crate::{Route, Request, Catcher};\nuse crate::router::Collide;\nuse crate::http::Status;\nuse crate::route::Color;\n\nimpl Route {\n    /// Returns `true` if `self` matches `request`.\n    ///\n    /// A [_match_](Route#routing) occurs when:\n    ///\n    ///   * The route's method matches that of the incoming request.\n    ///   * Either the route has no format _or_:\n    ///     - If the route's method supports a payload, the request's\n    ///       `Content-Type` is [fully specified] and [collides with] the\n    ///       route's format.\n    ///     - If the route's method does not support a payload, the request\n    ///       either has no `Accept` header or it [collides with] with the\n    ///       route's format.\n    ///   * All static segments in the route's URI match the corresponding\n    ///     components in the same position in the incoming request URI.\n    ///   * The route URI has no query part _or_ all static segments in the\n    ///     route's query string are in the request query string, though in any\n    ///     position.\n    ///\n    /// [fully specified]: crate::http::MediaType::specificity()\n    /// [collides with]: Route::collides_with()\n    ///\n    /// For a request to be routed to a particular route, that route must both\n    /// `match` _and_ have the highest precedence among all matching routes for\n    /// that request. In other words, a `match` is a necessary but insufficient\n    /// condition to determine if a route will handle a particular request.\n    ///\n    /// The precedence of a route is determined by its rank. Routes with lower\n    /// ranks have higher precedence. [By default](Route#default-ranking), more\n    /// specific routes are assigned a lower ranking.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Route;\n    /// use rocket::http::Method;\n    /// # use rocket::local::blocking::Client;\n    /// # use rocket::route::dummy_handler as handler;\n    ///\n    /// // This route handles GET requests to `/<hello>`.\n    /// let a = Route::new(Method::Get, \"/<hello>\", handler);\n    ///\n    /// // This route handles GET requests to `/здрасти`.\n    /// let b = Route::new(Method::Get, \"/здрасти\", handler);\n    ///\n    /// # let client = Client::debug(rocket::build()).unwrap();\n    /// // Let's say `request` is `GET /hello`. The request matches only `a`:\n    /// let request = client.get(\"/hello\");\n    /// # let request = request.inner();\n    /// assert!(a.matches(&request));\n    /// assert!(!b.matches(&request));\n    ///\n    /// // Now `request` is `GET /здрасти`. It matches both `a` and `b`:\n    /// let request = client.get(\"/здрасти\");\n    /// # let request = request.inner();\n    /// assert!(a.matches(&request));\n    /// assert!(b.matches(&request));\n    ///\n    /// // But `b` is more specific, so it has lower rank (higher precedence)\n    /// // by default, so Rocket would route the request to `b`, not `a`.\n    /// assert!(b.rank < a.rank);\n    /// ```\n    #[tracing::instrument(level = \"trace\", name = \"matching\", skip_all, ret)]\n    pub fn matches(&self, request: &Request<'_>) -> bool {\n        methods_match(self, request)\n            && paths_match(self, request)\n            && queries_match(self, request)\n            && formats_match(self, request)\n    }\n}\n\nimpl Catcher {\n    /// Returns `true` if `self` matches errors with `status` that occurred\n    /// during `request`.\n    ///\n    /// A [_match_](Catcher#routing) between a `Catcher` and a (`Status`,\n    /// `&Request`) pair occurs when:\n    ///\n    ///   * The catcher has the same [code](Catcher::code) as\n    ///     [`status`](Status::code) _or_ is `default`.\n    ///   * The catcher's [base](Catcher::base()) is a prefix of the `request`'s\n    ///     [normalized](crate::http::uri::Origin#normalization) URI.\n    ///\n    /// For an error arising from a request to be routed to a particular\n    /// catcher, that catcher must both `match` _and_ have higher precedence\n    /// than any other catcher that matches. In other words, a `match` is a\n    /// necessary but insufficient condition to determine if a catcher will\n    /// handle a particular error.\n    ///\n    /// The precedence of a catcher is determined by:\n    ///\n    ///   1. The number of _complete_ segments in the catcher's `base`.\n    ///   2. Whether the catcher is `default` or not.\n    ///\n    /// Non-default routes, and routes with more complete segments in their\n    /// base, have higher precedence.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Catcher;\n    /// use rocket::http::Status;\n    /// # use rocket::local::blocking::Client;\n    /// # use rocket::catcher::dummy_handler as handler;\n    ///\n    /// // This catcher handles 404 errors with a base of `/`.\n    /// let a = Catcher::new(404, handler);\n    ///\n    /// // This catcher handles 404 errors with a base of `/bar`.\n    /// let b = a.clone().map_base(|_| format!(\"/bar\")).unwrap();\n    ///\n    /// # let client = Client::debug(rocket::build()).unwrap();\n    /// // Let's say `request` is `GET /` that 404s. The error matches only `a`:\n    /// let request = client.get(\"/\");\n    /// # let request = request.inner();\n    /// assert!(a.matches(Status::NotFound, &request));\n    /// assert!(!b.matches(Status::NotFound, &request));\n    ///\n    /// // Now `request` is a 404 `GET /bar`. The error matches `a` and `b`:\n    /// let request = client.get(\"/bar\");\n    /// # let request = request.inner();\n    /// assert!(a.matches(Status::NotFound, &request));\n    /// assert!(b.matches(Status::NotFound, &request));\n    ///\n    /// // Note that because `b`'s base' has more complete segments that `a's,\n    /// // Rocket would route the error to `b`, not `a`, even though both match.\n    /// let a_count = a.base().segments().filter(|s| !s.is_empty()).count();\n    /// let b_count = b.base().segments().filter(|s| !s.is_empty()).count();\n    /// assert!(b_count > a_count);\n    /// ```\n    pub fn matches(&self, status: Status, request: &Request<'_>) -> bool {\n        self.code.map_or(true, |code| code == status.code)\n            && self.base().segments().prefix_of(request.uri().path().segments())\n    }\n}\n\nfn methods_match(route: &Route, req: &Request<'_>) -> bool {\n    trace!(?route.method, request.method = %req.method());\n    route.method.map_or(true, |method| method == req.method())\n}\n\nfn paths_match(route: &Route, req: &Request<'_>) -> bool {\n    trace!(route.uri = %route.uri, request.uri = %req.uri());\n    let route_segments = &route.uri.metadata.uri_segments;\n    let req_segments = req.uri().path().segments();\n\n    // A route can never have more segments than a request. Recall that a\n    // trailing slash is considering a segment, albeit empty.\n    if route_segments.len() > req_segments.num() {\n        return false;\n    }\n\n    // requests with longer paths only match if we have dynamic trail (<a..>).\n    if req_segments.num() > route_segments.len() && !route.uri.metadata.dynamic_trail {\n        return false;\n    }\n\n    // We've checked everything beyond the zip of their lengths already.\n    for (route_seg, req_seg) in route_segments.iter().zip(req_segments.clone()) {\n        if route_seg.dynamic_trail {\n            return true;\n        }\n\n        if !route_seg.dynamic && route_seg.value != req_seg {\n            return false;\n        }\n    }\n\n    true\n}\n\nfn queries_match(route: &Route, req: &Request<'_>) -> bool {\n    trace!(\n        route.query = route.uri.query().map(display),\n        route.query.color = route.uri.metadata.query_color.map(debug),\n        request.query = req.uri().query().map(display),\n    );\n\n    if matches!(route.uri.metadata.query_color, None | Some(Color::Wild)) {\n        return true;\n    }\n\n    let route_query_fields = route.uri.metadata.static_query_fields.iter();\n    for (key, val) in route_query_fields {\n        if let Some(query) = req.uri().query() {\n            if !query.segments().any(|req_seg| req_seg == (key, val)) {\n                debug!(key, val, request.query = %query, \"missing static query\");\n                return false;\n            }\n        } else {\n            debug!(key, val, \"missing static query (queryless request)\");\n            return false;\n        }\n    }\n\n    true\n}\n\nfn formats_match(route: &Route, req: &Request<'_>) -> bool {\n    trace!(\n        route.format = route.format.as_ref().map(display),\n        request.format = req.format().map(display),\n    );\n\n    let route_format = match route.format {\n        Some(ref format) => format,\n        None => return true,\n    };\n\n    match route.method.and_then(|m| m.allows_request_body()) {\n        Some(true) => match req.format() {\n            Some(f) if f.specificity() == 2 => route_format.collides_with(f),\n            _ => false\n        },\n        _ => match req.format() {\n            Some(f) => route_format.collides_with(f),\n            None => true\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::local::blocking::Client;\n    use crate::route::{Route, dummy_handler};\n    use crate::http::{Method, Method::*, MediaType, ContentType, Accept};\n\n    fn req_matches_route(a: &'static str, b: &'static str) -> bool {\n        let client = Client::debug_with(vec![]).expect(\"client\");\n        let route = Route::ranked(0, Get, b, dummy_handler);\n        route.matches(&client.get(a))\n    }\n\n    #[test]\n    fn request_route_matching() {\n        assert!(req_matches_route(\"/a/b?a=b\", \"/a/b?<c>\"));\n        assert!(req_matches_route(\"/a/b?a=b\", \"/<a>/b?<c>\"));\n        assert!(req_matches_route(\"/a/b?a=b\", \"/<a>/<b>?<c>\"));\n        assert!(req_matches_route(\"/a/b?a=b\", \"/a/<b>?<c>\"));\n        assert!(req_matches_route(\"/?b=c\", \"/?<b>\"));\n\n        assert!(req_matches_route(\"/a/b?a=b\", \"/a/b\"));\n        assert!(req_matches_route(\"/a/b\", \"/a/b\"));\n        assert!(req_matches_route(\"/a/b/c/d?\", \"/a/b/c/d\"));\n        assert!(req_matches_route(\"/a/b/c/d?v=1&v=2\", \"/a/b/c/d\"));\n\n        assert!(req_matches_route(\"/a/b\", \"/a/b?<c>\"));\n        assert!(req_matches_route(\"/a/b\", \"/a/b?<c..>\"));\n        assert!(req_matches_route(\"/a/b?c\", \"/a/b?c\"));\n        assert!(req_matches_route(\"/a/b?c\", \"/a/b?<c>\"));\n        assert!(req_matches_route(\"/a/b?c=foo&d=z\", \"/a/b?<c>\"));\n        assert!(req_matches_route(\"/a/b?c=foo&d=z\", \"/a/b?<c..>\"));\n        assert!(req_matches_route(\"/a/b?c=foo&d=z\", \"/a/b?c=foo&<c..>\"));\n        assert!(req_matches_route(\"/a/b?c=foo&d=z\", \"/a/b?d=z&<c..>\"));\n\n        assert!(req_matches_route(\"/\", \"/<foo>\"));\n        assert!(req_matches_route(\"/a\", \"/<foo>\"));\n        assert!(req_matches_route(\"/a\", \"/a\"));\n        assert!(req_matches_route(\"/a/\", \"/a/\"));\n\n        assert!(req_matches_route(\"//\", \"/\"));\n        assert!(req_matches_route(\"/a///\", \"/a/\"));\n        assert!(req_matches_route(\"/a/b\", \"/a/b\"));\n\n        assert!(!req_matches_route(\"/a///\", \"/a\"));\n        assert!(!req_matches_route(\"/a\", \"/a/\"));\n        assert!(!req_matches_route(\"/a/\", \"/a\"));\n        assert!(!req_matches_route(\"/a/b\", \"/a/b/\"));\n\n        assert!(!req_matches_route(\"/a\", \"/<a>/\"));\n        assert!(!req_matches_route(\"/a/\", \"/<a>\"));\n        assert!(!req_matches_route(\"/a/b\", \"/<a>/b/\"));\n        assert!(!req_matches_route(\"/a/b\", \"/<a>/<b>/\"));\n\n        assert!(!req_matches_route(\"/a/b/c\", \"/a/b?<c>\"));\n        assert!(!req_matches_route(\"/a?b=c\", \"/a/b?<c>\"));\n        assert!(!req_matches_route(\"/?b=c\", \"/a/b?<c>\"));\n        assert!(!req_matches_route(\"/?b=c\", \"/a?<c>\"));\n\n        assert!(!req_matches_route(\"/a/\", \"/<a>/<b>/<c..>\"));\n        assert!(!req_matches_route(\"/a/b\", \"/<a>/<b>/<c..>\"));\n\n        assert!(!req_matches_route(\"/a/b?c=foo&d=z\", \"/a/b?a=b&<c..>\"));\n        assert!(!req_matches_route(\"/a/b?c=foo&d=z\", \"/a/b?d=b&<c..>\"));\n        assert!(!req_matches_route(\"/a/b\", \"/a/b?c\"));\n        assert!(!req_matches_route(\"/a/b\", \"/a/b?foo\"));\n        assert!(!req_matches_route(\"/a/b\", \"/a/b?foo&<rest..>\"));\n        assert!(!req_matches_route(\"/a/b\", \"/a/b?<a>&b&<rest..>\"));\n    }\n\n    fn req_matches_format<S1, S2>(m: Method, mt1: S1, mt2: S2) -> bool\n        where S1: Into<Option<&'static str>>, S2: Into<Option<&'static str>>\n    {\n        let client = Client::debug_with(vec![]).expect(\"client\");\n        let mut req = client.req(m, \"/\");\n        if let Some(mt_str) = mt1.into() {\n            if m.allows_request_body() == Some(true) {\n                req.replace_header(mt_str.parse::<ContentType>().unwrap());\n            } else {\n                req.replace_header(mt_str.parse::<Accept>().unwrap());\n            }\n        }\n\n        let mut route = Route::new(m, \"/\", dummy_handler);\n        if let Some(mt_str) = mt2.into() {\n            route.format = Some(mt_str.parse::<MediaType>().unwrap());\n        }\n\n        route.matches(&req)\n    }\n\n    #[test]\n    fn test_req_route_mt_collisions() {\n        assert!(req_matches_format(Post, \"application/json\", \"application/json\"));\n        assert!(req_matches_format(Post, \"application/json\", \"application/*\"));\n        assert!(req_matches_format(Post, \"application/json\", \"*/json\"));\n        assert!(req_matches_format(Post, \"text/html\", \"*/*\"));\n\n        assert!(req_matches_format(Get, \"application/json\", \"application/json\"));\n        assert!(req_matches_format(Get, \"text/html\", \"text/html\"));\n        assert!(req_matches_format(Get, \"text/html\", \"*/*\"));\n        assert!(req_matches_format(Get, None, \"*/*\"));\n        assert!(req_matches_format(Get, None, \"text/*\"));\n        assert!(req_matches_format(Get, None, \"text/html\"));\n        assert!(req_matches_format(Get, None, \"application/json\"));\n\n        assert!(req_matches_format(Post, \"text/html\", None));\n        assert!(req_matches_format(Post, \"application/json\", None));\n        assert!(req_matches_format(Post, \"x-custom/anything\", None));\n        assert!(req_matches_format(Post, None, None));\n\n        assert!(req_matches_format(Get, \"text/html\", None));\n        assert!(req_matches_format(Get, \"application/json\", None));\n        assert!(req_matches_format(Get, \"x-custom/anything\", None));\n        assert!(req_matches_format(Get, None, None));\n        assert!(req_matches_format(Get, None, \"text/html\"));\n        assert!(req_matches_format(Get, None, \"application/json\"));\n\n        assert!(req_matches_format(Get, \"text/html, text/plain\", \"text/html\"));\n        assert!(req_matches_format(Get, \"text/html; q=0.5, text/xml\", \"text/xml\"));\n\n        assert!(!req_matches_format(Post, None, \"text/html\"));\n        assert!(!req_matches_format(Post, None, \"text/*\"));\n        assert!(!req_matches_format(Post, None, \"*/text\"));\n        assert!(!req_matches_format(Post, None, \"*/*\"));\n        assert!(!req_matches_format(Post, None, \"text/html\"));\n        assert!(!req_matches_format(Post, None, \"application/json\"));\n\n        assert!(!req_matches_format(Post, \"application/json\", \"text/html\"));\n        assert!(!req_matches_format(Post, \"application/json\", \"text/*\"));\n        assert!(!req_matches_format(Post, \"application/json\", \"*/xml\"));\n        assert!(!req_matches_format(Get, \"application/json\", \"text/html\"));\n        assert!(!req_matches_format(Get, \"application/json\", \"text/*\"));\n        assert!(!req_matches_format(Get, \"application/json\", \"*/xml\"));\n\n        assert!(!req_matches_format(Post, None, \"text/html\"));\n        assert!(!req_matches_format(Post, None, \"application/json\"));\n    }\n}\n"
  },
  {
    "path": "core/lib/src/router/mod.rs",
    "content": "//! Rocket's router.\n\nmod router;\nmod collider;\nmod matcher;\n\npub(crate) use router::*;\npub(crate) use collider::*;\n"
  },
  {
    "path": "core/lib/src/router/router.rs",
    "content": "use std::ops::{Deref, DerefMut};\nuse std::collections::HashMap;\n\nuse crate::request::Request;\nuse crate::http::{Method, Status};\nuse crate::{Route, Catcher};\nuse crate::router::Collide;\n\n#[derive(Debug)]\npub(crate) struct Router<T>(T);\n\n#[derive(Debug, Default)]\npub struct Pending {\n    pub routes: Vec<Route>,\n    pub catchers: Vec<Catcher>,\n}\n\n#[derive(Debug, Default)]\npub struct Finalized {\n    pub routes: Vec<Route>,\n    pub catchers: Vec<Catcher>,\n    route_map: HashMap<Method, Vec<usize>>,\n    catcher_map: HashMap<Option<u16>, Vec<usize>>,\n}\n\npub type Pair<T> = (T, T);\n\npub type Collisions = (Vec<Pair<Route>>, Vec<Pair<Catcher>>);\n\npub type Result<T, E = Collisions> = std::result::Result<T, E>;\n\nimpl Router<Pending> {\n    pub fn new() -> Self {\n        Router(Pending::default())\n    }\n\n    pub fn finalize(self) -> Result<Router<Finalized>, Collisions> {\n        fn collisions<'a, T>(items: &'a [T]) -> impl Iterator<Item = (T, T)> + 'a\n            where T: Collide + Clone + 'a,\n        {\n            items.iter()\n                .enumerate()\n                .flat_map(move |(i, a)| {\n                    items.iter()\n                        .skip(i + 1)\n                        .filter(move |b| a.collides_with(b))\n                        .map(move |b| (a.clone(), b.clone()))\n                })\n        }\n\n        let route_collisions: Vec<_> = collisions(&self.routes).collect();\n        let catcher_collisions: Vec<_> = collisions(&self.catchers).collect();\n\n        if !route_collisions.is_empty() || !catcher_collisions.is_empty() {\n            return Err((route_collisions, catcher_collisions))\n        }\n\n        // create the route map\n        let mut route_map: HashMap<Method, Vec<usize>> = HashMap::new();\n        for (i, route) in self.routes.iter().enumerate() {\n            match route.method {\n                Some(method) => route_map.entry(method).or_default().push(i),\n                None => for method in Method::ALL_VARIANTS {\n                    route_map.entry(*method).or_default().push(i);\n                }\n            }\n        }\n\n        // create the catcher map\n        let mut catcher_map: HashMap<Option<u16>, Vec<usize>> = HashMap::new();\n        for (i, catcher) in self.catchers.iter().enumerate() {\n            catcher_map.entry(catcher.code).or_default().push(i);\n        }\n\n        // sort routes by rank\n        for routes in route_map.values_mut() {\n            routes.sort_by_key(|&i| &self.routes[i].rank);\n        }\n\n        // sort catchers by rank\n        for catchers in catcher_map.values_mut() {\n            catchers.sort_by_key(|&i| &self.catchers[i].rank);\n        }\n\n        Ok(Router(Finalized {\n            routes: self.0.routes,\n            catchers: self.0.catchers,\n            route_map, catcher_map\n        }))\n    }\n}\n\nimpl Router<Finalized> {\n    #[track_caller]\n    pub fn route<'r, 'a: 'r>(\n        &'a self,\n        req: &'r Request<'r>\n    ) -> impl Iterator<Item = &'a Route> + 'r {\n        // Note that routes are presorted by ascending rank on each `add` and\n        // that all routes with `None` methods have been cloned into all methods.\n        self.route_map.get(&req.method())\n            .into_iter()\n            .flat_map(move |routes| routes.iter().map(move |&i| &self.routes[i]))\n            .filter(move |r| r.matches(req))\n    }\n\n    // For many catchers, using aho-corasick or similar should be much faster.\n    #[track_caller]\n    pub fn catch<'r>(&self, status: Status, req: &'r Request<'r>) -> Option<&Catcher> {\n        // Note that catchers are presorted by descending base length.\n        let explicit = self.catcher_map.get(&Some(status.code))\n            .map(|catchers| catchers.iter().map(|&i| &self.catchers[i]))\n            .and_then(|mut catchers| catchers.find(|c| c.matches(status, req)));\n\n        let default = self.catcher_map.get(&None)\n            .map(|catchers| catchers.iter().map(|&i| &self.catchers[i]))\n            .and_then(|mut catchers| catchers.find(|c| c.matches(status, req)));\n\n        match (explicit, default) {\n            (None, None) => None,\n            (None, c@Some(_)) | (c@Some(_), None) => c,\n            (Some(a), Some(b)) if a.rank <= b.rank => Some(a),\n            (Some(_), Some(b)) => Some(b),\n        }\n    }\n}\n\nimpl<T> Deref for Router<T> {\n    type Target = T;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl DerefMut for Router<Pending> {\n    fn deref_mut(&mut self) -> &mut Self::Target {\n        &mut self.0\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n\n    use crate::route::dummy_handler;\n    use crate::local::blocking::Client;\n    use crate::http::{Method::*, uri::Origin};\n\n    fn make_router<I>(routes: I) -> Result<Router<Finalized>, Collisions>\n        where I: Iterator<Item = (Option<isize>, &'static str)>\n    {\n        let mut router = Router::new();\n        for (rank, route) in routes {\n            let route = Route::ranked(rank, Get, route, dummy_handler);\n            router.routes.push(route);\n        }\n\n        router.finalize()\n    }\n\n    fn router_with_routes(routes: &[&'static str]) -> Router<Finalized> {\n        make_router(routes.iter().map(|r| (None, *r))).unwrap()\n    }\n\n    fn router_with_ranked_routes(routes: &[(isize, &'static str)]) -> Router<Finalized> {\n        make_router(routes.iter().map(|r| (Some(r.0), r.1))).unwrap()\n    }\n\n    fn rankless_route_collisions(routes: &[&'static str]) -> bool {\n        make_router(routes.iter().map(|r| (Some(0), *r))).is_err()\n    }\n\n    fn default_rank_route_collisions(routes: &[&'static str]) -> bool {\n        make_router(routes.iter().map(|r| (None, *r))).is_err()\n    }\n\n    #[test]\n    fn test_rankless_collisions() {\n        assert!(rankless_route_collisions(&[\"/hello\", \"/hello\"]));\n        assert!(rankless_route_collisions(&[\"/<a>\", \"/hello\"]));\n        assert!(rankless_route_collisions(&[\"/<a>\", \"/<b>\"]));\n        assert!(rankless_route_collisions(&[\"/hello/bob\", \"/hello/<b>\"]));\n        assert!(rankless_route_collisions(&[\"/a/b/<c>/d\", \"/<a>/<b>/c/d\"]));\n\n        assert!(rankless_route_collisions(&[\"/a/b\", \"/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/b/c\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/<a>/b\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<b>\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/b/<c>\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/<a..>\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<a..>\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/b/<a..>\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/b/c/d\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/\", \"/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<_>\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<_>\", \"/a/<_..>\"]));\n        assert!(rankless_route_collisions(&[\"/foo/bar/baz\", \"/foo/<_..>\"]));\n\n        assert!(rankless_route_collisions(&[\"/<_>\", \"/<_>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<_>\", \"/a/b\"]));\n        assert!(rankless_route_collisions(&[\"/a/<_>\", \"/a/<b>\"]));\n        assert!(rankless_route_collisions(&[\"/<_..>\", \"/a/b\"]));\n        assert!(rankless_route_collisions(&[\"/<_..>\", \"/<_>\"]));\n        assert!(rankless_route_collisions(&[\"/<_>/b\", \"/a/b\"]));\n        assert!(rankless_route_collisions(&[\"/\", \"/<foo..>\"]));\n        assert!(rankless_route_collisions(&[\"/<_>\", \"/\"]));\n    }\n\n    #[test]\n    fn test_collisions_normalize() {\n        assert!(rankless_route_collisions(&[\"//hello/\", \"/hello//\"]));\n        assert!(rankless_route_collisions(&[\"/hello///bob\", \"/hello/<b>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<a..>//\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<a..>//\", \"/a/b//c//d/\"]));\n        assert!(rankless_route_collisions(&[\"/<a..>//\", \"/a//<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<a..>/\", \"/a/bd/e/\"]));\n        assert!(rankless_route_collisions(&[\"/<a..>/\", \"/a/bd/e/\"]));\n        assert!(rankless_route_collisions(&[\"//\", \"/<foo..>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<a..>//\", \"/a/b//c//d/e/\"]));\n        assert!(rankless_route_collisions(&[\"/a//<a..>//\", \"/a/b//c//d/e/\"]));\n        assert!(rankless_route_collisions(&[\"///<_>\", \"/<_>\"]));\n        assert!(rankless_route_collisions(&[\"/a/<_>\", \"///a//b\"]));\n        assert!(rankless_route_collisions(&[\"//a///<_>\", \"/a//<b>\"]));\n        assert!(rankless_route_collisions(&[\"//<_..>\", \"/a/b\"]));\n        assert!(rankless_route_collisions(&[\"//<_..>\", \"/<_>\"]));\n        assert!(rankless_route_collisions(&[\"///<a>/\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"///<a..>/\", \"/a/<a..>\"]));\n        assert!(rankless_route_collisions(&[\"/<a..>\", \"/hello\"]));\n    }\n\n    #[test]\n    fn test_collisions_query() {\n        // Query shouldn't affect things when rankless.\n        assert!(rankless_route_collisions(&[\"/hello?<foo>\", \"/hello\"]));\n        assert!(rankless_route_collisions(&[\"/<a>?foo=bar\", \"/hello?foo=bar&cat=fat\"]));\n        assert!(rankless_route_collisions(&[\"/<a>?foo=bar\", \"/hello?foo=bar&cat=fat\"]));\n        assert!(rankless_route_collisions(&[\"/<a>\", \"/<b>?<foo>\"]));\n        assert!(rankless_route_collisions(&[\"/hello/bob?a=b\", \"/hello/<b>?d=e\"]));\n        assert!(rankless_route_collisions(&[\"/<foo>?a=b\", \"/foo?d=e\"]));\n        assert!(rankless_route_collisions(&[\"/<foo>?a=b&<c>\", \"/<foo>?d=e&<c>\"]));\n        assert!(rankless_route_collisions(&[\"/<foo>?a=b&<c>\", \"/<foo>?d=e\"]));\n    }\n\n    #[test]\n    fn test_no_collisions() {\n        assert!(!rankless_route_collisions(&[\"/a\", \"/a/\"]));\n        assert!(!rankless_route_collisions(&[\"/<a>\", \"/hello//\"]));\n        assert!(!rankless_route_collisions(&[\"/<a>\", \"/hello///\"]));\n        assert!(!rankless_route_collisions(&[\"/hello/\", \"/hello\"]));\n        assert!(!rankless_route_collisions(&[\"//hello/\", \"/hello\"]));\n        assert!(!rankless_route_collisions(&[\"/a/b\", \"/a/b/c\"]));\n        assert!(!rankless_route_collisions(&[\"/a/b/c/d\", \"/a/b/c/<d>/e\"]));\n        assert!(!rankless_route_collisions(&[\"/a/d/<b..>\", \"/a/b/c\"]));\n        assert!(!rankless_route_collisions(&[\"/a/<_>\", \"/a\"]));\n        assert!(!rankless_route_collisions(&[\"/a/<_>\", \"/<_>\"]));\n        assert!(!rankless_route_collisions(&[\"/a/<b>/<c..>\", \"/a/<c>\"]));\n        assert!(!rankless_route_collisions(&[\"/<_>\", \"/a/<_..>\"]));\n        assert!(!rankless_route_collisions(&[\"/foo\", \"/foo/<_..>\"]));\n        assert!(!rankless_route_collisions(&[\"/a/<_..>\", \"/<_>\"]));\n        assert!(!rankless_route_collisions(&[\"/a/<_..>\", \"/a\"]));\n        assert!(!rankless_route_collisions(&[\"/<a>\", \"/a/<a..>\"]));\n        assert!(!rankless_route_collisions(&[\"/a/d/<b..>\", \"/a/d\"]));\n    }\n\n    #[test]\n    fn test_no_collision_when_ranked() {\n        assert!(!default_rank_route_collisions(&[\"/<_>\", \"/\"]));\n        assert!(!default_rank_route_collisions(&[\"/<a>\", \"/hello\"]));\n        assert!(!default_rank_route_collisions(&[\"/hello/bob\", \"/hello/<b>\"]));\n        assert!(!default_rank_route_collisions(&[\"/a/b/c/d\", \"/<a>/<b>/c/d\"]));\n        assert!(!default_rank_route_collisions(&[\"/hi\", \"/<hi>\"]));\n        assert!(!default_rank_route_collisions(&[\"/a\", \"/a/<path..>\"]));\n        assert!(!default_rank_route_collisions(&[\"/\", \"/<path..>\"]));\n        assert!(!default_rank_route_collisions(&[\"/a/b\", \"/a/b/<c..>\"]));\n        assert!(!default_rank_route_collisions(&[\"/<_>\", \"/static\"]));\n        assert!(!default_rank_route_collisions(&[\"/<_..>\", \"/static\"]));\n        assert!(!default_rank_route_collisions(&[\"/<path..>\", \"/\"]));\n        assert!(!default_rank_route_collisions(&[\"/<_>/<_>\", \"/foo/bar\"]));\n        assert!(!default_rank_route_collisions(&[\"/foo/<_>\", \"/foo/bar\"]));\n\n        assert!(!default_rank_route_collisions(&[\"/<a>/<b>\", \"/hello/<b>\"]));\n        assert!(!default_rank_route_collisions(&[\"/<a>/<b..>\", \"/hello/<b>\"]));\n        assert!(!default_rank_route_collisions(&[\"/<a..>\", \"/hello/<b>\"]));\n        assert!(!default_rank_route_collisions(&[\"/<a..>\", \"/hello\"]));\n        assert!(!default_rank_route_collisions(&[\"/<a>\", \"/a/<path..>\"]));\n        assert!(!default_rank_route_collisions(&[\"/a/<b>/c\", \"/<d>/<c..>\"]));\n        assert!(!default_rank_route_collisions(&[\"/a/<b>/<c..>\", \"/a/<c>\"]));\n    }\n\n    #[test]\n    fn test_collision_when_ranked() {\n        assert!(default_rank_route_collisions(&[\"/<a>/b\", \"/a/<b>\"]));\n    }\n\n    #[test]\n    fn test_collision_when_ranked_query() {\n        assert!(default_rank_route_collisions(&[\"/a?a=b\", \"/a?c=d\"]));\n        assert!(default_rank_route_collisions(&[\"/a?a=b&<b>\", \"/a?<c>&c=d\"]));\n        assert!(default_rank_route_collisions(&[\"/a?a=b&<b..>\", \"/a?<c>&c=d\"]));\n    }\n\n    #[test]\n    fn test_no_collision_when_ranked_query() {\n        assert!(!default_rank_route_collisions(&[\"/\", \"/?<c..>\"]));\n        assert!(!default_rank_route_collisions(&[\"/hi\", \"/hi?<c>\"]));\n        assert!(!default_rank_route_collisions(&[\"/hi\", \"/hi?c\"]));\n        assert!(!default_rank_route_collisions(&[\"/hi?<c>\", \"/hi?c\"]));\n        assert!(!default_rank_route_collisions(&[\"/<foo>?a=b\", \"/<foo>?c=d&<d>\"]));\n    }\n\n    #[track_caller]\n    fn matches<'a>(router: &'a Router<Finalized>, method: Method, uri: &'a str) -> Vec<&'a Route> {\n        let client = Client::debug_with(vec![]).expect(\"client\");\n        let request = client.req(method, Origin::parse(uri).unwrap());\n        router.route(&request).collect()\n    }\n\n    #[track_caller]\n    fn route<'a>(router: &'a Router<Finalized>, method: Method, uri: &'a str) -> Option<&'a Route> {\n        matches(router, method, uri).into_iter().next()\n    }\n\n    #[test]\n    fn test_ok_routing() {\n        let router = router_with_routes(&[\"/hello\"]);\n        assert!(route(&router, Get, \"/hello\").is_some());\n\n        let router = router_with_routes(&[\"/<a>\"]);\n        assert!(route(&router, Get, \"/\").is_some());\n        assert!(route(&router, Get, \"/hello\").is_some());\n        assert!(route(&router, Get, \"/hi\").is_some());\n        assert!(route(&router, Get, \"/bobbbbbbbbbby\").is_some());\n        assert!(route(&router, Get, \"/dsfhjasdf\").is_some());\n\n        let router = router_with_routes(&[\"/<a>/<b>\"]);\n        assert!(route(&router, Get, \"/hello/hi\").is_some());\n        assert!(route(&router, Get, \"/i/a\").is_some());\n        assert!(route(&router, Get, \"/jdlk/asdij\").is_some());\n        assert!(route(&router, Get, \"/a/\").is_some());\n\n        let mut router = Router::new();\n        router.routes.push(Route::new(Put, \"/hello\", dummy_handler));\n        router.routes.push(Route::new(Post, \"/hello\", dummy_handler));\n        router.routes.push(Route::new(Delete, \"/hello\", dummy_handler));\n        let router = router.finalize().unwrap();\n        assert!(route(&router, Put, \"/hello\").is_some());\n        assert!(route(&router, Post, \"/hello\").is_some());\n        assert!(route(&router, Delete, \"/hello\").is_some());\n\n        let router = router_with_routes(&[\"/<a..>\"]);\n        assert!(route(&router, Get, \"/\").is_some());\n        assert!(route(&router, Get, \"//\").is_some());\n        assert!(route(&router, Get, \"/hi\").is_some());\n        assert!(route(&router, Get, \"/hello/hi\").is_some());\n        assert!(route(&router, Get, \"/a/b/\").is_some());\n        assert!(route(&router, Get, \"/i/a\").is_some());\n        assert!(route(&router, Get, \"/a/b/c/d/e/f\").is_some());\n\n        let router = router_with_routes(&[\"/foo/<a..>\"]);\n        assert!(route(&router, Get, \"/foo\").is_none());\n        assert!(route(&router, Get, \"/foo/\").is_some());\n        assert!(route(&router, Get, \"/foo///bar\").is_some());\n    }\n\n    #[test]\n    fn test_err_routing() {\n        let router = router_with_routes(&[\"/hello\"]);\n        assert!(route(&router, Put, \"/hello\").is_none());\n        assert!(route(&router, Post, \"/hello\").is_none());\n        assert!(route(&router, Options, \"/hello\").is_none());\n        assert!(route(&router, Get, \"/hell\").is_none());\n        assert!(route(&router, Get, \"/hi\").is_none());\n        assert!(route(&router, Get, \"/hello/there\").is_none());\n        assert!(route(&router, Get, \"/hello/i\").is_none());\n        assert!(route(&router, Get, \"/hillo\").is_none());\n\n        let router = router_with_routes(&[\"/<a>\"]);\n        assert!(route(&router, Put, \"/hello\").is_none());\n        assert!(route(&router, Post, \"/hello\").is_none());\n        assert!(route(&router, Options, \"/hello\").is_none());\n        assert!(route(&router, Get, \"/hello/\").is_none());\n        assert!(route(&router, Get, \"/hello/there/\").is_none());\n        assert!(route(&router, Get, \"/hello/there/\").is_none());\n\n        let router = router_with_routes(&[\"/<a>/<b>\"]);\n        assert!(route(&router, Get, \"/a/b/c\").is_none());\n        assert!(route(&router, Get, \"/a\").is_none());\n        assert!(route(&router, Get, \"/a/b/c/d\").is_none());\n        assert!(route(&router, Get, \"/a/b/\").is_none());\n        assert!(route(&router, Put, \"/hello/hi\").is_none());\n        assert!(route(&router, Put, \"/a/b\").is_none());\n\n        let router = router_with_routes(&[\"/prefix/<a..>\"]);\n        assert!(route(&router, Get, \"/\").is_none());\n        assert!(route(&router, Get, \"/prefi/\").is_none());\n    }\n\n    /// Asserts that `$to` routes to `$want` given `$routes` are present.\n    macro_rules! assert_ranked_match {\n        ($routes:expr, $to:expr => $want:expr) => ({\n            let router = router_with_routes($routes);\n            let route_path = route(&router, Get, $to).unwrap().uri.to_string();\n            assert_eq!(route_path, $want.to_string(),\n                \"\\nmatched {} with {}, wanted {} in {:#?}\", $to, route_path, $want, router);\n        })\n    }\n\n    #[test]\n    fn test_default_ranking() {\n        assert_ranked_match!(&[\"/hello\", \"/<name>\"], \"/hello\" => \"/hello\");\n        assert_ranked_match!(&[\"/<name>\", \"/hello\"], \"/hello\" => \"/hello\");\n        assert_ranked_match!(&[\"/<a>\", \"/hi\", \"/hi/<b>\"], \"/hi\" => \"/hi\");\n        assert_ranked_match!(&[\"/<a>/b\", \"/hi/c\"], \"/hi/c\" => \"/hi/c\");\n        assert_ranked_match!(&[\"/<a>/<b>\", \"/hi/a\"], \"/hi/c\" => \"/<a>/<b>\");\n        assert_ranked_match!(&[\"/hi/a\", \"/hi/<c>\"], \"/hi/c\" => \"/hi/<c>\");\n        assert_ranked_match!(&[\"/a\", \"/a?<b>\"], \"/a?b=c\" => \"/a?<b>\");\n        assert_ranked_match!(&[\"/a\", \"/a?<b>\"], \"/a\" => \"/a?<b>\");\n        assert_ranked_match!(&[\"/a\", \"/<a>\", \"/a?<b>\", \"/<a>?<b>\"], \"/a\" => \"/a?<b>\");\n        assert_ranked_match!(&[\"/a\", \"/<a>\", \"/a?<b>\", \"/<a>?<b>\"], \"/b\" => \"/<a>?<b>\");\n        assert_ranked_match!(&[\"/a\", \"/<a>\", \"/a?<b>\", \"/<a>?<b>\"], \"/b?v=1\" => \"/<a>?<b>\");\n        assert_ranked_match!(&[\"/a\", \"/<a>\", \"/a?<b>\", \"/<a>?<b>\"], \"/a?b=c\" => \"/a?<b>\");\n        assert_ranked_match!(&[\"/a\", \"/a?b\"], \"/a?b\" => \"/a?b\");\n        assert_ranked_match!(&[\"/<a>\", \"/a?b\"], \"/a?b\" => \"/a?b\");\n        assert_ranked_match!(&[\"/a\", \"/<a>?b\"], \"/a?b\" => \"/a\");\n        assert_ranked_match!(&[\"/a?<c>&b\", \"/a?<b>\"], \"/a\" => \"/a?<b>\");\n        assert_ranked_match!(&[\"/a?<c>&b\", \"/a?<b>\"], \"/a?b\" => \"/a?<c>&b\");\n        assert_ranked_match!(&[\"/a?<c>&b\", \"/a?<b>\"], \"/a?c\" => \"/a?<b>\");\n        assert_ranked_match!(&[\"/\", \"/<foo..>\"], \"/\" => \"/\");\n        assert_ranked_match!(&[\"/\", \"/<foo..>\"], \"/hi\" => \"/<foo..>\");\n        assert_ranked_match!(&[\"/hi\", \"/<foo..>\"], \"/hi\" => \"/hi\");\n    }\n\n    fn ranked_collisions(routes: &[(isize, &'static str)]) -> bool {\n        make_router(routes.iter().map(|r| (Some(r.0), r.1))).is_err()\n    }\n\n    #[test]\n    fn test_no_manual_ranked_collisions() {\n        assert!(!ranked_collisions(&[(1, \"/a/<b>\"), (2, \"/a/<b>\")]));\n        assert!(!ranked_collisions(&[(0, \"/a/<b>\"), (2, \"/a/<b>\")]));\n        assert!(!ranked_collisions(&[(5, \"/a/<b>\"), (2, \"/a/<b>\")]));\n        assert!(!ranked_collisions(&[(1, \"/a/<b>\"), (1, \"/b/<b>\")]));\n        assert!(!ranked_collisions(&[(1, \"/a/<b..>\"), (2, \"/a/<b..>\")]));\n        assert!(!ranked_collisions(&[(0, \"/a/<b..>\"), (2, \"/a/<b..>\")]));\n        assert!(!ranked_collisions(&[(5, \"/a/<b..>\"), (2, \"/a/<b..>\")]));\n        assert!(!ranked_collisions(&[(1, \"/<a..>\"), (2, \"/<a..>\")]));\n    }\n\n    #[test]\n    fn test_ranked_collisions() {\n        assert!(ranked_collisions(&[(2, \"/a/<b..>\"), (2, \"/a/<b..>\")]));\n        assert!(ranked_collisions(&[(2, \"/a/c/<b..>\"), (2, \"/a/<b..>\")]));\n        assert!(ranked_collisions(&[(2, \"/<b..>\"), (2, \"/a/<b..>\")]));\n    }\n\n    macro_rules! assert_ranked_routing {\n        (to: $to:expr, with: $routes:expr, expect: $($want:expr),+) => ({\n            let router = router_with_ranked_routes(&$routes);\n            let routed_to = matches(&router, Get, $to);\n            let expected = &[$($want),+];\n            assert_eq!(routed_to.len(), expected.len());\n            for (got, expected) in routed_to.iter().zip(expected.iter()) {\n                assert_eq!(got.rank, expected.0);\n                assert_eq!(got.uri.to_string(), expected.1.to_string());\n            }\n        })\n    }\n\n    #[test]\n    fn test_ranked_routing() {\n        assert_ranked_routing!(\n            to: \"/a/b\",\n            with: [(1, \"/a/<b>\"), (2, \"/a/<b>\")],\n            expect: (1, \"/a/<b>\"), (2, \"/a/<b>\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/b/b\",\n            with: [(1, \"/a/<b>\"), (2, \"/b/<b>\"), (3, \"/b/b\")],\n            expect: (2, \"/b/<b>\"), (3, \"/b/b\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/b/b\",\n            with: [(2, \"/b/<b>\"), (1, \"/a/<b>\"), (3, \"/b/b\")],\n            expect: (2, \"/b/<b>\"), (3, \"/b/b\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/b/b\",\n            with: [(3, \"/b/b\"), (2, \"/b/<b>\"), (1, \"/a/<b>\")],\n            expect: (2, \"/b/<b>\"), (3, \"/b/b\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/b/b\",\n            with: [(1, \"/a/<b>\"), (2, \"/b/<b>\"), (0, \"/b/b\")],\n            expect: (0, \"/b/b\"), (2, \"/b/<b>\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/profile/sergio/edit\",\n            with: [(1, \"/<a>/<b>/edit\"), (2, \"/profile/<d>\"), (0, \"/<a>/<b>/<c>\")],\n            expect: (0, \"/<a>/<b>/<c>\"), (1, \"/<a>/<b>/edit\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/profile/sergio/edit\",\n            with: [(0, \"/<a>/<b>/edit\"), (2, \"/profile/<d>\"), (5, \"/<a>/<b>/<c>\")],\n            expect: (0, \"/<a>/<b>/edit\"), (5, \"/<a>/<b>/<c>\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/a/b\",\n            with: [(0, \"/a/b\"), (1, \"/a/<b..>\")],\n            expect: (0, \"/a/b\"), (1, \"/a/<b..>\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/a/b/c/d/e/f\",\n            with: [(1, \"/a/<b..>\"), (2, \"/a/b/<c..>\")],\n            expect: (1, \"/a/<b..>\"), (2, \"/a/b/<c..>\")\n        );\n\n        assert_ranked_routing!(\n            to: \"/hi/\",\n            with: [(1, \"/hi/<foo..>\"), (0, \"/hi/<foo>\")],\n            expect: (0, \"/hi/<foo>\"), (1, \"/hi/<foo..>\")\n        );\n    }\n\n    macro_rules! assert_default_ranked_routing {\n        (to: $to:expr, with: $routes:expr, expect: $($want:expr),+) => ({\n            let router = router_with_routes(&$routes);\n            let routed_to = matches(&router, Get, $to);\n            let expected = &[$($want),+];\n            assert!(routed_to.len() == expected.len());\n            for (got, expected) in routed_to.iter().zip(expected.iter()) {\n                assert_eq!(got.uri.to_string(), expected.to_string());\n            }\n        })\n    }\n\n    #[test]\n    fn test_default_ranked_routing() {\n        assert_default_ranked_routing!(\n            to: \"/a/b?v=1\",\n            with: [\"/a/<b>\", \"/a/b\"],\n            expect: \"/a/b\", \"/a/<b>\"\n        );\n\n        assert_default_ranked_routing!(\n            to: \"/a/b?v=1\",\n            with: [\"/a/<b>\", \"/a/b\", \"/a/b?<v>\"],\n            expect: \"/a/b?<v>\", \"/a/b\", \"/a/<b>\"\n        );\n\n        assert_default_ranked_routing!(\n            to: \"/a/b?v=1\",\n            with: [\"/a/<b>\", \"/a/b\", \"/a/b?<v>\", \"/a/<b>?<v>\"],\n            expect: \"/a/b?<v>\", \"/a/b\", \"/a/<b>?<v>\", \"/a/<b>\"\n        );\n\n        assert_default_ranked_routing!(\n            to: \"/a/b\",\n            with: [\"/a/<b>\", \"/a/b\", \"/a/b?<v>\", \"/a/<b>?<v>\"],\n            expect: \"/a/b?<v>\", \"/a/b\", \"/a/<b>?<v>\", \"/a/<b>\"\n        );\n\n        assert_default_ranked_routing!(\n            to: \"/a/b?c\",\n            with: [\"/a/b\", \"/a/b?<c>\", \"/a/b?c\", \"/a/<b>?c\", \"/a/<b>?<c>\", \"/<a>/<b>\"],\n            expect: \"/a/b?c\", \"/a/b?<c>\", \"/a/b\", \"/a/<b>?c\", \"/a/<b>?<c>\", \"/<a>/<b>\"\n        );\n    }\n\n    fn router_with_catchers(catchers: &[(Option<u16>, &str)]) -> Result<Router<Finalized>> {\n        let mut router = Router::new();\n        for (code, base) in catchers {\n            let catcher = Catcher::new(*code, crate::catcher::dummy_handler);\n            router.catchers.push(catcher.map_base(|_| base.to_string()).unwrap());\n        }\n\n        router.finalize()\n    }\n\n    #[track_caller]\n    fn catcher<'a>(r: &'a Router<Finalized>, status: Status, uri: &str) -> Option<&'a Catcher> {\n        let client = Client::debug_with(vec![]).expect(\"client\");\n        let request = client.get(Origin::parse(uri).unwrap());\n        r.catch(status, &request)\n    }\n\n    macro_rules! assert_catcher_routing {\n        (\n            catch: [$(($code:expr, $uri:expr)),+],\n            reqs: [$($r:expr),+],\n            with: [$(($ecode:expr, $euri:expr)),+]\n        ) => ({\n            let catchers = vec![$(($code.into(), $uri)),+];\n            let requests = vec![$($r),+];\n            let expected = vec![$(($ecode.into(), $euri)),+];\n\n            let router = router_with_catchers(&catchers).expect(\"valid router\");\n            for (req, expected) in requests.iter().zip(expected.iter()) {\n                let req_status = Status::from_code(req.0).expect(\"valid status\");\n                let catcher = catcher(&router, req_status, req.1).expect(\"some catcher\");\n                assert_eq!(catcher.code, expected.0,\n                    \"\\nmatched {:?}, expected {:?} for req {:?}\", catcher, expected, req);\n\n                assert_eq!(catcher.base.path(), expected.1,\n                    \"\\nmatched {:?}, expected {:?} for req {:?}\", catcher, expected, req);\n            }\n        })\n    }\n\n    #[test]\n    fn test_catcher_routing() {\n        // Check that the default `/` catcher catches everything.\n        assert_catcher_routing! {\n            catch: [(None, \"/\")],\n            reqs: [(404, \"/a/b/c\"), (500, \"/a/b\"), (415, \"/a/b/d\"), (422, \"/a/b/c/d?foo\")],\n            with: [(None, \"/\"), (None, \"/\"), (None, \"/\"), (None, \"/\")]\n        }\n\n        // Check prefixes when they're exact.\n        assert_catcher_routing! {\n            catch: [(None, \"/\"), (None, \"/a\"), (None, \"/a/b\")],\n            reqs: [\n                (404, \"/\"), (500, \"/\"),\n                (404, \"/a\"), (500, \"/a\"),\n                (404, \"/a/b\"), (500, \"/a/b\")\n            ],\n            with: [\n                (None, \"/\"), (None, \"/\"),\n                (None, \"/a\"), (None, \"/a\"),\n                (None, \"/a/b\"), (None, \"/a/b\")\n            ]\n        }\n\n        // Check prefixes when they're not exact.\n        assert_catcher_routing! {\n            catch: [(None, \"/\"), (None, \"/a\"), (None, \"/a/b\")],\n            reqs: [\n                (404, \"/foo\"), (500, \"/bar\"), (422, \"/baz/bar\"), (418, \"/poodle?yes\"),\n                (404, \"/a/foo\"), (500, \"/a/bar/baz\"), (510, \"/a/c\"), (423, \"/a/c/b\"),\n                (404, \"/a/b/c\"), (500, \"/a/b/c/d\"), (500, \"/a/b?foo\"), (400, \"/a/b/yes\")\n            ],\n            with: [\n                (None, \"/\"), (None, \"/\"), (None, \"/\"), (None, \"/\"),\n                (None, \"/a\"), (None, \"/a\"), (None, \"/a\"), (None, \"/a\"),\n                (None, \"/a/b\"), (None, \"/a/b\"), (None, \"/a/b\"), (None, \"/a/b\")\n            ]\n        }\n\n        // Check that we prefer specific to default.\n        assert_catcher_routing! {\n            catch: [(400, \"/\"), (404, \"/\"), (None, \"/\")],\n            reqs: [\n                (400, \"/\"), (400, \"/bar\"), (400, \"/foo/bar\"),\n                (404, \"/\"), (404, \"/bar\"), (404, \"/foo/bar\"),\n                (405, \"/\"), (405, \"/bar\"), (406, \"/foo/bar\")\n            ],\n            with: [\n                (400, \"/\"), (400, \"/\"), (400, \"/\"),\n                (404, \"/\"), (404, \"/\"), (404, \"/\"),\n                (None, \"/\"), (None, \"/\"), (None, \"/\")\n            ]\n        }\n\n        // Check that we prefer longer prefixes over specific.\n        assert_catcher_routing! {\n            catch: [(None, \"/a/b\"), (404, \"/a\"), (422, \"/a\")],\n            reqs: [\n                (404, \"/a/b\"), (404, \"/a/b/c\"), (422, \"/a/b/c\"),\n                (404, \"/a\"), (404, \"/a/c\"), (404, \"/a/cat/bar\"),\n                (422, \"/a\"), (422, \"/a/c\"), (422, \"/a/cat/bar\")\n            ],\n            with: [\n                (None, \"/a/b\"), (None, \"/a/b\"), (None, \"/a/b\"),\n                (404, \"/a\"), (404, \"/a\"), (404, \"/a\"),\n                (422, \"/a\"), (422, \"/a\"), (422, \"/a\")\n            ]\n        }\n\n        // Just a fun one.\n        assert_catcher_routing! {\n            catch: [(None, \"/\"), (None, \"/a/b\"), (500, \"/a/b/c\"), (500, \"/a/b\")],\n            reqs: [(404, \"/a/b/c\"), (500, \"/a/b\"), (400, \"/a/b/d\"), (500, \"/a/b/c/d?foo\")],\n            with: [(None, \"/a/b\"), (500, \"/a/b\"), (None, \"/a/b\"), (500, \"/a/b/c\")]\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/sentinel.rs",
    "content": "use std::fmt;\nuse std::any::TypeId;\n\nuse crate::{Rocket, Ignite};\n\n/// An automatic last line of defense against launching an invalid [`Rocket`].\n///\n/// A sentinel, automatically run on [`ignition`](Rocket::ignite()), can trigger\n/// a launch abort should an instance fail to meet arbitrary conditions. Every\n/// type that appears in a **mounted** route's type signature is eligible to be\n/// a sentinel. Of these, those that implement `Sentinel` have their\n/// [`abort()`](Sentinel::abort()) method invoked automatically, immediately\n/// after ignition, once for each unique type. Sentinels inspect the finalized\n/// instance of `Rocket` and can trigger a launch abort by returning `true`.\n///\n/// # Built-In Sentinels\n///\n/// The [`State<T>`] type is a sentinel that triggers an abort if the finalized\n/// `Rocket` instance is not managing state for type `T`. Doing so prevents\n/// run-time failures of the `State` request guard.\n///\n/// [`State<T>`]: crate::State\n/// [`State`]: crate::State\n///\n/// ## Example\n///\n/// As an example, consider the following simple application:\n///\n/// ```rust\n/// # use rocket::*;\n/// # type Response = ();\n/// #[get(\"/<id>\")]\n/// fn index(id: usize, state: &State<String>) -> Response {\n///     /* ... */\n/// }\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().mount(\"/\", routes![index])\n/// }\n///\n/// # use rocket::{Config, error::ErrorKind};\n/// # rocket::async_test(async {\n/// #    let result = rocket().reconfigure(Config::debug_default()).ignite().await;\n/// #    assert!(matches!(result.unwrap_err().kind(), ErrorKind::SentinelAborts(..)));\n/// # })\n/// ```\n///\n/// At ignition time, effected by the `#[launch]` attribute here, Rocket probes\n/// all types in all mounted routes for `Sentinel` implementations. In this\n/// example, the types are: `usize`, `State<String>`, and `Response`. Those that\n/// implement `Sentinel` are queried for an abort trigger via their\n/// [`Sentinel::abort()`] method. In this example, the sentinel types are\n/// [`State`] and _potentially_ `Response`, if it implements\n/// `Sentinel`. If `abort()` returns true, launch is aborted with a\n/// corresponding error.\n///\n/// In this example, launch will be aborted because state of type `String` is\n/// not being managed. To correct the error and allow launching to proceed\n/// nominally, a value of type `String` must be managed:\n///\n/// ```rust\n/// # use rocket::*;\n/// # type Response = ();\n/// # #[get(\"/<id>\")]\n/// # fn index(id: usize, state: &State<String>) -> Response {\n/// #     /* ... */\n/// # }\n/// #\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build()\n///         .mount(\"/\", routes![index])\n///         .manage(String::from(\"my managed string\"))\n/// }\n///\n/// # use rocket::{Config, error::ErrorKind};\n/// # rocket::async_test(async {\n/// #    rocket().reconfigure(Config::debug_default()).ignite().await.unwrap();\n/// # })\n/// ```\n///\n/// # Embedded Sentinels\n///\n/// Embedded types -- type parameters of already eligible types -- are also\n/// eligible to be sentinels. Consider the following route:\n///\n/// ```rust\n/// # use rocket::*;\n/// # use either::Either;\n/// # type Inner<T> = Option<T>;\n/// # type Foo = ();\n/// # type Bar = ();\n/// #[get(\"/\")]\n/// fn f(guard: Option<&State<String>>) -> Either<Foo, Inner<Bar>> {\n///     unimplemented!()\n/// }\n/// ```\n///\n/// The directly eligible sentinel types, guard and responders, are:\n///\n///   * `Option<&State<String>>`\n///   * `Either<Foo, Inner<Bar>>`\n///\n/// In addition, all embedded types are _also_ eligible. These are:\n///\n///   * `&State<String>`\n///   * `State<String>`\n///   * `String`\n///   * `Foo`\n///   * `Inner<Bar>`\n///   * `Bar`\n///\n/// A type, whether embedded or not, is queried if it is a `Sentinel` _and_ none\n/// of its parent types are sentinels. Said a different way, if every _directly_\n/// eligible type is viewed as the root of an acyclic graph with edges between a\n/// type and its type parameters, the _first_ `Sentinel` in breadth-first order\n/// is queried:\n///\n/// ```text\n/// 1.     Option<&State<String>>        Either<Foo, Inner<Bar>>\n///                 |                           /         \\\n/// 2.        &State<String>                   Foo     Inner<Bar>\n///                 |                                     |\n/// 3.         State<String>                              Bar\n///                 |\n/// 4.            String\n/// ```\n///\n/// In each graph above, types are queried from top to bottom, level 1 to 4.\n/// Querying continues down paths where the parents were _not_ sentinels. For\n/// example, if `Option` is a sentinel but `Either` is not, then querying stops\n/// for the left subgraph (`Option`) but continues for the right subgraph\n/// `Either`.\n///\n/// # Limitations\n///\n/// Because Rocket must know which `Sentinel` implementation to query based on\n/// its _written_ type, generally only explicitly written, resolved, concrete\n/// types are eligible to be sentinels. A typical application will only work\n/// with such types, but there are several common cases to be aware of.\n///\n/// ## `impl Trait`\n///\n/// Occasionally an existential `impl Trait` may find its way into return types:\n///\n/// ```rust\n/// # use rocket::*;\n/// # use either::Either;\n/// use rocket::response::Responder;\n/// # type AnotherSentinel = ();\n///\n/// #[get(\"/\")]\n/// fn f<'r>() -> Either<impl Responder<'r, 'static>, AnotherSentinel> {\n///     /* ... */\n///     # Either::Left(())\n/// }\n/// ```\n///\n/// **Note:** _Rocket actively discourages using `impl Trait` in route\n/// signatures. In addition to impeding sentinel discovery, doing so decreases\n/// the ability to glean a handler's functionality based on its type signature._\n///\n/// The return type of the route `f` depends on its implementation. At present,\n/// it is not possible to name the underlying concrete type of an `impl Trait`\n/// at compile-time and thus not possible to determine if it implements\n/// `Sentinel`. As such, existentials _are not_ eligible to be sentinels.\n///\n/// That being said, this limitation only applies _per embedding_: types\n/// embedded inside of an `impl Trait` _are_ eligible. As such, in the example\n/// above, the named `AnotherSentinel` type continues to be eligible.\n///\n/// When possible, prefer to name all types:\n///\n/// ```rust\n/// # use rocket::*;\n/// # use either::Either;\n/// # type AbortingSentinel = ();\n/// # type AnotherSentinel = ();\n/// #[get(\"/\")]\n/// fn f() -> Either<AbortingSentinel, AnotherSentinel> {\n///     /* ... */\n///     # unimplemented!()\n/// }\n/// ```\n///\n/// ## Aliases\n///\n/// _Embedded_ sentinels made opaque by a type alias will fail to be considered;\n/// the aliased type itself _is_ considered. In the example below, only\n/// `Result<Foo, Bar>` will be considered, while the embedded `Foo` and `Bar`\n/// will not.\n///\n/// ```rust\n/// # use rocket::get;\n/// # type Foo = ();\n/// # type Bar = ();\n/// type SomeAlias = Result<Foo, Bar>;\n///\n/// #[get(\"/\")]\n/// fn f() -> SomeAlias {\n///     /* ... */\n///     # unimplemented!()\n/// }\n/// ```\n///\n/// Note, however, that `Option<T>` and [`Debug<T>`](crate::response::Debug) are\n/// a sentinels if `T: Sentinel`, and `Result<T, E>` and `Either<T, E>` are\n/// sentinels if _both_ `T: Sentinel, E: Sentinel`. Thus, for these specific\n/// cases, a type alias _will_ \"consider\" embeddings. Nevertheless, prefer to\n/// write concrete types when possible.\n///\n/// ## Type Macros\n///\n/// It is impossible to determine, a priori, what a type macro will expand to.\n/// As such, Rocket is unable to determine which sentinels, if any, a type macro\n/// references, and thus no sentinels are discovered from type macros.\n///\n/// Even approximations are impossible. For example, consider the following:\n///\n/// ```rust\n/// # use rocket::*;\n/// macro_rules! MyType {\n///     (State<'_, u32>) => (&'_ rocket::Config)\n/// }\n///\n/// #[get(\"/\")]\n/// fn f(guard: MyType![State<'_, u32>]) {\n///     /* ... */\n/// }\n/// ```\n///\n/// While the `MyType![State<'_, u32>]` type _appears_ to contain a `State`\n/// sentinel, the macro actually expands to `&'_ rocket::Config`, which is _not_\n/// the `State` sentinel.\n///\n/// Because Rocket knows the exact syntax expected by type macros that it\n/// exports, such as the [typed stream] macros, discovery in these macros works\n/// as expected. You should prefer not to use type macros aside from those\n/// exported by Rocket, or if necessary, restrict your use to those that always\n/// expand to types without sentinels.\n///\n/// [typed stream]: crate::response::stream\n///\n/// # Custom Sentinels\n///\n/// Any type can implement `Sentinel`, and the implementation can arbitrarily\n/// inspect an ignited instance of `Rocket`. For illustration, consider the\n/// following implementation of `Sentinel` for a custom `Responder` which\n/// requires:\n///\n///   * state for a type `T` to be managed\n///   * a catcher for status code `400` at base `/`\n///\n/// ```rust\n/// use rocket::{Rocket, Ignite, Sentinel};\n/// # struct MyResponder;\n/// # struct T;\n///\n/// impl Sentinel for MyResponder {\n///     fn abort(rocket: &Rocket<Ignite>) -> bool {\n///         if rocket.state::<T>().is_none() {\n///             return true;\n///         }\n///\n///         if !rocket.catchers().any(|c| c.code == Some(400) && c.base() == \"/\") {\n///             return true;\n///         }\n///\n///         false\n///     }\n/// }\n/// ```\n///\n/// If a `MyResponder` is returned by any mounted route, its `abort()` method\n/// will be invoked. If the required conditions aren't met, signaled by\n/// returning `true` from `abort()`, Rocket aborts launch.\npub trait Sentinel {\n    /// Returns `true` if launch should be aborted and `false` otherwise.\n    fn abort(rocket: &Rocket<Ignite>) -> bool;\n}\n\nimpl<T: Sentinel> Sentinel for Option<T> {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        T::abort(rocket)\n    }\n}\n\n// In the next impls, we want to run _both_ sentinels _without_ short\n// circuiting, for the logs. Ideally we could check if these are the same type\n// or not, but `TypeId` only works with `'static`, and adding those bounds to\n// `T` and `E` would reduce the types for which the implementations work, which\n// would mean more types that we miss in type applies. When the type _isn't_ an\n// alias, however, the existence of these implementations is strictly worse.\n\nimpl<T: Sentinel, E: Sentinel> Sentinel for Result<T, E> {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        let left = T::abort(rocket);\n        let right = E::abort(rocket);\n        left || right\n    }\n}\n\nimpl<T: Sentinel, E: Sentinel> Sentinel for either::Either<T, E> {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        let left = T::abort(rocket);\n        let right = E::abort(rocket);\n        left || right\n    }\n}\n\n/// A sentinel that never aborts. The `Responder` impl for `Debug` will never be\n/// called, so it's okay to not abort for failing `T: Sentinel`.\nimpl<T> Sentinel for crate::response::Debug<T> {\n    fn abort(_: &Rocket<Ignite>) -> bool {\n        false\n    }\n}\n\n/// Information resolved at compile-time from eligible [`Sentinel`] types.\n///\n/// Returned as a result of the [`ignition`](Rocket::ignite()) method, this\n/// struct contains information about a resolved sentinel including the type ID\n/// and type name. It is made available via the [`ErrorKind::SentinelAborts`]\n/// variant of the [`ErrorKind`] enum.\n///\n/// [`ErrorKind`]: crate::error::ErrorKind\n/// [`ErrorKind::SentinelAborts`]: crate::error::ErrorKind::SentinelAborts\n///\n// The information resolved from a `T: ?Sentinel` by the `resolve!()` macro.\n#[derive(Clone, Copy)]\npub struct Sentry {\n    /// The type ID of `T`.\n    #[doc(hidden)]\n    pub type_id: TypeId,\n    /// The type name `T` as a string.\n    #[doc(hidden)]\n    pub type_name: &'static str,\n    /// The type ID of type in which `T` is nested if not a top-level type.\n    #[doc(hidden)]\n    pub parent: Option<TypeId>,\n    /// The source (file, column, line) location of the resolved `T`.\n    #[doc(hidden)]\n    pub location: (&'static str, u32, u32),\n    /// The value of `<T as Sentinel>::SPECIALIZED` or the fallback.\n    ///\n    /// This is `true` when `T: Sentinel` and `false` when `T: !Sentinel`.\n    #[doc(hidden)]\n    pub specialized: bool,\n    /// The value of `<T as Sentinel>::abort` or the fallback.\n    #[doc(hidden)]\n    pub abort: fn(&Rocket<Ignite>) -> bool,\n}\n\nimpl Sentry {\n    /// Returns the type ID of the resolved sentinel type.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Sentry;\n    ///\n    /// fn handle_error(sentry: &Sentry) {\n    ///     let type_id = sentry.type_id();\n    /// }\n    /// ```\n    pub fn type_id(&self) -> TypeId {\n        self.type_id\n    }\n\n    /// Returns the type name of the resolved sentinel type.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::Sentry;\n    ///\n    /// fn handle_error(sentry: &Sentry) {\n    ///     let type_name = sentry.type_name();\n    ///     println!(\"Type name: {}\", type_name);\n    /// }\n    pub fn type_name(&self) -> &'static str {\n        self.type_name\n    }\n}\n\n/// Query `sentinels`, once for each unique `type_id`, returning an `Err` of all\n/// of the sentinels that triggered an abort or `Ok(())` if none did.\npub(crate) fn query<'s>(\n    sentinels: impl Iterator<Item = &'s Sentry>,\n    rocket: &Rocket<Ignite>,\n) -> Result<(), Vec<Sentry>> {\n    use std::collections::{HashMap, VecDeque};\n\n    // Build a graph of the sentinels.\n    let mut roots: VecDeque<&'s Sentry> = VecDeque::new();\n    let mut map: HashMap<TypeId, VecDeque<&'s Sentry>> = HashMap::new();\n    for sentinel in sentinels {\n        match sentinel.parent {\n            Some(parent) => map.entry(parent).or_default().push_back(sentinel),\n            None => roots.push_back(sentinel),\n        }\n    }\n\n    // Traverse the graph in breadth-first order. If we find a specialized\n    // sentinel, query it (once for a unique type) and don't traverse its\n    // children. Otherwise, traverse its children. Record queried aborts.\n    let mut remaining = roots;\n    let mut visited: HashMap<TypeId, bool> = HashMap::new();\n    let mut aborted = vec![];\n    while let Some(sentinel) = remaining.pop_front() {\n        if sentinel.specialized {\n            if *visited.entry(sentinel.type_id).or_insert_with(|| (sentinel.abort)(rocket)) {\n                aborted.push(sentinel);\n            }\n        } else if let Some(mut children) = map.remove(&sentinel.type_id) {\n            remaining.append(&mut children);\n        }\n    }\n\n    match aborted.is_empty() {\n        true => Ok(()),\n        false => Err(aborted.into_iter().cloned().collect())\n    }\n}\n\nimpl fmt::Debug for Sentry {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Sentry\")\n            .field(\"type_id\", &self.type_id)\n            .field(\"type_name\", &self.type_name)\n            .field(\"parent\", &self.parent)\n            .field(\"location\", &self.location)\n            .field(\"default\", &self.specialized)\n            .finish()\n    }\n}\n\n/// Resolves a `T` to the specialized or fallback implementation of\n/// `Sentinel`, returning a `Sentry` struct with the resolved items.\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! resolve {\n    ($T:ty $(, $P:ty)?) => ({\n        #[allow(unused_imports)]\n        use $crate::sentinel::resolution::{Resolve, DefaultSentinel as _};\n\n        $crate::sentinel::Sentry {\n            type_id: std::any::TypeId::of::<$T>(),\n            type_name: std::any::type_name::<$T>(),\n            parent: None $(.or(Some(std::any::TypeId::of::<$P>())))?,\n            location: (std::file!(), std::line!(), std::column!()),\n            specialized: Resolve::<$T>::SPECIALIZED,\n            abort: Resolve::<$T>::abort,\n        }\n    })\n}\n\npub use resolve;\n\npub mod resolution {\n    use super::*;\n\n    /// The *magic*.\n    ///\n    /// `Resolve<T>::item` for `T: Sentinel` is `<T as Sentinel>::item`.\n    /// `Resolve<T>::item` for `T: !Sentinel` is `DefaultSentinel::item`.\n    ///\n    /// This _must_ be used as `Resolve::<T>:item` for resolution to work. This\n    /// is a fun, static dispatch hack for \"specialization\" that works because\n    /// Rust prefers inherent methods over blanket trait impl methods.\n    pub struct Resolve<T: ?Sized>(std::marker::PhantomData<T>);\n\n    /// Fallback trait \"implementing\" `Sentinel` for all types. This is what\n    /// Rust will resolve `Resolve<T>::item` to when `T: !Sentinel`.\n    pub trait DefaultSentinel {\n        const SPECIALIZED: bool = false;\n\n        fn abort(_: &Rocket<Ignite>) -> bool { false }\n    }\n\n    impl<T: ?Sized> DefaultSentinel for T {}\n\n    /// \"Specialized\" \"implementation\" of `Sentinel` for `T: Sentinel`. This is\n    /// what Rust will resolve `Resolve<T>::item` to when `T: Sentinel`.\n    impl<T: Sentinel + ?Sized> Resolve<T> {\n        pub const SPECIALIZED: bool = true;\n\n        pub fn abort(rocket: &Rocket<Ignite>) -> bool {\n            T::abort(rocket)\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use std::any::TypeId;\n\n    struct NotASentinel;\n    struct YesASentinel;\n\n    impl super::Sentinel for YesASentinel {\n        fn abort(_: &crate::Rocket<crate::Ignite>) -> bool {\n            unimplemented!()\n        }\n    }\n\n    #[test]\n    fn check_can_determine() {\n        let not_a_sentinel = resolve!(NotASentinel);\n        assert!(not_a_sentinel.type_name.ends_with(\"NotASentinel\"));\n        assert!(!not_a_sentinel.specialized);\n\n        let yes_a_sentinel = resolve!(YesASentinel);\n        assert!(yes_a_sentinel.type_name.ends_with(\"YesASentinel\"));\n        assert!(yes_a_sentinel.specialized);\n    }\n\n    struct HasSentinel<T>(T);\n\n    #[test]\n    fn parent_works() {\n        let child = resolve!(YesASentinel, HasSentinel<YesASentinel>);\n        assert!(child.type_name.ends_with(\"YesASentinel\"));\n        assert_eq!(child.parent.unwrap(), TypeId::of::<HasSentinel<YesASentinel>>());\n        assert!(child.specialized);\n\n        let not_a_direct_sentinel = resolve!(HasSentinel<YesASentinel>);\n        assert!(not_a_direct_sentinel.type_name.contains(\"HasSentinel\"));\n        assert!(not_a_direct_sentinel.type_name.contains(\"YesASentinel\"));\n        assert!(not_a_direct_sentinel.parent.is_none());\n        assert!(!not_a_direct_sentinel.specialized);\n    }\n}\n"
  },
  {
    "path": "core/lib/src/serde/json.rs",
    "content": "//! Automatic JSON (de)serialization support.\n//!\n//! See [`Json`] for details.\n//!\n//! # Enabling\n//!\n//! This module is only available when the `json` feature is enabled. Enable it\n//! in `Cargo.toml` as follows:\n//!\n//! ```toml\n//! [dependencies.rocket]\n//! version = \"0.6.0-dev\"\n//! features = [\"json\"]\n//! ```\n//!\n//! # Testing\n//!\n//! The [`LocalRequest`] and [`LocalResponse`] types provide [`json()`] and\n//! [`into_json()`] methods to create a request with serialized JSON and\n//! deserialize a response as JSON, respectively.\n//!\n//! [`LocalRequest`]: crate::local::blocking::LocalRequest\n//! [`LocalResponse`]: crate::local::blocking::LocalResponse\n//! [`json()`]: crate::local::blocking::LocalRequest::json()\n//! [`into_json()`]: crate::local::blocking::LocalResponse::into_json()\n\nuse std::{io, fmt, error};\nuse std::ops::{Deref, DerefMut};\n\nuse crate::request::{Request, local_cache};\nuse crate::data::{Limits, Data, FromData, Outcome};\nuse crate::response::{self, Responder, content};\nuse crate::form::prelude as form;\nuse crate::http::uri::fmt::{UriDisplay, FromUriParam, Query, Formatter as UriFormatter};\nuse crate::http::Status;\n\nuse serde::{Serialize, Deserialize};\n\n#[doc(hidden)]\npub use serde_json;\n\n/// The JSON guard: easily consume and return JSON.\n///\n/// ## Sending JSON\n///\n/// To respond with serialized JSON data, return a `Json<T>` type, where `T`\n/// implements [`Serialize`] from [`serde`]. The content type of the response is\n/// set to `application/json` automatically.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type User = usize;\n/// use rocket::serde::json::Json;\n///\n/// #[get(\"/users/<id>\")]\n/// fn user(id: usize) -> Json<User> {\n///     let user_from_id = User::from(id);\n///     /* ... */\n///     Json(user_from_id)\n/// }\n/// ```\n///\n/// ## Receiving JSON\n///\n/// `Json` is both a data guard and a form guard.\n///\n/// ### Data Guard\n///\n/// To deserialize request body data as JSON , add a `data` route argument with\n/// a target type of `Json<T>`, where `T` is some type you'd like to parse from\n/// JSON. `T` must implement [`serde::Deserialize`].\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type User = usize;\n/// use rocket::serde::json::Json;\n///\n/// #[post(\"/user\", format = \"json\", data = \"<user>\")]\n/// fn new_user(user: Json<User>) {\n///     /* ... */\n/// }\n/// ```\n///\n/// You don't _need_ to use `format = \"json\"`, but it _may_ be what you want.\n/// Using `format = json` means that any request that doesn't specify\n/// \"application/json\" as its `Content-Type` header value will not be routed to\n/// the handler.\n///\n/// ### Form Guard\n///\n/// `Json<T>`, as a form guard, accepts value and data fields and parses the\n/// data as a `T`. Simple use `Json<T>`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type Metadata = usize;\n/// use rocket::form::{Form, FromForm};\n/// use rocket::serde::json::Json;\n///\n/// #[derive(FromForm)]\n/// struct User<'r> {\n///     name: &'r str,\n///     metadata: Json<Metadata>\n/// }\n///\n/// #[post(\"/user\", data = \"<form>\")]\n/// fn new_user(form: Form<User<'_>>) {\n///     /* ... */\n/// }\n/// ```\n///\n/// ### Incoming Data Limits\n///\n/// The default size limit for incoming JSON data is 1MiB. Setting a limit\n/// protects your application from denial of service (DoS) attacks and from\n/// resource exhaustion through high memory consumption. The limit can be\n/// increased by setting the `limits.json` configuration parameter. For\n/// instance, to increase the JSON limit to 5MiB for all environments, you may\n/// add the following to your `Rocket.toml`:\n///\n/// ```toml\n/// [global.limits]\n/// json = 5242880\n/// ```\n#[repr(transparent)]\n#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct Json<T>(pub T);\n\n/// Error returned by the [`Json`] guard when JSON deserialization fails.\n#[derive(Debug)]\npub enum Error<'a> {\n    /// An I/O error occurred while reading the incoming request data.\n    Io(io::Error),\n\n    /// The client's data was received successfully but failed to parse as valid\n    /// JSON or as the requested type. The `&str` value in `.0` is the raw data\n    /// received from the user, while the `Error` in `.1` is the deserialization\n    /// error from `serde`.\n    Parse(&'a str, serde_json::error::Error),\n}\n\nimpl<'a> fmt::Display for Error<'a> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Self::Io(err) => write!(f, \"i/o error: {}\", err),\n            Self::Parse(_, err) => write!(f, \"parse error: {}\", err),\n        }\n    }\n}\n\nimpl<'a> error::Error for Error<'a> {\n    fn source(&self) -> Option<&(dyn error::Error + 'static)> {\n        match self {\n            Self::Io(err) => Some(err),\n            Self::Parse(_, err) => Some(err),\n        }\n    }\n}\n\nimpl<T> Json<T> {\n    /// Consumes the JSON wrapper and returns the wrapped item.\n    ///\n    /// # Example\n    /// ```rust\n    /// # use rocket::serde::json::Json;\n    /// let string = \"Hello\".to_string();\n    /// let my_json = Json(string);\n    /// assert_eq!(my_json.into_inner(), \"Hello\".to_string());\n    /// ```\n    #[inline(always)]\n    pub fn into_inner(self) -> T {\n        self.0\n    }\n}\n\nimpl<'r, T: Deserialize<'r>> Json<T> {\n    fn from_str(s: &'r str) -> Result<Self, Error<'r>> {\n        serde_json::from_str(s).map(Json).map_err(|e| Error::Parse(s, e))\n    }\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Result<Self, Error<'r>> {\n        let limit = req.limits().get(\"json\").unwrap_or(Limits::JSON);\n        let string = match data.open(limit).into_string().await {\n            Ok(s) if s.is_complete() => s.into_inner(),\n            Ok(_) => {\n                let eof = io::ErrorKind::UnexpectedEof;\n                return Err(Error::Io(io::Error::new(eof, \"data limit exceeded\")));\n            },\n            Err(e) => return Err(Error::Io(e)),\n        };\n\n        Self::from_str(local_cache!(req, string))\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: Deserialize<'r>> FromData<'r> for Json<T> {\n    type Error = Error<'r>;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        match Self::from_data(req, data).await {\n            Ok(value) => Outcome::Success(value),\n            Err(Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {\n                Outcome::Error((Status::PayloadTooLarge, Error::Io(e)))\n            },\n            Err(Error::Parse(s, e)) if e.classify() == serde_json::error::Category::Data => {\n                Outcome::Error((Status::UnprocessableEntity, Error::Parse(s, e)))\n            },\n            Err(e) => Outcome::Error((Status::BadRequest, e)),\n\n        }\n    }\n}\n\n/// Serializes the wrapped value into JSON. Returns a response with Content-Type\n/// JSON and a fixed-size body with the serialized value. If serialization\n/// fails, an `Err` of `Status::InternalServerError` is returned.\nimpl<'r, T: Serialize> Responder<'r, 'static> for Json<T> {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n        let string = serde_json::to_string(&self.0)\n            .map_err(|e| {\n                error!(\"JSON serialize failure: {}\", e);\n                Status::InternalServerError\n            })?;\n\n        content::RawJson(string).respond_to(req)\n    }\n}\n\nimpl<T: Serialize> UriDisplay<Query> for Json<T> {\n    fn fmt(&self, f: &mut UriFormatter<'_, Query>) -> fmt::Result {\n        let string = to_string(&self.0).map_err(|_| fmt::Error)?;\n        f.write_value(&string)\n    }\n}\n\nmacro_rules! impl_from_uri_param_from_inner_type {\n    ($($lt:lifetime)?, $T:ty) => (\n        impl<$($lt,)? T: Serialize> FromUriParam<Query, $T> for Json<T> {\n            type Target = Json<$T>;\n\n            #[inline(always)]\n            fn from_uri_param(param: $T) -> Self::Target {\n                Json(param)\n            }\n        }\n    )\n}\n\nimpl_from_uri_param_from_inner_type!(, T);\nimpl_from_uri_param_from_inner_type!('a, &'a T);\nimpl_from_uri_param_from_inner_type!('a, &'a mut T);\n\ncrate::http::impl_from_uri_param_identity!([Query] (T: Serialize) Json<T>);\n\nimpl<T> From<T> for Json<T> {\n    fn from(value: T) -> Self {\n        Json(value)\n    }\n}\n\nimpl<T> Deref for Json<T> {\n    type Target = T;\n\n    #[inline(always)]\n    fn deref(&self) -> &T {\n        &self.0\n    }\n}\n\nimpl<T> DerefMut for Json<T> {\n    #[inline(always)]\n    fn deref_mut(&mut self) -> &mut T {\n        &mut self.0\n    }\n}\n\nimpl From<Error<'_>> for form::Error<'_> {\n    fn from(e: Error<'_>) -> Self {\n        match e {\n            Error::Io(e) => e.into(),\n            Error::Parse(_, e) => form::Error::custom(e)\n        }\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: Deserialize<'v> + Send> form::FromFormField<'v> for Json<T> {\n    fn from_value(field: form::ValueField<'v>) -> Result<Self, form::Errors<'v>> {\n        Ok(Self::from_str(field.value)?)\n    }\n\n    async fn from_data(f: form::DataField<'v, '_>) -> Result<Self, form::Errors<'v>> {\n        Ok(Self::from_data(f.request, f.data).await?)\n    }\n}\n\n/// Serializes the value into JSON. Returns a response with Content-Type JSON\n/// and a fixed-size body with the serialized value.\nimpl<'r> Responder<'r, 'static> for Value {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n        content::RawJson(self.to_string()).respond_to(req)\n    }\n}\n\ncrate::export! {\n    /// A macro to create ad-hoc JSON serializable values using JSON syntax.\n    ///\n    /// The return type of a `json!` invocation is [`Value`](Value). A value\n    /// created with this macro can be returned from a handler as follows:\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::serde::json::{json, Value};\n    ///\n    /// #[get(\"/json\")]\n    /// fn get_json() -> Value {\n    ///     json!({\n    ///         \"key\": \"value\",\n    ///         \"array\": [1, 2, 3, 4]\n    ///     })\n    /// }\n    /// ```\n    ///\n    /// The [`Responder`](crate::response::Responder) implementation for\n    /// `Value` serializes the value into a JSON string and sets it as the body\n    /// of the response with a `Content-Type` of `application/json`.\n    ///\n    /// # Examples\n    ///\n    /// Create a simple JSON object with two keys: `\"username\"` and `\"id\"`:\n    ///\n    /// ```rust\n    /// use rocket::serde::json::json;\n    ///\n    /// let value = json!({\n    ///     \"username\": \"mjordan\",\n    ///     \"id\": 23\n    /// });\n    /// ```\n    ///\n    /// Create a more complex object with a nested object and array:\n    ///\n    /// ```rust\n    /// # use rocket::serde::json::json;\n    /// let value = json!({\n    ///     \"code\": 200,\n    ///     \"success\": true,\n    ///     \"payload\": {\n    ///         \"features\": [\"serde\", \"json\"],\n    ///         \"ids\": [12, 121],\n    ///     },\n    /// });\n    /// ```\n    ///\n    /// Variables or expressions can be interpolated into the JSON literal. Any type\n    /// interpolated into an array element or object value must implement serde's\n    /// `Serialize` trait, while any type interpolated into a object key must\n    /// implement `Into<String>`.\n    ///\n    /// ```rust\n    /// # use rocket::serde::json::json;\n    /// let code = 200;\n    /// let features = vec![\"serde\", \"json\"];\n    ///\n    /// let value = json!({\n    ///    \"code\": code,\n    ///    \"success\": code == 200,\n    ///    \"payload\": {\n    ///        features[0]: features[1]\n    ///    }\n    /// });\n    /// ```\n    ///\n    /// Trailing commas are allowed inside both arrays and objects.\n    ///\n    /// ```rust\n    /// # use rocket::serde::json::json;\n    /// let value = json!([\n    ///     \"notice\",\n    ///     \"the\",\n    ///     \"trailing\",\n    ///     \"comma -->\",\n    /// ]);\n    /// ```\n    macro_rules! json {\n        ($($json:tt)+) => ($crate::serde::json::serde_json::json!($($json)*));\n    }\n}\n\n/// An arbitrary JSON value as returned by [`json!`].\n///\n/// # `Responder`\n///\n/// `Value` is a `Responder` that serializes the represented value into a JSON\n/// string and sets the string as the body of a fixed-sized response with a\n/// `Content-Type` of `application/json`.\n///\n/// # Usage\n///\n/// A value of this type is returned by [`json!`]. The macro and this type are\n/// typically used to construct JSON values in an ad-hoc fashion during request\n/// handling. This looks something like:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::serde::json::{json, Value};\n///\n/// #[get(\"/json\")]\n/// fn get_json() -> Value {\n///     json!({\n///         \"id\": 83,\n///         \"values\": [1, 2, 3, 4]\n///     })\n/// }\n/// ```\n#[doc(inline)]\npub use serde_json::Value;\n\n/// Deserialize an instance of type `T` from bytes of JSON text.\n///\n/// **_Always_ use [`Json`] to deserialize JSON request data.**\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, json};\n///\n/// #[derive(Debug, PartialEq, Deserialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data<'r> {\n///     framework: &'r str,\n///     stars: usize,\n/// }\n///\n/// let bytes = br#\"\n///     {\n///         \"framework\": \"Rocket\",\n///         \"stars\": 5\n///     }\n/// \"#;\n///\n/// let data: Data = json::from_slice(bytes).unwrap();\n/// assert_eq!(data, Data { framework: \"Rocket\", stars: 5, });\n/// ```\n///\n/// # Errors\n///\n/// This conversion can fail if the structure of the input does not match the\n/// structure expected by `T`, for example if `T` is a struct type but the input\n/// contains something other than a JSON map. It can also fail if the structure\n/// is correct but `T`'s implementation of `Deserialize` decides that something\n/// is wrong with the data, for example required struct fields are missing from\n/// the JSON map or some number is too big to fit in the expected primitive\n/// type.\n#[inline(always)]\npub fn from_slice<'a, T>(slice: &'a [u8]) -> Result<T, serde_json::error::Error>\n    where T: Deserialize<'a>,\n{\n    serde_json::from_slice(slice)\n}\n\n/// Deserialize an instance of type `T` from a string of JSON text.\n///\n/// **_Always_ use [`Json`] to deserialize JSON request data.**\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, json};\n///\n/// #[derive(Debug, PartialEq, Deserialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data<'r> {\n///     framework: &'r str,\n///     stars: usize,\n/// }\n///\n/// let string = r#\"\n///     {\n///         \"framework\": \"Rocket\",\n///         \"stars\": 5\n///     }\n/// \"#;\n///\n/// let data: Data = json::from_str(string).unwrap();\n/// assert_eq!(data, Data { framework: \"Rocket\", stars: 5, });\n/// ```\n///\n/// # Errors\n///\n/// This conversion can fail if the structure of the input does not match the\n/// structure expected by `T`, for example if `T` is a struct type but the input\n/// contains something other than a JSON map. It can also fail if the structure\n/// is correct but `T`'s implementation of `Deserialize` decides that something\n/// is wrong with the data, for example required struct fields are missing from\n/// the JSON map or some number is too big to fit in the expected primitive\n/// type.\n#[inline(always)]\npub fn from_str<'a, T>(string: &'a str) -> Result<T, serde_json::error::Error>\n    where T: Deserialize<'a>,\n{\n    serde_json::from_str(string)\n}\n\n/// Serialize a `T` into a JSON string with compact representation.\n///\n/// **_Always_ use [`Json`] to serialize JSON response data.**\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, Serialize, json};\n///\n/// #[derive(Debug, PartialEq, Deserialize, Serialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data<'r> {\n///     framework: &'r str,\n///     stars: usize,\n/// }\n///\n/// let data = Data {\n///     framework: \"Rocket\",\n///     stars: 5,\n/// };\n///\n/// let string = json::to_string(&data).unwrap();\n/// let data: Data = json::from_str(&string).unwrap();\n/// assert_eq!(data, Data { framework: \"Rocket\", stars: 5, });\n/// ```\n///\n/// # Errors\n///\n/// Serialization fails if `T`'s `Serialize` implementation fails or if `T`\n/// contains a map with non-string keys.\n#[inline(always)]\npub fn to_string<T>(value: &T) -> Result<String, serde_json::error::Error>\n    where T: Serialize\n{\n    serde_json::to_string(value)\n}\n\n/// Serialize a `T` into a JSON string with \"pretty\" formatted representation.\n///\n/// **_Always_ use [`Json`] to serialize JSON response data.**\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, Serialize, json};\n///\n/// #[derive(Debug, PartialEq, Deserialize, Serialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data<'r> {\n///     framework: &'r str,\n///     stars: usize,\n/// }\n///\n/// let data = Data {\n///     framework: \"Rocket\",\n///     stars: 5,\n/// };\n///\n/// let string = json::to_pretty_string(&data).unwrap();\n/// # let compact = json::to_string(&data).unwrap();\n/// # assert_ne!(compact, string);\n/// let data: Data = json::from_str(&string).unwrap();\n/// assert_eq!(data, Data { framework: \"Rocket\", stars: 5, });\n/// ```\n///\n/// # Errors\n///\n/// Serialization fails if `T`'s `Serialize` implementation fails or if `T`\n/// contains a map with non-string keys.\n#[inline(always)]\npub fn to_pretty_string<T>(value: &T) -> Result<String, serde_json::error::Error>\n    where T: Serialize\n{\n    serde_json::to_string_pretty(value)\n}\n\n/// Interpret a [`Value`] as an instance of type `T`.\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, json};\n///\n/// #[derive(Debug, PartialEq, Deserialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data {\n///     framework: String ,\n///     stars: usize,\n/// }\n///\n/// let value = json::json!({\n///     \"framework\": \"Rocket\",\n///     \"stars\": 5\n/// });\n///\n/// let data: Data = json::from_value(value).unwrap();\n/// assert_eq!(data, Data { framework: \"Rocket\".into(), stars: 5, });\n/// ```\n///\n/// # Errors\n///\n/// This conversion can fail if the structure of the input does not match the\n/// structure expected by `T`, for example if `T` is a struct type but the input\n/// contains something other than a JSON map. It can also fail if the structure\n/// is correct but `T`'s implementation of `Deserialize` decides that something\n/// is wrong with the data, for example required struct fields are missing from\n/// the JSON map or some number is too big to fit in the expected primitive\n/// type.\n#[inline(always)]\npub fn from_value<T>(value: Value) -> Result<T, serde_json::error::Error>\n    where T: crate::serde::DeserializeOwned\n{\n    serde_json::from_value(value)\n}\n\n/// Convert a `T` into a [`Value`], an opaque value representing JSON data.\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, Serialize, json};\n///\n/// #[derive(Deserialize, Serialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data {\n///     framework: String ,\n///     stars: usize,\n/// }\n///\n/// let value = json::json!({\n///     \"framework\": \"Rocket\",\n///     \"stars\": 5\n/// });\n///\n/// let data: Data = json::from_value(value.clone()).unwrap();\n/// let data_value = json::to_value(data).unwrap();\n/// assert_eq!(value, data_value);\n/// ```\n///\n/// # Errors\n///\n/// This conversion fails if `T`’s implementation of `Serialize` decides to fail\n/// or if `T` contains a map with non-string keys.\n#[inline(always)]\npub fn to_value<T>(item: T) -> Result<Value, serde_json::error::Error>\n    where T: Serialize\n{\n    serde_json::to_value(item)\n}\n"
  },
  {
    "path": "core/lib/src/serde/mod.rs",
    "content": "//! Serialization and deserialization support.\n//!\n//! * JSON support is provided by the [`Json`](json::Json) type.\n//! * MessagePack support is provided by the [`MsgPack`](msgpack::MsgPack) type.\n//! * UUID support is provided by the [`UUID`](uuid) type.\n//!\n//! Types implement one or all of [`FromParam`](crate::request::FromParam),\n//! [`FromForm`](crate::form::FromForm), [`FromData`](crate::data::FromData),\n//! and [`Responder`](crate::response::Responder).\n//!\n//! ## Deriving `Serialize`, `Deserialize`\n//!\n//! For convenience, Rocket re-exports `serde`'s `Serialize` and `Deserialize`\n//! traits and derive macros from this module. However, due to Rust's limited\n//! support for derive macro re-exports, using the re-exported derive macros\n//! requires annotating structures with `#[serde(crate = \"rocket::serde\")]`:\n//!\n//! ```rust\n//! use rocket::serde::{Serialize, Deserialize};\n//!\n//! #[derive(Serialize, Deserialize)]\n//! #[serde(crate = \"rocket::serde\")]\n//! struct MyStruct {\n//!     foo: String,\n//! }\n//! ```\n//!\n//! If you'd like to avoid this extra annotation, you must depend on `serde`\n//! directly via your crate's `Cargo.toml`:\n//!\n//! ```toml\n//! [dependencies]\n//! serde = { version = \"1.0\", features = [\"derive\"] }\n//! ```\n\n#[doc(inline)]\npub use serde::ser::{Serialize, Serializer};\n\n#[doc(inline)]\npub use serde::de::{Deserialize, DeserializeOwned, Deserializer};\n\n#[doc(hidden)]\npub use serde::*;\n\n#[cfg(feature = \"json\")]\n#[cfg_attr(nightly, doc(cfg(feature = \"json\")))]\npub mod json;\n\n#[cfg(feature = \"msgpack\")]\n#[cfg_attr(nightly, doc(cfg(feature = \"msgpack\")))]\npub mod msgpack;\n\n#[cfg(feature = \"uuid\")]\n#[cfg_attr(nightly, doc(cfg(feature = \"uuid\")))]\npub mod uuid;\n"
  },
  {
    "path": "core/lib/src/serde/msgpack.rs",
    "content": "//! Automatic MessagePack (de)serialization support.\n//!\n//! See [`MsgPack`] for further details.\n//!\n//! # Enabling\n//!\n//! This module is only available when the `msgpack` feature is enabled. Enable\n//! it in `Cargo.toml` as follows:\n//!\n//! ```toml\n//! [dependencies.rocket]\n//! version = \"0.6.0-dev\"\n//! features = [\"msgpack\"]\n//! ```\n//!\n//! # Testing\n//!\n//! The [`LocalRequest`] and [`LocalResponse`] types provide [`msgpack()`] and\n//! [`into_msgpack()`] methods to create a request with serialized MessagePack\n//! and deserialize a response as MessagePack, respectively.\n//!\n//! [`LocalRequest`]: crate::local::blocking::LocalRequest\n//! [`LocalResponse`]: crate::local::blocking::LocalResponse\n//! [`msgpack()`]: crate::local::blocking::LocalRequest::msgpack()\n//! [`into_msgpack()`]: crate::local::blocking::LocalResponse::into_msgpack()\n\nuse std::io;\nuse std::ops::{Deref, DerefMut};\n\nuse crate::request::{Request, local_cache};\nuse crate::data::{Limits, Data, FromData, Outcome};\nuse crate::response::{self, Responder, content};\nuse crate::http::Status;\nuse crate::form::prelude as form;\n// use crate::http::uri::fmt;\n\nuse serde::{Serialize, Deserialize};\n\n#[doc(inline)]\npub use rmp_serde::decode::Error;\n\n/// The MessagePack guard: easily consume and return MessagePack.\n///\n/// ## Sending MessagePack\n///\n/// To respond with serialized MessagePack data, return either [`MsgPack<T>`] or\n/// [`Compact<T>`] from your handler. `T` must implement [`serde::Serialize`].\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type User = usize;\n/// use rocket::serde::msgpack::MsgPack;\n///\n/// #[get(\"/users/<id>\")]\n/// fn user(id: usize) -> MsgPack<User> {\n///     let user_from_id = User::from(id);\n///     /* ... */\n///     MsgPack(user_from_id)\n/// }\n/// ```\n///\n/// The differences between [`MsgPack<T>`] and [`Compact<T>`] are documented on\n/// [`Compact<T>`]. In most cases, [`MsgPack<T>`] is preferable, although compact\n/// was the default prior to Rocket version 0.6.\n///\n/// ## Receiving MessagePack\n///\n/// `MsgPack` is both a data guard and a form guard.\n///\n/// ### Data Guard\n///\n/// To deserialize request body data as MessagePack, add a `data` route\n/// argument with a target type of `MsgPack<T>`, where `T` is some type you'd\n/// like to parse from JSON. `T` must implement [`serde::Deserialize`].\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type User = usize;\n/// use rocket::serde::msgpack::MsgPack;\n///\n/// #[post(\"/users\", format = \"msgpack\", data = \"<user>\")]\n/// fn new_user(user: MsgPack<User>) {\n///     /* ... */\n/// }\n/// ```\n///\n/// You don't _need_ to use `format = \"msgpack\"`, but it _may_ be what you want.\n/// Using `format = msgpack` means that any request that doesn't specify\n/// \"application/msgpack\" as its first `Content-Type:` header parameter will not\n/// be routed to this handler.\n///\n/// ### Form Guard\n///\n/// `MsgPack<T>`, as a form guard, accepts value and data fields and parses the\n/// data as a `T`. Simple use `MsgPack<T>`:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type Metadata = usize;\n/// use rocket::form::{Form, FromForm};\n/// use rocket::serde::msgpack::MsgPack;\n///\n/// #[derive(FromForm)]\n/// struct User<'r> {\n///     name: &'r str,\n///     metadata: MsgPack<Metadata>\n/// }\n///\n/// #[post(\"/users\", data = \"<form>\")]\n/// fn new_user(form: Form<User<'_>>) {\n///     /* ... */\n/// }\n/// ```\n///\n/// ### Incoming Data Limits\n///\n/// The default size limit for incoming MessagePack data is 1MiB. Setting a\n/// limit protects your application from denial of service (DOS) attacks and\n/// from resource exhaustion through high memory consumption. The limit can be\n/// increased by setting the `limits.msgpack` configuration parameter. For\n/// instance, to increase the MessagePack limit to 5MiB for all environments,\n/// you may add the following to your `Rocket.toml`:\n///\n/// ```toml\n/// [global.limits]\n/// msgpack = 5242880\n/// ```\n#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct MsgPack<T, const COMPACT: bool = false>(pub T);\n\n/// Serializes responses in a compact MesagePack format, where structs are\n/// serialized as arrays of their field values.\n///\n/// To respond with compact MessagePack data, return a `Compact<T>` type,\n/// where `T` implements [`Serialize`] from [`serde`]. The content type of the\n/// response is set to `application/msgpack` automatically.\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// # type User = usize;\n/// use rocket::serde::msgpack;\n///\n/// #[get(\"/users/<id>\")]\n/// fn user(id: usize) -> msgpack::Compact<User> {\n///     let user_from_id = User::from(id);\n///     /* ... */\n///     msgpack::MsgPack(user_from_id)\n/// }\n/// ```\n///\n/// Prefer using [`MsgPack<T>`] for request guards, as the named/compact\n/// distinction is not relevant for request data - the correct option is\n/// implemented automatically. Using [`Compact<T>`] as a request guard will\n/// NOT prevent named requests from being accepted.\npub type Compact<T> = MsgPack<T, true>;\n\nimpl<T, const COMPACT: bool> MsgPack<T, COMPACT> {\n    /// Consumes the `MsgPack` wrapper and returns the wrapped item.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::serde::msgpack::MsgPack;\n    /// let string = \"Hello\".to_string();\n    /// let my_msgpack: MsgPack<_> = MsgPack(string);\n    /// assert_eq!(my_msgpack.into_inner(), \"Hello\".to_string());\n    /// ```\n    #[inline(always)]\n    pub fn into_inner(self) -> T {\n        self.0\n    }\n}\n\nimpl<'r, T: Deserialize<'r>> MsgPack<T> {\n    fn from_bytes(buf: &'r [u8]) -> Result<Self, Error> {\n        rmp_serde::from_slice(buf).map(MsgPack)\n    }\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Result<Self, Error> {\n        let limit = req.limits().get(\"msgpack\").unwrap_or(Limits::MESSAGE_PACK);\n        let bytes = match data.open(limit).into_bytes().await {\n            Ok(buf) if buf.is_complete() => buf.into_inner(),\n            Ok(_) => {\n                let eof = io::ErrorKind::UnexpectedEof;\n                return Err(Error::InvalidDataRead(io::Error::new(eof, \"data limit exceeded\")));\n            },\n            Err(e) => return Err(Error::InvalidDataRead(e)),\n        };\n\n        Self::from_bytes(local_cache!(req, bytes))\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: Deserialize<'r>> FromData<'r> for MsgPack<T> {\n    type Error = Error;\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {\n        match Self::from_data(req, data).await {\n            Ok(value) => Outcome::Success(value),\n            Err(Error::InvalidDataRead(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {\n                Outcome::Error((Status::PayloadTooLarge, Error::InvalidDataRead(e)))\n            },\n            | Err(e@Error::TypeMismatch(_))\n            | Err(e@Error::OutOfRange)\n            | Err(e@Error::LengthMismatch(_))\n            => {\n                Outcome::Error((Status::UnprocessableEntity, e))\n            },\n            Err(e) => Outcome::Error((Status::BadRequest, e)),\n        }\n    }\n}\n\n/// Serializes the wrapped value into MessagePack. Returns a response with\n/// Content-Type `MsgPack` and a fixed-size body with the serialization. If\n/// serialization fails, an `Err` of `Status::InternalServerError` is returned.\nimpl<'r, T: Serialize, const COMPACT: bool> Responder<'r, 'static> for MsgPack<T, COMPACT> {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n        let maybe_buf = if COMPACT {\n            rmp_serde::to_vec(&self.0)\n        } else {\n            rmp_serde::to_vec_named(&self.0)\n        };\n        let buf = maybe_buf\n            .map_err(|e| {\n                error!(\"MsgPack serialize failure: {}\", e);\n                Status::InternalServerError\n            })?;\n\n        content::RawMsgPack(buf).respond_to(req)\n    }\n}\n\n#[crate::async_trait]\nimpl<'v, T: Deserialize<'v> + Send> form::FromFormField<'v> for MsgPack<T> {\n    // TODO: To implement `from_value`, we need to the raw string so we can\n    // decode it into bytes as opposed to a string as it won't be UTF-8.\n\n    async fn from_data(f: form::DataField<'v, '_>) -> Result<Self, form::Errors<'v>> {\n        Self::from_data(f.request, f.data).await.map_err(|e| {\n            match e {\n                Error::InvalidMarkerRead(e) | Error::InvalidDataRead(e) => e.into(),\n                Error::Utf8Error(e) => e.into(),\n                _ => form::Error::custom(e).into(),\n            }\n        })\n    }\n}\n\n// impl<T: Serialize> fmt::UriDisplay<fmt::Query> for MsgPack<T> {\n//     fn fmt(&self, f: &mut fmt::Formatter<'_, fmt::Query>) -> std::fmt::Result {\n//         let bytes = to_vec(&self.0).map_err(|_| std::fmt::Error)?;\n//         let encoded = crate::http::RawStr::percent_encode_bytes(&bytes);\n//         f.write_value(encoded.as_str())\n//     }\n// }\n\nimpl<T, const COMPACT: bool> From<T> for MsgPack<T, COMPACT> {\n    fn from(value: T) -> Self {\n        MsgPack(value)\n    }\n}\n\nimpl<T, const COMPACT: bool> Deref for MsgPack<T, COMPACT> {\n    type Target = T;\n\n    #[inline(always)]\n    fn deref(&self) -> &T {\n        &self.0\n    }\n}\n\nimpl<T, const COMPACT: bool> DerefMut for MsgPack<T, COMPACT> {\n    #[inline(always)]\n    fn deref_mut(&mut self) -> &mut T {\n        &mut self.0\n    }\n}\n\n/// Deserialize an instance of type `T` from MessagePack encoded bytes.\n///\n/// Deserialization is performed in a zero-copy manner whenever possible.\n///\n/// **_Always_ use [`MsgPack`] to deserialize MessagePack request data.**\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, msgpack};\n///\n/// #[derive(Debug, PartialEq, Deserialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data<'r> {\n///     framework: &'r str,\n///     stars: usize,\n/// }\n///\n/// let bytes = &[\n///     130, 169, 102, 114, 97, 109, 101, 119, 111, 114, 107, 166, 82, 111,\n///     99, 107, 101, 116, 165, 115, 116, 97, 114, 115, 5\n/// ];\n///\n/// let data: Data = msgpack::from_slice(bytes).unwrap();\n/// assert_eq!(data, Data { framework: \"Rocket\", stars: 5, });\n/// ```\n///\n/// # Errors\n///\n/// Deserialization fails if `v` does not represent a valid MessagePack encoding\n/// of any instance of `T` or if `T`'s `Deserialize` implementation fails\n/// otherwise.\n#[inline(always)]\npub fn from_slice<'a, T>(v: &'a [u8]) -> Result<T, Error>\n    where T: Deserialize<'a>,\n{\n    rmp_serde::from_slice(v)\n}\n\n/// Serialize a `T` into a MessagePack byte vector with compact representation.\n///\n/// The compact representation represents structs as arrays.\n///\n/// **_Always_ use [`Compact`] to serialize MessagePack response data in a\n/// compact format.**\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, Serialize, msgpack};\n///\n/// #[derive(Deserialize, Serialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data<'r> {\n///     framework: &'r str,\n///     stars: usize,\n/// }\n///\n/// let bytes = &[146, 166, 82, 111, 99, 107, 101, 116, 5];\n/// let data: Data = msgpack::from_slice(bytes).unwrap();\n/// let byte_vec = msgpack::to_compact_vec(&data).unwrap();\n/// assert_eq!(bytes, &byte_vec[..]);\n/// ```\n///\n/// # Errors\n///\n/// Serialization fails if `T`'s `Serialize` implementation fails.\n#[inline(always)]\npub fn to_compact_vec<T>(value: &T) -> Result<Vec<u8>, rmp_serde::encode::Error>\n    where T: Serialize + ?Sized\n{\n    rmp_serde::to_vec(value)\n}\n\n/// Serialize a `T` into a MessagePack byte vector with named representation.\n///\n/// The named representation represents structs as maps with field names.\n///\n/// **_Always_ use [`MsgPack`] to serialize MessagePack response data.**\n///\n/// # Example\n///\n/// ```\n/// use rocket::serde::{Deserialize, Serialize, msgpack};\n///\n/// #[derive(Deserialize, Serialize)]\n/// #[serde(crate = \"rocket::serde\")]\n/// struct Data<'r> {\n///     framework: &'r str,\n///     stars: usize,\n/// }\n///\n/// let bytes = &[\n///     130, 169, 102, 114, 97, 109, 101, 119, 111, 114, 107, 166, 82, 111,\n///     99, 107, 101, 116, 165, 115, 116, 97, 114, 115, 5\n/// ];\n///\n/// let data: Data = msgpack::from_slice(bytes).unwrap();\n/// let byte_vec = msgpack::to_vec(&data).unwrap();\n/// assert_eq!(bytes, &byte_vec[..]);\n/// ```\n///\n/// # Errors\n///\n/// Serialization fails if `T`'s `Serialize` implementation fails.\n#[inline(always)]\npub fn to_vec<T>(value: &T) -> Result<Vec<u8>, rmp_serde::encode::Error>\n    where T: Serialize + ?Sized\n{\n    rmp_serde::to_vec_named(value)\n}\n"
  },
  {
    "path": "core/lib/src/serde/uuid.rs",
    "content": "//! UUID path/query parameter and form value parsing support.\n//!\n//! # Enabling\n//!\n//! This module is only available when the `uuid` feature is enabled. Enable it\n//! in `Cargo.toml` as follows:\n//!\n//! ```toml\n//! [dependencies.rocket]\n//! version = \"0.6.0-dev\"\n//! features = [\"uuid\"]\n//! ```\n//!\n//! # Usage\n//!\n//! `Uuid` implements [`FromParam`] and [`FromFormField`] (i.e,\n//! [`FromForm`](crate::form::FromForm)), allowing UUID values to be accepted\n//! directly in paths, queries, and forms. You can use the `Uuid` type directly\n//! as a target of a dynamic parameter:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use rocket::serde::uuid::Uuid;\n//!\n//! #[get(\"/users/<id>\")]\n//! fn user(id: Uuid) -> String {\n//!     format!(\"We found: {}\", id)\n//! }\n//! ```\n//!\n//! You can also use the `Uuid` as a form value, including in query strings:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use rocket::serde::uuid::Uuid;\n//!\n//! #[get(\"/user?<id>\")]\n//! fn user(id: Uuid) -> String {\n//!     format!(\"User ID: {}\", id)\n//! }\n//! ```\n//!\n//! Additionally, `Uuid` implements `UriDisplay<P>` for all `P`. As such, route\n//! URIs including `Uuid`s can be generated in a type-safe manner:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use rocket::serde::uuid::Uuid;\n//! use rocket::response::Redirect;\n//!\n//! #[get(\"/user/<id>\")]\n//! fn user(id: Uuid) -> String {\n//!     format!(\"User ID: {}\", id)\n//! }\n//!\n//! #[get(\"/user?<id>\")]\n//! fn old_user_path(id: Uuid) -> Redirect {\n//!     # let _ = Redirect::to(uri!(user(&id)));\n//!     # let _ = Redirect::to(uri!(old_user_path(id)));\n//!     # let _ = Redirect::to(uri!(old_user_path(&id)));\n//!     Redirect::to(uri!(user(id)))\n//! }\n//! ```\n//!\n//! # Extra Features\n//!\n//! The [`uuid`](https://docs.rs/uuid/1) crate exposes extra `v{n}` features\n//! for generating UUIDs which are not enabled by Rocket. To enable these\n//! features, depend on `uuid` directly. The extra functionality can be accessed\n//! via both `rocket::serde::uuid::Uuid` or the direct `uuid::Uuid`; the types\n//! are one and the same.\n//!\n//! ```toml\n//! [dependencies.uuid]\n//! version = \"1\"\n//! features = [\"v1\", \"v4\"]\n//! ```\n\nuse crate::request::FromParam;\nuse crate::form::{self, FromFormField, ValueField};\n\n/// Error returned on [`FromParam`] or [`FromFormField`] failures.\n///\npub use uuid_::Error;\n\npub use uuid_::{Uuid, Builder, Variant, Version, Bytes, uuid, fmt};\n\nimpl<'a> FromParam<'a> for Uuid {\n    type Error = Error;\n\n    /// A value is successfully parsed if `param` is a properly formatted Uuid.\n    /// Otherwise, an error is returned.\n    #[inline(always)]\n    fn from_param(param: &'a str) -> Result<Uuid, Self::Error> {\n        param.parse()\n    }\n}\n\nimpl<'v> FromFormField<'v> for Uuid {\n    #[inline]\n    fn from_value(field: ValueField<'v>) -> form::Result<'v, Self> {\n        Ok(field.value.parse().map_err(form::error::Error::custom)?)\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::{Uuid, FromParam};\n\n    #[test]\n    fn test_from_param() {\n        let uuid_str = \"c1aa1e3b-9614-4895-9ebd-705255fa5bc2\";\n        let uuid = Uuid::from_param(uuid_str).unwrap();\n        assert_eq!(uuid_str, uuid.to_string());\n    }\n\n    #[test]\n    fn test_from_param_invalid() {\n        let uuid_str = \"c1aa1e3b-9614-4895-9ebd-705255fa5bc2p\";\n        assert!(Uuid::from_param(uuid_str).is_err());\n    }\n}\n"
  },
  {
    "path": "core/lib/src/server.rs",
    "content": "use std::io;\nuse std::pin::pin;\nuse std::sync::Arc;\nuse std::time::Duration;\n\nuse hyper::service::service_fn;\nuse hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer};\nuse hyper_util::server::conn::auto::Builder;\nuse futures::{Future, TryFutureExt};\nuse tokio::io::{AsyncRead, AsyncWrite};\n\nuse crate::{Ignite, Orbit, Request, Rocket};\nuse crate::request::ConnectionMeta;\nuse crate::erased::{ErasedRequest, ErasedResponse, ErasedIoHandler};\nuse crate::listener::{Listener, Connection, BouncedExt, CancellableExt};\nuse crate::error::log_server_error;\nuse crate::data::{IoStream, RawStream};\nuse crate::util::{spawn_inspect, FutureExt, ReaderStream};\nuse crate::http::Status;\nuse crate::trace::{Trace, TraceAll};\n\ntype Result<T, E = crate::Error> = std::result::Result<T, E>;\n\nimpl Rocket<Orbit> {\n    #[tracing::instrument(\"request\", skip_all, fields(\n        method = %parts.method,\n        uri = %parts.uri,\n        autohandled\n    ))]\n    async fn service<T: for<'a> Into<RawStream<'a>>>(\n        self: Arc<Self>,\n        parts: http::request::Parts,\n        stream: T,\n        upgrade: Option<hyper::upgrade::OnUpgrade>,\n        connection: ConnectionMeta,\n    ) -> Result<hyper::Response<ReaderStream<ErasedResponse>>, http::Error> {\n        connection.trace_debug();\n        let request = ErasedRequest::new(self, parts, |rocket, parts| {\n            Request::from_hyp(rocket, parts, connection).unwrap_or_else(|e| e)\n        });\n\n        span_debug!(\"request headers\" => request.inner().headers().iter().trace_all_debug());\n        let mut response = request.into_response(\n            stream,\n            |rocket, request, data| Box::pin(rocket.preprocess(request, data)),\n            |token, rocket, request, data| Box::pin(async move {\n                if !request.errors.is_empty() {\n                    return rocket.dispatch_error(Status::BadRequest, request).await;\n                }\n\n                rocket.dispatch(token, request, data).await\n            })\n        ).await;\n\n        // TODO: Should upgrades be handled in dispatch?\n        response.inner().trace_info();\n        span_debug!(\"response headers\" => response.inner().headers().iter().trace_all_debug());\n        let io_handler = response.make_io_handler(Rocket::extract_io_handler);\n        if let (Some((proto, handler)), Some(upgrade)) = (io_handler, upgrade) {\n            let upgrade = upgrade.map_ok(IoStream::from).map_err(io::Error::other);\n            tokio::task::spawn(io_handler_task(proto, upgrade, handler));\n        }\n\n        let mut builder = hyper::Response::builder();\n        builder = builder.status(response.inner().status().code);\n        for header in response.inner().headers().iter() {\n            builder = builder.header(header.name().as_str(), header.value());\n        }\n\n        let chunk_size = response.inner().body().max_chunk_size();\n        builder.body(ReaderStream::with_capacity(response, chunk_size))\n    }\n\n    pub(crate) fn alt_svc(&self) -> Option<&'static str> {\n        cfg!(feature = \"http3-preview\").then(|| {\n            static ALT_SVC: state::InitCell<Option<String>> = state::InitCell::new();\n\n            ALT_SVC.get_or_init(|| {\n                let addr = self.endpoints().find_map(|v| v.quic())?;\n                Some(format!(\"h3=\\\":{}\\\"\", addr.port()))\n            }).as_deref()\n        })?\n    }\n}\n\n#[tracing::instrument(\"upgrade\", skip_all, fields(protocol = proto))]\nasync fn io_handler_task<S>(proto: String, stream: S, mut handler: ErasedIoHandler)\n    where S: Future<Output = io::Result<IoStream>>\n{\n    let stream = match stream.await {\n        Ok(stream) => stream,\n        Err(e) => return warn!(error = %e, \"i/o upgrade failed\"),\n    };\n\n    debug!(\"i/o upgrade succeeded\");\n    if let Err(e) = handler.take().io(stream).await {\n        match e.kind() {\n            io::ErrorKind::BrokenPipe => warn!(\"i/o handler closed\"),\n            _ => warn!(error = %e, \"i/o handler terminated unsuccessfully\"),\n        }\n    }\n}\n\nimpl Rocket<Ignite> {\n    pub(crate) async fn listen_and_serve<L, R>(\n        self,\n        listener: L,\n        orbit_callback: impl FnOnce(Rocket<Orbit>) -> R,\n    ) -> Result<Arc<Rocket<Orbit>>>\n        where L: Listener + 'static,\n              R: Future<Output = Result<Arc<Rocket<Orbit>>>>\n    {\n        let endpoint = listener.endpoint()?;\n\n        #[cfg(feature = \"http3-preview\")]\n        if let (Some(addr), Some(tls)) = (endpoint.tcp(), endpoint.tls_config()) {\n            use crate::error::ErrorKind;\n\n            let h3listener = crate::listener::quic::QuicListener::bind(addr, tls.clone())\n                .map_err(|e| ErrorKind::Bind(Some(endpoint.clone()), Box::new(e)))\n                .await?;\n\n            let rocket = self.into_orbit(vec![h3listener.endpoint()?, endpoint]);\n            let rocket = orbit_callback(rocket).await?;\n\n            let http12 = tokio::task::spawn(rocket.clone().serve12(listener));\n            let http3 = tokio::task::spawn(rocket.clone().serve3(h3listener));\n            let (r1, r2) = tokio::join!(http12, http3);\n            r1.map_err(|e| ErrorKind::Liftoff(Err(rocket.clone()), e))??;\n            r2.map_err(|e| ErrorKind::Liftoff(Err(rocket.clone()), e))??;\n            return Ok(rocket);\n        }\n\n        if cfg!(feature = \"http3-preview\") {\n            warn!(\"HTTP/3 cannot start without a valid TCP + TLS configuration.\\n\\\n                Falling back to HTTP/1 + HTTP/2 server.\");\n        }\n\n        let rocket = self.into_orbit(vec![endpoint]);\n        let rocket = orbit_callback(rocket).await?;\n        rocket.clone().serve12(listener).await?;\n        Ok(rocket)\n    }\n}\n\nimpl Rocket<Orbit> {\n    pub(crate) async fn serve12<L>(self: Arc<Self>, listener: L) -> Result<()>\n        where L: Listener + 'static,\n              L::Connection: AsyncRead + AsyncWrite\n    {\n        let mut builder = Builder::new(TokioExecutor::new());\n        let keep_alive = Duration::from_secs(self.config.keep_alive.into());\n        builder.http1()\n            .half_close(true)\n            .timer(TokioTimer::new())\n            .keep_alive(keep_alive > Duration::ZERO)\n            .preserve_header_case(true)\n            .header_read_timeout(Duration::from_secs(15));\n\n        #[cfg(feature = \"http2\")] {\n            builder.http2().timer(TokioTimer::new());\n            if keep_alive > Duration::ZERO {\n                builder.http2()\n                    .timer(TokioTimer::new())\n                    .keep_alive_interval(keep_alive / 4)\n                    .keep_alive_timeout(keep_alive);\n            }\n        }\n\n        let (listener, server) = (Arc::new(listener.bounced()), Arc::new(builder));\n        while let Some(accept) = listener.accept().race(self.shutdown()).await.left().transpose()? {\n            let (listener, rocket, server) = (listener.clone(), self.clone(), server.clone());\n            spawn_inspect(|e| log_server_error(&**e), async move {\n                let conn = listener.connect(accept).race_io(rocket.shutdown()).await?;\n                let meta = ConnectionMeta::new(\n                    conn.endpoint(),\n                    conn.certificates(),\n                    conn.server_name()\n                );\n                let service = service_fn(|mut req| {\n                    let upgrade = hyper::upgrade::on(&mut req);\n                    let (parts, incoming) = req.into_parts();\n                    rocket.clone().service(parts, incoming, Some(upgrade), meta.clone())\n                });\n\n                let io = TokioIo::new(conn.cancellable(rocket.shutdown.clone()));\n                let mut server = pin!(server.serve_connection_with_upgrades(io, service));\n                match server.as_mut().race(rocket.shutdown()).await.left() {\n                    Some(result) => result,\n                    None => {\n                        server.as_mut().graceful_shutdown();\n                        server.await\n                    },\n                }\n            });\n        }\n\n        Ok(())\n    }\n\n    #[cfg(feature = \"http3-preview\")]\n    async fn serve3(self: Arc<Self>, listener: crate::listener::quic::QuicListener) -> Result<()> {\n        let rocket = self.clone();\n        let listener = Arc::new(listener);\n        while let Some(Some(accept)) = listener.accept().race(rocket.shutdown()).await.left() {\n            let (listener, rocket) = (listener.clone(), rocket.clone());\n            spawn_inspect(|e: &io::Error| log_server_error(e), async move {\n                let mut stream = listener.connect(accept).race_io(rocket.shutdown()).await?;\n                while let Some(mut conn) = stream.accept().race_io(rocket.shutdown()).await? {\n                    let rocket = rocket.clone();\n                    spawn_inspect(|e: &io::Error| log_server_error(e), async move {\n                        let meta = ConnectionMeta::new(conn.endpoint(), None, None);\n                        let rx = conn.rx.cancellable(rocket.shutdown.clone());\n                        let response = rocket.clone()\n                            .service(conn.parts, rx, None, meta)\n                            .map_err(io::Error::other)\n                            .race_io(rocket.shutdown.mercy.clone())\n                            .await?;\n\n                        let grace = rocket.shutdown.grace.clone();\n                        match conn.tx.send_response(response).race(grace).await.left() {\n                            Some(result) => result,\n                            None => Ok(conn.tx.cancel()),\n                        }\n                    });\n                }\n\n                Ok(())\n            });\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/shield/mod.rs",
    "content": "//! Security and privacy headers for all outgoing responses.\n//!\n//! The [`Shield`] fairing provides a typed interface for injecting HTTP\n//! security and privacy headers into all outgoing responses. It takes some\n//! inspiration from [helmetjs], a similar piece of middleware for [express].\n//!\n//! [fairing]: https://rocket.rs/master/guide/fairings/\n//! [helmetjs]: https://helmetjs.github.io/\n//! [express]: https://expressjs.com\n//!\n//! # Supported Headers\n//!\n//! | HTTP Header                 | Description                            | Policy         | Default? |\n//! | --------------------------- | -------------------------------------- | -------------- | -------- |\n//! | [X-XSS-Protection]          | Prevents some reflected XSS attacks.   | [`XssFilter`]  | ✗        |\n//! | [X-Content-Type-Options]    | Prevents client sniffing of MIME type. | [`NoSniff`]    | ✔        |\n//! | [X-Frame-Options]           | Prevents [clickjacking].               | [`Frame`]      | ✔        |\n//! | [Strict-Transport-Security] | Enforces strict use of HTTPS.          | [`Hsts`]       | ?        |\n//! | [Expect-CT]                 | Enables certificate transparency.      | [`ExpectCt`]   | ✗        |\n//! | [Referrer-Policy]           | Enables referrer policy.               | [`Referrer`]   | ✗        |\n//! | [X-DNS-Prefetch-Control]    | Controls browser DNS prefetching.      | [`Prefetch`]   | ✗        |\n//! | [Permissions-Policy]        | Allows or block browser features.      | [`Permission`] | ✔        |\n//!\n//! <small>? If TLS is enabled in a non-debug profile, HSTS is automatically\n//! enabled with its default policy and a warning is logged at liftoff.</small>\n//!\n//! [X-XSS-Protection]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection\n//! [X-Content-Type-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options\n//! [X-Frame-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options\n//! [Strict-Transport-Security]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security\n//! [Expect-CT]:  https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT\n//! [Referrer-Policy]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy\n//! [X-DNS-Prefetch-Control]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control\n//! [clickjacking]: https://en.wikipedia.org/wiki/Clickjacking\n//! [Permissions-Policy]: https://github.com/w3c/webappsec-permissions-policy/blob/a45df7b237e2a85e1909d7f226ca4eb4ce5095ba/permissions-policy-explainer.md\n//!\n//! [`XssFilter`]: self::XssFilter\n//! [`NoSniff`]: self::NoSniff\n//! [`Frame`]: self::Frame\n//! [`Hsts`]: self::Hsts\n//! [`ExpectCt`]: self::ExpectCt\n//! [`Referrer`]: self::Referrer\n//! [`Prefetch`]: self::Prefetch\n//!\n//! # Usage\n//!\n//! By default, [`Shield::default()`] is attached to all instances Rocket. To\n//! change the default, including removing all `Shield` headers, attach a\n//! configured instance of [`Shield`]:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use rocket::shield::Shield;\n//!\n//! #[launch]\n//! fn rocket() -> _ {\n//!     // Remove all `Shield` headers.\n//!     rocket::build().attach(Shield::new())\n//! }\n//! ```\n//!\n//! Each header can be configured individually. To enable a particular header,\n//! call the chainable [`enable()`](shield::Shield::enable()) method\n//! on an instance of `Shield`, passing in the configured policy type.\n//! Similarly, to disable a header, call the chainable\n//! [`disable()`](shield::Shield::disable()) method on an instance of\n//! `Shield`:\n//!\n//! ```rust\n//! # #[macro_use] extern crate rocket;\n//! use time::Duration;\n//!\n//! use rocket::http::uri::Uri;\n//! use rocket::shield::{Shield, Referrer, Prefetch, ExpectCt, NoSniff};\n//!\n//! let report_uri = uri!(\"https://report.rocket.rs\");\n//! let shield = Shield::default()\n//!     .enable(Referrer::NoReferrer)\n//!     .enable(Prefetch::Off)\n//!     .enable(ExpectCt::ReportAndEnforce(Duration::days(30), report_uri))\n//!     .disable::<NoSniff>();\n//! ```\n//!\n//! # FAQ\n//!\n//! * **Which policies should I choose?**\n//!\n//!   See the links in the table above for individual header documentation. The\n//!   [helmetjs] docs are also a good resource, and [OWASP] has a collection of\n//!   references on these headers.\n//!\n//! * **Do I need any headers beyond what `Shield` enables by default?**\n//!\n//!   Maybe! The other headers may protect against many important\n//!   vulnerabilities. Please consult their documentation and other resources to\n//!   determine if they are needed for your project.\n//!\n//! [OWASP]: https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers\n\nmod shield;\nmod policy;\n\npub use self::shield::Shield;\npub use self::policy::*;\n"
  },
  {
    "path": "core/lib/src/shield/policy.rs",
    "content": "//! Module containing the [`Policy`] trait and types that implement it.\n\nuse std::fmt;\nuse std::borrow::Cow;\n\nuse indexmap::IndexMap;\nuse time::Duration;\n\nuse crate::http::{Header, uri::Absolute, uncased::Uncased};\n\n/// Trait implemented by security and privacy policy headers.\n///\n/// Types that implement this trait can be [`enable()`]d and [`disable()`]d on\n/// instances of [`Shield`].\n///\n/// [`Shield`]: crate::shield::Shield\n/// [`enable()`]: crate::shield::Shield::enable()\n/// [`disable()`]: crate::shield::Shield::disable()\npub trait Policy: Default + Send + Sync + 'static {\n    /// The actual name of the HTTP header.\n    ///\n    /// This name must uniquely identify the header as it is used to determine\n    /// whether two implementations of `Policy` are for the same header. Use the\n    /// real HTTP header's name.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// # use rocket::http::Header;\n    /// use rocket::shield::Policy;\n    ///\n    /// #[derive(Default)]\n    /// struct MyPolicy;\n    ///\n    /// impl Policy for MyPolicy {\n    ///     const NAME: &'static str = \"X-My-Policy\";\n    /// #   fn header(&self) -> Header<'static> { unimplemented!() }\n    /// }\n    /// ```\n    const NAME: &'static str;\n\n    /// Returns the [`Header`](../../rocket/http/struct.Header.html) to attach\n    /// to all outgoing responses.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::http::Header;\n    /// use rocket::shield::Policy;\n    ///\n    /// #[derive(Default)]\n    /// struct MyPolicy;\n    ///\n    /// impl Policy for MyPolicy {\n    /// #   const NAME: &'static str = \"X-My-Policy\";\n    ///     fn header(&self) -> Header<'static> {\n    ///         Header::new(Self::NAME, \"value-to-enable\")\n    ///     }\n    /// }\n    /// ```\n    fn header(&self) -> Header<'static>;\n}\n\nmacro_rules! impl_policy {\n    ($T:ty, $name:expr) => (\n        impl Policy for $T {\n            const NAME: &'static str = $name;\n\n            fn header(&self) -> Header<'static> {\n                self.into()\n            }\n        }\n    )\n}\n\n// Keep this in-sync with the top-level module docs.\nimpl_policy!(XssFilter, \"X-XSS-Protection\");\nimpl_policy!(NoSniff, \"X-Content-Type-Options\");\nimpl_policy!(Frame, \"X-Frame-Options\");\nimpl_policy!(Hsts, \"Strict-Transport-Security\");\nimpl_policy!(ExpectCt, \"Expect-CT\");\nimpl_policy!(Referrer, \"Referrer-Policy\");\nimpl_policy!(Prefetch, \"X-DNS-Prefetch-Control\");\nimpl_policy!(Permission, \"Permissions-Policy\");\n\n/// The [Referrer-Policy] header: controls the value set by the browser for the\n/// [Referer] header.\n///\n/// Tells the browser if it should send all or part of URL of the current page\n/// to the next site the user navigates to via the [Referer] header. This can be\n/// important for security as the URL itself might expose sensitive data, such\n/// as a hidden file path or personal identifier.\n///\n/// [Referrer-Policy]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy\n/// [Referer]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer\npub enum Referrer {\n    /// Omits the `Referer` header (returned by [`Referrer::default()`]).\n    NoReferrer,\n\n    /// Omits the `Referer` header on connection downgrade i.e. following HTTP\n    /// link from HTTPS site (_Browser default_).\n    NoReferrerWhenDowngrade,\n\n    /// Only send the origin of part of the URL, e.g. the origin of\n    /// `https://foo.com/bob.html` is `https://foo.com`.\n    Origin,\n\n    /// Send full URL for same-origin requests, only send origin part when\n    /// replying to [cross-origin] requests.\n    ///\n    /// [cross-origin]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS\n    OriginWhenCrossOrigin,\n\n    /// Send full URL for same-origin requests only.\n    SameOrigin,\n\n    /// Only send origin part of URL, only send if protocol security level\n    /// remains the same e.g. HTTPS to HTTPS.\n    StrictOrigin,\n\n    /// Send full URL for same-origin requests. For cross-origin requests, only\n    /// send origin part of URL if protocol security level remains the same e.g.\n    /// HTTPS to HTTPS.\n    StrictOriginWhenCrossOrigin,\n\n    /// Send full URL for same-origin or cross-origin requests. _This will leak\n    /// the full URL of TLS protected resources to insecure origins. Use with\n    /// caution._\n    UnsafeUrl,\n }\n\n/// Defaults to [`Referrer::NoReferrer`]. Tells the browser to omit the\n/// `Referer` header.\nimpl Default for Referrer {\n    fn default() -> Referrer {\n        Referrer::NoReferrer\n    }\n}\n\nimpl From<&Referrer> for Header<'static> {\n    fn from(referrer: &Referrer) -> Self {\n        let policy_string = match referrer {\n            Referrer::NoReferrer => \"no-referrer\",\n            Referrer::NoReferrerWhenDowngrade => \"no-referrer-when-downgrade\",\n            Referrer::Origin => \"origin\",\n            Referrer::OriginWhenCrossOrigin => \"origin-when-cross-origin\",\n            Referrer::SameOrigin => \"same-origin\",\n            Referrer::StrictOrigin => \"strict-origin\",\n            Referrer::StrictOriginWhenCrossOrigin => \"strict-origin-when-cross-origin\",\n            Referrer::UnsafeUrl => \"unsafe-url\",\n        };\n\n        Header::new(Referrer::NAME, policy_string)\n    }\n}\n\n/// The [Expect-CT] header: enables reporting and/or enforcement of [Certificate\n/// Transparency].\n///\n/// [Certificate Transparency] can detect and prevent the use of incorrectly\n/// issued malicious, or revoked TLS certificates. It solves a variety of\n/// problems with public TLS/SSL certificate management and is valuable measure\n/// for all public TLS applications.\n///\n/// If you're just [getting started] with certificate transparency, ensure that\n/// your [site is in compliance][getting started] before you enable enforcement\n/// with [`ExpectCt::Enforce`] or [`ExpectCt::ReportAndEnforce`]. Failure to do\n/// so will result in the browser refusing to communicate with your application.\n/// _You have been warned_.\n///\n/// [Expect-CT]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT\n/// [Certificate Transparency]: http://www.certificate-transparency.org/what-is-ct\n/// [getting started]: http://www.certificate-transparency.org/getting-started\npub enum ExpectCt {\n    /// Enforce certificate compliance for the next [`Duration`]. Ensure that\n    /// your certificates are in compliance before turning on enforcement.\n    /// (_Shield_ default).\n    Enforce(Duration),\n\n    /// Report to `Absolute`, but do not enforce, compliance violations for the\n    /// next [`Duration`]. Doesn't provide any protection but is a good way make\n    /// sure things are working correctly before turning on enforcement in\n    /// production.\n    Report(Duration, Absolute<'static>),\n\n    /// Enforce compliance and report violations to `Absolute` for the next\n    /// [`Duration`].\n    ReportAndEnforce(Duration, Absolute<'static>),\n}\n\n/// Defaults to [`ExpectCt::Enforce`] with a 30 day duration, enforce CT\n/// compliance, see [draft] standard for more.\n///\n/// [draft]: https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct-03#page-15\nimpl Default for ExpectCt {\n    fn default() -> ExpectCt {\n        ExpectCt::Enforce(Duration::days(30))\n    }\n}\n\nimpl From<&ExpectCt> for Header<'static> {\n    fn from(expect: &ExpectCt) -> Self {\n        let policy_string =  match expect {\n            ExpectCt::Enforce(age) => format!(\"max-age={}, enforce\", age.whole_seconds()),\n            ExpectCt::Report(age, uri) => {\n                format!(r#\"max-age={}, report-uri=\"{}\"\"#, age.whole_seconds(), uri)\n            }\n            ExpectCt::ReportAndEnforce(age, uri) => {\n                format!(\"max-age={}, enforce, report-uri=\\\"{}\\\"\", age.whole_seconds(), uri)\n            }\n        };\n\n        Header::new(ExpectCt::NAME, policy_string)\n    }\n}\n\n/// The [X-Content-Type-Options] header: turns off [mime sniffing] which can\n/// prevent certain [attacks].\n///\n/// [mime sniffing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#MIME_sniffing\n/// [X-Content-Type-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options\n/// [attacks]: https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/\npub enum NoSniff {\n    /// Turns off mime sniffing.\n    Enable,\n}\n\n/// Defaults to [`NoSniff::Enable`], turns off mime sniffing.\nimpl Default for NoSniff {\n    fn default() -> NoSniff {\n        NoSniff::Enable\n    }\n}\n\nimpl From<&NoSniff> for Header<'static> {\n    fn from(_: &NoSniff) -> Self {\n        Header::new(NoSniff::NAME, \"nosniff\")\n    }\n}\n\n/// The HTTP [Strict-Transport-Security] (HSTS) header: enforces strict HTTPS\n/// usage.\n///\n/// HSTS tells the browser that the site should only be accessed using HTTPS\n/// instead of HTTP. HSTS prevents a variety of downgrading attacks and should\n/// always be used when [TLS] is enabled. `Shield` will turn HSTS on and issue a\n/// warning if you enable TLS without enabling HSTS when the application is run\n/// in non-debug profiles.\n///\n/// While HSTS is important for HTTPS security, incorrectly configured HSTS can\n/// lead to problems as you are disallowing access to non-HTTPS enabled parts of\n/// your site. [Yelp engineering] has good discussion of potential challenges\n/// that can arise and how to roll this out in a large scale setting. So, if\n/// you use TLS, use HSTS, but roll it out with care.\n///\n/// [TLS]: https://rocket.rs/guide/configuration/#configuring-tls\n/// [Strict-Transport-Security]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security\n/// [Yelp engineering]: https://engineeringblog.yelp.com/2017/09/the-road-to-hsts.html\n#[derive(PartialEq, Copy, Clone)]\npub enum Hsts {\n    /// Browser should only permit this site to be accesses by HTTPS for the\n    /// next [`Duration`].\n    Enable(Duration),\n\n    /// Like [`Hsts::Enable`], but also apply to all of the site's subdomains.\n    IncludeSubDomains(Duration),\n\n    /// Send a \"preload\" HSTS header, which requests inclusion in the HSTS\n    /// preload list. This variant implies [`Hsts::IncludeSubDomains`], which\n    /// implies [`Hsts::Enable`].\n    ///\n    /// The provided `Duration` must be _at least_ 365 days. If the duration\n    /// provided is less than 365 days, the header will be written out with a\n    /// `max-age` of 365 days.\n    ///\n    /// # Details\n    ///\n    /// Google maintains an [HSTS preload service] that can be used to prevent\n    /// the browser from ever connecting to your site over an insecure\n    /// connection. Read more at [MDN]. Don't enable this before you have\n    /// registered your site and you ensure that it meets the requirements\n    /// specified by the preload service.\n    ///\n    /// [HSTS preload service]: https://hstspreload.org/\n    /// [MDN]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#Preloading_Strict_Transport_Security\n    Preload(Duration),\n}\n\n/// Defaults to `Hsts::Enable(Duration::days(365))`.\nimpl Default for Hsts {\n    fn default() -> Hsts {\n        Hsts::Enable(Duration::days(365))\n    }\n}\n\nimpl From<&Hsts> for Header<'static> {\n    fn from(hsts: &Hsts) -> Self {\n        if hsts == &Hsts::default() {\n            static DEFAULT: Header<'static> = Header {\n                name: Uncased::from_borrowed(Hsts::NAME),\n                value: Cow::Borrowed(\"max-age=31536000\")\n            };\n\n            return DEFAULT.clone();\n        }\n\n        let policy_string = match hsts {\n            Hsts::Enable(age) => format!(\"max-age={}\", age.whole_seconds()),\n            Hsts::IncludeSubDomains(age) => {\n                format!(\"max-age={}; includeSubDomains\", age.whole_seconds())\n            }\n            Hsts::Preload(age) => {\n                // Google says it needs to be >= 365 days for preload list.\n                static YEAR: Duration = Duration::seconds(31536000);\n\n                format!(\"max-age={}; includeSubDomains; preload\", age.max(&YEAR).whole_seconds())\n            }\n        };\n\n        Header::new(Hsts::NAME, policy_string)\n    }\n}\n\n/// The [X-Frame-Options] header: helps prevent [clickjacking] attacks.\n///\n/// Controls whether the browser should allow the page to render in a `<frame>`,\n/// [`<iframe>`][iframe] or `<object>`. This can be used to prevent\n/// [clickjacking] attacks.\n///\n/// [X-Frame-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options\n/// [clickjacking]: https://en.wikipedia.org/wiki/Clickjacking\n/// [owasp-clickjacking]: https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet\n/// [iframe]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe\npub enum Frame {\n    /// Page cannot be displayed in a frame.\n    Deny,\n\n    /// Page can only be displayed in a frame if the page trying to render it is\n    /// in the same origin. Interpretation of same-origin is [browser\n    /// dependent][X-Frame-Options].\n    ///\n    /// [X-Frame-Options]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options\n    SameOrigin,\n}\n\n/// Defaults to [`Frame::SameOrigin`].\nimpl Default for Frame {\n    fn default() -> Frame {\n        Frame::SameOrigin\n    }\n}\n\nimpl From<&Frame> for Header<'static> {\n    fn from(frame: &Frame) -> Self {\n        let policy_string: &'static str = match frame {\n            Frame::Deny => \"DENY\",\n            Frame::SameOrigin => \"SAMEORIGIN\",\n        };\n\n        Header::new(Frame::NAME, policy_string)\n    }\n}\n\n/// The [X-XSS-Protection] header: filters some forms of reflected [XSS]\n/// attacks. Modern browsers do not support or enforce this header.\n///\n/// [X-XSS-Protection]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection\n/// [XSS]: https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting\npub enum XssFilter {\n    /// Disables XSS filtering.\n    Disable,\n\n    /// Enables XSS filtering. If XSS is detected, the browser will sanitize\n    /// before rendering the page (_Shield default_).\n    Enable,\n\n    /// Enables XSS filtering. If XSS is detected, the browser will not\n    /// render the page.\n    EnableBlock,\n}\n\n/// Defaults to [`XssFilter::Enable`].\nimpl Default for XssFilter {\n    fn default() -> XssFilter {\n        XssFilter::Enable\n    }\n}\n\nimpl From<&XssFilter> for Header<'static> {\n    fn from(filter: &XssFilter) -> Self {\n        let policy_string: &'static str = match filter {\n            XssFilter::Disable => \"0\",\n            XssFilter::Enable => \"1\",\n            XssFilter::EnableBlock => \"1; mode=block\",\n        };\n\n        Header::new(XssFilter::NAME, policy_string)\n    }\n}\n\n/// The [X-DNS-Prefetch-Control] header: controls browser DNS prefetching.\n///\n/// Tells the browser if it should perform domain name resolution on both links\n/// that the user may choose to follow as well as URLs for items referenced by\n/// the document including images, CSS, JavaScript, and so forth. Disabling\n/// prefetching is useful if you don't control the link on the pages, or know\n/// that you don't want to leak information to these domains.\n///\n/// [X-DNS-Prefetch-Control]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control\n#[derive(Default)]\npub enum Prefetch {\n    /// Enables DNS prefetching. This is the browser default.\n    On,\n    /// Disables DNS prefetching. This is the shield policy default.\n    #[default]\n    Off,\n}\n\nimpl From<&Prefetch> for Header<'static> {\n    fn from(prefetch: &Prefetch) -> Self {\n        let policy_string = match prefetch {\n            Prefetch::On => \"on\",\n            Prefetch::Off => \"off\",\n        };\n\n        Header::new(Prefetch::NAME, policy_string)\n    }\n}\n\n/// The [Permissions-Policy] header: allow or block the use of browser features.\n///\n/// Tells the browser to allow or block the use of a browser feature in the\n/// top-level page as well as allow or block _requesting access to_ (via the\n/// `allow` `iframe` attribute) features in embedded iframes.\n///\n/// By default, the top-level page may access ~all features and any embedded\n/// iframes may request access to ~any feature. This header allows the server to\n/// control exactly _which_ (if any) origins may access or request access to\n/// browser features.\n///\n/// Features are enabled via the [`Permission::allowed()`] constructor and\n/// chainable [`allow()`](Self::allow()) build method. Features can be blocked\n/// via the [`Permission::blocked()`] and chainable [`block()`](Self::block())\n/// builder method.\n///\n/// ```rust\n    /// # #[macro_use] extern crate rocket;\n/// use rocket::shield::{Shield, Permission, Feature, Allow};\n///\n/// // In addition to defaults, block access to geolocation and USB features.\n/// // Enable camera and microphone features only for the serving origin. Enable\n/// // payment request access for the current origin and `https://rocket.rs`.\n/// let permission = Permission::default()\n///     .block(Feature::Geolocation)\n///     .block(Feature::Usb)\n///     .allow(Feature::Camera, Allow::This)\n///     .allow(Feature::Microphone, Allow::This)\n///     .allow(Feature::Payment, [Allow::This, Allow::Origin(uri!(\"https://rocket.rs\"))]);\n///\n/// rocket::build().attach(Shield::default().enable(permission));\n/// ```\n///\n/// # Default\n///\n/// The default returned via [`Permission::default()`] blocks access to the\n/// `interest-cohort` feature, otherwise known as FLoC, which disables using the\n/// current site in ad targeting tracking computations.\n///\n/// [Permissions-Policy]: https://github.com/w3c/webappsec-permissions-policy/blob/a45df7b237e2a85e1909d7f226ca4eb4ce5095ba/permissions-policy-explainer.md\n#[derive(PartialEq, Clone)]\npub struct Permission(IndexMap<Feature, Vec<Allow>>);\n\nimpl Default for Permission {\n    /// The default `Permission` policy blocks access to the `interest-cohort`\n    /// feature, otherwise known as FLoC, which disables using the current site\n    /// in ad targeting tracking computations.\n    fn default() -> Self {\n        Permission::blocked(Feature::InterestCohort)\n    }\n}\n\nimpl Permission {\n    /// Constructs a new `Permission` policy with only `feature` allowed for the\n    /// set of origins in `allow` which may be a single [`Allow`], a slice\n    /// (`[Allow]` or `&[Allow]`), or a vector (`Vec<Allow>`).\n    ///\n    /// If `allow` is empty, the use of the feature is blocked unless another\n    /// call to `allow()` allows it. If `allow` contains [`Allow::Any`], the\n    /// feature is allowable for all origins. Otherwise, the feature is\n    /// allowable only for the origin specified in `allow`.\n    ///\n    /// # Panics\n    ///\n    /// Panics if an `Absolute` URI in an `Allow::Origin` does not contain a\n    /// host part.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::shield::{Permission, Feature, Allow};\n    ///\n    /// let rocket = Allow::Origin(uri!(\"https://rocket.rs\"));\n    ///\n    /// let perm = Permission::allowed(Feature::Usb, Allow::This);\n    /// let perm = Permission::allowed(Feature::Usb, Allow::Any);\n    /// let perm = Permission::allowed(Feature::Usb, [Allow::This, rocket]);\n    /// ```\n    pub fn allowed<L>(feature: Feature, allow: L) -> Self\n        where L: IntoIterator<Item = Allow>\n    {\n        Permission(IndexMap::new()).allow(feature, allow)\n    }\n\n    /// Constructs a new `Permission` policy with only `feature` blocked.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::{Permission, Feature};\n    ///\n    /// let perm = Permission::blocked(Feature::Usb);\n    /// let perm = Permission::blocked(Feature::Payment);\n    /// ```\n    pub fn blocked(feature: Feature) -> Self {\n        Permission(IndexMap::new()).block(feature)\n    }\n\n    /// Adds `feature` as allowable for the set of origins in `allow` which may\n    /// be a single [`Allow`], a slice (`[Allow]` or `&[Allow]`), or a vector\n    /// (`Vec<Allow>`).\n    ///\n    /// This policy supersedes any previous policy set for `feature`.\n    ///\n    /// If `allow` is empty, the use of the feature is blocked unless another\n    /// call to `allow()` allows it. If `allow` contains [`Allow::Any`], the\n    /// feature is allowable for all origins. Otherwise, the feature is\n    /// allowable only for the origin specified in `allow`.\n    ///\n    /// # Panics\n    ///\n    /// Panics if an `Absolute` URI in an `Allow::Origin` does not contain a\n    /// host part.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::shield::{Permission, Feature, Allow};\n    ///\n    /// let rocket = Allow::Origin(uri!(\"https://rocket.rs\"));\n    /// let perm = Permission::allowed(Feature::Usb, Allow::This)\n    ///     .allow(Feature::Payment, [rocket, Allow::This]);\n    /// ```\n    pub fn allow<L>(mut self, feature: Feature, allow: L) -> Self\n        where L: IntoIterator<Item = Allow>\n    {\n        let mut allow: Vec<_> = allow.into_iter().collect();\n        for allow in &allow {\n            if let Allow::Origin(absolute) = allow {\n                let auth = absolute.authority();\n                if auth.is_none() || matches!(auth, Some(a) if a.host().is_empty()) {\n                    panic!(\"...\")\n                }\n            }\n        }\n\n        if allow.contains(&Allow::Any) {\n            allow = vec![Allow::Any];\n        }\n\n        self.0.insert(feature, allow);\n        self\n    }\n\n    /// Blocks `feature`. This policy supersedes any previous policy set for\n    /// `feature`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::{Permission, Feature};\n    ///\n    /// let perm = Permission::default()\n    ///     .block(Feature::Usb)\n    ///     .block(Feature::Payment);\n    /// ```\n    pub fn block(mut self, feature: Feature) -> Self {\n        self.0.insert(feature, vec![]);\n        self\n    }\n\n    /// Returns the allow list (so far) for `feature` if feature is allowed.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::{Permission, Feature, Allow};\n    ///\n    /// let perm = Permission::default();\n    /// assert!(perm.get(Feature::Usb).is_none());\n    ///\n    /// let perm = perm.allow(Feature::Usb, Allow::Any);\n    /// assert_eq!(perm.get(Feature::Usb).unwrap(), &[Allow::Any]);\n    /// ```\n    pub fn get(&self, feature: Feature) -> Option<&[Allow]> {\n        Some(self.0.get(&feature)?)\n    }\n\n    /// Returns an iterator over the pairs of features and their allow lists,\n    /// empty if the feature is blocked.\n    ///\n    /// Features are returned in the order in which they were first added.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #[macro_use] extern crate rocket;\n    /// use rocket::shield::{Permission, Feature, Allow};\n    ///\n    /// let foo = uri!(\"https://foo.com:1234\");\n    /// let perm = Permission::blocked(Feature::Camera)\n    ///     .allow(Feature::Gyroscope, [Allow::This, Allow::Origin(foo.clone())])\n    ///     .block(Feature::Payment)\n    ///     .allow(Feature::Camera, Allow::Any);\n    ///\n    /// let perms: Vec<_> = perm.iter().collect();\n    /// assert_eq!(perms.len(), 3);\n    /// assert_eq!(perms, vec![\n    ///     (Feature::Camera, &[Allow::Any][..]),\n    ///     (Feature::Gyroscope, &[Allow::This, Allow::Origin(foo)][..]),\n    ///     (Feature::Payment, &[][..]),\n    /// ]);\n    /// ```\n    pub fn iter(&self) -> impl Iterator<Item = (Feature, &[Allow])> {\n        self.0.iter().map(|(feature, list)| (*feature, &**list))\n    }\n}\n\nimpl From<&Permission> for Header<'static> {\n    fn from(perm: &Permission) -> Self {\n        if perm == &Permission::default() {\n            static DEFAULT: Header<'static> = Header {\n                name: Uncased::from_borrowed(Permission::NAME),\n                value: Cow::Borrowed(\"interest-cohort=()\")\n            };\n\n            return DEFAULT.clone();\n        }\n\n        let value = perm.0.iter()\n            .map(|(feature, allow)| {\n                let list = allow.iter()\n                    .map(|origin| origin.rendered())\n                    .collect::<Vec<_>>()\n                    .join(\" \");\n\n                format!(\"{}=({})\", feature, list)\n            })\n            .collect::<Vec<_>>()\n            .join(\", \");\n\n        Header::new(Permission::NAME, value)\n    }\n}\n\n/// Specifies the origin(s) allowed to access a browser [`Feature`] via\n/// [`Permission`].\n#[derive(Debug, PartialEq, Clone)]\npub enum Allow {\n    /// Allow this specific origin. The feature is allowed only for this\n    /// specific origin.\n    ///\n    /// The `user_info`, `path`, and `query` parts of the URI, if any, are\n    /// ignored.\n    Origin(Absolute<'static>),\n    /// Any origin at all.\n    ///\n    /// The feature will be allowed in all browsing contexts regardless of their\n    /// origin.\n    Any,\n    /// The current origin.\n    ///\n    /// The feature will be allowed in the immediately returned document and in\n    /// all nested browsing contexts (iframes) in the same origin.\n    This,\n}\n\nimpl Allow {\n    fn rendered(&self) -> Cow<'static, str> {\n        match self {\n            Allow::Origin(uri) => {\n                let mut string = String::with_capacity(32);\n                string.push('\"');\n                string.push_str(uri.scheme());\n\n                // This should never fail when rendering a header for `Shield`\n                // due to `panic` in `.allow()`.\n                if let Some(auth) = uri.authority() {\n                    use std::fmt::Write;\n\n                    let _ = write!(string, \"://{}\", auth.host());\n                    if let Some(port) = auth.port() {\n                        let _ = write!(string, \":{}\", port);\n                    }\n                }\n\n                string.push('\"');\n                string.into()\n            }\n            Allow::Any => \"*\".into(),\n            Allow::This => \"self\".into(),\n        }\n    }\n}\n\nimpl IntoIterator for Allow {\n    type Item = Self;\n\n    type IntoIter = std::iter::Once<Self>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        std::iter::once(self)\n    }\n}\n\n/// A browser feature that can be enabled or blocked via [`Permission`].\n#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]\n#[non_exhaustive]\npub enum Feature {\n    // Standardized.\n\n    /// The \"accelerometer\" feature.\n    Accelerometer,\n    /// The \"ambient-light-sensor\" feature.\n    AmbientLightSensor,\n    /// The \"autoplay\" feature.\n    Autoplay,\n    /// The \"battery\" feature.\n    Battery,\n    /// The \"camera\" feature.\n    Camera,\n    /// The \"cross-origin-isolated\" feature.\n    CrossOriginIsolated,\n    /// The \"display-capture\" feature.\n    Displaycapture,\n    /// The \"document-domain\" feature.\n    DocumentDomain,\n    /// The \"encrypted-media\" feature.\n    EncryptedMedia,\n    /// The \"execution-while-not-rendered\" feature.\n    ExecutionWhileNotRendered,\n    /// The \"execution-while-out-of-viewport\" feature.\n    ExecutionWhileOutOfviewport,\n    /// The \"fullscreen\" feature.\n    Fullscreen,\n    /// The \"geolocation\" feature.\n    Geolocation,\n    /// The \"gyroscope\" feature.\n    Gyroscope,\n    /// The \"magnetometer\" feature.\n    Magnetometer,\n    /// The \"microphone\" feature.\n    Microphone,\n    /// The \"midi\" feature.\n    Midi,\n    /// The \"navigation-override\" feature.\n    NavigationOverride,\n    /// The \"payment\" feature.\n    Payment,\n    /// The \"picture-in-picture\" feature.\n    PictureInPicture,\n    /// The \"publickey-credentials-get\" feature.\n    PublickeyCredentialsGet,\n    /// The \"screen-wake-lock\" feature.\n    ScreenWakeLock,\n    /// The \"sync-xhr\" feature.\n    SyncXhr,\n    /// The \"usb\" feature.\n    Usb,\n    /// The \"web-share\" feature.\n    WebShare,\n    /// The \"xr-spatial-tracking\" feature.\n    XrSpatialTracking,\n\n    // Proposed.\n\n    /// The \"clipboard-read\" feature.\n    ClipboardRead,\n    /// The \"clipboard-write\" feature.\n    ClipboardWrite,\n    /// The \"gamepad\" feature.\n    Gamepad,\n    /// The \"speaker-selection\" feature.\n    SpeakerSelection,\n    /// The \"interest-cohort\" feature.\n    InterestCohort,\n\n    // Experimental.\n\n    /// The \"conversion-measurement\" feature.\n    ConversionMeasurement,\n    /// The \"focus-without-user-activation\" feature.\n    FocusWithoutUserActivation,\n    /// The \"hid\" feature.\n    Hid,\n    /// The \"idle-detection\" feature.\n    IdleDetection,\n    /// The \"serial\" feature.\n    Serial,\n    /// The \"sync-script\" feature.\n    SyncScript,\n    /// The \"trust-token-redemption\" feature.\n    TrustTokenRedemption,\n    /// The \"vertical-scroll\" feature.\n    VerticalScroll,\n}\n\nimpl Feature {\n    /// Returns the feature string as it appears in the header.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::Feature;\n    ///\n    /// assert_eq!(Feature::Camera.as_str(), \"camera\");\n    /// assert_eq!(Feature::SyncScript.as_str(), \"sync-script\");\n    /// ```\n    pub const fn as_str(self) -> &'static str {\n        use Feature::*;\n\n        match self {\n            Accelerometer => \"accelerometer\",\n            AmbientLightSensor => \"ambient-light-sensor\",\n            Autoplay => \"autoplay\",\n            Battery => \"battery\",\n            Camera => \"camera\",\n            CrossOriginIsolated => \"cross-origin-isolated\",\n            Displaycapture => \"display-capture\",\n            DocumentDomain => \"document-domain\",\n            EncryptedMedia => \"encrypted-media\",\n            ExecutionWhileNotRendered => \"execution-while-not-rendered\",\n            ExecutionWhileOutOfviewport => \"execution-while-out-of-viewport\",\n            Fullscreen => \"fullscreen\",\n            Geolocation => \"geolocation\",\n            Gyroscope => \"gyroscope\",\n            Magnetometer => \"magnetometer\",\n            Microphone => \"microphone\",\n            Midi => \"midi\",\n            NavigationOverride => \"navigation-override\",\n            Payment => \"payment\",\n            PictureInPicture => \"picture-in-picture\",\n            PublickeyCredentialsGet => \"publickey-credentials-get\",\n            ScreenWakeLock => \"screen-wake-lock\",\n            SyncXhr => \"sync-xhr\",\n            Usb => \"usb\",\n            WebShare => \"web-share\",\n            XrSpatialTracking => \"xr-spatial-tracking\",\n\n            ClipboardRead => \"clipboard-read\",\n            ClipboardWrite => \"clipboard-write\",\n            Gamepad => \"gamepad\",\n            SpeakerSelection => \"speaker-selection\",\n            InterestCohort => \"interest-cohort\",\n\n            ConversionMeasurement => \"conversion-measurement\",\n            FocusWithoutUserActivation => \"focus-without-user-activation\",\n            Hid => \"hid\",\n            IdleDetection => \"idle-detection\",\n            Serial => \"serial\",\n            SyncScript => \"sync-script\",\n            TrustTokenRedemption => \"trust-token-redemption\",\n            VerticalScroll => \"vertical-scroll\",\n        }\n    }\n}\n\nimpl fmt::Display for Feature {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.as_str().fmt(f)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/shield/shield.rs",
    "content": "use std::collections::HashMap;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\nuse crate::{Rocket, Request, Response, Orbit, Config};\nuse crate::fairing::{Fairing, Info, Kind};\nuse crate::http::{Header, uncased::UncasedStr};\nuse crate::shield::{Frame, Hsts, NoSniff, Permission, Policy};\nuse crate::trace::{Trace, TraceAll};\n\n/// A [`Fairing`] that injects browser security and privacy headers into all\n/// outgoing responses.\n///\n/// # Usage\n///\n/// To use `Shield`, first construct an instance of it. To use the default\n/// set of headers, construct with [`Shield::default()`](#method.default).\n/// For an instance with no preset headers, use [`Shield::new()`]. To\n/// enable an additional header, use [`enable()`](Shield::enable()), and to\n/// disable a header, use [`disable()`](Shield::disable()):\n///\n/// ```rust\n/// use rocket::shield::Shield;\n/// use rocket::shield::{XssFilter, ExpectCt};\n///\n/// // A `Shield` with the default headers:\n/// let shield = Shield::default();\n///\n/// // A `Shield` with the default headers minus `XssFilter`:\n/// let shield = Shield::default().disable::<XssFilter>();\n///\n/// // A `Shield` with the default headers plus `ExpectCt`.\n/// let shield = Shield::default().enable(ExpectCt::default());\n///\n/// // A `Shield` with only `XssFilter` and `ExpectCt`.\n/// let shield = Shield::default()\n///     .enable(XssFilter::default())\n///     .enable(ExpectCt::default());\n/// ```\n///\n/// Then, attach the instance of `Shield` to your application's instance of\n/// `Rocket`:\n///\n/// ```rust\n/// # extern crate rocket;\n/// # use rocket::shield::Shield;\n/// # let shield = Shield::default();\n/// rocket::build()\n///     // ...\n///     .attach(shield)\n/// # ;\n/// ```\n///\n/// The fairing will inject all enabled headers into all outgoing responses\n/// _unless_ the response already contains a header with the same name. If it\n/// does contain the header, a warning is emitted, and the header is not\n/// overwritten.\n///\n/// # TLS and HSTS\n///\n/// If TLS is configured and enabled when the application is launched in a\n/// non-debug profile, HSTS is automatically enabled with its default policy and\n/// a warning is logged. To get rid of this warning, explicitly\n/// [`Shield::enable()`] an [`Hsts`] policy.\npub struct Shield {\n    /// Enabled policies where the key is the header name.\n    policies: HashMap<&'static UncasedStr, Header<'static>>,\n    /// Whether to enforce HSTS even though the user didn't enable it.\n    force_hsts: AtomicBool,\n}\n\nimpl Clone for Shield {\n    fn clone(&self) -> Self {\n        Self {\n            policies: self.policies.clone(),\n            force_hsts: AtomicBool::from(self.force_hsts.load(Ordering::Acquire)),\n        }\n    }\n}\n\nimpl Default for Shield {\n    /// Returns a new `Shield` instance. See the [table] for a description\n    /// of the policies used by default.\n    ///\n    /// [table]: ./#supported-headers\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # extern crate rocket;\n    /// use rocket::shield::Shield;\n    ///\n    /// let shield = Shield::default();\n    /// ```\n    fn default() -> Self {\n        Shield::new()\n            .enable(NoSniff::default())\n            .enable(Frame::default())\n            .enable(Permission::default())\n    }\n}\n\nimpl Shield {\n    /// Returns an instance of `Shield` with no headers enabled.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::Shield;\n    ///\n    /// let shield = Shield::new();\n    /// ```\n    pub fn new() -> Self {\n        Shield {\n            policies: HashMap::new(),\n            force_hsts: AtomicBool::new(false),\n        }\n    }\n\n    /// Enables the policy header `policy`.\n    ///\n    /// If the policy was previously enabled, the configuration is replaced\n    /// with that of `policy`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::Shield;\n    /// use rocket::shield::NoSniff;\n    ///\n    /// let shield = Shield::new().enable(NoSniff::default());\n    /// ```\n    pub fn enable<P: Policy>(mut self, policy: P) -> Self {\n        self.policies.insert(P::NAME.into(), policy.header());\n        self\n    }\n\n    /// Disables the policy header `policy`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::Shield;\n    /// use rocket::shield::NoSniff;\n    ///\n    /// let shield = Shield::default().disable::<NoSniff>();\n    /// ```\n    pub fn disable<P: Policy>(mut self) -> Self {\n        self.policies.remove(UncasedStr::new(P::NAME));\n        self\n    }\n\n    /// Returns `true` if the policy `P` is enabled.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::shield::Shield;\n    /// use rocket::shield::{Permission, NoSniff, Frame};\n    /// use rocket::shield::{Prefetch, ExpectCt, Referrer};\n    ///\n    /// let shield = Shield::default();\n    ///\n    /// assert!(shield.is_enabled::<NoSniff>());\n    /// assert!(shield.is_enabled::<Frame>());\n    /// assert!(shield.is_enabled::<Permission>());\n    ///\n    /// assert!(!shield.is_enabled::<Prefetch>());\n    /// assert!(!shield.is_enabled::<ExpectCt>());\n    /// assert!(!shield.is_enabled::<Referrer>());\n    /// ```\n    pub fn is_enabled<P: Policy>(&self) -> bool {\n        self.policies.contains_key(UncasedStr::new(P::NAME))\n    }\n}\n\n#[crate::async_trait]\nimpl Fairing for Shield {\n    fn info(&self) -> Info {\n        Info {\n            name: \"Shield\",\n            kind: Kind::Liftoff | Kind::Response | Kind::Singleton,\n        }\n    }\n\n    async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {\n        if self.policies.is_empty() {\n            return;\n        }\n\n        let force_hsts = rocket.endpoints().all(|v| v.is_tls())\n            && rocket.figment().profile() != Config::DEBUG_PROFILE\n            && !self.is_enabled::<Hsts>();\n\n        if force_hsts {\n            self.force_hsts.store(true, Ordering::Release);\n        }\n\n        span_info!(\"shield\", policies = self.policies.len() => {\n            self.policies.values().trace_all_info();\n\n            if force_hsts {\n                warn!(\"Detected TLS-enabled liftoff without enabling HSTS.\\n\\\n                    Shield has enabled a default HSTS policy.\\n\\\n                    To remove this warning, configure an HSTS policy.\");\n            }\n        })\n    }\n\n    async fn on_response<'r>(&self, _: &'r Request<'_>, response: &mut Response<'r>) {\n        // Set all of the headers in `self.policies` in `response` as long as\n        // the header is not already in the response.\n        for header in self.policies.values() {\n            if response.headers().contains(header.name()) {\n                span_warn!(\"shield\", \"shield refusing to overwrite existing response header\" => {\n                    header.trace_warn();\n                });\n\n                continue\n            }\n\n            response.set_header(header.clone());\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/shutdown/config.rs",
    "content": "#[cfg(unix)]\nuse std::collections::HashSet;\nuse std::time::Duration;\n\nuse futures::stream::Stream;\nuse serde::{Deserialize, Serialize};\n\nuse crate::shutdown::Sig;\n\n/// Graceful shutdown configuration.\n///\n/// # Summary\n///\n/// This structure configures when and how graceful shutdown occurs. The `ctrlc`\n/// and `signals` properties control _when_ and the `grace` and `mercy`\n/// properties control _how_.\n///\n/// When a shutdown is triggered by an externally or internally initiated\n/// [`Shutdown::notify()`], Rocket allows application I/O to make progress for\n/// at most `grace` seconds before initiating connection-level shutdown.\n/// Connection shutdown forcibly terminates _application_ I/O, but connections\n/// are allowed an additional `mercy` seconds to shutdown before being\n/// forcefully terminated. This implies that a _cooperating_ and active remote\n/// client maintaining an open connection can stall shutdown for at most `grace`\n/// seconds, while an _uncooperative_ remote client can stall shutdown for at\n/// most `grace + mercy` seconds.\n///\n/// # Triggers\n///\n/// _All_ graceful shutdowns are initiated via [`Shutdown::notify()`]. Rocket\n/// can be configured to call [`Shutdown::notify()`] automatically on certain\n/// conditions, specified via the `ctrlc` and `signals` properties of this\n/// structure. More specifically, if `ctrlc` is `true` (the default), `ctrl-c`\n/// (`SIGINT`) initiates a server shutdown, and on Unix, `signals` specifies a\n/// list of IPC signals that trigger a shutdown (`[\"term\"]` by default).\n///\n/// [`Shutdown::notify()`]: crate::Shutdown::notify()\n///\n/// # Grace Period\n///\n/// Once a shutdown is triggered, Rocket stops accepting new connections and\n/// waits at most `grace` seconds before initiating connection shutdown.\n/// Applications can `await` the [`Shutdown`] future to detect\n/// a shutdown and cancel any server-initiated I/O, such as from [infinite\n/// responders](crate::response::stream#graceful-shutdown), to avoid abrupt I/O\n/// cancellation.\n///\n/// [`Shutdown`]: crate::Shutdown\n///\n/// # Mercy Period\n///\n/// After the grace period has elapsed, Rocket initiates connection shutdown,\n/// allowing connection-level I/O termination such as TLS's `close_notify` to\n/// proceed nominally. Rocket waits at most `mercy` seconds for connections to\n/// shutdown before forcefully terminating all connections.\n///\n/// # Runaway I/O\n///\n/// If tasks are _still_ executing after both periods _and_ a Rocket configured\n/// async runtime is in use, Rocket waits an unspecified amount of time (not to\n/// exceed 1s) and forcefully terminates the asynchronous runtime. This\n/// guarantees that the server process terminates, prohibiting uncooperative,\n/// runaway I/O from preventing shutdown altogether.\n///\n/// A \"Rocket configured runtime\" is one started by the `#[rocket::main]` and\n/// `#[launch]` attributes. Rocket _never_ forcefully terminates a custom\n/// runtime. A server that creates its own async runtime must take care to\n/// terminate itself if tasks it spawns fail to cooperate.\n///\n/// Under normal circumstances, forced termination should never occur. No use of\n/// \"normal\" cooperative I/O (that is, via `.await` or `task::spawn()`) should\n/// trigger abrupt termination. Instead, forced cancellation is intended to\n/// prevent _buggy_ code, such as an unintended infinite loop or unknown use of\n/// blocking I/O, from preventing shutdown.\n///\n/// This behavior can be disabled by setting [`ShutdownConfig::force`] to\n/// `false`.\n///\n/// # Example\n///\n/// As with all Rocket configuration options, when using the default\n/// [`Config::figment()`](crate::Config::figment()), `Shutdown` can be\n/// configured via a `Rocket.toml` file. As always, defaults are provided\n/// (documented below), and thus configuration only needs to provided to change\n/// defaults.\n///\n/// ```rust\n/// # use rocket::figment::{Figment, providers::{Format, Toml}};\n/// use rocket::Config;\n///\n/// // If these are the contents of `Rocket.toml`...\n/// # let toml = Toml::string(r#\"\n/// [default.shutdown]\n/// ctrlc = false\n/// signals = [\"term\", \"hup\"]\n/// grace = 10\n/// mercy = 5\n/// # force = false\n/// # \"#).nested();\n///\n/// // The config parses as follows:\n/// # let config = Config::from(Figment::from(Config::debug_default()).merge(toml));\n/// assert_eq!(config.shutdown.ctrlc, false);\n/// assert_eq!(config.shutdown.grace, 10);\n/// assert_eq!(config.shutdown.mercy, 5);\n/// # assert_eq!(config.shutdown.force, false);\n///\n/// # #[cfg(unix)] {\n/// use rocket::config::Sig;\n///\n/// assert_eq!(config.shutdown.signals.len(), 2);\n/// assert!(config.shutdown.signals.contains(&Sig::Term));\n/// assert!(config.shutdown.signals.contains(&Sig::Hup));\n/// # }\n/// ```\n///\n/// Or, as with all configuration options, programmatically:\n///\n/// ```rust\n/// # use rocket::figment::{Figment, providers::{Format, Toml}};\n/// use rocket::config::{Config, ShutdownConfig};\n///\n/// #[cfg(unix)]\n/// use rocket::config::Sig;\n///\n/// let config = Config {\n///     shutdown: ShutdownConfig {\n///         ctrlc: false,\n///         #[cfg(unix)]\n///         signals: {\n///             let mut set = std::collections::HashSet::new();\n///             set.insert(Sig::Term);\n///             set.insert(Sig::Hup);\n///             set\n///         },\n///         grace: 10,\n///         mercy: 5,\n///         force: true,\n///         ..Default::default()\n///     },\n///     ..Config::default()\n/// };\n///\n/// assert_eq!(config.shutdown.ctrlc, false);\n/// assert_eq!(config.shutdown.grace, 10);\n/// assert_eq!(config.shutdown.mercy, 5);\n/// assert_eq!(config.shutdown.force, true);\n///\n/// #[cfg(unix)] {\n///     assert_eq!(config.shutdown.signals.len(), 2);\n///     assert!(config.shutdown.signals.contains(&Sig::Term));\n///     assert!(config.shutdown.signals.contains(&Sig::Hup));\n/// }\n/// ```\n#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]\npub struct ShutdownConfig {\n    /// Whether `ctrl-c` (`SIGINT`) initiates a server shutdown.\n    ///\n    /// **default: `true`**\n    #[serde(deserialize_with = \"figment::util::bool_from_str_or_int\")]\n    pub ctrlc: bool,\n    /// On Unix, a set of signal which trigger a shutdown. On non-Unix, this\n    /// option is unavailable and silently ignored.\n    ///\n    /// **default: { [`Sig::Term`] }**\n    #[cfg(unix)]\n    #[cfg_attr(nightly, doc(cfg(unix)))]\n    pub signals: HashSet<Sig>,\n    /// The grace period: number of seconds to continue to try to finish\n    /// outstanding _server_ I/O for before forcibly terminating it.\n    ///\n    /// **default: `2`**\n    pub grace: u32,\n    /// The mercy period: number of seconds to continue to try to finish\n    /// outstanding _connection_ I/O for before forcibly terminating it.\n    ///\n    /// **default: `3`**\n    pub mercy: u32,\n    /// Whether to force termination of an async runtime that refuses to\n    /// cooperatively shutdown.\n    ///\n    /// Rocket _never_ forcefully terminates a custom runtime, irrespective of\n    /// this value. A server that creates its own async runtime must take care\n    /// to terminate itself if it fails to cooperate.\n    ///\n    /// _**Note:** Rocket only reads this value from sources in the [default\n    /// provider](crate::Config::figment())._\n    ///\n    /// **default: `true`**\n    #[serde(deserialize_with = \"figment::util::bool_from_str_or_int\")]\n    pub force: bool,\n    /// PRIVATE: This structure may grow (but never change otherwise) in a\n    /// non-breaking release. As such, constructing this structure should\n    /// _always_ be done using a public constructor or update syntax:\n    ///\n    /// ```rust\n    /// use rocket::config::ShutdownConfig;\n    ///\n    /// let config = ShutdownConfig {\n    ///     grace: 5,\n    ///     mercy: 10,\n    ///     ..Default::default()\n    /// };\n    /// ```\n    #[doc(hidden)]\n    #[serde(skip)]\n    pub __non_exhaustive: (),\n}\n\nimpl Default for ShutdownConfig {\n    fn default() -> Self {\n        ShutdownConfig {\n            ctrlc: true,\n            #[cfg(unix)]\n            signals: { let mut set = HashSet::new(); set.insert(Sig::Term); set },\n            grace: 2,\n            mercy: 3,\n            force: true,\n            __non_exhaustive: (),\n        }\n    }\n}\n\nimpl ShutdownConfig {\n    pub(crate) fn grace(&self) -> Duration {\n        Duration::from_secs(self.grace as u64)\n    }\n\n    pub(crate) fn mercy(&self) -> Duration {\n        Duration::from_secs(self.mercy as u64)\n    }\n\n    #[cfg(unix)]\n    pub(crate) fn signal_stream(&self) -> Option<impl Stream<Item = Sig>> {\n        use tokio_stream::{StreamExt, StreamMap, wrappers::SignalStream};\n        use tokio::signal::unix::{signal, SignalKind};\n\n        if !self.ctrlc && self.signals.is_empty() {\n            return None;\n        }\n\n        let mut signals = self.signals.clone();\n        if self.ctrlc {\n            signals.insert(Sig::Int);\n        }\n\n        let mut map = StreamMap::new();\n        for sig in signals {\n            let sigkind = match sig {\n                Sig::Alrm => SignalKind::alarm(),\n                Sig::Chld => SignalKind::child(),\n                Sig::Hup => SignalKind::hangup(),\n                Sig::Int => SignalKind::interrupt(),\n                Sig::Io => SignalKind::io(),\n                Sig::Pipe => SignalKind::pipe(),\n                Sig::Quit => SignalKind::quit(),\n                Sig::Term => SignalKind::terminate(),\n                Sig::Usr1 => SignalKind::user_defined1(),\n                Sig::Usr2 => SignalKind::user_defined2()\n            };\n\n            match signal(sigkind) {\n                Ok(signal) => { map.insert(sig, SignalStream::new(signal)); },\n                Err(e) => warn!(\"Failed to enable `{}` shutdown signal: {}\", sig, e),\n            }\n        }\n\n        Some(map.map(|(k, _)| k))\n    }\n\n    #[cfg(not(unix))]\n    pub(crate) fn signal_stream(&self) -> Option<impl Stream<Item = Sig>> {\n        use tokio_stream::StreamExt;\n        use futures::stream::once;\n\n        self.ctrlc.then(|| tokio::signal::ctrl_c())\n            .map(|signal| once(Box::pin(signal)))\n            .map(|stream| stream.filter_map(|result| {\n                result.map(|_| Sig::Int)\n                    .map_err(|e| warn!(\"Failed to enable `ctrl-c` shutdown signal: {}\", e))\n                    .ok()\n            }))\n    }\n}\n"
  },
  {
    "path": "core/lib/src/shutdown/handle.rs",
    "content": "use std::future::Future;\nuse std::task::{Context, Poll};\nuse std::pin::Pin;\n\nuse futures::{FutureExt, StreamExt};\n\nuse crate::shutdown::{ShutdownConfig, TripWire};\nuse crate::request::{FromRequest, Outcome, Request};\n\n/// A request guard and future for graceful shutdown.\n///\n/// A server shutdown is manually requested by calling [`Shutdown::notify()`]\n/// or, if enabled, through [automatic triggers] like `Ctrl-C`. Rocket will stop\n/// accepting new requests, finish handling any pending requests, wait a grace\n/// period before cancelling any outstanding I/O, and return `Ok()` to the\n/// caller of [`Rocket::launch()`]. Graceful shutdown is configured via\n/// [`ShutdownConfig`](crate::config::ShutdownConfig).\n///\n/// [`Rocket::launch()`]: crate::Rocket::launch()\n/// [automatic triggers]: crate::shutdown::Shutdown#triggers\n///\n/// # Detecting Shutdown\n///\n/// `Shutdown` is also a future that resolves when [`Shutdown::notify()`] is\n/// called. This can be used to detect shutdown in any part of the application:\n///\n/// ```rust\n/// # use rocket::*;\n/// use rocket::Shutdown;\n///\n/// #[get(\"/wait/for/shutdown\")]\n/// async fn wait_for_shutdown(shutdown: Shutdown) -> &'static str {\n///     shutdown.await;\n///     \"Somewhere, shutdown was requested.\"\n/// }\n/// ```\n///\n/// See the [`stream`](crate::response::stream#graceful-shutdown) docs for an\n/// example of detecting shutdown in an infinite responder.\n///\n/// Additionally, a completed shutdown request resolves the future returned from\n/// [`Rocket::launch()`](crate::Rocket::launch()):\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate rocket;\n/// #\n/// use rocket::Shutdown;\n///\n/// #[get(\"/shutdown\")]\n/// fn shutdown(shutdown: Shutdown) -> &'static str {\n///     shutdown.notify();\n///     \"Shutting down...\"\n/// }\n///\n/// #[rocket::main]\n/// async fn main() {\n///     let result = rocket::build()\n///         .mount(\"/\", routes![shutdown])\n///         .launch()\n///         .await;\n///\n///     // If the server shut down (by visiting `/shutdown`), `result` is `Ok`.\n///     result.expect(\"server failed unexpectedly\");\n/// }\n/// ```\n#[derive(Debug, Clone)]\n#[must_use = \"`Shutdown` does nothing unless polled or `notify`ed\"]\npub struct Shutdown {\n    wire: TripWire,\n}\n\n#[derive(Debug, Clone)]\npub struct Stages {\n    pub start: Shutdown,\n    pub grace: Shutdown,\n    pub mercy: Shutdown,\n}\n\nimpl Shutdown {\n    fn new() -> Self {\n        Shutdown {\n            wire: TripWire::new(),\n        }\n    }\n\n    /// Notify the application to shut down gracefully.\n    ///\n    /// This function returns immediately; pending requests will continue to run\n    /// until completion or expiration of the grace period, which ever comes\n    /// first, before the actual shutdown occurs. The grace period can be\n    /// configured via [`ShutdownConfig`]'s `grace` field.\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use rocket::Shutdown;\n    ///\n    /// #[get(\"/shutdown\")]\n    /// fn shutdown(shutdown: Shutdown) -> &'static str {\n    ///     shutdown.notify();\n    ///     \"Shutting down...\"\n    /// }\n    /// ```\n    #[inline(always)]\n    pub fn notify(&self) {\n        self.wire.trip();\n    }\n\n    /// Returns `true` if `Shutdown::notify()` has already been called.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use rocket::*;\n    /// use rocket::Shutdown;\n    ///\n    /// #[get(\"/shutdown\")]\n    /// fn shutdown(shutdown: Shutdown) {\n    ///     shutdown.notify();\n    ///     assert!(shutdown.notified());\n    /// }\n    /// ```\n    #[must_use]\n    #[inline(always)]\n    pub fn notified(&self) -> bool {\n        self.wire.tripped()\n    }\n}\n\nimpl Future for Shutdown {\n    type Output = ();\n\n    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        self.wire.poll_unpin(cx)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r> FromRequest<'r> for Shutdown {\n    type Error = std::convert::Infallible;\n\n    #[inline]\n    async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {\n        Outcome::Success(request.rocket().shutdown())\n    }\n}\n\nimpl Stages {\n    pub fn new() -> Self {\n        Stages {\n            start: Shutdown::new(),\n            grace: Shutdown::new(),\n            mercy: Shutdown::new(),\n        }\n    }\n\n    pub(crate) fn spawn_listener(&self, config: &ShutdownConfig) {\n        use futures::stream;\n        use futures::future::{select, Either};\n\n        let mut signal = match config.signal_stream() {\n            Some(stream) => Either::Left(stream.chain(stream::pending())),\n            None => Either::Right(stream::pending()),\n        };\n\n        let start  = self.start.clone();\n        let (grace, grace_duration)  = (self.grace.clone(), config.grace());\n        let (mercy, mercy_duration)  = (self.mercy.clone(), config.mercy());\n        tokio::spawn(async move {\n            if let Either::Left((sig, start)) = select(signal.next(), start).await {\n                warn!(\"Received {}. Shutdown started.\", sig.unwrap());\n                start.notify();\n            }\n\n            tokio::time::sleep(grace_duration).await;\n            warn!(\"Shutdown grace period elapsed. Shutting down I/O.\");\n            grace.notify();\n\n            tokio::time::sleep(mercy_duration).await;\n            warn!(\"Mercy period elapsed. Terminating I/O.\");\n            mercy.notify();\n        });\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::Shutdown;\n\n    #[test]\n    fn ensure_is_send_sync_clone_unpin() {\n        fn is_send_sync_clone_unpin<T: Send + Sync + Clone + Unpin>() {}\n        is_send_sync_clone_unpin::<Shutdown>();\n    }\n}\n"
  },
  {
    "path": "core/lib/src/shutdown/mod.rs",
    "content": "//! Shutdown configuration and notification handle.\n\nmod tripwire;\nmod handle;\nmod sig;\nmod config;\n\npub(crate) use tripwire::TripWire;\npub(crate) use handle::Stages;\n\npub use config::ShutdownConfig;\npub use handle::Shutdown;\npub use sig::Sig;\n"
  },
  {
    "path": "core/lib/src/shutdown/sig.rs",
    "content": "use std::fmt;\n\nuse serde::{Deserialize, Serialize};\n\n/// A Unix signal for triggering graceful shutdown.\n///\n/// Each variant corresponds to a Unix process signal which can be used to\n/// trigger a graceful shutdown. See [`Shutdown`](crate::Shutdown) for details.\n///\n/// ## (De)serialization\n///\n/// A `Sig` variant serializes and deserializes as a lowercase string equal to\n/// the name of the variant: `\"alrm\"` for [`Sig::Alrm`], `\"chld\"` for\n/// [`Sig::Chld`], and so on.\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]\n#[serde(rename_all = \"lowercase\")]\n#[cfg_attr(nightly, doc(cfg(unix)))]\npub enum Sig {\n    /// The `SIGALRM` Unix signal.\n    Alrm,\n    /// The `SIGCHLD` Unix signal.\n    Chld,\n    /// The `SIGHUP` Unix signal.\n    Hup,\n    /// The `SIGINT` Unix signal.\n    Int,\n    /// The `SIGIO` Unix signal.\n    Io,\n    /// The `SIGPIPE` Unix signal.\n    Pipe,\n    /// The `SIGQUIT` Unix signal.\n    Quit,\n    /// The `SIGTERM` Unix signal.\n    Term,\n    /// The `SIGUSR1` Unix signal.\n    Usr1,\n    /// The `SIGUSR2` Unix signal.\n    Usr2\n}\n\nimpl Sig {\n    pub fn as_str(&self) -> &'static str {\n        match self {\n            Sig::Alrm => \"SIGALRM\",\n            Sig::Chld => \"SIGCHLD\",\n            Sig::Hup => \"SIGHUP\",\n            Sig::Int => \"SIGINT\",\n            Sig::Io => \"SIGIO\",\n            Sig::Pipe => \"SIGPIPE\",\n            Sig::Quit => \"SIGQUIT\",\n            Sig::Term => \"SIGTERM\",\n            Sig::Usr1 => \"SIGUSR1\",\n            Sig::Usr2 => \"SIGUSR2\",\n        }\n    }\n}\n\nimpl fmt::Display for Sig {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(self.as_str())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/shutdown/tripwire.rs",
    "content": "use std::fmt;\nuse std::{ops::Deref, pin::Pin, future::Future};\nuse std::task::{Context, Poll};\nuse std::sync::{Arc, atomic::{AtomicBool, Ordering}};\n\nuse futures::future::FusedFuture;\nuse tokio::sync::futures::Notified;\nuse tokio::sync::Notify;\n\n#[doc(hidden)]\npub struct State {\n    tripped: AtomicBool,\n    notify: Notify,\n}\n\n#[must_use = \"`TripWire` does nothing unless polled or `trip()`ed\"]\npub struct TripWire {\n    state: Arc<State>,\n    // `Notified` is `!Unpin`. Even if we could name it, we'd need to pin it.\n    event: Option<Pin<Box<Notified<'static>>>>,\n}\n\nimpl Deref for TripWire {\n    type Target = State;\n\n    fn deref(&self) -> &Self::Target {\n        &self.state\n    }\n}\n\nimpl Clone for TripWire {\n    fn clone(&self) -> Self {\n        TripWire {\n            state: self.state.clone(),\n            event: None\n        }\n    }\n}\n\nimpl Drop for TripWire {\n    fn drop(&mut self) {\n        // SAFETY: Ensure we drop the self-reference before `self`.\n        self.event = None;\n    }\n}\n\nimpl fmt::Debug for TripWire {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"TripWire\")\n            .field(\"tripped\", &self.tripped)\n            .finish()\n    }\n}\n\nimpl Future for TripWire {\n    type Output = ();\n\n    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        if self.tripped() {\n            self.event = None;\n            return Poll::Ready(());\n        }\n\n        if self.event.is_none() {\n            let notified = self.state.notify.notified();\n\n            // SAFETY: This is a self reference to the `state`.\n            self.event = Some(Box::pin(unsafe { std::mem::transmute(notified) }));\n        }\n\n        if let Some(ref mut event) = self.event {\n            // The order here is important! We need to know:\n            //   !self.tripped() => not notified == notified => self.tripped()\n            if event.as_mut().poll(cx).is_ready() || self.tripped() {\n                self.event = None;\n                return Poll::Ready(());\n            }\n        }\n\n        Poll::Pending\n    }\n}\n\nimpl FusedFuture for TripWire {\n    fn is_terminated(&self) -> bool {\n        self.tripped()\n    }\n}\n\nimpl TripWire {\n    pub fn new() -> Self {\n        TripWire {\n            state: Arc::new(State {\n                tripped: AtomicBool::new(false),\n                notify: Notify::new()\n            }),\n            event: None,\n        }\n    }\n\n    pub fn trip(&self) {\n        self.tripped.store(true, Ordering::Release);\n        self.notify.notify_waiters();\n    }\n\n    #[inline(always)]\n    pub fn tripped(&self) -> bool {\n        self.tripped.load(Ordering::Acquire)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::TripWire;\n\n    #[test]\n    fn ensure_is_send_sync_clone_unpin() {\n        fn is_send_sync_clone_unpin<T: Send + Sync + Clone + Unpin>() {}\n        is_send_sync_clone_unpin::<TripWire>();\n    }\n\n    #[tokio::test]\n    async fn simple_trip() {\n        let wire = TripWire::new();\n        wire.trip();\n        wire.await;\n    }\n\n    #[tokio::test(flavor = \"multi_thread\", worker_threads = 2)]\n    async fn no_trip() {\n        use tokio::time::{sleep, Duration};\n        use futures::stream::{FuturesUnordered as Set, StreamExt};\n        use futures::future::{BoxFuture, FutureExt};\n\n        let wire = TripWire::new();\n        let mut futs: Set<BoxFuture<'static, bool>> = Set::new();\n        for _ in 0..10 {\n            futs.push(Box::pin(wire.clone().map(|_| false)));\n        }\n\n        let sleep = sleep(Duration::from_secs(1));\n        futs.push(Box::pin(sleep.map(|_| true)));\n        assert!(futs.next().await.unwrap());\n    }\n\n    #[tokio::test(flavor = \"multi_thread\", worker_threads = 10)]\n    async fn general_trip() {\n        let wire = TripWire::new();\n        let mut tasks = vec![];\n        for _ in 0..1000 {\n            tasks.push(tokio::spawn(wire.clone()));\n            tokio::task::yield_now().await;\n        }\n\n        wire.trip();\n        for task in tasks {\n            task.await.unwrap();\n        }\n    }\n\n    #[tokio::test(flavor = \"multi_thread\", worker_threads = 10)]\n    async fn single_stage_trip() {\n        let mut tasks = vec![];\n        for i in 0..1000 {\n            // Trip once every 100. 50 will be left \"untripped\", but should be.\n            if i % 2 == 0 {\n                let wire = TripWire::new();\n                tasks.push(tokio::spawn(wire.clone()));\n                tasks.push(tokio::spawn(async move { wire.trip() }));\n            } else {\n                let wire = TripWire::new();\n                let wire2 = wire.clone();\n                tasks.push(tokio::spawn(async move { wire.trip() }));\n                tasks.push(tokio::spawn(wire2));\n            }\n        }\n\n        for task in tasks {\n            task.await.unwrap();\n        }\n    }\n\n    #[tokio::test(flavor = \"multi_thread\", worker_threads = 10)]\n    async fn staged_trip() {\n        let wire = TripWire::new();\n        let mut tasks = vec![];\n        for i in 0..1050 {\n            let wire = wire.clone();\n            // Trip once every 100. 50 will be left \"untripped\", but should be.\n            let task = if i % 100 == 0 {\n                tokio::spawn(async move { wire.trip() })\n            } else {\n                tokio::spawn(wire)\n            };\n\n            if i % 20 == 0 {\n                tokio::task::yield_now().await;\n            }\n\n            tasks.push(task);\n        }\n\n        for task in tasks {\n            task.await.unwrap();\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/state.rs",
    "content": "use std::fmt;\nuse std::ops::Deref;\nuse std::any::type_name;\n\nuse ref_cast::RefCast;\n\nuse crate::{Phase, Rocket, Ignite, Sentinel};\nuse crate::request::{self, FromRequest, Request};\nuse crate::outcome::Outcome;\nuse crate::http::Status;\n\n/// Request guard to retrieve managed state.\n///\n/// A reference `&State<T>` type is a request guard which retrieves the managed\n/// state managing for some type `T`. A value for the given type must previously\n/// have been registered to be managed by Rocket via [`Rocket::manage()`]. The\n/// type being managed must be thread safe and sendable across thread\n/// boundaries as multiple handlers in multiple threads may be accessing the\n/// value at once. In other words, it must implement [`Send`] + [`Sync`] +\n/// `'static`.\n///\n/// # Example\n///\n/// Imagine you have some configuration struct of the type `MyConfig` that you'd\n/// like to initialize at start-up and later access it in several handlers. The\n/// following example does just this:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate rocket;\n/// use rocket::State;\n///\n/// // In a real application, this would likely be more complex.\n/// struct MyConfig {\n///     user_val: String\n/// }\n///\n/// #[get(\"/\")]\n/// fn index(state: &State<MyConfig>) -> String {\n///     format!(\"The config value is: {}\", state.user_val)\n/// }\n///\n/// #[get(\"/raw\")]\n/// fn raw_config_value(state: &State<MyConfig>) -> &str {\n///     &state.user_val\n/// }\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build()\n///         .mount(\"/\", routes![index, raw_config_value])\n///         .manage(MyConfig { user_val: \"user input\".to_string() })\n/// }\n/// ```\n///\n/// # Within Request Guards\n///\n/// Because `State` is itself a request guard, managed state can be retrieved\n/// from another request guard's implementation using either\n/// [`Request::guard()`] or [`Rocket::state()`]. In the following code example,\n/// the `Item` request guard retrieves `MyConfig` from managed state:\n///\n/// ```rust\n/// use rocket::State;\n/// use rocket::request::{self, Request, FromRequest};\n/// use rocket::outcome::IntoOutcome;\n/// use rocket::http::Status;\n///\n/// # struct MyConfig { user_val: String };\n/// struct Item<'r>(&'r str);\n///\n/// #[rocket::async_trait]\n/// impl<'r> FromRequest<'r> for Item<'r> {\n///     type Error = ();\n///\n///     async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {\n///         // Using `State` as a request guard. Use `inner()` to get an `'r`.\n///         let outcome = request.guard::<&State<MyConfig>>().await\n///             .map(|my_config| Item(&my_config.user_val));\n///\n///         // Or alternatively, using `Rocket::state()`:\n///         let outcome = request.rocket().state::<MyConfig>()\n///             .map(|my_config| Item(&my_config.user_val))\n///             .or_forward(Status::InternalServerError);\n///\n///         outcome\n///     }\n/// }\n/// ```\n///\n/// # Testing with `State`\n///\n/// When unit testing your application, you may find it necessary to manually\n/// construct a type of `State` to pass to your functions. To do so, use the\n/// [`State::get()`] static method or the `From<&T>` implementation:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::State;\n///\n/// struct MyManagedState(usize);\n///\n/// #[get(\"/\")]\n/// fn handler(state: &State<MyManagedState>) -> String {\n///     state.0.to_string()\n/// }\n///\n/// let mut rocket = rocket::build().manage(MyManagedState(127));\n/// let state = State::get(&rocket).expect(\"managed `MyManagedState`\");\n/// assert_eq!(handler(state), \"127\");\n///\n/// let managed = MyManagedState(77);\n/// assert_eq!(handler(State::from(&managed)), \"77\");\n/// ```\n#[repr(transparent)]\n#[derive(RefCast, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub struct State<T: Send + Sync + 'static>(T);\n\nimpl<T: Send + Sync + 'static> State<T> {\n    /// Returns the managed state value in `rocket` for the type `T` if it is\n    /// being managed by `rocket`. Otherwise, returns `None`.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::State;\n    ///\n    /// #[derive(Debug, PartialEq)]\n    /// struct Managed(usize);\n    ///\n    /// #[derive(Debug, PartialEq)]\n    /// struct Unmanaged(usize);\n    ///\n    /// let rocket = rocket::build().manage(Managed(7));\n    ///\n    /// let state: Option<&State<Managed>> = State::get(&rocket);\n    /// assert_eq!(state.map(|s| s.inner()), Some(&Managed(7)));\n    ///\n    /// let state: Option<&State<Unmanaged>> = State::get(&rocket);\n    /// assert_eq!(state, None);\n    /// ```\n    #[inline(always)]\n    pub fn get<P: Phase>(rocket: &Rocket<P>) -> Option<&State<T>> {\n        rocket.state::<T>().map(State::ref_cast)\n    }\n\n    /// This exists because `State::from()` would otherwise be nothing. But we\n    /// want `State::from(&foo)` to give us `<&State>::from(&foo)`. Here it is.\n    #[doc(hidden)]\n    #[inline(always)]\n    pub fn from(value: &T) -> &State<T> {\n        State::ref_cast(value)\n    }\n\n    /// Borrow the inner value.\n    ///\n    /// Using this method is typically unnecessary as `State` implements\n    /// [`Deref`] with a [`Deref::Target`] of `T`. This means Rocket will\n    /// automatically coerce a `State<T>` to an `&T` as required. This method\n    /// should only be used when a longer lifetime is required.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::State;\n    ///\n    /// #[derive(Clone)]\n    /// struct MyConfig {\n    ///     user_val: String\n    /// }\n    ///\n    /// fn handler1<'r>(config: &State<MyConfig>) -> String {\n    ///     let config = config.inner().clone();\n    ///     config.user_val\n    /// }\n    ///\n    /// // Use the `Deref` implementation which coerces implicitly\n    /// fn handler2(config: &State<MyConfig>) -> String {\n    ///     config.user_val.clone()\n    /// }\n    /// ```\n    #[inline(always)]\n    pub fn inner(&self) -> &T {\n        &self.0\n    }\n}\n\nimpl<'r, T: Send + Sync + 'static> From<&'r T> for &'r State<T> {\n    #[inline(always)]\n    fn from(reference: &'r T) -> Self {\n        State::ref_cast(reference)\n    }\n}\n\n#[crate::async_trait]\nimpl<'r, T: Send + Sync + 'static> FromRequest<'r> for &'r State<T> {\n    type Error = ();\n\n    #[inline(always)]\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        match State::get(req.rocket()) {\n            Some(state) => Outcome::Success(state),\n            None => {\n            error!(type_name = type_name::<T>(),\n                \"retrieving unmanaged state\\n\\\n                state must be managed via `rocket.manage()`\");\n\n                Outcome::Error((Status::InternalServerError, ()))\n            }\n        }\n    }\n}\n\nimpl<T: Send + Sync + 'static> Sentinel for &State<T> {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        if rocket.state::<T>().is_none() {\n            error!(type_name = type_name::<T>(),\n                \"unmanaged state detected\\n\\\n                ensure type is being managed via `rocket.manage()`\");\n\n            return true;\n        }\n\n        false\n    }\n}\n\nimpl<T: Send + Sync + fmt::Display + 'static> fmt::Display for State<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl<T: Send + Sync + 'static> Deref for State<T> {\n    type Target = T;\n\n    #[inline(always)]\n    fn deref(&self) -> &T {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "core/lib/src/tls/config.rs",
    "content": "use std::io;\nuse std::sync::Arc;\n\nuse futures::TryFutureExt;\nuse figment::value::magic::{Either, RelativePathBuf};\nuse serde::{Deserialize, Serialize};\nuse indexmap::IndexSet;\nuse rustls::crypto::{ring, CryptoProvider};\nuse rustls::pki_types::{CertificateDer, PrivateKeyDer};\nuse rustls::server::{ServerSessionMemoryCache, ServerConfig, WebPkiClientVerifier};\n\nuse crate::tls::resolver::DynResolver;\nuse crate::tls::error::{Result, Error, KeyError};\n\n/// TLS configuration: certificate chain, key, and ciphersuites.\n///\n/// Four parameters control `tls` configuration:\n///\n///   * `certs`, `key`\n///\n///     Both `certs` and `key` can be configured as a path or as raw bytes.\n///     `certs` must be a DER-encoded X.509 TLS certificate chain, while `key`\n///     must be a DER-encoded ASN.1 key in either PKCS#8, PKCS#1, or SEC1\n///     format. When a path is configured in a file, such as `Rocket.toml`,\n///     relative paths are interpreted as relative to the source file's\n///     directory.\n///\n///   * `ciphers`\n///\n///     A list of supported [`CipherSuite`]s in server-preferred order, from\n///     most to least. It is not required and defaults to\n///     [`CipherSuite::DEFAULT_SET`], the recommended setting.\n///\n///   * `prefer_server_cipher_order`\n///\n///     A boolean that indicates whether the server should regard its own\n///     ciphersuite preferences over the client's. The default and recommended\n///     value is `false`.\n///\n/// Additionally, the `mutual` parameter controls if and how the server\n/// authenticates clients via mutual TLS. It works in concert with the\n/// [`mtls`](crate::mtls) module. See [`MtlsConfig`](crate::mtls::MtlsConfig)\n/// for configuration details.\n///\n/// In `Rocket.toml`, configuration might look like:\n///\n/// ```toml\n/// [default.tls]\n/// certs = \"private/rsa_sha256_cert.pem\"\n/// key = \"private/rsa_sha256_key.pem\"\n/// ```\n///\n/// With a custom programmatic configuration, this might look like:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use rocket::tls::{TlsConfig, CipherSuite};\n/// use rocket::figment::providers::Serialized;\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     let tls = TlsConfig::from_paths(\"/ssl/certs.pem\", \"/ssl/key.pem\")\n///         .with_ciphers(CipherSuite::TLS_V13_SET)\n///         .with_preferred_server_cipher_order(true);\n///\n///     rocket::custom(rocket::Config::figment().merge((\"tls\", tls)))\n/// }\n/// ```\n///\n/// Or by creating a custom figment:\n///\n/// ```rust\n/// use rocket::figment::Figment;\n/// use rocket::tls::TlsConfig;\n///\n/// let figment = Figment::new()\n///     .merge((\"certs\", \"path/to/certs.pem\"))\n///     .merge((\"key\", vec![0; 32]));\n/// #\n/// # let tls_config: TlsConfig = figment.extract().unwrap();\n/// # assert!(tls_config.certs().is_left());\n/// # assert!(tls_config.key().is_right());\n/// # assert_eq!(tls_config.ciphers().count(), 9);\n/// # assert!(!tls_config.prefer_server_cipher_order());\n/// ```\n#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]\npub struct TlsConfig {\n    /// Path to a PEM file with, or raw bytes for, a DER-encoded X.509 TLS\n    /// certificate chain.\n    pub(crate) certs: Either<RelativePathBuf, Vec<u8>>,\n    /// Path to a PEM file with, or raw bytes for, DER-encoded private key in\n    /// either PKCS#8 or PKCS#1 format.\n    pub(crate) key: Either<RelativePathBuf, Vec<u8>>,\n    /// List of TLS cipher suites in server-preferred order.\n    #[serde(default = \"CipherSuite::default_set\")]\n    pub(crate) ciphers: IndexSet<CipherSuite>,\n    /// Whether to prefer the server's cipher suite order over the client's.\n    #[serde(default)]\n    pub(crate) prefer_server_cipher_order: bool,\n    /// Configuration for mutual TLS, if any.\n    #[serde(default)]\n    #[cfg(feature = \"mtls\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"mtls\")))]\n    pub(crate) mutual: Option<crate::mtls::MtlsConfig>,\n    #[serde(skip)]\n    pub(crate) resolver: Option<DynResolver>,\n}\n\n/// A supported TLS cipher suite.\n#[allow(non_camel_case_types)]\n#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash, Deserialize, Serialize)]\n#[non_exhaustive]\npub enum CipherSuite {\n    /// The TLS 1.3 `TLS_CHACHA20_POLY1305_SHA256` cipher suite.\n    TLS_CHACHA20_POLY1305_SHA256,\n    /// The TLS 1.3 `TLS_AES_256_GCM_SHA384` cipher suite.\n    TLS_AES_256_GCM_SHA384,\n    /// The TLS 1.3 `TLS_AES_128_GCM_SHA256` cipher suite.\n    TLS_AES_128_GCM_SHA256,\n\n    /// The TLS 1.2 `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256` cipher suite.\n    TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n    /// The TLS 1.2 `TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256` cipher suite.\n    TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n    /// The TLS 1.2 `TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384` cipher suite.\n    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n    /// The TLS 1.2 `TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256` cipher suite.\n    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n    /// The TLS 1.2 `TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384` cipher suite.\n    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n    /// The TLS 1.2 `TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256` cipher suite.\n    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\n}\n\nimpl Default for TlsConfig {\n    fn default() -> Self {\n        TlsConfig {\n            certs: Either::Right(vec![]),\n            key: Either::Right(vec![]),\n            ciphers: CipherSuite::default_set(),\n            prefer_server_cipher_order: false,\n            #[cfg(feature = \"mtls\")]\n            mutual: None,\n            resolver: None,\n        }\n    }\n}\n\nimpl TlsConfig {\n    /// Constructs a `TlsConfig` from paths to a `certs` certificate chain\n    /// a `key` private-key. This method does no validation; it simply creates a\n    /// structure suitable for passing into a [`Config`](crate::Config).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::tls::TlsConfig;\n    ///\n    /// let tls_config = TlsConfig::from_paths(\"/ssl/certs.pem\", \"/ssl/key.pem\");\n    /// ```\n    pub fn from_paths<C, K>(certs: C, key: K) -> Self\n        where C: AsRef<std::path::Path>, K: AsRef<std::path::Path>,\n    {\n        TlsConfig {\n            certs: Either::Left(certs.as_ref().to_path_buf().into()),\n            key: Either::Left(key.as_ref().to_path_buf().into()),\n            ..TlsConfig::default()\n        }\n    }\n\n    /// Constructs a `TlsConfig` from byte buffers to a `certs`\n    /// certificate chain a `key` private-key. This method does no validation;\n    /// it simply creates a structure suitable for passing into a\n    /// [`Config`](crate::Config).\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::tls::TlsConfig;\n    ///\n    /// # let certs_buf = &[];\n    /// # let key_buf = &[];\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf);\n    /// ```\n    pub fn from_bytes(certs: &[u8], key: &[u8]) -> Self {\n        TlsConfig {\n            certs: Either::Right(certs.to_vec()),\n            key: Either::Right(key.to_vec()),\n            ..TlsConfig::default()\n        }\n    }\n\n    /// Sets the cipher suites supported by the server and their order of\n    /// preference from most to least preferred.\n    ///\n    /// If a suite appears more than once in `ciphers`, only the first suite\n    /// (and its relative order) is considered. If all cipher suites for a\n    /// version oF TLS are disabled, the respective protocol itself is disabled\n    /// entirely.\n    ///\n    /// # Example\n    ///\n    /// Disable TLS v1.2 by selecting only TLS v1.3 cipher suites:\n    ///\n    /// ```rust\n    /// use rocket::tls::{TlsConfig, CipherSuite};\n    ///\n    /// # let certs_buf = &[];\n    /// # let key_buf = &[];\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf)\n    ///     .with_ciphers(CipherSuite::TLS_V13_SET);\n    /// ```\n    ///\n    /// Enable only ChaCha20-Poly1305 based TLS v1.2 and TLS v1.3 cipher suites:\n    ///\n    /// ```rust\n    /// use rocket::tls::{TlsConfig, CipherSuite};\n    ///\n    /// # let certs_buf = &[];\n    /// # let key_buf = &[];\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf)\n    ///     .with_ciphers([\n    ///         CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n    ///         CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n    ///         CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n    ///     ]);\n    /// ```\n    ///\n    /// Later duplicates are ignored.\n    ///\n    /// ```rust\n    /// use rocket::tls::{TlsConfig, CipherSuite};\n    ///\n    /// # let certs_buf = &[];\n    /// # let key_buf = &[];\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf)\n    ///     .with_ciphers([\n    ///         CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n    ///         CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n    ///         CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n    ///         CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n    ///         CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n    ///     ]);\n    ///\n    /// let ciphers: Vec<_> = tls_config.ciphers().collect();\n    /// assert_eq!(ciphers, &[\n    ///     CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n    ///     CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n    ///     CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n    /// ]);\n    /// ```\n    pub fn with_ciphers<C>(mut self, ciphers: C) -> Self\n        where C: IntoIterator<Item = CipherSuite>\n    {\n        self.ciphers = ciphers.into_iter().collect();\n        self\n    }\n\n    /// Whether to prefer the server's cipher suite order and ignore the\n    /// client's preferences (`true`) or choose the first supported ciphersuite\n    /// in the client's preference list (`false`). The default prefer's the\n    /// client's order (`false`).\n    ///\n    /// During TLS cipher suite negotiation, the client presents a set of\n    /// supported ciphers in its preferred order. From this list, the server\n    /// chooses one cipher suite. By default, the server chooses the first\n    /// cipher it supports from the list.\n    ///\n    /// By setting `prefer_server_order` to `true`, the server instead chooses\n    /// the first ciphersuite in it prefers that the client also supports,\n    /// ignoring the client's preferences.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::tls::{TlsConfig, CipherSuite};\n    ///\n    /// # let certs_buf = &[];\n    /// # let key_buf = &[];\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf)\n    ///     .with_ciphers(CipherSuite::TLS_V13_SET)\n    ///     .with_preferred_server_cipher_order(true);\n    /// ```\n    pub fn with_preferred_server_cipher_order(mut self, prefer_server_order: bool) -> Self {\n        self.prefer_server_cipher_order = prefer_server_order;\n        self\n    }\n\n    /// Set mutual TLS configuration. See\n    /// [`MtlsConfig`](crate::mtls::MtlsConfig) for details.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::tls::TlsConfig;\n    /// use rocket::mtls::MtlsConfig;\n    ///\n    /// # let certs = &[];\n    /// # let key = &[];\n    /// let mtls_config = MtlsConfig::from_path(\"path/to/cert.pem\").mandatory(true);\n    /// let tls_config = TlsConfig::from_bytes(certs, key).with_mutual(mtls_config);\n    /// assert!(tls_config.mutual().is_some());\n    /// ```\n    #[cfg(feature = \"mtls\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"mtls\")))]\n    pub fn with_mutual(mut self, config: crate::mtls::MtlsConfig) -> Self {\n        self.mutual = Some(config);\n        self\n    }\n\n    /// Returns the value of the `certs` parameter.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use std::path::Path;\n    /// use rocket::tls::TlsConfig;\n    /// use rocket::figment::Figment;\n    ///\n    /// let figment = Figment::new()\n    ///     .merge((\"certs\", \"/path/to/certs.pem\"))\n    ///     .merge((\"key\", vec![0; 32]));\n    ///\n    /// let tls_config: TlsConfig = figment.extract().unwrap();\n    /// let cert_path = tls_config.certs().left().unwrap();\n    /// assert_eq!(cert_path, Path::new(\"/path/to/certs.pem\"));\n    /// ```\n    pub fn certs(&self) -> either::Either<std::path::PathBuf, &[u8]> {\n        match &self.certs {\n            Either::Left(path) => either::Either::Left(path.relative()),\n            Either::Right(bytes) => either::Either::Right(bytes),\n        }\n    }\n\n    pub fn certs_reader(&self) -> io::Result<Box<dyn io::BufRead + Sync + Send>> {\n        to_reader(&self.certs)\n    }\n\n    /// Returns the value of the `key` parameter.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # use std::path::Path;\n    /// use rocket::tls::TlsConfig;\n    /// use rocket::figment::Figment;\n    ///\n    /// let figment = Figment::new()\n    ///     .merge((\"certs\", vec![0; 32]))\n    ///     .merge((\"key\", \"/etc/ssl/key.pem\"));\n    ///\n    /// let tls_config: TlsConfig = figment.extract().unwrap();\n    /// let key_path = tls_config.key().left().unwrap();\n    /// assert_eq!(key_path, Path::new(\"/etc/ssl/key.pem\"));\n    /// ```\n    pub fn key(&self) -> either::Either<std::path::PathBuf, &[u8]> {\n        match &self.key {\n            Either::Left(path) => either::Either::Left(path.relative()),\n            Either::Right(bytes) => either::Either::Right(bytes),\n        }\n    }\n\n    pub fn key_reader(&self) -> io::Result<Box<dyn io::BufRead + Sync + Send>> {\n        to_reader(&self.key)\n    }\n\n    /// Returns an iterator over the enabled cipher suites in their order of\n    /// preference from most to least preferred.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::tls::{TlsConfig, CipherSuite};\n    ///\n    /// # let certs_buf = &[];\n    /// # let key_buf = &[];\n    /// // The default set is CipherSuite::DEFAULT_SET.\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf);\n    /// assert_eq!(tls_config.ciphers().count(), 9);\n    /// assert!(tls_config.ciphers().eq(CipherSuite::DEFAULT_SET.iter().copied()));\n    ///\n    /// // Enable only the TLS v1.3 ciphers.\n    /// let tls_v13_config = TlsConfig::from_bytes(certs_buf, key_buf)\n    ///     .with_ciphers(CipherSuite::TLS_V13_SET);\n    ///\n    /// assert_eq!(tls_v13_config.ciphers().count(), 3);\n    /// assert!(tls_v13_config.ciphers().eq(CipherSuite::TLS_V13_SET.iter().copied()));\n    /// ```\n    pub fn ciphers(&self) -> impl Iterator<Item = CipherSuite> + '_ {\n        self.ciphers.iter().copied()\n    }\n\n    /// Whether the server's cipher suite ordering is preferred or not.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use rocket::tls::TlsConfig;\n    ///\n    /// # let certs_buf = &[];\n    /// # let key_buf = &[];\n    /// // The default prefers the server's order.\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf);\n    /// assert!(!tls_config.prefer_server_cipher_order());\n    ///\n    /// // Which can be overridden with the eponymous builder method.\n    /// let tls_config = TlsConfig::from_bytes(certs_buf, key_buf)\n    ///     .with_preferred_server_cipher_order(true);\n    ///\n    /// assert!(tls_config.prefer_server_cipher_order());\n    /// ```\n    pub fn prefer_server_cipher_order(&self) -> bool {\n        self.prefer_server_cipher_order\n    }\n\n    /// Returns the value of the `mutual` parameter.\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use std::path::Path;\n    ///\n    /// use rocket::tls::TlsConfig;\n    /// use rocket::mtls::MtlsConfig;\n    ///\n    /// # let certs = &[];\n    /// # let key = &[];\n    /// let mtls_config = MtlsConfig::from_path(\"path/to/cert.pem\").mandatory(true);\n    /// let tls_config = TlsConfig::from_bytes(certs, key).with_mutual(mtls_config);\n    ///\n    /// let mtls = tls_config.mutual().unwrap();\n    /// assert_eq!(mtls.ca_certs().unwrap_left(), Path::new(\"path/to/cert.pem\"));\n    /// assert!(mtls.mandatory);\n    /// ```\n    #[cfg(feature = \"mtls\")]\n    #[cfg_attr(nightly, doc(cfg(feature = \"mtls\")))]\n    pub fn mutual(&self) -> Option<&crate::mtls::MtlsConfig> {\n        self.mutual.as_ref()\n    }\n\n    /// Try to convert `self` into a [rustls] [`ServerConfig`].\n    ///\n    /// [`ServerConfig`]: rustls::server::ServerConfig\n    pub async fn server_config(&self) -> Result<rustls::server::ServerConfig> {\n        let this = self.clone();\n        tokio::task::spawn_blocking(move || this._server_config())\n            .map_err(io::Error::other)\n            .await?\n    }\n\n    /// Try to convert `self` into a [rustls] [`ServerConfig`].\n    ///\n    /// [`ServerConfig`]: rustls::server::ServerConfig\n    pub(crate) fn _server_config(&self) -> Result<rustls::server::ServerConfig> {\n        let provider = Arc::new(self.default_crypto_provider());\n\n        #[cfg(feature = \"mtls\")]\n        let verifier = match self.mutual {\n            Some(ref mtls) => {\n                let ca = Arc::new(mtls.load_ca_certs()?);\n                let verifier = WebPkiClientVerifier::builder_with_provider(ca, provider.clone());\n                match mtls.mandatory {\n                    true => verifier.build()?,\n                    false => verifier.allow_unauthenticated().build()?,\n                }\n            },\n            None => WebPkiClientVerifier::no_client_auth(),\n        };\n\n        #[cfg(not(feature = \"mtls\"))]\n        let verifier = WebPkiClientVerifier::no_client_auth();\n\n        let mut tls_config = ServerConfig::builder_with_provider(provider)\n            .with_safe_default_protocol_versions()?\n            .with_client_cert_verifier(verifier)\n            .with_single_cert(self.load_certs()?, self.load_key()?)?;\n\n        tls_config.ignore_client_order = self.prefer_server_cipher_order;\n        tls_config.session_storage = ServerSessionMemoryCache::new(1024);\n        tls_config.ticketer = rustls::crypto::ring::Ticketer::new()?;\n        tls_config.alpn_protocols = vec![b\"http/1.1\".to_vec()];\n        if cfg!(feature = \"http2\") {\n            tls_config.alpn_protocols.insert(0, b\"h2\".to_vec());\n        }\n\n        Ok(tls_config)\n    }\n\n    /// NOTE: This is a blocking function.\n    pub fn validate(&self) -> Result<()> {\n        self._server_config().map(|_| ())\n    }\n}\n\n/// Loads certificates from `reader`.\nimpl TlsConfig {\n    pub(crate) fn load_certs(&self) -> Result<Vec<CertificateDer<'static>>> {\n        rustls_pemfile::certs(&mut self.certs_reader()?)\n            .collect::<Result<_, _>>()\n            .map_err(Error::CertChain)\n    }\n\n    /// Load and decode the private key  from `reader`.\n    pub(crate) fn load_key(&self) -> Result<PrivateKeyDer<'static>> {\n        use rustls_pemfile::Item::*;\n\n        let mut keys = rustls_pemfile::read_all(&mut self.key_reader()?)\n            .map(|result| result.map_err(KeyError::Io)\n                .and_then(|item| match item {\n                    Pkcs1Key(key) => Ok(key.into()),\n                    Pkcs8Key(key) => Ok(key.into()),\n                    Sec1Key(key) => Ok(key.into()),\n                    _ => Err(KeyError::BadItem(item))\n                })\n            )\n            .collect::<Result<Vec<PrivateKeyDer<'static>>, _>>()?;\n\n        if keys.len() != 1 {\n            return Err(KeyError::BadKeyCount(keys.len()).into());\n        }\n\n        // Ensure we can use the key.\n        let key = keys.remove(0);\n        self.default_crypto_provider()\n            .key_provider\n            .load_private_key(key.clone_key())\n            .map_err(KeyError::Unsupported)?;\n\n        Ok(key)\n    }\n\n    pub(crate) fn default_crypto_provider(&self) -> CryptoProvider {\n        CryptoProvider::get_default()\n            .map(|arc| (**arc).clone())\n            .unwrap_or_else(|| rustls::crypto::CryptoProvider {\n                cipher_suites: self.ciphers().map(|cipher| match cipher {\n                    CipherSuite::TLS_CHACHA20_POLY1305_SHA256 =>\n                        ring::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,\n                    CipherSuite::TLS_AES_256_GCM_SHA384 =>\n                        ring::cipher_suite::TLS13_AES_256_GCM_SHA384,\n                    CipherSuite::TLS_AES_128_GCM_SHA256 =>\n                        ring::cipher_suite::TLS13_AES_128_GCM_SHA256,\n                    CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 =>\n                        ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n                    CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 =>\n                        ring::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n                    CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 =>\n                        ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n                    CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 =>\n                        ring::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n                    CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 =>\n                        ring::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n                    CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 =>\n                        ring::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\n                }).collect(),\n                ..ring::default_provider()\n            })\n    }\n}\n\nimpl CipherSuite {\n    /// The default set and order of cipher suites. These are all of the\n    /// variants in [`CipherSuite`] in their declaration order.\n    pub const DEFAULT_SET: [CipherSuite; 9] = [\n        // TLS v1.3 suites...\n        CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n        CipherSuite::TLS_AES_256_GCM_SHA384,\n        CipherSuite::TLS_AES_128_GCM_SHA256,\n\n        // TLS v1.2 suites...\n        CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n        CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n        CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n        CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n        CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n        CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\n    ];\n\n    /// The default set and order of cipher suites. These are the TLS 1.3\n    /// variants in [`CipherSuite`] in their declaration order.\n    pub const TLS_V13_SET: [CipherSuite; 3] = [\n        CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n        CipherSuite::TLS_AES_256_GCM_SHA384,\n        CipherSuite::TLS_AES_128_GCM_SHA256,\n    ];\n\n    /// The default set and order of cipher suites. These are the TLS 1.2\n    /// variants in [`CipherSuite`] in their declaration order.\n    pub const TLS_V12_SET: [CipherSuite; 6] = [\n        CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n        CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n        CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n        CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n        CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n        CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\n    ];\n\n    /// Used as the `serde` default for `ciphers`.\n    fn default_set() -> IndexSet<Self> {\n        Self::DEFAULT_SET.iter().copied().collect()\n    }\n}\n\npub(crate) fn to_reader(\n    value: &Either<RelativePathBuf, Vec<u8>>\n) -> io::Result<Box<dyn io::BufRead + Sync + Send>> {\n    match value {\n        Either::Left(path) => {\n            let path = path.relative();\n            let file = std::fs::File::open(&path)\n                .map_err(move |e| {\n                    let source = figment::Source::File(path);\n                    let msg = format!(\"error reading TLS file `{source}`: {e}\");\n                    io::Error::new(e.kind(), msg)\n                })?;\n\n            Ok(Box::new(io::BufReader::new(file)))\n        }\n        Either::Right(vec) => Ok(Box::new(io::Cursor::new(vec.clone()))),\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use figment::{Figment, providers::{Toml, Format}};\n\n    #[test]\n    fn test_tls_config_from_file() {\n        use crate::tls::{TlsConfig, CipherSuite};\n        use pretty_assertions::assert_eq;\n\n        figment::Jail::expect_with(|jail| {\n            jail.create_file(\"Rocket.toml\", r#\"\n                [global]\n                shutdown.ctrlc = 0\n                ident = false\n\n                [global.tls]\n                certs = \"/ssl/cert.pem\"\n                key = \"/ssl/key.pem\"\n\n                [global.limits]\n                forms = \"1mib\"\n                json = \"10mib\"\n                stream = \"50kib\"\n            \"#)?;\n\n            let config: TlsConfig = crate::Config::figment().extract_inner(\"tls\")?;\n            assert_eq!(config, TlsConfig::from_paths(\"/ssl/cert.pem\", \"/ssl/key.pem\"));\n\n            jail.create_file(\"Rocket.toml\", r#\"\n                [global.tls]\n                certs = \"cert.pem\"\n                key = \"key.pem\"\n            \"#)?;\n\n            let config: TlsConfig = crate::Config::figment().extract_inner(\"tls\")?;\n            assert_eq!(config, TlsConfig::from_paths(\n                jail.directory().join(\"cert.pem\"),\n                jail.directory().join(\"key.pem\")\n            ));\n\n            jail.create_file(\"TLS.toml\", r#\"\n                certs = \"cert.pem\"\n                key = \"key.pem\"\n                prefer_server_cipher_order = true\n                ciphers = [\n                    \"TLS_CHACHA20_POLY1305_SHA256\",\n                    \"TLS_AES_256_GCM_SHA384\",\n                    \"TLS_AES_128_GCM_SHA256\",\n                    \"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\",\n                    \"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\",\n                    \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\",\n                ]\n            \"#)?;\n\n            let config: TlsConfig = Figment::from(Toml::file(\"TLS.toml\")).extract()?;\n            let cert_path = jail.directory().join(\"cert.pem\");\n            let key_path = jail.directory().join(\"key.pem\");\n            assert_eq!(config, TlsConfig::from_paths(cert_path, key_path)\n                 .with_preferred_server_cipher_order(true)\n                 .with_ciphers([\n                     CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n                     CipherSuite::TLS_AES_256_GCM_SHA384,\n                     CipherSuite::TLS_AES_128_GCM_SHA256,\n                     CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n                     CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n                     CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n                 ]));\n\n            jail.create_file(\"Rocket.toml\", r#\"\n                [global]\n                shutdown.ctrlc = 0\n                ident = false\n\n                [global.tls]\n                certs = \"/ssl/cert.pem\"\n                key = \"/ssl/key.pem\"\n\n                [global.limits]\n                forms = \"1mib\"\n                json = \"10mib\"\n                stream = \"50kib\"\n            \"#)?;\n\n            let config: TlsConfig = crate::Config::figment().extract_inner(\"tls\")?;\n            assert_eq!(config, TlsConfig::from_paths(\"/ssl/cert.pem\", \"/ssl/key.pem\"));\n\n            jail.create_file(\"Rocket.toml\", r#\"\n                [global.tls]\n                certs = \"cert.pem\"\n                key = \"key.pem\"\n            \"#)?;\n\n            let config: TlsConfig = crate::Config::figment().extract_inner(\"tls\")?;\n            assert_eq!(config, TlsConfig::from_paths(\n                jail.directory().join(\"cert.pem\"),\n                jail.directory().join(\"key.pem\")\n            ));\n\n            jail.create_file(\"Rocket.toml\", r#\"\n                [global.tls]\n                certs = \"cert.pem\"\n                key = \"key.pem\"\n                prefer_server_cipher_order = true\n                ciphers = [\n                    \"TLS_CHACHA20_POLY1305_SHA256\",\n                    \"TLS_AES_256_GCM_SHA384\",\n                    \"TLS_AES_128_GCM_SHA256\",\n                    \"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\",\n                    \"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\",\n                    \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\",\n                ]\n            \"#)?;\n\n            let config: TlsConfig = crate::Config::figment().extract_inner(\"tls\")?;\n            let cert_path = jail.directory().join(\"cert.pem\");\n            let key_path = jail.directory().join(\"key.pem\");\n            assert_eq!(config, TlsConfig::from_paths(cert_path, key_path)\n                 .with_preferred_server_cipher_order(true)\n                 .with_ciphers([\n                     CipherSuite::TLS_CHACHA20_POLY1305_SHA256,\n                     CipherSuite::TLS_AES_256_GCM_SHA384,\n                     CipherSuite::TLS_AES_128_GCM_SHA256,\n                     CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,\n                     CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n                     CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n                 ]));\n\n            Ok(())\n        });\n    }\n\n    macro_rules! tls_example_private_pem {\n        ($k:expr) => {\n            concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/../../examples/tls/private/\", $k)\n        }\n    }\n\n    #[test]\n    fn verify_load_private_keys_of_different_types() -> Result<()> {\n        let key_paths = [\n            tls_example_private_pem!(\"rsa_sha256_key.pem\"),\n            tls_example_private_pem!(\"ecdsa_nistp256_sha256_key_pkcs8.pem\"),\n            tls_example_private_pem!(\"ecdsa_nistp384_sha384_key_pkcs8.pem\"),\n            tls_example_private_pem!(\"ed25519_key.pem\"),\n        ];\n\n        for key in key_paths {\n            TlsConfig::from_paths(\"\", key).load_key()?;\n        }\n\n        Ok(())\n    }\n\n    #[test]\n    fn verify_load_certs_of_different_types() -> Result<()> {\n        let cert_paths = [\n            tls_example_private_pem!(\"rsa_sha256_cert.pem\"),\n            tls_example_private_pem!(\"ecdsa_nistp256_sha256_cert.pem\"),\n            tls_example_private_pem!(\"ecdsa_nistp384_sha384_cert.pem\"),\n            tls_example_private_pem!(\"ed25519_cert.pem\"),\n        ];\n\n        for cert in cert_paths {\n            TlsConfig::from_paths(cert, \"\").load_certs()?;\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "core/lib/src/tls/error.rs",
    "content": "pub type Result<T, E = Error> = std::result::Result<T, E>;\n\n#[derive(Debug)]\npub enum KeyError {\n    BadKeyCount(usize),\n    Io(std::io::Error),\n    Unsupported(rustls::Error),\n    BadItem(rustls_pemfile::Item),\n}\n\n#[derive(Debug)]\npub enum Error {\n    Io(std::io::Error),\n    Bind(Box<dyn std::error::Error + Send + 'static>),\n    Tls(rustls::Error),\n    Mtls(rustls::server::VerifierBuilderError),\n    CertChain(std::io::Error),\n    PrivKey(KeyError),\n    CertAuth(rustls::Error),\n    Config(figment::Error),\n}\n\nimpl std::fmt::Display for Error {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        use Error::*;\n\n        match self {\n            Io(e) => write!(f, \"i/o error during tls binding: {e}\"),\n            Tls(e) => write!(f, \"tls configuration error: {e}\"),\n            Mtls(e) => write!(f, \"mtls verifier error: {e}\"),\n            CertChain(e) => write!(f, \"failed to process certificate chain: {e}\"),\n            PrivKey(e) => write!(f, \"failed to process private key: {e}\"),\n            CertAuth(e) => write!(f, \"failed to process certificate authority: {e}\"),\n            Bind(e) => write!(f, \"failed to bind to network interface: {e}\"),\n            Config(e) => write!(f, \"failed to read tls configuration: {e}\"),\n        }\n    }\n}\n\nimpl std::fmt::Display for KeyError {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        use KeyError::*;\n\n        match self {\n            Io(e) => write!(f, \"error reading key file: {e}\"),\n            BadKeyCount(0) => write!(f, \"no valid keys found. is the file malformed?\"),\n            BadKeyCount(n) => write!(f, \"expected exactly 1 key, found {n}\"),\n            Unsupported(e) => write!(f, \"key is valid but is unsupported: {e}\"),\n            BadItem(i) => write!(f, \"found unexpected item in key file: {i:#?}\"),\n        }\n    }\n}\n\nimpl std::error::Error for KeyError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        match self {\n            KeyError::Io(e) => Some(e),\n            KeyError::Unsupported(e) => Some(e),\n            _ => None,\n        }\n    }\n}\n\nimpl std::error::Error for Error {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        match self {\n            Error::Io(e) => Some(e),\n            Error::Tls(e) => Some(e),\n            Error::Mtls(e) => Some(e),\n            Error::CertChain(e) => Some(e),\n            Error::PrivKey(e) => Some(e),\n            Error::CertAuth(e) => Some(e),\n            Error::Bind(e) => Some(&**e),\n            Error::Config(e) => Some(e),\n        }\n    }\n}\n\nimpl From<std::io::Error> for Error {\n    fn from(e: std::io::Error) -> Self {\n       Error::Io(e)\n    }\n}\n\nimpl From<rustls::Error> for Error {\n    fn from(e: rustls::Error) -> Self {\n        Error::Tls(e)\n    }\n}\n\nimpl From<rustls::server::VerifierBuilderError> for Error {\n    fn from(value: rustls::server::VerifierBuilderError) -> Self {\n        Error::Mtls(value)\n    }\n}\n\nimpl From<KeyError> for Error {\n    fn from(value: KeyError) -> Self {\n        Error::PrivKey(value)\n    }\n}\n\nimpl From<std::convert::Infallible> for Error {\n    fn from(v: std::convert::Infallible) -> Self {\n        v.into()\n    }\n}\n\nimpl From<figment::Error> for Error {\n    fn from(value: figment::Error) -> Self {\n        Error::Config(value)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/tls/listener.rs",
    "content": "use std::io;\nuse std::sync::Arc;\n\nuse futures::TryFutureExt;\nuse tokio::io::{AsyncRead, AsyncWrite};\nuse tokio_rustls::LazyConfigAcceptor;\nuse rustls::server::{Acceptor, ServerConfig};\n\nuse crate::{Ignite, Rocket};\nuse crate::listener::{Bind, Certificates, Connection, Endpoint, Listener};\nuse crate::tls::{TlsConfig, Result, Error};\nuse super::resolver::DynResolver;\n\n#[doc(inline)]\npub use tokio_rustls::server::TlsStream;\n\n/// A TLS listener over some listener interface L.\npub struct TlsListener<L> {\n    listener: L,\n    config: TlsConfig,\n    default: Arc<ServerConfig>,\n}\n\nimpl<L> TlsListener<L>\n    where L: Listener<Accept = <L as Listener>::Connection>,\n{\n    pub async fn from(listener: L, config: TlsConfig) -> Result<TlsListener<L>> {\n        Ok(TlsListener {\n            default: Arc::new(config.server_config().await?),\n            listener,\n            config,\n        })\n    }\n}\n\nimpl<L: Bind> Bind for TlsListener<L>\n    where L: Listener<Accept = <L as Listener>::Connection>\n{\n    type Error = Error;\n\n    async fn bind(rocket: &Rocket<Ignite>) -> Result<Self, Self::Error> {\n        let listener = L::bind(rocket).map_err(|e| Error::Bind(Box::new(e))).await?;\n        let mut config: TlsConfig = rocket.figment().extract_inner(\"tls\")?;\n        config.resolver = DynResolver::extract(rocket);\n        Self::from(listener, config).await\n    }\n\n    fn bind_endpoint(rocket: &Rocket<Ignite>) -> Result<Endpoint, Self::Error> {\n        let config: TlsConfig = rocket.figment().extract_inner(\"tls\")?;\n        L::bind_endpoint(rocket)\n            .map(|e| e.with_tls(&config))\n            .map_err(|e| Error::Bind(Box::new(e)))\n    }\n}\n\nimpl<L> Listener for TlsListener<L>\n    where L: Listener<Accept = <L as Listener>::Connection>,\n          L::Connection: AsyncRead + AsyncWrite\n{\n    type Accept = L::Connection;\n\n    type Connection = TlsStream<L::Connection>;\n\n    async fn accept(&self) -> io::Result<Self::Accept> {\n        self.listener.accept().await\n    }\n\n    async fn connect(&self, conn: L::Connection) -> io::Result<Self::Connection> {\n        let acceptor = LazyConfigAcceptor::new(Acceptor::default(), conn);\n        let handshake = acceptor.await?;\n        let hello = handshake.client_hello();\n        let config = match &self.config.resolver {\n            Some(r) => r.resolve(hello).await.unwrap_or_else(|| self.default.clone()),\n            None => self.default.clone(),\n        };\n\n        handshake.into_stream(config).await\n    }\n\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        Ok(self.listener.endpoint()?.with_tls(&self.config))\n    }\n}\n\nimpl<C: Connection> Connection for TlsStream<C> {\n    fn endpoint(&self) -> io::Result<Endpoint> {\n        Ok(self.get_ref().0.endpoint()?.assume_tls())\n    }\n\n    fn certificates(&self) -> Option<Certificates<'_>> {\n        #[cfg(feature = \"mtls\")] {\n            let cert_chain = self.get_ref().1.peer_certificates()?;\n            Some(Certificates::from(cert_chain))\n        }\n\n        #[cfg(not(feature = \"mtls\"))]\n        None\n    }\n\n    fn server_name(&self) -> Option<&str> {\n        #[cfg(feature = \"tls\")] {\n            self.get_ref().1.server_name()\n        }\n\n        #[cfg(not(feature = \"tls\"))]\n        None\n    }\n}\n"
  },
  {
    "path": "core/lib/src/tls/mod.rs",
    "content": "mod error;\nmod resolver;\nmod listener;\npub(crate) mod config;\n\npub use error::{Error, Result};\npub use config::{TlsConfig, CipherSuite};\npub use resolver::{Resolver, ClientHello, ServerConfig};\npub use listener::{TlsListener, TlsStream};\n"
  },
  {
    "path": "core/lib/src/tls/resolver.rs",
    "content": "use std::fmt;\nuse std::marker::PhantomData;\nuse std::ops::Deref;\nuse std::sync::Arc;\n\npub use rustls::server::{ClientHello, ServerConfig};\n\nuse crate::{Build, Ignite, Rocket};\nuse crate::fairing::{self, Info, Kind};\n\n/// Proxy type to get PartialEq + Debug impls.\n#[derive(Clone)]\npub(crate) struct DynResolver(Arc<dyn Resolver>);\n\npub struct Fairing<T: ?Sized>(PhantomData<T>);\n\n/// A dynamic TLS configuration resolver.\n///\n/// # Example\n///\n/// This is an async trait. Implement it as follows:\n///\n/// ```rust\n/// # #[macro_use] extern crate rocket;\n/// use std::sync::Arc;\n/// use rocket::tls::{self, Resolver, TlsConfig, ClientHello, ServerConfig};\n/// use rocket::{Rocket, Build};\n///\n/// struct MyResolver(Arc<ServerConfig>);\n///\n/// #[rocket::async_trait]\n/// impl Resolver for MyResolver {\n///     async fn init(rocket: &Rocket<Build>) -> tls::Result<Self> {\n///         // This is equivalent to what the default resolver would do.\n///         let config: TlsConfig = rocket.figment().extract_inner(\"tls\")?;\n///         let server_config = config.server_config().await?;\n///         Ok(MyResolver(Arc::new(server_config)))\n///     }\n///\n///     async fn resolve(&self, hello: ClientHello<'_>) -> Option<Arc<ServerConfig>> {\n///         // return a `ServerConfig` based on `hello`; here we ignore it\n///         Some(self.0.clone())\n///     }\n/// }\n///\n/// #[launch]\n/// fn rocket() -> _ {\n///     rocket::build().attach(MyResolver::fairing())\n/// }\n/// ```\n#[crate::async_trait]\npub trait Resolver: Send + Sync + 'static {\n    async fn init(rocket: &Rocket<Build>) -> crate::tls::Result<Self> where Self: Sized {\n        let _rocket = rocket;\n        let type_name = std::any::type_name::<Self>();\n        Err(figment::Error::from(format!(\"{type_name}: Resolver::init() unimplemented\")).into())\n    }\n\n    async fn resolve(&self, hello: ClientHello<'_>) -> Option<Arc<ServerConfig>>;\n\n    fn fairing() -> Fairing<Self> where Self: Sized {\n        Fairing(PhantomData)\n    }\n}\n\n#[crate::async_trait]\nimpl<T: Resolver> fairing::Fairing for Fairing<T> {\n    fn info(&self) -> Info {\n        Info {\n            name: \"Resolver Fairing\",\n            kind: Kind::Ignite | Kind::Singleton\n        }\n    }\n\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {\n        let result = T::init(&rocket).await;\n        match result {\n            Ok(resolver) => Ok(rocket.manage(Arc::new(resolver) as Arc<dyn Resolver>)),\n            Err(e) => {\n                let type_name = std::any::type_name::<T>();\n                error!(type_name, reason = %e, \"TLS resolver failed to initialize\");\n                Err(rocket)\n            }\n        }\n    }\n}\n\nimpl DynResolver {\n    pub fn extract(rocket: &Rocket<Ignite>) -> Option<Self> {\n        rocket.state::<Arc<dyn Resolver>>().map(|r| Self(r.clone()))\n    }\n}\n\nimpl fmt::Debug for DynResolver {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_tuple(\"Resolver\").finish()\n    }\n}\n\nimpl PartialEq for DynResolver {\n    fn eq(&self, _: &Self) -> bool {\n        false\n    }\n}\n\nimpl Deref for DynResolver {\n    type Target = dyn Resolver;\n\n    fn deref(&self) -> &Self::Target {\n        &*self.0\n    }\n}\n"
  },
  {
    "path": "core/lib/src/trace/level.rs",
    "content": "use std::fmt;\n\nuse serde::{de, Serialize, Deserializer, Serializer};\nuse tracing::{level_filters::LevelFilter, Level};\n\npub fn serialize<S: Serializer>(level: &Option<Level>, s: S) -> Result<S::Ok, S::Error> {\n    LevelFilter::from(*level).to_string().serialize(s)\n}\n\npub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<Option<Level>, D::Error> {\n    struct Visitor;\n\n    const E: &str = r#\"one of \"off\", \"error\", \"warn\", \"info\", \"debug\", \"trace\", or 0-5\"#;\n\n    impl<'de> de::Visitor<'de> for Visitor {\n        type Value = Option<Level>;\n\n        fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n            write!(f, \"expected {E}\")\n        }\n\n        fn visit_i64<E: de::Error>(self, v: i64) -> Result<Self::Value, E> {\n            v.try_into()\n                .map_err(|_| E::invalid_value(de::Unexpected::Signed(v), &E))\n                .and_then(|v| self.visit_u64(v))\n        }\n\n        fn visit_u64<E: de::Error>(self, v: u64) -> Result<Self::Value, E> {\n            let filter = match v {\n                0 => LevelFilter::OFF,\n                1 => LevelFilter::ERROR,\n                2 => LevelFilter::WARN,\n                3 => LevelFilter::INFO,\n                4 => LevelFilter::DEBUG,\n                5 => LevelFilter::TRACE,\n                _ => return Err(E::invalid_value(de::Unexpected::Unsigned(v), &E)),\n            };\n\n            Ok(filter.into_level())\n        }\n\n        fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {\n            v.parse::<LevelFilter>()\n                .map(|f| f.into_level())\n                .map_err(|_| E::invalid_value(de::Unexpected::Str(v), &E))\n        }\n    }\n\n    de.deserialize_map(Visitor)\n}\n"
  },
  {
    "path": "core/lib/src/trace/macros.rs",
    "content": "macro_rules! declare_span_macro {\n    ($name:ident $level:ident) => (\n        declare_span_macro!([$] $name $level);\n    );\n\n    ([$d:tt] $name:ident $level:ident) => (\n        #[doc(hidden)]\n        #[macro_export]\n        macro_rules! $name {\n            (@[$d ($t:tt)+] => $in_scope:expr) => ({\n                $crate::tracing::span!($crate::tracing::Level::$level, $d ($t)+)\n                    .in_scope(|| $in_scope);\n            });\n\n            (@[$d ($t:tt)+] $token:tt $d ($rest:tt)*) => ({\n                $crate::trace::$name!(@[$d ($t)+ $token] $d ($rest)*);\n            });\n\n            // base case\n            ($t:tt $d ($rest:tt)*) => ({\n                $crate::trace::$name!(@[$t] $d ($rest)*);\n            });\n        }\n\n        #[doc(hidden)]\n        pub use $name as $name;\n    );\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! event {\n    ($level:expr, $($args:tt)*) => {{\n        match $level {\n            $crate::tracing::Level::ERROR => event!(@$crate::tracing::Level::ERROR, $($args)*),\n            $crate::tracing::Level::WARN => event!(@$crate::tracing::Level::WARN, $($args)*),\n            $crate::tracing::Level::INFO => event!(@$crate::tracing::Level::INFO, $($args)*),\n            $crate::tracing::Level::DEBUG => event!(@$crate::tracing::Level::DEBUG, $($args)*),\n            $crate::tracing::Level::TRACE => event!(@$crate::tracing::Level::TRACE, $($args)*),\n        }\n    }};\n\n    (@$level:expr, $n:expr, $($args:tt)*) => {{\n        $crate::tracing::event!(name: $n, target: concat!(\"rocket::\", $n), $level, $($args)*);\n    }};\n}\n\n// Re-exports the macro at $path with the name $name. The point is to allow\n// a `#[macro_use] extern crate rocket` to also automatically import the\n// relevant tracing macros.\nmacro_rules! reexport {\n    ($path:ident::$name:ident) => (\n        reexport!([$] $path::$name);\n    );\n\n    ([ $d:tt ] $path:ident::$name:ident) => {\n        #[doc(hidden)]\n        #[macro_export]\n        macro_rules! $name {\n            ($d ($f:tt)*) => {\n                $crate::$path::$name!($d ($f)*)\n            }\n        }\n    };\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! span {\n    ($level:expr, $($args:tt)*) => {{\n        match $level {\n            $crate::tracing::Level::ERROR =>\n                $crate::tracing::span!($crate::tracing::Level::ERROR, $($args)*),\n            $crate::tracing::Level::WARN =>\n                $crate::tracing::span!($crate::tracing::Level::WARN, $($args)*),\n            $crate::tracing::Level::INFO =>\n                $crate::tracing::span!($crate::tracing::Level::INFO, $($args)*),\n            $crate::tracing::Level::DEBUG =>\n                $crate::tracing::span!($crate::tracing::Level::DEBUG, $($args)*),\n            $crate::tracing::Level::TRACE =>\n                $crate::tracing::span!($crate::tracing::Level::TRACE, $($args)*),\n        }\n    }};\n}\n\n#[doc(inline)]\npub use span as span;\n\ndeclare_span_macro!(span_error ERROR);\ndeclare_span_macro!(span_warn WARN);\ndeclare_span_macro!(span_info INFO);\ndeclare_span_macro!(span_debug DEBUG);\ndeclare_span_macro!(span_trace TRACE);\n\n#[doc(inline)]\npub use event as event;\n\nreexport!(tracing::error);\nreexport!(tracing::warn);\nreexport!(tracing::info);\nreexport!(tracing::debug);\nreexport!(tracing::trace);\n\n#[doc(hidden)] pub use tracing::error;\n#[doc(hidden)] pub use tracing::warn;\n#[doc(hidden)] pub use tracing::info;\n#[doc(hidden)] pub use tracing::debug;\n#[doc(hidden)] pub use tracing::trace;\n"
  },
  {
    "path": "core/lib/src/trace/mod.rs",
    "content": "#[macro_use]\nmod macros;\nmod traceable;\n\n#[cfg(feature = \"trace\")]\n#[cfg_attr(nightly, doc(cfg(feature = \"trace\")))]\npub mod subscriber;\n\npub(crate) mod level;\n\n#[doc(inline)]\npub use macros::*;\n\n#[doc(inline)]\npub use traceable::{Trace, TraceAll};\n\n#[doc(inline)]\npub use tracing::{Level, level_filters::LevelFilter};\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]\n#[serde(crate = \"rocket::serde\")]\n#[non_exhaustive]\npub enum TraceFormat {\n    #[serde(rename = \"pretty\")]\n    #[serde(alias = \"PRETTY\")]\n    Pretty,\n    #[serde(rename = \"compact\")]\n    #[serde(alias = \"COMPACT\")]\n    Compact\n}\n\n#[cfg_attr(nightly, doc(cfg(feature = \"trace\")))]\npub fn init<'a, T: Into<Option<&'a crate::Config>>>(config: T) {\n    #[cfg(not(feature = \"trace\"))]\n    let _ = config;\n\n    #[cfg(feature = \"trace\")]\n    crate::trace::subscriber::RocketDynFmt::init(config.into())\n}\n"
  },
  {
    "path": "core/lib/src/trace/subscriber/common.rs",
    "content": "use std::fmt;\nuse std::cell::Cell;\n\nuse tracing::field::Field;\nuse tracing::{Level, Metadata};\nuse tracing_subscriber::filter;\nuse tracing_subscriber::field::RecordFields;\n\nuse thread_local::ThreadLocal;\nuse yansi::{Condition, Paint, Style};\n\nuse crate::config::CliColors;\nuse crate::trace::subscriber::RecordDisplay;\nuse crate::util::Formatter;\n\nmod private {\n    pub trait FmtKind: Send + Sync + 'static { }\n\n    impl FmtKind for crate::trace::subscriber::Pretty { }\n    impl FmtKind for crate::trace::subscriber::Compact { }\n}\n\n#[derive(Default)]\npub struct RocketFmt<K: private::FmtKind> {\n    state: ThreadLocal<Cell<K>>,\n    pub(crate) level: Option<Level>,\n    pub(crate) filter: filter::Targets,\n    pub(crate) style: Style,\n}\n\nimpl<K: private::FmtKind + Default + Copy> RocketFmt<K> {\n    pub(crate) fn state(&self) -> K {\n        self.state.get_or_default().get()\n    }\n\n    pub(crate) fn update_state<F: FnOnce(&mut K)>(&self, update: F) {\n        let cell = self.state.get_or_default();\n        let mut old = cell.get();\n        update(&mut old);\n        cell.set(old);\n    }\n}\n\nimpl<K: private::FmtKind> RocketFmt<K> {\n    pub fn new(workers: usize, cli_colors: CliColors, level: Option<Level>) -> Self {\n        Self {\n            state: ThreadLocal::with_capacity(workers),\n            level,\n            filter: filter::Targets::new()\n                .with_default(level)\n                .with_target(\"rustls\", level.filter(|&l| l == Level::TRACE))\n                .with_target(\"hyper\", level.filter(|&l| l == Level::TRACE)),\n            style: match cli_colors {\n                CliColors::Always => Style::new().whenever(Condition::ALWAYS),\n                CliColors::Auto => Style::new().whenever(Condition::DEFAULT),\n                CliColors::Never => Style::new().whenever(Condition::NEVER),\n            }\n        }\n    }\n\n    pub fn style(&self, metadata: &Metadata<'_>) -> Style {\n        match *metadata.level() {\n            Level::ERROR => self.style.red(),\n            Level::WARN => self.style.yellow(),\n            Level::INFO => self.style.blue(),\n            Level::DEBUG => self.style.green(),\n            Level::TRACE => self.style.magenta(),\n        }\n    }\n\n    pub(crate) fn has_message(&self, meta: &Metadata<'_>) -> bool {\n        meta.fields().field(\"message\").is_some()\n    }\n\n    pub(crate) fn has_data_fields(&self, meta: &Metadata<'_>) -> bool {\n        meta.fields().iter().any(|f| f.name() != \"message\")\n    }\n\n    pub(crate) fn message<'a, F: RecordFields + 'a>(&self,\n        init_prefix: &'a dyn fmt::Display,\n        cont_prefix: &'a dyn fmt::Display,\n        meta: &'a Metadata<'_>,\n        data: F\n    ) -> impl fmt::Display + 'a {\n        let style = self.style(meta);\n        Formatter(move |f| {\n            let fields = meta.fields();\n            let message = fields.field(\"message\");\n            if let Some(message_field) = &message {\n                data.record_display(|field: &Field, value: &dyn fmt::Display| {\n                    if field != message_field {\n                        return;\n                    }\n\n                    for (i, line) in value.to_string().lines().enumerate() {\n                        let line = line.paint(style);\n                        if i == 0 {\n                            let _ = writeln!(f, \"{init_prefix}{line}\");\n                        } else {\n                            let _ = writeln!(f, \"{cont_prefix}{line}\");\n                        }\n                    }\n                });\n            }\n\n            Ok(())\n        })\n    }\n\n    pub(crate) fn compact_fields<'a, F: RecordFields + 'a>(\n        &self,\n        meta: &'a Metadata<'_>,\n        data: F\n    ) -> impl fmt::Display + 'a {\n        let key_style = self.style(meta).bold();\n        let val_style = self.style(meta).primary();\n\n        Formatter(move |f| {\n            let mut printed = false;\n            data.record_display(|field: &Field, val: &dyn fmt::Display| {\n                let key = field.name();\n                if key != \"message\" {\n                    if printed { let _ = write!(f, \" \"); }\n                    let _ = write!(f, \"{}: {}\", key.paint(key_style), val.paint(val_style));\n                    printed = true;\n                }\n            });\n\n            Ok(())\n        })\n    }\n\n    pub(crate) fn print<F: RecordFields>(\n        &self,\n        prefix: &dyn fmt::Display,\n        cont_prefix: &dyn fmt::Display,\n        m: &Metadata<'_>,\n        data: F\n    ) {\n        if self.has_message(m) {\n            let message = self.message(prefix, cont_prefix, m, &data);\n            if self.has_data_fields(m) {\n                println!(\"{message}{cont_prefix}{}\", self.compact_fields(m, &data));\n            } else {\n                print!(\"{message}\");\n            }\n        } else if self.has_data_fields(m) {\n            println!(\"{prefix}{}\", self.compact_fields(m, &data));\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/trace/subscriber/compact.rs",
    "content": "use std::fmt;\nuse std::time::Instant;\nuse std::num::NonZeroU64;\n\nuse tracing::{Event, Level, Metadata, Subscriber};\nuse tracing::span::{Attributes, Id, Record};\nuse tracing_subscriber::layer::{Layer, Context};\nuse tracing_subscriber::registry::LookupSpan;\nuse tracing_subscriber::field::RecordFields;\n\nuse time::OffsetDateTime;\nuse yansi::{Paint, Painted};\n\nuse crate::util::Formatter;\nuse crate::trace::subscriber::{Data, RocketFmt};\nuse crate::http::{Status, StatusClass};\nuse super::RecordDisplay;\n\n#[derive(Debug, Default, Copy, Clone)]\npub struct Compact {\n    /// The `tracing::Span::Id` of the request we're in, if any.\n    request: Option<NonZeroU64>,\n}\n\n#[derive(Debug)]\npub struct RequestData {\n    start: Instant,\n    fields: Data,\n    item: Option<(String, String)>,\n}\n\nimpl RequestData {\n    pub fn new<T: RecordFields>(attrs: T) -> Self {\n        Self {\n            start: Instant::now(),\n            fields: Data::new(attrs),\n            item: None,\n        }\n    }\n}\n\nimpl RocketFmt<Compact> {\n    fn request_span_id(&self) -> Option<Id> {\n        self.state().request.map(Id::from_non_zero_u64)\n    }\n\n    fn timestamp_for(&self, datetime: OffsetDateTime) -> impl fmt::Display {\n        Formatter(move |f| {\n            let (date, time) = (datetime.date(), datetime.time());\n            let (year, month, day) = (date.year(), date.month() as u8, date.day());\n            let (h, m, s, l) = (time.hour(), time.minute(), time.second(), time.millisecond());\n            write!(f, \"{year:04}-{month:02}-{day:02}T{h:02}:{m:02}:{s:02}.{l:03}Z\")\n        })\n    }\n\n    fn in_debug(&self) -> bool {\n        self.level.map_or(false, |l| l >= Level::DEBUG)\n    }\n\n    fn prefix<'a>(&self, meta: &'a Metadata<'_>) -> impl fmt::Display + 'a {\n        let style = self.style(meta);\n        let name = meta.name()\n            .starts_with(\"event \")\n            .then_some(meta.target())\n            .unwrap_or(meta.name());\n\n        let pad = self.level.map_or(0, |lvl| lvl.as_str().len());\n        let timestamp = self.timestamp_for(OffsetDateTime::now_utc());\n        Formatter(move |f| write!(f, \"{} {:>pad$} {} \",\n            timestamp.paint(style).primary().dim(),\n            meta.level().paint(style),\n            name.paint(style).primary()))\n    }\n\n    fn chevron(&self, meta: &Metadata<'_>) -> Painted<&'static str> {\n        \"›\".paint(self.style(meta)).bold()\n    }\n\n    fn print_compact<F: RecordFields>(&self, m: &Metadata<'_>, data: F) {\n        let style = self.style(m);\n        let prefix = self.prefix(m);\n        let chevron = self.chevron(m);\n        let init_prefix = Formatter(|f| write!(f, \"{prefix}{chevron} \"));\n        let cont_prefix = Formatter(|f| write!(f, \"{prefix}{} \", \"+\".paint(style).dim()));\n        self.print(&init_prefix, &cont_prefix, m, data);\n    }\n}\n\nimpl<S: Subscriber + for<'a> LookupSpan<'a>> Layer<S> for RocketFmt<Compact> {\n    fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool {\n        self.filter.would_enable(metadata.target(), metadata.level())\n            && (self.in_debug()\n                || self.request_span_id().is_none()\n                || metadata.name() == \"request\"\n                || metadata.name() == \"response\")\n    }\n\n    fn on_event(&self, event: &Event<'_>, ctxt: Context<'_, S>) {\n        if let Some(id) = self.request_span_id() {\n            let name = event.metadata().name();\n            if name == \"response\" {\n                let req_span = ctxt.span(&id).expect(\"on_event: req does not exist\");\n                let mut exts = req_span.extensions_mut();\n                let data = exts.get_mut::<RequestData>().unwrap();\n                event.record(&mut data.fields);\n            } else if name == \"catcher\" || name == \"route\" {\n                let req_span = ctxt.span(&id).expect(\"on_event: req does not exist\");\n                let mut exts = req_span.extensions_mut();\n                let data = exts.get_mut::<RequestData>().unwrap();\n                data.item = event.find_map_display(\"name\", |v| (name.into(), v.to_string()))\n            }\n\n            if !self.in_debug() {\n                return;\n            }\n        }\n\n        self.print_compact(event.metadata(), event);\n    }\n\n    fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"new_span: span does not exist\");\n\n        if span.name() == \"request\" {\n            let data = RequestData::new(attrs);\n            span.extensions_mut().replace(data);\n\n            if !self.in_debug() {\n                return;\n            }\n        }\n\n        if self.state().request.is_none() {\n            self.print_compact(span.metadata(), attrs);\n        }\n    }\n\n    fn on_record(&self, id: &Id, values: &Record<'_>, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"record: span does not exist\");\n        if self.request_span_id().as_ref() == Some(id) {\n            let mut extensions = span.extensions_mut();\n            match extensions.get_mut::<RequestData>() {\n                Some(data) => values.record(&mut data.fields),\n                None => span.extensions_mut().insert(RequestData::new(values)),\n            }\n        }\n\n        if self.in_debug() {\n            println!(\"{}{} {}\",\n                self.prefix(span.metadata()),\n                self.chevron(span.metadata()),\n                self.compact_fields(span.metadata(), values));\n        }\n    }\n\n    fn on_enter(&self, id: &Id, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"new_span: span does not exist\");\n        if span.name() == \"request\" {\n            self.update_state(|state| state.request = Some(id.into_non_zero_u64()));\n        }\n    }\n\n    fn on_exit(&self, id: &Id, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"new_span: span does not exist\");\n        if span.name() == \"request\" {\n            self.update_state(|state| state.request = None);\n        }\n    }\n\n    fn on_close(&self, id: Id, ctxt: Context<'_, S>) {\n        let span = ctxt.span(&id).expect(\"new_span: span does not exist\");\n        if span.name() == \"request\" {\n            let extensions = span.extensions();\n            let data = extensions.get::<RequestData>().unwrap();\n\n            let elapsed = data.start.elapsed();\n            let datetime = OffsetDateTime::now_utc() - elapsed;\n            let timestamp = self.timestamp_for(datetime);\n\n            let s = self.style(span.metadata());\n            let prefix = self.prefix(span.metadata());\n            let chevron = self.chevron(span.metadata());\n            let arrow = \"→\".paint(s.primary().bright());\n\n            let status_class = data.fields[\"status\"].parse().ok()\n                .and_then(Status::from_code)\n                .map(|status| status.class());\n\n            let status_style = match status_class {\n                Some(StatusClass::Informational) => s,\n                Some(StatusClass::Success) => s.green(),\n                Some(StatusClass::Redirection) => s.magenta(),\n                Some(StatusClass::ClientError) => s.yellow(),\n                Some(StatusClass::ServerError) => s.red(),\n                Some(StatusClass::Unknown) => s.cyan(),\n                None => s.primary(),\n            };\n\n            let autohandle = Formatter(|f| {\n                match data.fields.get(\"autohandled\") {\n                    Some(\"true\") => write!(f, \" {} {}\", \"via\".paint(s.dim()), \"GET\".paint(s)),\n                    _ => Ok(())\n                }\n            });\n\n            let item = Formatter(|f| {\n                match &data.item {\n                    Some((kind, name)) => write!(f,\n                        \"{} {} {arrow} \",\n                        kind.paint(s),\n                        name.paint(s.bold()),\n                    ),\n                    None => Ok(())\n                }\n            });\n\n            println!(\"{prefix}{chevron} ({} {}ms) {}{autohandle} {} {arrow} {item}{}\",\n                timestamp.paint(s).primary().dim(),\n                elapsed.as_millis(),\n                &data.fields[\"method\"].paint(s),\n                &data.fields[\"uri\"],\n                &data.fields[\"status\"].paint(status_style),\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/trace/subscriber/dynamic.rs",
    "content": "use std::sync::OnceLock;\n\nuse tracing::{Dispatch, Event, Metadata};\nuse tracing::subscriber::{Subscriber, Interest};\nuse tracing::span::{Attributes, Id, Record};\n\nuse tracing_subscriber::reload;\nuse tracing_subscriber::registry::{Registry, LookupSpan};\nuse tracing_subscriber::layer::{Context, Layer, Layered, SubscriberExt};\nuse tracing_subscriber::util::SubscriberInitExt;\n\nuse crate::config::Config;\nuse crate::trace::subscriber::{Compact, Pretty, RequestId, RequestIdLayer, RocketFmt};\nuse crate::trace::TraceFormat;\n\n/// A subscriber that is either a [`Pretty`] or [`Compact`] [`RocketFmt`].\npub struct RocketDynFmt {\n    inner: either::Either<RocketFmt<Compact>, RocketFmt<Pretty>>,\n}\n\nimpl From<RocketFmt<Compact>> for RocketDynFmt {\n    fn from(value: RocketFmt<Compact>) -> Self {\n        RocketDynFmt { inner: either::Either::Left(value) }\n    }\n}\n\nimpl From<RocketFmt<Pretty>> for RocketDynFmt {\n    fn from(value: RocketFmt<Pretty>) -> Self {\n        RocketDynFmt { inner: either::Either::Right(value) }\n    }\n}\n\nimpl RocketDynFmt {\n    /// Creates a new `RocketDynFmt` subscriber given a `Config`.\n    ///\n    /// [`Config::log_format`] determines which `RocketFmt` subscriber (either\n    /// [`Pretty`] or [`Compact`]) is used.\n    ///\n    /// If `config` is `None`, [`Config::debug_default()`] is used, which uses\n    /// the [`Pretty`] subscriber by default.\n    pub fn new(config: Option<&Config>) -> Self {\n        let default = Config::debug_default();\n        let workers = config.map_or(default.workers, |c| c.workers);\n        let colors = config.map_or(default.cli_colors, |c| c.cli_colors);\n        let level = config.map_or(default.log_level, |c| c.log_level);\n        let format = config.map_or(default.log_format, |c| c.log_format);\n\n        match format {\n            TraceFormat::Pretty => Self::from(RocketFmt::<Pretty>::new(workers, colors, level)),\n            TraceFormat::Compact => Self::from(RocketFmt::<Compact>::new(workers, colors, level)),\n        }\n    }\n\n    pub(crate) fn init(config: Option<&Config>) {\n        type Handle = reload::Handle<RocketDynFmt, Layered<RequestIdLayer, Registry>>;\n\n        static HANDLE: OnceLock<Handle> = OnceLock::new();\n\n        // Do nothing if there's no config and we've already initialized.\n        if config.is_none() && HANDLE.get().is_some() {\n            return;\n        }\n\n        let formatter = Self::new(config);\n        if let Some(handle) = HANDLE.get() {\n            return assert!(handle.modify(|layer| *layer = formatter).is_ok());\n        }\n\n        let (layer, reload_handle) = reload::Layer::new(formatter);\n        let result = tracing_subscriber::registry()\n            .with(RequestId::layer())\n            .with(layer)\n            .try_init();\n\n        if result.is_ok() {\n            assert!(HANDLE.set(reload_handle).is_ok());\n        }\n    }\n}\n\nmacro_rules! forward {\n    ($T:ident => $(& $r:tt)? $method:ident ( $($p:ident : $t:ty),* ) $(-> $R:ty)?) => {\n        #[inline(always)]\n        fn $method(& $($r)? self $(, $p : $t)*) $(-> $R)? {\n            match & $($r)* self.inner {\n                either::Either::Left(layer) => Layer::<$T>::$method(layer, $($p),*),\n                either::Either::Right(layer) => Layer::<$T>::$method(layer, $($p),*),\n            }\n        }\n    };\n}\n\nimpl<S: Subscriber + for<'a> LookupSpan<'a>> Layer<S> for RocketDynFmt {\n    forward!(S => on_register_dispatch(subscriber: &Dispatch));\n    forward!(S => &mut on_layer(subscriber: &mut S));\n    forward!(S => register_callsite(metadata: &'static Metadata<'static>) -> Interest);\n    forward!(S => enabled(metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool);\n    forward!(S => on_new_span(attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>));\n    forward!(S => on_record(_span: &Id, _values: &Record<'_>, _ctx: Context<'_, S>));\n    forward!(S => on_follows_from(_span: &Id, _follows: &Id, _ctx: Context<'_, S>));\n    forward!(S => event_enabled(_event: &Event<'_>, _ctx: Context<'_, S>) -> bool);\n    forward!(S => on_event(_event: &Event<'_>, _ctx: Context<'_, S>));\n    forward!(S => on_enter(_id: &Id, _ctx: Context<'_, S>));\n    forward!(S => on_exit(_id: &Id, _ctx: Context<'_, S>));\n    forward!(S => on_close(_id: Id, _ctx: Context<'_, S>));\n    forward!(S => on_id_change(_old: &Id, _new: &Id, _ctx: Context<'_, S>));\n}\n"
  },
  {
    "path": "core/lib/src/trace/subscriber/mod.rs",
    "content": "mod visit;\nmod pretty;\nmod compact;\nmod dynamic;\nmod common;\nmod request_id;\n\npub use pretty::Pretty;\npub use compact::Compact;\npub use common::RocketFmt;\npub use request_id::{RequestId, RequestIdLayer};\npub use dynamic::RocketDynFmt;\n\npub(crate) use visit::{RecordDisplay, Data};\n"
  },
  {
    "path": "core/lib/src/trace/subscriber/pretty.rs",
    "content": "use std::fmt;\n\nuse tracing::field::Field;\nuse tracing::{Event, Level, Metadata, Subscriber};\nuse tracing::span::{Attributes, Id, Record};\nuse tracing_subscriber::layer::{Layer, Context};\nuse tracing_subscriber::registry::LookupSpan;\nuse tracing_subscriber::field::RecordFields;\n\nuse yansi::{Paint, Painted};\n\nuse crate::util::Formatter;\nuse crate::trace::subscriber::{Data, RecordDisplay, RocketFmt};\n\n#[derive(Debug, Default, Copy, Clone)]\npub struct Pretty {\n    depth: u32,\n}\n\nimpl RocketFmt<Pretty> {\n    fn indent(&self) -> &'static str {\n        static INDENT: &[&str] = &[\"\", \"   \", \"      \"];\n        INDENT.get(self.state().depth as usize).copied().unwrap_or(\"         \")\n    }\n\n    fn marker(&self) -> &'static str {\n        static MARKER: &[&str] = &[\"\", \">> \", \":: \"];\n        MARKER.get(self.state().depth as usize).copied().unwrap_or(\"-- \")\n    }\n\n    fn emoji(&self, _emoji: &'static str) -> Painted<&'static str> {\n        #[cfg(windows)] { \"\".paint(self.style).mask() }\n        #[cfg(not(windows))] { _emoji.paint(self.style).mask() }\n    }\n\n    fn prefix<'a>(&self, meta: &'a Metadata<'_>) -> impl fmt::Display + 'a {\n        let (i, m, s) = (self.indent(), self.marker(), self.style(meta));\n        Formatter(move |f| match *meta.level() {\n            Level::WARN => write!(f, \"{i}{m}{} \", \"warning:\".paint(s).bold()),\n            Level::ERROR => write!(f, \"{i}{m}{} \", \"error:\".paint(s).bold()),\n            Level::INFO => write!(f, \"{i}{m}\"),\n            level => write!(f, \"{i}{m}[{} {}] \", level.paint(s).bold(), meta.target()),\n        })\n    }\n\n    fn print_pretty<F: RecordFields>(&self, m: &Metadata<'_>, data: F) {\n        let prefix = self.prefix(m);\n        let cont_prefix = Formatter(|f| {\n            let style = self.style(m);\n            write!(f, \"{}{} \", self.indent(), \"++\".paint(style).dim())\n        });\n\n        self.print(&prefix, &cont_prefix, m, data);\n    }\n\n    fn print_fields<F>(&self, metadata: &Metadata<'_>, fields: F)\n        where F: RecordFields\n    {\n        let style = self.style(metadata);\n        let prefix = self.prefix(metadata);\n        fields.record_display(|key: &Field, value: &dyn fmt::Display| {\n            if key.name() != \"message\" {\n                println!(\"{prefix}{}: {}\", key.paint(style), value.paint(style).primary());\n            }\n        })\n    }\n}\n\nimpl<S: Subscriber + for<'a> LookupSpan<'a>> Layer<S> for RocketFmt<Pretty> {\n    fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool {\n        self.filter.would_enable(metadata.target(), metadata.level())\n    }\n\n    fn on_event(&self, event: &Event<'_>, _: Context<'_, S>) {\n        let (meta, data) = (event.metadata(), Data::new(event));\n        let style = self.style(meta);\n        match meta.name() {\n            \"config\" => self.print_fields(meta, event),\n            \"liftoff\" => {\n                let prefix = self.prefix(meta);\n                println!(\"{prefix}{}{} {}\", self.emoji(\"🚀 \"),\n                    \"Rocket has launched on\".paint(style).primary().bold(),\n                    &data[\"endpoint\"].paint(style).primary().bold().underline());\n            },\n            \"route\" => println!(\"{}\", Formatter(|f| {\n                write!(f, \"{}{}{}: \", self.indent(), self.marker(), \"route\".paint(style))?;\n\n                let (base, mut relative) = (&data[\"uri.base\"], &data[\"uri.unmounted\"]);\n                if base.ends_with('/') && relative.starts_with('/') {\n                    relative = &relative[1..];\n                }\n\n                write!(f, \"{:>3} {} {}{}\",\n                    &data[\"rank\"].paint(style.bright().dim()),\n                    &data[\"method\"].paint(style.bold()),\n                    base.paint(style.primary().underline()),\n                    relative.paint(style.primary()),\n                )?;\n\n                if let Some(name) = data.get(\"name\") {\n                    write!(f, \" ({}\", name.paint(style.bold().bright()))?;\n\n                    if let Some(location) = data.get(\"location\") {\n                        write!(f, \" {}\", location.paint(style.dim()))?;\n                    }\n\n                    write!(f, \")\")?;\n                }\n\n                Ok(())\n            })),\n            \"catcher\" => println!(\"{}\", Formatter(|f| {\n                write!(f, \"{}{}{}: \", self.indent(), self.marker(), \"catcher\".paint(style))?;\n\n                match data.get(\"code\") {\n                    Some(code) => write!(f, \"{} \", code.paint(style.bold()))?,\n                    None => write!(f, \"{} \", \"default\".paint(style.bold()))?,\n                }\n\n                write!(f, \"{}\", &data[\"uri.base\"].paint(style.primary()))?;\n                if let Some(name) = data.get(\"name\") {\n                    write!(f, \" ({}\", name.paint(style.bold().bright()))?;\n\n                    if let Some(location) = data.get(\"location\") {\n                        write!(f, \" {}\", location.paint(style.dim()))?;\n                    }\n\n                    write!(f, \")\")?;\n                }\n\n                Ok(())\n            })),\n            \"header\" => println!(\"{}{}{}: {}: {}\",\n                self.indent(), self.marker(), \"header\".paint(style),\n                &data[\"name\"].paint(style.bold()),\n                &data[\"value\"].paint(style.primary()),\n            ),\n            \"fairing\" => println!(\"{}{}{}: {} {}\",\n                self.indent(), self.marker(), \"fairing\".paint(style),\n                &data[\"name\"].paint(style.bold()),\n                &data[\"kind\"].paint(style.primary().dim()),\n            ),\n            _ => self.print_pretty(meta, event),\n        }\n    }\n\n    fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctxt: Context<'_, S>) {\n        let data = Data::new(attrs);\n        let span = ctxt.span(id).expect(\"new_span: span does not exist\");\n        if &data[\"count\"] != \"0\" {\n            let name = span.name();\n            let icon = match name {\n                \"config\" => \"🔧 \",\n                \"routes\" => \"📬 \",\n                \"catchers\" => \"🚧 \",\n                \"fairings\" => \"📦 \",\n                \"shield\" => \"🛡️ \",\n                \"templating\" => \"📐 \",\n                \"request\" => \"● \",\n                _ => \"\",\n            };\n\n            let meta = span.metadata();\n            let style = self.style(meta);\n            let emoji = self.emoji(icon);\n            let name = name.paint(style).bold();\n\n            let fields = self.compact_fields(meta, attrs);\n            let prefix = self.prefix(meta);\n            let fieldless_prefix = Formatter(|f| write!(f, \"{prefix}{emoji}{name} \"));\n            let field_prefix = Formatter(|f| write!(f, \"{prefix}{emoji}{name} ({fields}) \"));\n\n            if self.has_message(meta) && self.has_data_fields(meta) {\n                print!(\"{}\", self.message(&field_prefix, &fieldless_prefix, meta, attrs));\n            } else if self.has_message(meta) {\n                print!(\"{}\", self.message(&fieldless_prefix, &fieldless_prefix, meta, attrs));\n            } else if self.has_data_fields(meta) {\n                println!(\"{field_prefix}\");\n            } else {\n                println!(\"{fieldless_prefix}\");\n            }\n        }\n\n        span.extensions_mut().replace(data);\n    }\n\n    fn on_record(&self, id: &Id, values: &Record<'_>, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"new_span: span does not exist\");\n        match span.extensions_mut().get_mut::<Data>() {\n            Some(data) => values.record(data),\n            None => span.extensions_mut().insert(Data::new(values)),\n        }\n\n        let meta = span.metadata();\n        println!(\"{}{}\", self.prefix(meta), self.compact_fields(meta, values));\n    }\n\n    fn on_enter(&self, _: &Id, _: Context<'_, S>) {\n        self.update_state(|state| state.depth = state.depth.saturating_add(1));\n    }\n\n    fn on_exit(&self, _: &Id, _: Context<'_, S>) {\n        self.update_state(|state| state.depth = state.depth.saturating_sub(1));\n    }\n}\n"
  },
  {
    "path": "core/lib/src/trace/subscriber/request_id.rs",
    "content": "use std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::thread::ThreadId;\nuse std::cell::Cell;\n\nuse tracing::Subscriber;\nuse tracing::span::{Attributes, Id};\nuse tracing_subscriber::{layer::Context, Layer};\nuse tracing_subscriber::registry::{LookupSpan, SpanRef};\n\npub struct RequestIdLayer;\n\n#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]\npub struct RequestId(u128);\n\n#[derive(Default)]\npub struct IdentHasher(u128);\n\nimpl RequestId {\n    fn new() -> Self {\n        thread_local! {\n            pub static COUNTER: Cell<u64> = Cell::new(0);\n            pub static THREAD_ID: Cell<Option<ThreadId>> = Cell::new(None);\n        }\n\n        let thread_id = THREAD_ID.get().unwrap_or_else(|| {\n            let id = std::thread::current().id();\n            THREAD_ID.set(Some(id));\n            id\n        });\n\n        let local_id = COUNTER.get();\n        COUNTER.set(local_id.wrapping_add(1));\n\n        let mut hasher = IdentHasher::default();\n        thread_id.hash(&mut hasher);\n        local_id.hash(&mut hasher);\n        RequestId(hasher.0)\n    }\n\n    pub fn of<R: for<'a> LookupSpan<'a>>(span: &SpanRef<'_, R>) -> Option<Self> {\n        span.extensions().get::<Self>().copied()\n    }\n\n    pub fn current() -> Option<Self> {\n        RequestIdLayer::current()\n    }\n\n    fn short(&self) -> u32 {\n        let mut x = ((self.0 & (0xFFFFFFFF << 48)) >> 48) as u32;\n        x = (x ^ (x >> 16)).wrapping_mul(0x21f0aaad);\n        x = (x ^ (x >> 15)).wrapping_mul(0x735a2d97);\n        x = x ^ (x >> 15);\n        x\n    }\n\n    pub fn layer() -> RequestIdLayer {\n        RequestIdLayer\n    }\n}\n\nimpl RequestIdLayer {\n    thread_local! {\n        static CURRENT_REQUEST_ID: Cell<Option<RequestId>> = Cell::new(None);\n    }\n\n    pub fn current() -> Option<RequestId> {\n        Self::CURRENT_REQUEST_ID.get()\n    }\n}\n\nimpl<S: Subscriber + for<'a> LookupSpan<'a>> Layer<S> for RequestIdLayer {\n    fn on_new_span(&self, _: &Attributes<'_>, id: &Id, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"new_span: span does not exist\");\n        if span.name() == \"request\" {\n            span.extensions_mut().replace(RequestId::new());\n        }\n    }\n\n    fn on_enter(&self, id: &Id, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"enter: span does not exist\");\n        if span.name() == \"request\" {\n            Self::CURRENT_REQUEST_ID.set(RequestId::of(&span));\n        }\n    }\n\n    fn on_exit(&self, id: &Id, ctxt: Context<'_, S>) {\n        let span = ctxt.span(id).expect(\"enter: span does not exist\");\n        if span.name() == \"request\" {\n            Self::CURRENT_REQUEST_ID.set(None);\n        }\n    }\n}\n\nimpl fmt::Display for RequestId {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Display::fmt(&self.short(), f)\n    }\n}\n\nimpl fmt::LowerHex for RequestId {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::LowerHex::fmt(&self.short(), f)\n    }\n}\n\nimpl fmt::UpperHex for RequestId {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::UpperHex::fmt(&self.short(), f)\n    }\n}\n\nimpl Hasher for IdentHasher {\n    fn finish(&self) -> u64 {\n        self.0 as u64\n    }\n\n    fn write(&mut self, bytes: &[u8]) {\n        for &byte in bytes {\n            self.0 = (self.0 << 8) | (byte as u128);\n        }\n    }\n\n    fn write_u64(&mut self, i: u64) {\n        // https://github.com/skeeto/hash-prospector\n        fn shuffle(mut x: u64) -> u64 {\n            x = x.wrapping_add(1);\n            x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);\n            x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);\n            x = x ^ (x >> 31);\n            x\n        }\n\n        self.0 = (self.0 << 64) | shuffle(i) as u128;\n    }\n}\n"
  },
  {
    "path": "core/lib/src/trace/subscriber/visit.rs",
    "content": "use std::fmt;\n\nuse tinyvec::TinyVec;\nuse tracing::field::{Field, Visit};\nuse tracing_subscriber::field::RecordFields;\n\nuse crate::util::Formatter;\n\npub trait RecordDisplay: RecordFields {\n    fn find_map_display<T, F: Fn(&dyn fmt::Display) -> T>(&self, name: &str, f: F) -> Option<T>;\n    fn record_display<F: FnMut(&Field, &dyn fmt::Display)>(&self, f: F);\n}\n\n#[derive(Debug)]\npub struct Data {\n    // start: Instant,\n    map: TinyVec<[(&'static str, String); 3]>,\n}\n\nimpl Data {\n    pub fn new<T: RecordFields>(attrs: T) -> Self {\n        let mut data = Data {\n            // start: Instant::now(),\n            map: TinyVec::new(),\n        };\n\n        attrs.record(&mut data);\n        data\n    }\n\n    pub fn get(&self, key: &str) -> Option<&str> {\n        self.map.iter()\n            .find(|(k, _)| k == &key)\n            .map(|(_, v)| v.as_str())\n    }\n}\n\nimpl std::ops::Index<&str> for Data {\n    type Output = str;\n\n    fn index(&self, index: &str) -> &Self::Output {\n        self.get(index).unwrap_or(\"[internal error: missing key]\")\n    }\n}\n\nimpl Visit for Data {\n    fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {\n        self.map.push((field.name(), format!(\"{:?}\", value)));\n    }\n\n    fn record_str(&mut self, field: &Field, value: &str) {\n        self.map.push((field.name(), value.into()));\n    }\n}\n\nimpl<T: RecordFields> RecordDisplay for T {\n    fn find_map_display<V, F: Fn(&dyn fmt::Display) -> V>(&self, name: &str, f: F) -> Option<V> {\n        let mut value = None;\n        self.record_display(|field, item| if field.name() == name { value = Some(f(item)); });\n        value\n    }\n\n    fn record_display<F: FnMut(&Field, &dyn fmt::Display)>(&self, f: F) {\n        struct DisplayVisit<F>(F);\n\n        impl<F: FnMut(&Field, &dyn fmt::Display)> Visit for DisplayVisit<F> {\n            fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {\n                (self.0)(field, &Formatter(|f| value.fmt(f)));\n            }\n\n            fn record_str(&mut self, field: &Field, value: &str) {\n                (self.0)(field, &value)\n            }\n        }\n\n        self.record(&mut DisplayVisit(f));\n    }\n}\n"
  },
  {
    "path": "core/lib/src/trace/traceable.rs",
    "content": "use std::error::Error as StdError;\n\nuse crate::request::ConnectionMeta;\nuse crate::sentinel::Sentry;\nuse crate::util::Formatter;\nuse crate::{route, Catcher, Config, Error, Request, Response, Route};\nuse crate::error::ErrorKind;\n\nuse figment::Figment;\nuse rocket::http::Header;\nuse tracing::Level;\n\npub trait Trace {\n    fn trace(&self, level: Level);\n\n    #[inline(always)] fn trace_info(&self) { self.trace(Level::INFO) }\n    #[inline(always)] fn trace_warn(&self) { self.trace(Level::WARN) }\n    #[inline(always)] fn trace_error(&self) { self.trace(Level::ERROR) }\n    #[inline(always)] fn trace_debug(&self) { self.trace(Level::DEBUG) }\n    #[inline(always)] fn trace_trace(&self) { self.trace(Level::TRACE) }\n}\n\npub trait TraceAll: Sized {\n    fn trace_all(self, level: Level);\n\n    #[inline(always)] fn trace_all_info(self) { self.trace_all(Level::INFO) }\n    #[inline(always)] fn trace_all_warn(self) { self.trace_all(Level::WARN) }\n    #[inline(always)] fn trace_all_error(self) { self.trace_all(Level::ERROR) }\n    #[inline(always)] fn trace_all_debug(self) { self.trace_all(Level::DEBUG) }\n    #[inline(always)] fn trace_all_trace(self) { self.trace_all(Level::TRACE) }\n}\n\nimpl<T: Trace, I: IntoIterator<Item = T>> TraceAll for I {\n    fn trace_all(self, level: Level) {\n        self.into_iter().for_each(|i| i.trace(level))\n    }\n}\n\nimpl<T: Trace> Trace for &T {\n    #[inline(always)]\n    fn trace(&self, level: Level) {\n        T::trace(self, level)\n    }\n}\n\nimpl Trace for Figment {\n    fn trace(&self, level: Level) {\n        for param in Config::PARAMETERS {\n            if let Some(source) = self.find_metadata(param) {\n                if param.contains(\"secret\") {\n                    continue;\n                }\n\n                event! { level, \"figment\",\n                    param,\n                    %source.name,\n                    source.source = source.source.as_ref().map(display),\n                    value = self.find_value(param).ok().map(debug),\n                }\n            }\n        }\n\n        // Check for now deprecated config values.\n        for (key, replacement) in Config::DEPRECATED_KEYS {\n            if let Some(source) = self.find_metadata(key) {\n                event! { Level::WARN, \"deprecated\",\n                    key,\n                    replacement,\n                    %source.name,\n                    source.source = source.source.as_ref().map(display),\n                    \"config key `{key}` is deprecated and has no meaning\"\n                }\n            }\n        }\n    }\n}\n\nimpl Trace for Config {\n    fn trace(&self, level: Level) {\n        event! { level, \"config\",\n            http2 = cfg!(feature = \"http2\"),\n            log_level = self.log_level.map(|l| l.as_str()),\n            log_format = ?self.log_format,\n            cli_colors = %self.cli_colors,\n            workers = self.workers,\n            max_blocking = self.max_blocking,\n            ident = %self.ident,\n            ip_header = self.ip_header.as_ref().map(|s| s.as_str()),\n            proxy_proto_header = self.proxy_proto_header.as_ref().map(|s| s.as_str()),\n            limits = %Formatter(|f| f.debug_map()\n                .entries(self.limits.limits.iter().map(|(k, v)| (k.as_str(), display(v))))\n                .finish()),\n            temp_dir = %self.temp_dir.relative().display(),\n            keep_alive = (self.keep_alive != 0).then_some(self.keep_alive),\n            shutdown.ctrlc = self.shutdown.ctrlc,\n            shutdown.signals = %{\n                #[cfg(not(unix))] {\n                    \"disabled (not unix)\"\n                }\n\n                #[cfg(unix)] {\n                    Formatter(|f| f.debug_set()\n                        .entries(self.shutdown.signals.iter().map(|s| s.as_str()))\n                        .finish())\n                }\n            },\n                shutdown.grace = self.shutdown.grace,\n                shutdown.mercy = self.shutdown.mercy,\n                shutdown.force = self.shutdown.force,\n        }\n\n        #[cfg(feature = \"secrets\")] {\n            if !self.secret_key.is_provided() {\n                warn! {\n                    name: \"volatile_secret_key\",\n                    \"secrets enabled without configuring a stable `secret_key`\\n\\\n                    private/signed cookies will become unreadable after restarting\\n\\\n                    disable the `secrets` feature or configure a `secret_key`\\n\\\n                    this becomes a hard error in non-debug profiles\",\n                }\n            }\n\n            let secret_key_is_known = Config::KNOWN_SECRET_KEYS.iter().any(|&key_str| {\n                let value = figment::value::Value::from(key_str);\n                self.secret_key == value.deserialize().expect(\"known key is valid\")\n            });\n\n            if secret_key_is_known {\n                warn! {\n                    name: \"insecure_secret_key\",\n                    \"The configured `secret_key` is exposed and insecure. \\\n                    The configured key is publicly published and thus insecure. \\\n                    Try generating a new key with `head -c64 /dev/urandom | base64`.\"\n                }\n            }\n        }\n    }\n}\n\nimpl Trace for Route {\n    fn trace(&self, level: Level) {\n        event! { level, \"route\",\n            name = self.name.as_ref().map(|n| &**n),\n            rank = self.rank,\n            method = %Formatter(|f| match self.method {\n                Some(method) => write!(f, \"{}\", method),\n                None => write!(f, \"[any]\"),\n            }),\n            uri = %self.uri,\n            uri.base = %self.uri.base(),\n            uri.unmounted = %self.uri.unmounted(),\n            format = self.format.as_ref().map(display),\n            location = self.location.as_ref()\n                .map(|(file, line, _)| Formatter(move |f| write!(f, \"{file}:{line}\")))\n                .map(display),\n        }\n\n        event! { Level::DEBUG, \"sentinels\",\n            route = self.name.as_ref().map(|n| &**n),\n            sentinels = %Formatter(|f| {\n                f.debug_set()\n                    .entries(self.sentinels.iter().filter(|s| s.specialized).map(|s| s.type_name))\n                    .finish()\n            })\n        }\n    }\n}\n\nimpl Trace for Catcher {\n    fn trace(&self, level: Level) {\n        event! { level, \"catcher\",\n            name = self.name.as_ref().map(|n| &**n),\n            code = %Formatter(|f| match self.code {\n                Some(code) => write!(f, \"{}\", code),\n                None => write!(f, \"default\"),\n            }),\n            rank = self.rank,\n            uri.base = %self.base(),\n            location = self.location.as_ref()\n                .map(|(file, line, _)| Formatter(move |f| write!(f, \"{file}:{line}\")))\n                .map(display),\n        }\n    }\n}\n\nimpl Trace for &dyn crate::fairing::Fairing {\n    fn trace(&self, level: Level) {\n        self.info().trace(level)\n    }\n}\n\nimpl Trace for crate::fairing::Info {\n    fn trace(&self, level: Level) {\n        event!(level, \"fairing\", name = self.name, kind = %self.kind)\n    }\n}\n\nimpl Trace for figment::error::Kind {\n    fn trace(&self, _: Level) {\n        use figment::error::{OneOf as V, Kind::*};\n\n        match self {\n            Message(message) => error!(message),\n            InvalidType(actual, expected) => error!(%actual, expected, \"invalid type\"),\n            InvalidValue(actual, expected) => error!(%actual, expected, \"invalid value\"),\n            InvalidLength(actual, expected) => error!(%actual, expected, \"invalid length\"),\n            UnknownVariant(actual, v) => error!(actual, expected = %V(v), \"unknown variant\"),\n            UnknownField(actual, v) => error!(actual, expected = %V(v), \"unknown field\"),\n            UnsupportedKey(actual, v) => error!(%actual, expected = &**v, \"unsupported key\"),\n            MissingField(value) => error!(value = &**value, \"missing field\"),\n            DuplicateField(value) => error!(value, \"duplicate field\"),\n            ISizeOutOfRange(value) => error!(value, \"out of range signed integer\"),\n            USizeOutOfRange(value) => error!(value, \"out of range unsigned integer\"),\n            Unsupported(value) => error!(%value, \"unsupported type\"),\n        }\n    }\n}\n\nimpl Trace for figment::Error {\n    fn trace(&self, _: Level) {\n        for e in self.clone() {\n            span_error!(\"config\",\n                key = (!e.path.is_empty()).then_some(&e.path).and_then(|path| {\n                    let (profile, metadata) = (e.profile.as_ref()?, e.metadata.as_ref()?);\n                    Some(metadata.interpolate(profile, path))\n                }),\n                source.name = e.metadata.as_ref().map(|m| &*m.name),\n                source.source = e.metadata.as_ref().and_then(|m| m.source.as_ref()).map(display)\n                => e.kind.trace_error());\n        }\n    }\n}\n\nimpl Trace for Header<'_> {\n    fn trace(&self, level: Level) {\n        event!(level, \"header\", name = self.name().as_str(), value = self.value());\n    }\n}\n\nimpl Trace for route::Outcome<'_> {\n    fn trace(&self, level: Level) {\n        event!(level, \"outcome\",\n            outcome = match self {\n                Self::Success(..) => \"success\",\n                Self::Error(..) => \"error\",\n                Self::Forward(..) => \"forward\",\n            },\n            status = match self {\n                Self::Success(r) => r.status().code,\n                Self::Error(s) => s.code,\n                Self::Forward((_, s)) => s.code,\n            },\n        )\n    }\n}\n\nimpl Trace for Response<'_> {\n    fn trace(&self, level: Level) {\n        event!(level, \"response\", status = self.status().code);\n    }\n}\n\nimpl Trace for Error {\n    fn trace(&self, level: Level) {\n        self.kind.trace(level);\n    }\n}\n\nimpl Trace for Sentry {\n    fn trace(&self, level: Level) {\n        let (file, line, col) = self.location;\n        event!(level, \"sentry\",\n            type_name = self.type_name,\n            location = %Formatter(|f| write!(f, \"{file}:{line}:{col}\"))\n        );\n    }\n}\n\nimpl Trace for Request<'_> {\n    fn trace(&self, level: Level) {\n        event!(level, \"request\", method = %self.method(), uri = %self.uri())\n    }\n}\n\nimpl Trace for ConnectionMeta {\n    fn trace(&self, level: Level) {\n        event!(level, \"connection\",\n            endpoint = self.peer_endpoint.as_ref().map(display),\n            certs = self.peer_certs.is_some(),\n        )\n    }\n}\n\nimpl Trace for ErrorKind {\n    fn trace(&self, level: Level) {\n        use ErrorKind::*;\n\n        fn try_downcast<'a, T>(error: &'a (dyn StdError + 'static)) -> Option<&'a T>\n            where T: StdError + 'static\n        {\n            error.downcast_ref().or_else(|| error.source()?.downcast_ref())\n        }\n\n        match self {\n            Bind(endpoint, error) => {\n                if let Some(e) = try_downcast::<crate::Error>(&**error) {\n                    e.trace(level);\n                } else if let Some(e) = try_downcast::<figment::Error>(&**error) {\n                    e.trace(level);\n                } else {\n                    event!(level, \"error::bind\",\n                        reason = %error,\n                        endpoint = endpoint.as_ref().map(display),\n                        \"binding to network interface failed\"\n                    )\n                }\n            }\n            Io(reason) => event!(level, \"error::io\", %reason, \"i/o error\"),\n            Config(error) => error.trace(level),\n            Collisions { routes, catchers }=> {\n                span!(level, \"collision\",\n                    route.pairs = routes.len(),\n                    catcher.pairs = catchers.len(),\n                    \"colliding items detected\"\n                ).in_scope(|| {\n                    for (a, b) in routes {\n                        span!(level, \"colliding route pair\").in_scope(|| {\n                            a.trace(level);\n                            b.trace(level);\n                        })\n                    }\n\n                    for (a, b) in catchers {\n                        span!(level, \"colliding catcher pair\").in_scope(|| {\n                            a.trace(level);\n                            b.trace(level);\n                        })\n                    }\n\n                    span!(Level::INFO, \"collisions can usually be resolved by ranking items\");\n                });\n            }\n            FailedFairings(fairings) => {\n                let span = span!(level, \"failed ignite fairings\", count = fairings.len());\n                span.in_scope(|| fairings.iter().trace_all(level));\n            },\n            SentinelAborts(sentries) => {\n                let span = span!(level, \"sentries\", \"sentry launch abort\");\n                span.in_scope(|| sentries.iter().trace_all(level));\n            }\n            InsecureSecretKey(profile) => event!(level, \"insecure_key\", %profile,\n                \"secrets enabled in a non-debug profile without a stable `secret_key`\\n\\\n                disable the `secrets` feature or configure a `secret_key`\"\n            ),\n            Liftoff(_, reason) => event!(level, \"panic\", %reason, \"liftoff fairing failed\"),\n            Shutdown(_) => event!(level, \"shutdown\", \"shutdown failed\"),\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/src/util/chain.rs",
    "content": "use std::io;\nuse std::task::{Poll, Context};\nuse std::pin::Pin;\n\nuse pin_project_lite::pin_project;\nuse tokio::io::{AsyncRead, ReadBuf};\n\npin_project! {\n    /// Stream for the [`chain`](super::AsyncReadExt::chain) method.\n    #[must_use = \"streams do nothing unless polled\"]\n    pub struct Chain<T, U> {\n        #[pin]\n        first: Option<T>,\n        #[pin]\n        second: U,\n    }\n}\n\nimpl<T, U> Chain<T, U> {\n    pub(crate) fn new(first: T, second: U) -> Self {\n        Self { first: Some(first), second }\n    }\n}\n\nimpl<T: AsyncRead, U: AsyncRead> Chain<T, U> {\n    /// Gets references to the underlying readers in this `Chain`.\n    pub fn get_ref(&self) -> (Option<&T>, &U) {\n        (self.first.as_ref(), &self.second)\n    }\n}\n\nimpl<T: AsyncRead, U: AsyncRead> AsyncRead for Chain<T, U> {\n    fn poll_read(\n        mut self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n        buf: &mut ReadBuf<'_>,\n    ) -> Poll<io::Result<()>> {\n        let me = self.as_mut().project();\n        if let Some(first) = me.first.as_pin_mut() {\n            let init_rem = buf.remaining();\n            futures::ready!(first.poll_read(cx, buf))?;\n            if buf.remaining() == init_rem {\n                self.as_mut().project().first.set(None);\n            } else {\n                return Poll::Ready(Ok(()));\n            }\n        }\n\n        let me = self.as_mut().project();\n        me.second.poll_read(cx, buf)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/util/join.rs",
    "content": "use std::pin::Pin;\nuse std::task::{Poll, Context};\n\nuse pin_project_lite::pin_project;\n\nuse futures::stream::Stream;\nuse futures::ready;\n\n/// Join two streams, `a` and `b`, into a new `Join` stream that returns items\n/// from both streams, biased to `a`, until `a` finishes. The joined stream\n/// completes when `a` completes, irrespective of `b`. If `b` stops producing\n/// values, then the joined stream acts exactly like a fused `a`.\n///\n/// Values are biased to those of `a`: if `a` provides a value, it is always\n/// emitted before a value provided by `b`. In other words, values from `b` are\n/// emitted when and only when `a` is not producing a value.\npub fn join<A: Stream, B: Stream>(a: A, b: B) -> Join<A, B> {\n    Join { a, b: Some(b), done: false, }\n}\n\npin_project! {\n    /// Stream returned by [`join`].\n    pub struct Join<T, U> {\n        #[pin]\n        a: T,\n        #[pin]\n        b: Option<U>,\n        // Set when `a` returns `None`.\n        done: bool,\n    }\n}\n\nimpl<T, U> Stream for Join<T, U>\n    where T: Stream,\n          U: Stream<Item = T::Item>,\n{\n    type Item = T::Item;\n\n    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T::Item>> {\n        if self.done {\n            return Poll::Ready(None);\n        }\n\n        let me = self.as_mut().project();\n        match me.a.poll_next(cx) {\n            Poll::Ready(opt) => {\n                *me.done = opt.is_none();\n                Poll::Ready(opt)\n            },\n            Poll::Pending => match me.b.as_pin_mut() {\n                None => Poll::Pending,\n                Some(b) => match ready!(b.poll_next(cx)) {\n                    Some(value) => Poll::Ready(Some(value)),\n                    None => {\n                        self.as_mut().project().b.set(None);\n                        Poll::Pending\n                    }\n                }\n            }\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let (left_low, left_high) = self.a.size_hint();\n        let (right_low, right_high) = self.b.as_ref()\n            .map(|b| b.size_hint())\n            .unwrap_or_default();\n\n        let low = left_low.saturating_add(right_low);\n        let high = match (left_high, right_high) {\n            (Some(h1), Some(h2)) => h1.checked_add(h2),\n            _ => None,\n        };\n\n        (low, high)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/util/mod.rs",
    "content": "mod chain;\nmod reader_stream;\nmod join;\n\n#[cfg(unix)]\npub mod unix;\n\npub use chain::Chain;\npub use reader_stream::ReaderStream;\npub use join::join;\n\n#[track_caller]\npub fn spawn_inspect<E, F, Fut>(or: F, future: Fut)\n    where F: FnOnce(&E) + Send + Sync + 'static,\n          E: Send + Sync + 'static,\n        Fut: std::future::Future<Output = Result<(), E>> + Send + 'static,\n{\n    use futures::TryFutureExt;\n    tokio::spawn(future.inspect_err(or));\n}\n\nuse std::{fmt, io};\nuse std::pin::pin;\nuse std::future::Future;\nuse either::Either;\nuse futures::future;\n\npub trait FutureExt: Future + Sized {\n    /// Await `self` or `other`, whichever finishes first.\n    async fn race<B: Future>(self, other: B) -> Either<Self::Output, B::Output> {\n        match future::select(pin!(self), pin!(other)).await {\n            future::Either::Left((v, _)) => Either::Left(v),\n            future::Either::Right((v, _)) => Either::Right(v),\n        }\n    }\n\n    async fn race_io<T, K: Future>(self, trigger: K) -> io::Result<T>\n        where Self: Future<Output = io::Result<T>>\n    {\n        match future::select(pin!(self), pin!(trigger)).await {\n            future::Either::Left((v, _)) => v,\n            future::Either::Right((_, _)) => Err(io::Error::other(\"i/o terminated\")),\n        }\n    }\n}\n\nimpl<F: Future + Sized> FutureExt for F { }\n\npub struct Formatter<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result>(pub F);\n\nimpl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for Formatter<F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        (self.0)(f)\n    }\n}\n\nimpl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Display for Formatter<F> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        (self.0)(f)\n    }\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! for_both {\n    ($value:expr, $pattern:pat => $result:expr) => {\n        match $value {\n            tokio_util::either::Either::Left($pattern) => $result,\n            tokio_util::either::Either::Right($pattern) => $result,\n        }\n    };\n}\n\npub use for_both;\n"
  },
  {
    "path": "core/lib/src/util/reader_stream.rs",
    "content": "use std::pin::Pin;\nuse std::task::{Context, Poll};\n\nuse bytes::{Bytes, BytesMut};\nuse futures::stream::Stream;\nuse pin_project_lite::pin_project;\nuse tokio::io::AsyncRead;\n\npin_project! {\n    /// Convert an [`AsyncRead`] into a [`Stream`] of byte chunks.\n    ///\n    /// This stream is fused. It performs the inverse operation of\n    /// [`StreamReader`].\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// # #[tokio::main]\n    /// # async fn main() -> std::io::Result<()> {\n    /// use tokio_stream::StreamExt;\n    /// use tokio_util::io::ReaderStream;\n    ///\n    /// // Create a stream of data.\n    /// let data = b\"hello, world!\";\n    /// let mut stream = ReaderStream::new(&data[..]);\n    ///\n    /// // Read all of the chunks into a vector.\n    /// let mut stream_contents = Vec::new();\n    /// while let Some(chunk) = stream.next().await {\n    ///    stream_contents.extend_from_slice(&chunk?);\n    /// }\n    ///\n    /// // Once the chunks are concatenated, we should have the\n    /// // original data.\n    /// assert_eq!(stream_contents, data);\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// [`AsyncRead`]: tokio::io::AsyncRead\n    /// [`StreamReader`]: crate::io::StreamReader\n    /// [`Stream`]: futures_core::Stream\n    #[derive(Debug)]\n    pub struct ReaderStream<R> {\n        // Reader itself.\n        //\n        // This value is `None` if the stream has terminated.\n        #[pin]\n        reader: R,\n        // Working buffer, used to optimize allocations.\n        buf: BytesMut,\n        capacity: usize,\n        done: bool,\n    }\n}\n\nimpl<R: AsyncRead> ReaderStream<R> {\n    /// Convert an [`AsyncRead`] into a [`Stream`] with item type\n    /// `Result<Bytes, std::io::Error>`,\n    /// with a specific read buffer initial capacity.\n    ///\n    /// [`AsyncRead`]: tokio::io::AsyncRead\n    /// [`Stream`]: futures_core::Stream\n    pub fn with_capacity(reader: R, capacity: usize) -> Self {\n        ReaderStream {\n            reader,\n            buf: BytesMut::with_capacity(capacity),\n            capacity,\n            done: false,\n        }\n    }\n}\n\nimpl<R: AsyncRead> Stream for ReaderStream<R> {\n    type Item = std::io::Result<Bytes>;\n\n    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {\n        use tokio_util::io::poll_read_buf;\n\n        let mut this = self.as_mut().project();\n\n        if *this.done {\n            return Poll::Ready(None);\n        }\n\n        if this.buf.capacity() == 0 {\n            this.buf.reserve(*this.capacity);\n        }\n\n        let reader = this.reader;\n        match poll_read_buf(reader, cx, &mut this.buf) {\n            Poll::Pending => Poll::Pending,\n            Poll::Ready(Err(err)) => {\n                *this.done = true;\n                Poll::Ready(Some(Err(err)))\n            }\n            Poll::Ready(Ok(0)) => {\n                *this.done = true;\n                Poll::Ready(None)\n            }\n            Poll::Ready(Ok(_)) => {\n                let chunk = this.buf.split();\n                Poll::Ready(Some(Ok(chunk.freeze())))\n            }\n        }\n    }\n\n    // fn size_hint(&self) -> (usize, Option<usize>) {\n    //     self.reader.size_hint()\n    // }\n}\n\nimpl<R: AsyncRead> hyper::body::Body for ReaderStream<R> {\n    type Data = bytes::Bytes;\n\n    type Error = std::io::Error;\n\n    fn poll_frame(\n        self: Pin<&mut Self>,\n        cx: &mut Context<'_>,\n    ) -> Poll<Option<Result<hyper::body::Frame<Self::Data>, Self::Error>>> {\n        self.poll_next(cx).map_ok(hyper::body::Frame::data)\n    }\n}\n"
  },
  {
    "path": "core/lib/src/util/unix.rs",
    "content": "use std::io;\nuse std::os::fd::AsRawFd;\n\npub fn lock_exclusive_nonblocking<T: AsRawFd>(file: &T) -> io::Result<()> {\n    let raw_fd = file.as_raw_fd();\n    let res = unsafe {\n        libc::flock(raw_fd, libc::LOCK_EX | libc::LOCK_NB)\n    };\n\n    match res {\n        0 => Ok(()),\n        _ => Err(io::Error::last_os_error()),\n    }\n}\n\npub fn unlock_nonblocking<T: AsRawFd>(file: &T) -> io::Result<()> {\n    let res = unsafe {\n        libc::flock(file.as_raw_fd(), libc::LOCK_UN | libc::LOCK_NB)\n    };\n\n    match res {\n        0 => Ok(()),\n        _ => Err(io::Error::last_os_error()),\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/absolute-uris-okay-issue-443.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::response::Redirect;\n\n#[get(\"/http\")]\nfn http() -> Redirect {\n    Redirect::to(uri!(\"http://rocket.rs\"))\n}\n\n#[get(\"/rocket\")]\nfn redirect() -> Redirect {\n    Redirect::to(\"https://rocket.rs:80\")\n}\n\nmod test_absolute_uris_okay {\n    use super::*;\n    use rocket::local::blocking::Client;\n\n    #[test]\n    fn redirect_works() {\n        let client = Client::debug_with(routes![http, redirect]).unwrap();\n\n        let response = client.get(uri!(http)).dispatch();\n        let location = response.headers().get_one(\"Location\");\n        assert_eq!(location, Some(\"http://rocket.rs\"));\n\n        let response = client.get(uri!(redirect)).dispatch();\n        let location = response.headers().get_one(\"Location\");\n        assert_eq!(location, Some(\"https://rocket.rs:80\"));\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/adhoc-uri-normalizer.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse std::path::PathBuf;\n\nuse rocket::local::blocking::Client;\nuse rocket::fairing::AdHoc;\n\n#[get(\"/foo\")]\nfn foo() -> &'static str { \"foo\" }\n\n#[get(\"/bar\")]\nfn not_bar() -> &'static str { \"not_bar\" }\n\n#[get(\"/bar/\")]\nfn bar() -> &'static str { \"bar\" }\n\n#[get(\"/foo/<_>/<_baz..>\")]\nfn baz(_baz: PathBuf) -> &'static str { \"baz\" }\n\n#[get(\"/doggy/<_>/<_baz..>?doggy\")]\nfn doggy(_baz: PathBuf) -> &'static str { \"doggy\" }\n\n#[get(\"/<_..>\")]\nfn rest() -> &'static str { \"rest\" }\n\nmacro_rules! assert_response {\n    ($client:ident : $path:expr => $response:expr) => {\n        let response = $client.get($path).dispatch().into_string().unwrap();\n        assert_eq!(response, $response, \"\\nGET {}: got {} but expected {}\",\n            $path, response, $response);\n    };\n}\n\n#[test]\nfn test_adhoc_normalizer_works_as_expected () {\n    let rocket = rocket::build()\n        .mount(\"/\", routes![foo, bar, not_bar, baz, doggy])\n        .mount(\"/base\", routes![foo, bar, not_bar, baz, doggy, rest])\n        .attach(AdHoc::uri_normalizer());\n\n    let client = Client::debug(rocket).unwrap();\n\n    assert_response!(client: \"/foo\" => \"foo\");\n    assert_response!(client: \"/foo/\" => \"foo\");\n    assert_response!(client: \"/bar/\" => \"bar\");\n    assert_response!(client: \"/bar\" => \"not_bar\");\n    assert_response!(client: \"/foo/bar\" => \"baz\");\n    assert_response!(client: \"/doggy/bar?doggy\" => \"doggy\");\n    assert_response!(client: \"/foo/bar/\" => \"baz\");\n    assert_response!(client: \"/foo/bar/baz\" => \"baz\");\n    assert_response!(client: \"/base/foo/\" => \"foo\");\n    assert_response!(client: \"/base/foo\" => \"foo\");\n    assert_response!(client: \"/base/bar/\" => \"bar\");\n    assert_response!(client: \"/base/bar\" => \"not_bar\");\n    assert_response!(client: \"/base/foo/bar\" => \"baz\");\n    assert_response!(client: \"/doggy/foo/bar?doggy\" => \"doggy\");\n    assert_response!(client: \"/base/foo/bar/\" => \"baz\");\n    assert_response!(client: \"/base/foo/bar/baz\" => \"baz\");\n\n    assert_response!(client: \"/base/cat\" => \"rest\");\n    assert_response!(client: \"/base/cat/\" => \"rest\");\n    assert_response!(client: \"/base/cat/dog\" => \"rest\");\n}\n"
  },
  {
    "path": "core/lib/tests/byte-slices-form-field-issue-2148.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse std::str::from_utf8;\n\nuse rocket::form::Form;\nuse rocket::http::{ContentType, Status};\nuse rocket::local::blocking::Client;\n\n#[derive(FromForm)]\nstruct DataForm<'r> {\n    foo: &'r [u8],\n    bar: &'r [u8],\n}\n\n#[post(\"/\", data = \"<form>\")]\nfn form(form: Form<DataForm<'_>>) -> String {\n    from_utf8(form.foo).unwrap().to_string() + from_utf8(form.bar).unwrap()\n}\n\n#[test]\nfn test_from_form_fields_of_multipart_files_into_byte_slices() {\n    let body = &[\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"foo\"; filename=\"foo.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"start>\",\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"foo\"; filename=\"foo2.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"second-start...\",\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"bar\"; filename=\"bar.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"<finish\",\n        \"--X-BOUNDARY--\",\n        \"\",\n    ].join(\"\\r\\n\");\n\n    let client = Client::debug_with(routes![form]).unwrap();\n    let response = client.post(\"/\")\n        .header(\"multipart/form-data; boundary=X-BOUNDARY\".parse::<ContentType>().unwrap())\n        .body(body)\n        .dispatch();\n\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.into_string().unwrap(), \"start><finish\");\n}\n\n#[test]\nfn test_from_form_fields_of_values_into_byte_slices() {\n    let client = Client::debug_with(routes![form]).unwrap();\n    let response = client.post(\"/\")\n        .header(ContentType::Form)\n        .body(format!(\"bar={}&foo={}\", \"...finish\", \"start...\"))\n        .dispatch();\n\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.into_string().unwrap(), \"start......finish\");\n}\n"
  },
  {
    "path": "core/lib/tests/can-correct-bad-local-uri.rs",
    "content": "use rocket::http::uri::Origin;\nuse rocket::local::blocking::Client;\n\n#[test]\nfn can_correct_bad_local_uri() {\n    #[rocket::get(\"/\")] fn f() {}\n\n    let client = Client::debug_with(rocket::routes![f]).unwrap();\n    let mut req = client.get(\"this is a bad URI\");\n    req.set_uri(Origin::parse(\"/\").unwrap());\n\n    assert_eq!(req.uri(), \"/\");\n    assert!(req.dispatch().status().class().is_success());\n\n    let req = client.get(\"this is a bad URI\");\n    assert!(req.dispatch().status().class().is_client_error());\n}\n"
  },
  {
    "path": "core/lib/tests/can-launch-tls.rs",
    "content": "#![cfg(feature = \"tls\")]\n\nuse rocket::fs::relative;\nuse rocket::local::asynchronous::Client;\nuse rocket::tls::{TlsConfig, CipherSuite};\nuse rocket::figment::providers::Serialized;\n\n#[rocket::async_test]\nasync fn can_launch_tls() {\n    let cert_path = relative!(\"examples/tls/private/rsa_sha256_cert.pem\");\n    let key_path = relative!(\"examples/tls/private/rsa_sha256_key.pem\");\n\n    let tls = TlsConfig::from_paths(cert_path, key_path)\n        .with_ciphers([\n            CipherSuite::TLS_AES_128_GCM_SHA256,\n            CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\n        ]);\n\n    let config = rocket::Config::figment().merge(Serialized::defaults(tls));\n    let client = Client::debug(rocket::custom(config)).await.unwrap();\n    client.rocket().shutdown().notify();\n    client.rocket().shutdown().await;\n}\n"
  },
  {
    "path": "core/lib/tests/catcher-cookies-1213.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::request::Request;\nuse rocket::http::CookieJar;\n\n#[catch(404)]\nfn not_found(request: &Request<'_>) -> &'static str {\n    request.cookies().add((\"not_found\", \"404\"));\n    \"404 - Not Found\"\n}\n\n#[get(\"/\")]\nfn index(cookies: &CookieJar<'_>) -> &'static str {\n    cookies.add((\"index\", \"hi\"));\n    \"Hello, world!\"\n}\n\nmod tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n    use rocket::fairing::AdHoc;\n\n    #[test]\n    fn error_catcher_sets_cookies() {\n        let rocket = rocket::build()\n            .mount(\"/\", routes![index])\n            .register(\"/\", catchers![not_found])\n            .attach(AdHoc::on_request(\"Add Cookie\", |req, _| Box::pin(async move {\n                req.cookies().add((\"fairing\", \"woo\"));\n            })));\n\n        let client = Client::debug(rocket).unwrap();\n\n        // Check that the index returns the `index` and `fairing` cookie.\n        let response = client.get(\"/\").dispatch();\n        let cookies = response.cookies();\n        assert_eq!(cookies.iter().count(), 2);\n        assert_eq!(cookies.get(\"index\").unwrap().value(), \"hi\");\n        assert_eq!(cookies.get(\"fairing\").unwrap().value(), \"woo\");\n\n        // Check that the catcher returns only the `not_found` cookie.\n        let response = client.get(\"/not-existent\").dispatch();\n        let cookies = response.cookies();\n        assert_eq!(cookies.iter().count(), 1);\n        assert_eq!(cookies.get(\"not_found\").unwrap().value(), \"404\");\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/conditionally-set-server-header-996.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::http::Header;\n\n#[derive(Responder)]\nstruct HeaderOnly((), Header<'static>);\n\n#[get(\"/do_not_overwrite\")]\nfn do_not_overwrite() -> HeaderOnly {\n    HeaderOnly((), Header::new(\"Server\", \"Test\"))\n}\n\n#[get(\"/use_default\")]\nfn use_default() { }\n\nmod conditionally_set_server_header {\n    use super::*;\n    use rocket::local::blocking::Client;\n\n    #[test]\n    fn do_not_overwrite_server_header() {\n        let client = Client::debug_with(routes![do_not_overwrite, use_default]).unwrap();\n\n        let response = client.get(\"/do_not_overwrite\").dispatch();\n        let server = response.headers().get_one(\"Server\");\n        assert_eq!(server, Some(\"Test\"));\n\n        let response = client.get(\"/use_default\").dispatch();\n        let server = response.headers().get_one(\"Server\");\n        assert_eq!(server, Some(\"Rocket\"));\n\n        // Now with a special `Ident`.\n\n        let config = rocket::Config {\n            ident: rocket::config::Ident::try_new(\"My Special Server\").unwrap(),\n            ..rocket::Config::debug_default()\n        };\n\n        let rocket = rocket::custom(config)\n            .mount(\"/\", routes![do_not_overwrite, use_default]);\n\n        let client = Client::debug(rocket).unwrap();\n\n        let response = client.get(\"/do_not_overwrite\").dispatch();\n        let server = response.headers().get_one(\"Server\");\n        assert_eq!(server, Some(\"Test\"));\n\n        let response = client.get(\"/use_default\").dispatch();\n        let server = response.headers().get_one(\"Server\");\n        assert_eq!(server, Some(\"My Special Server\"));\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/config-proxy-proto-header.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[get(\"/\")]\nfn inspect_proto(proto: rocket::http::ProxyProto<'_>) -> String {\n    proto.to_string()\n}\n\nmod tests {\n    use rocket::{Rocket, Build, Route};\n    use rocket::http::{Header, Status};\n    use rocket::local::blocking::Client;\n    use rocket::figment::Figment;\n\n    fn routes() -> Vec<Route> {\n        routes![super::inspect_proto]\n    }\n\n    fn rocket_with_proto_header(header: Option<&'static str>) -> Rocket<Build> {\n        let mut config = rocket::Config::debug_default();\n        config.proxy_proto_header = header.map(|h| h.into());\n        rocket::custom(config).mount(\"/\", routes())\n    }\n\n    #[test]\n    fn check_proxy_proto_header_works() {\n        let client = Client::debug(rocket_with_proto_header(Some(\"X-Url-Scheme\"))).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Forwarded-Proto\", \"https\"))\n            .header(Header::new(\"X-Url-Scheme\", \"http\"))\n            .dispatch();\n\n        assert_eq!(response.into_string().unwrap(), \"http\");\n\n        let response = client.get(\"/\").header(Header::new(\"X-Url-Scheme\", \"https\")).dispatch();\n        assert_eq!(response.into_string().unwrap(), \"https\");\n\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.status(), Status::InternalServerError);\n    }\n\n    #[test]\n    fn check_proxy_proto_header_works_again() {\n        let client = Client::debug(rocket_with_proto_header(Some(\"x-url-scheme\"))).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Url-Scheme\", \"hTTpS\"))\n            .dispatch();\n\n        assert_eq!(response.into_string().unwrap(), \"https\");\n\n        let config = Figment::from(rocket::Config::debug_default())\n            .merge((\"proxy_proto_header\", \"x-url-scheme\"));\n\n        let client = Client::debug(rocket::custom(config).mount(\"/\", routes())).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-url-Scheme\", \"HTTPS\"))\n            .dispatch();\n\n        assert_eq!(response.into_string().unwrap(), \"https\");\n    }\n\n    #[test]\n    fn check_default_proxy_proto_header_works() {\n        let client = Client::debug_with(routes()).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Forwarded-Proto\", \"https\"))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::InternalServerError);\n    }\n\n    #[test]\n    fn check_no_proxy_proto_header_works() {\n        let client = Client::debug(rocket_with_proto_header(None)).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Forwarded-Proto\", \"https\"))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::InternalServerError);\n\n        let config =\n            Figment::from(rocket::Config::debug_default()).merge((\"proxy_proto_header\", false));\n\n        let client = Client::debug(rocket::custom(config).mount(\"/\", routes())).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Forwarded-Proto\", \"https\"))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::InternalServerError);\n\n        let config = Figment::from(rocket::Config::debug_default())\n            .merge((\"proxy_proto_header\", \"x-forwarded-proto\"));\n\n        let client = Client::debug(rocket::custom(config).mount(\"/\", routes())).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"x-Forwarded-Proto\", \"https\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"https\".into()));\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/config-real-ip-header.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[get(\"/\")]\nfn inspect_ip(ip: Option<std::net::IpAddr>) -> String {\n    ip.map(|ip| ip.to_string()).unwrap_or(\"<none>\".into())\n}\n\nmod tests {\n    use rocket::{Rocket, Build, Route};\n    use rocket::local::blocking::Client;\n    use rocket::figment::Figment;\n    use rocket::http::Header;\n\n    fn routes() -> Vec<Route> {\n        routes![super::inspect_ip]\n    }\n\n    fn rocket_with_custom_ip_header(header: Option<&'static str>) -> Rocket<Build> {\n        let mut config = rocket::Config::debug_default();\n        config.ip_header = header.map(|h| h.into());\n        rocket::custom(config).mount(\"/\", routes())\n    }\n\n    #[test]\n    fn check_real_ip_header_works() {\n        let client = Client::debug(rocket_with_custom_ip_header(Some(\"IP\"))).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Real-IP\", \"1.2.3.4\"))\n            .header(Header::new(\"IP\", \"8.8.8.8\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"8.8.8.8\".into()));\n\n        let response = client.get(\"/\")\n            .header(Header::new(\"IP\", \"1.1.1.1\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"1.1.1.1\".into()));\n\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.into_string(), Some(\"<none>\".into()));\n    }\n\n    #[test]\n    fn check_real_ip_header_works_again() {\n        let client = Client::debug(rocket_with_custom_ip_header(Some(\"x-forward-ip\"))).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Forward-IP\", \"1.2.3.4\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"1.2.3.4\".into()));\n\n        let config = Figment::from(rocket::Config::debug_default())\n            .merge((\"ip_header\", \"x-forward-ip\"));\n\n        let client = Client::debug(rocket::custom(config).mount(\"/\", routes())).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Forward-IP\", \"1.2.3.4\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"1.2.3.4\".into()));\n    }\n\n    #[test]\n    fn check_default_real_ip_header_works() {\n        let client = Client::debug_with(routes()).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Real-IP\", \"1.2.3.4\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"1.2.3.4\".into()));\n    }\n\n    #[test]\n    fn check_no_ip_header_works() {\n        let client = Client::debug(rocket_with_custom_ip_header(None)).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Real-IP\", \"1.2.3.4\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"<none>\".into()));\n\n        let config = Figment::from(rocket::Config::debug_default())\n            .merge((\"ip_header\", false));\n\n        let client = Client::debug(rocket::custom(config).mount(\"/\", routes())).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Real-IP\", \"1.2.3.4\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"<none>\".into()));\n\n        let config = Figment::from(rocket::Config::debug_default());\n        let client = Client::debug(rocket::custom(config).mount(\"/\", routes())).unwrap();\n        let response = client.get(\"/\")\n            .header(Header::new(\"X-Real-IP\", \"1.2.3.4\"))\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"1.2.3.4\".into()));\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/config-secret-key-1500.rs",
    "content": "#![cfg(feature = \"secrets\")]\n\nuse rocket::figment::Figment;\nuse rocket::config::{Config, SecretKey};\n\n#[test]\nfn secret_key_in_config_not_zero() {\n    let original_key = SecretKey::generate().expect(\"get key\");\n\n    let config = Config { secret_key: original_key.clone(), ..Default::default() };\n    let figment = Figment::from(config);\n    let figment_key: SecretKey = figment.extract_inner(\"secret_key\").unwrap();\n    assert_eq!(original_key, figment_key);\n}\n"
  },
  {
    "path": "core/lib/tests/content-length.rs",
    "content": "#[macro_use]\nextern crate rocket;\n\n#[get(\"/\")]\nfn index() -> String {\n    \"Hello, world!\".into()\n}\n\n#[test]\nfn content_length_header() {\n    let rocket = rocket::build().mount(\"/\", routes![index]);\n    let client = rocket::local::blocking::Client::debug(rocket).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert!(response.headers().get_one(\"Content-Length\").is_some());\n}\n"
  },
  {
    "path": "core/lib/tests/cookies-private.rs",
    "content": "#![cfg(feature = \"secrets\")]\n#![deny(warnings)]\n\nuse rocket::http::{Cookie, CookieJar, SameSite};\nuse rocket::{get, post, routes};\n\n#[post(\"/\")]\nfn cookie_add_private(jar: &CookieJar<'_>) {\n    let mut cookie_a = Cookie::new(\"a\", \"v1\");\n    jar.add(cookie_a.clone());\n    let mut cookie_b = Cookie::new(\"b\", \"v2\");\n    jar.add_private(cookie_b.clone());\n    jar.add((\"c\", \"v3\"));\n\n    // private: CookieJar::set_defaults(&mut cookie_a);\n    cookie_a.set_path(\"/\");\n    cookie_a.set_same_site(SameSite::Strict);\n    assert_eq!(jar.get_pending(cookie_a.name()), Some(cookie_a));\n\n    // private: CookieJar::set_private_defaults(&mut cookie_b);\n    cookie_b.set_path(\"/\");\n    cookie_b.set_same_site(SameSite::Strict);\n    cookie_b.set_http_only(true);\n    let expires = time::OffsetDateTime::now_utc() + time::Duration::weeks(1);\n    cookie_b.set_expires(expires);\n    let mut cookie_b_pending = jar\n        .get_pending(cookie_b.name())\n        .expect(\"cookie_b_pending None\");\n    cookie_b_pending.set_expires(expires);\n    assert_eq!(cookie_b_pending, cookie_b);\n}\n\n#[get(\"/\")]\nfn cookie_get_private(jar: &CookieJar<'_>) -> String {\n    let (a, b, c) = (jar.get(\"a\"), jar.get_private(\"b\"), jar.get(\"c\"));\n    assert_ne!(a, b.as_ref());\n    assert_ne!(a, c);\n    assert_ne!(b.as_ref(), c);\n    assert_eq!(b, jar.get_pending(\"b\"));\n\n    format!(\n        \"{}{}{}\",\n        a.unwrap().value(),\n        b.unwrap().value(),\n        c.unwrap().value()\n    )\n}\n\n/// For test if we got really a private cookie\n#[get(\"/oh-no\")]\nfn cookie_get(jar: &CookieJar<'_>) -> String {\n    let (a, b, c) = (jar.get(\"a\"), jar.get(\"b\"), jar.get(\"c\"));\n    assert_eq!(b.cloned(), jar.get_pending(\"b\"));\n\n    format!(\n        \"{}{}{}\",\n        a.unwrap().value(),\n        b.unwrap().value(),\n        c.unwrap().value()\n    )\n}\n\n#[cfg(test)]\nmod cookies_private_tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n    use rocket::{Build, Rocket};\n\n    fn rocket() -> Rocket<Build> {\n        rocket::build()\n            .mount(\"/\", routes![cookie_add_private, cookie_get, cookie_get_private])\n    }\n\n    #[test]\n    fn test_cookie_add_private() {\n        let client = Client::debug(rocket()).unwrap();\n        let response = client.post(\"/\").dispatch();\n        let cookies = response.cookies();\n        assert_eq!(cookies.iter().count(), 3);\n        assert_eq!(cookies.get(\"a\").unwrap().value(), \"v1\");\n        assert_eq!(cookies.get_private(\"b\").unwrap().value(), \"v2\");\n        assert_eq!(cookies.get_pending(\"b\").unwrap().value(), \"v2\");\n        assert_ne!(cookies.get(\"b\").unwrap().value(), \"v2\");\n        assert_eq!(cookies.get(\"c\").unwrap().value(), \"v3\");\n    }\n\n    #[test]\n    fn test_cookie_get_private() {\n        let client = Client::debug(rocket()).unwrap();\n        let response = client\n            .get(\"/\")\n            .cookie((\"a\", \"Cookie\"))\n            .private_cookie((\"b\", \" tastes \"))\n            .cookie((\"c\", \"good!\"))\n            .dispatch();\n\n        assert_eq!(response.into_string().unwrap(), \"Cookie tastes good!\");\n    }\n\n    /// Test if we got really a private cookie\n    #[test]\n    fn test_cookie_get_ohno() {\n        let client = Client::debug(rocket()).unwrap();\n        let response = client\n            .get(\"/oh-no\")\n            .cookie((\"a\", \"Cookie\"))\n            .private_cookie((\"b\", \" tastes \"))\n            .cookie((\"c\", \"good!\"))\n            .dispatch();\n\n        assert_ne!(response.into_string().unwrap(), \"Cookie tastes good!\");\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/derive-reexports.rs",
    "content": "use rocket::{get, routes};\nuse rocket::form::{FromForm, FromFormField};\nuse rocket::response::Responder;\n\n#[derive(FromFormField)]\nenum Thing {\n    A,\n    B,\n    C,\n}\n\nimpl std::fmt::Display for Thing {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match *self {\n            Thing::A => write!(f, \"a\"),\n            Thing::B => write!(f, \"b\"),\n            Thing::C => write!(f, \"c\"),\n        }\n    }\n}\n\n#[derive(FromForm)]\nstruct ThingForm {\n    thing: Thing,\n}\n\n#[derive(Responder)]\nstruct DerivedResponder {\n    data: String,\n}\n\n#[get(\"/\")]\nfn index() -> DerivedResponder {\n    DerivedResponder { data: \"hello\".to_string() }\n}\n\n#[get(\"/?<params..>\")]\nfn number(params: ThingForm) -> DerivedResponder {\n    DerivedResponder { data: params.thing.to_string() }\n}\n\n#[test]\nfn test_derive_reexports() {\n    use rocket::local::blocking::Client;\n\n    let client = Client::debug_with(routes![index, number]).unwrap();\n\n    let response = client.get(\"/\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"hello\");\n\n    let response = client.get(\"/?thing=b\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"b\");\n}\n"
  },
  {
    "path": "core/lib/tests/deserialize-limits-issue-2268.rs",
    "content": "use rocket::config::Config;\nuse rocket::data::Limits;\nuse rocket::figment::{providers::Serialized, Figment};\nuse ubyte::ToByteUnit;\n\n#[test]\nfn deserialize_mixed_case_limits_should_work() {\n    let figment = Figment::default()\n        .merge(Serialized::default(\"key1\", 1.kibibytes()))\n        .merge(Serialized::default(\"key5\", 5.kibibytes()))\n        .merge(Serialized::default(\"key3\", 3.kibibytes()))\n        .merge(Serialized::default(\"Key2\", 2.kibibytes()))\n        .merge(Serialized::default(\"Key4\", 4.kibibytes()))\n        .merge(Serialized::default(\"Key6\", 6.kibibytes()));\n\n    let limits: Limits = figment.extract().unwrap();\n    assert_eq!(limits.get(\"key1\"), Some(1.kibibytes()));\n    assert_eq!(limits.get(\"key2\"), Some(2.kibibytes()));\n    assert_eq!(limits.get(\"key3\"), Some(3.kibibytes()));\n    assert_eq!(limits.get(\"key4\"), Some(4.kibibytes()));\n    assert_eq!(limits.get(\"key5\"), Some(5.kibibytes()));\n    assert_eq!(limits.get(\"key6\"), Some(6.kibibytes()));\n}\n\n#[test]\nfn deserialize_extra_limits_in_config_should_work() {\n    let extra_limits = Limits::new().limit(\"Phactory\", 1.kibibytes());\n    let figment = Config::figment().merge((\"limits\", extra_limits));\n    let config = Config::from(figment);\n    assert_eq!(config.limits.get(\"Phactory\"), Some(1.kibibytes()));\n}\n"
  },
  {
    "path": "core/lib/tests/encoded-uris.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[get(\"/hello süper $?a&?&<value>\")]\nfn index(value: &str) -> &str {\n    value\n}\n\nmod encoded_uris {\n    use rocket::local::blocking::Client;\n\n    #[test]\n    fn can_route_to_encoded_uri() {\n        let client = Client::debug_with(routes![super::index]).unwrap();\n        let response = client.get(\"/hello%20s%C3%BCper%20%24?a&%3F&value=a+b\")\n            .dispatch()\n            .into_string();\n\n        assert_eq!(response.unwrap(), \"a b\");\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/fairing_before_head_strip-issue-546.rs",
    "content": "#[macro_use] extern crate rocket;\n\nconst RESPONSE_STRING: &'static str = \"This is the body. Hello, world!\";\n\n#[head(\"/\")]\nfn head() -> &'static str {\n    RESPONSE_STRING\n}\n\n#[get(\"/\")]\nfn auto() -> &'static str {\n    RESPONSE_STRING\n}\n\n// Test that response fairings see the response body for all `HEAD` requests,\n// whether they are auto-handled or not.\nmod fairing_before_head_strip {\n    use super::*;\n    use std::sync::atomic::{AtomicUsize, Ordering};\n    use std::io::Cursor;\n\n    use rocket::fairing::AdHoc;\n    use rocket::local::blocking::Client;\n    use rocket::http::{Method, Status};\n\n    #[test]\n    fn not_auto_handled() {\n        let rocket = rocket::build()\n            .mount(\"/\", routes![head])\n            .attach(AdHoc::on_request(\"Check HEAD\", |req, _| {\n                Box::pin(async move {\n                    assert_eq!(req.method(), Method::Head);\n                })\n            }))\n            .attach(AdHoc::on_response(\"Check HEAD 2\", |req, res| {\n                Box::pin(async move {\n                    assert_eq!(req.method(), Method::Head);\n                    let body_bytes = res.body_mut().to_bytes().await.unwrap();\n                    assert_eq!(body_bytes, RESPONSE_STRING.as_bytes());\n                    res.set_sized_body(body_bytes.len(), Cursor::new(body_bytes));\n                })\n            }));\n\n        let client = Client::debug(rocket).unwrap();\n        let response = client.head(\"/\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        assert!(response.into_string().unwrap_or_default().is_empty());\n    }\n\n    #[test]\n    fn auto_handled() {\n        #[derive(Default)]\n        struct Counter(AtomicUsize);\n\n        let counter = Counter::default();\n        let rocket = rocket::build()\n            .mount(\"/\", routes![auto])\n            .manage(counter)\n            .attach(AdHoc::on_request(\"Check HEAD + Count\", |req, _| {\n                Box::pin(async move {\n                    assert_eq!(req.method(), Method::Head);\n\n                    // This should be called exactly once.\n                    let c = req.rocket().state::<Counter>().unwrap();\n                    assert_eq!(c.0.fetch_add(1, Ordering::SeqCst), 0);\n                })\n            }))\n            .attach(AdHoc::on_response(\"Check GET\", |req, res| {\n                Box::pin(async move {\n                    assert_eq!(req.method(), Method::Get);\n                    let body_bytes = res.body_mut().to_bytes().await.unwrap();\n                    assert_eq!(body_bytes, RESPONSE_STRING.as_bytes());\n                    res.set_sized_body(body_bytes.len(), Cursor::new(body_bytes));\n                })\n            }));\n\n        let client = Client::debug(rocket).unwrap();\n        let response = client.head(\"/\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        assert!(response.into_string().unwrap_or_default().is_empty());\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/file_server.rs",
    "content": "use std::{io::Read, fs};\nuse std::path::Path;\n\nuse rocket::{Rocket, Route, Build};\nuse rocket::http::Status;\nuse rocket::local::blocking::Client;\nuse rocket::fs::{FileServer, relative, rewrite::*};\n\nfn static_root() -> &'static Path {\n    Path::new(relative!(\"/tests/static\"))\n}\n\nfn rocket() -> Rocket<Build> {\n    let root = static_root();\n    rocket::build()\n        .mount(\"/default\", FileServer::new(&root))\n        .mount(\n            \"/no_index\",\n            FileServer::identity()\n                .filter(|f, _| f.is_visible())\n                .rewrite(Prefix::checked(&root))\n        )\n        .mount(\n            \"/dots\",\n            FileServer::identity()\n                .rewrite(Prefix::checked(&root))\n        )\n        .mount(\n            \"/index\",\n            FileServer::identity()\n                .filter(|f, _| f.is_visible())\n                .rewrite(Prefix::checked(&root))\n                .rewrite(DirIndex::unconditional(\"index.html\"))\n        )\n        .mount(\n            \"/try_index\",\n            FileServer::identity()\n                .filter(|f, _| f.is_visible())\n                .rewrite(Prefix::checked(&root))\n                .rewrite(DirIndex::if_exists(\"index.html\"))\n                .rewrite(DirIndex::if_exists(\"index.htm\"))\n        )\n        .mount(\n            \"/both\",\n            FileServer::identity()\n                .rewrite(Prefix::checked(&root))\n                .rewrite(DirIndex::unconditional(\"index.html\"))\n        )\n        .mount(\n            \"/redir\",\n            FileServer::identity()\n                .filter(|f, _| f.is_visible())\n                .rewrite(Prefix::checked(&root))\n                .rewrite(TrailingDirs)\n        )\n        .mount(\n            \"/redir_index\",\n            FileServer::identity()\n                .filter(|f, _| f.is_visible())\n                .rewrite(Prefix::checked(&root))\n                .rewrite(TrailingDirs)\n                .rewrite(DirIndex::unconditional(\"index.html\"))\n        )\n        .mount(\n            \"/index_file\",\n            FileServer::identity()\n                .filter(|f, _| f.is_visible())\n                .rewrite(File::checked(root.join(\"other/hello.txt\")))\n        )\n        .mount(\n            \"/missing_root\",\n            FileServer::identity()\n                .filter(|f, _| f.is_visible())\n                .rewrite(File::new(root.join(\"no_file\")))\n        )\n}\n\nstatic REGULAR_FILES: &[&str] = &[\n    \"index.html\",\n    \"inner/goodbye\",\n    \"inner/index.html\",\n    \"other/hello.txt\",\n    \"other/index.htm\",\n];\n\nstatic HIDDEN_FILES: &[&str] = &[\n    \".hidden\",\n    \"inner/.hideme\",\n];\n\nstatic INDEXED_DIRECTORIES: &[&str] = &[\n    \"\",\n    \"inner/\",\n];\n\nfn assert_file_matches(client: &Client, prefix: &str, path: &str, disk_path: Option<&str>) {\n    let full_path = format!(\"/{}/{}\", prefix, path);\n    let response = client.get(full_path).dispatch();\n    if let Some(disk_path) = disk_path {\n        assert_eq!(response.status(), Status::Ok);\n\n        let mut path = static_root().join(disk_path);\n        if path.is_dir() {\n            path = path.join(\"index.html\");\n        }\n\n        let mut file = fs::File::open(path).expect(\"open file\");\n        let mut expected_contents = String::new();\n        file.read_to_string(&mut expected_contents).expect(\"read file\");\n        assert_eq!(response.into_string(), Some(expected_contents));\n    } else {\n        assert_eq!(response.status(), Status::NotFound);\n    }\n}\n\nfn assert_file(client: &Client, prefix: &str, path: &str, exists: bool) {\n    if exists {\n        assert_file_matches(client, prefix, path, Some(path))\n    } else {\n        assert_file_matches(client, prefix, path, None)\n    }\n}\n\nfn assert_all(client: &Client, prefix: &str, paths: &[&str], exist: bool) {\n    for path in paths.iter() {\n        assert_file(client, prefix, path, exist);\n    }\n}\n\n#[test]\nfn test_static_no_index() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n    assert_all(&client, \"no_index\", REGULAR_FILES, true);\n    assert_all(&client, \"no_index\", HIDDEN_FILES, false);\n    assert_all(&client, \"no_index\", INDEXED_DIRECTORIES, false);\n}\n\n#[test]\nfn test_static_hidden() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n    assert_all(&client, \"dots\", REGULAR_FILES, true);\n    assert_all(&client, \"dots\", HIDDEN_FILES, true);\n    assert_all(&client, \"dots\", INDEXED_DIRECTORIES, false);\n}\n\n#[test]\nfn test_static_index() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n    assert_all(&client, \"index\", REGULAR_FILES, true);\n    assert_all(&client, \"index\", HIDDEN_FILES, false);\n    assert_all(&client, \"index\", INDEXED_DIRECTORIES, true);\n\n    assert_all(&client, \"default\", REGULAR_FILES, true);\n    assert_all(&client, \"default\", HIDDEN_FILES, false);\n    assert_all(&client, \"default\", INDEXED_DIRECTORIES, true);\n}\n\n#[test]\nfn test_static_all() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n    assert_all(&client, \"both\", REGULAR_FILES, true);\n    assert_all(&client, \"both\", HIDDEN_FILES, true);\n    assert_all(&client, \"both\", INDEXED_DIRECTORIES, true);\n}\n\n#[test]\nfn test_alt_roots() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n    assert_file(&client, \"missing_root\", \"\", false);\n    assert_file_matches(&client, \"index_file\", \"\", Some(\"other/hello.txt\"));\n}\n\n#[test]\nfn test_allow_special_dotpaths() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n    assert_file_matches(&client, \"no_index\", \"./index.html\", Some(\"index.html\"));\n    assert_file_matches(&client, \"no_index\", \"foo/../index.html\", Some(\"index.html\"));\n    assert_file_matches(&client, \"no_index\", \"inner/./index.html\", Some(\"inner/index.html\"));\n    assert_file_matches(&client, \"no_index\", \"../index.html\", Some(\"index.html\"));\n}\n\n#[test]\nfn test_try_index() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n    assert_file_matches(&client, \"try_index\", \"inner\", Some(\"inner/index.html\"));\n    assert_file_matches(&client, \"try_index\", \"other\", Some(\"other/index.htm\"));\n}\n\n#[test]\nfn test_ranking() {\n    let root = static_root();\n    for rank in -128..128 {\n        let a = FileServer::new(&root).rank(rank);\n        let b = FileServer::new(&root).rank(rank);\n\n        for handler in vec![a, b] {\n            let routes: Vec<Route> = handler.into();\n            assert!(routes.iter().all(|route| route.rank == rank), \"{}\", rank);\n        }\n    }\n}\n\n#[test]\nfn test_forwarding() {\n    use rocket::{get, routes};\n\n    #[get(\"/<value>\", rank = 20)]\n    fn catch_one(value: String) -> String { value }\n\n    #[get(\"/<a>/<b>\", rank = 20)]\n    fn catch_two(a: &str, b: &str) -> String { format!(\"{}/{}\", a, b) }\n\n    let rocket = rocket().mount(\"/default\", routes![catch_one, catch_two]);\n    let client = Client::debug(rocket).expect(\"valid rocket\");\n\n    let response = client.get(\"/default/ireallydontexist\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.into_string().unwrap(), \"ireallydontexist\");\n\n    let response = client.get(\"/default/idont/exist\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.into_string().unwrap(), \"idont/exist\");\n\n    assert_all(&client, \"both\", REGULAR_FILES, true);\n    assert_all(&client, \"both\", HIDDEN_FILES, true);\n    assert_all(&client, \"both\", INDEXED_DIRECTORIES, true);\n}\n\n#[test]\nfn test_redirection() {\n    let client = Client::debug(rocket()).expect(\"valid rocket\");\n\n    // Redirection only happens if enabled, and doesn't affect index behavior.\n    let response = client.get(\"/no_index/inner\").dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n\n    let response = client.get(\"/index/inner\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n\n    let response = client.get(\"/redir/inner\").dispatch();\n    assert_eq!(response.status(), Status::TemporaryRedirect);\n    assert_eq!(response.headers().get(\"Location\").next(), Some(\"/redir/inner/\"));\n\n    let response = client.get(\"/redir/inner?foo=bar\").dispatch();\n    assert_eq!(response.status(), Status::TemporaryRedirect);\n    assert_eq!(response.headers().get(\"Location\").next(), Some(\"/redir/inner/?foo=bar\"));\n\n    let response = client.get(\"/redir_index/inner\").dispatch();\n    assert_eq!(response.status(), Status::TemporaryRedirect);\n    assert_eq!(response.headers().get(\"Location\").next(), Some(\"/redir_index/inner/\"));\n\n    // Paths with trailing slash are unaffected.\n    let response = client.get(\"/redir/inner/\").dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n\n    let response = client.get(\"/redir_index/inner/\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n\n    // Root of route is also redirected.\n    let response = client.get(\"/no_index/\").dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n\n    let response = client.get(\"/index/\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n\n    let response = client.get(\"/redir/inner\").dispatch();\n    assert_eq!(response.status(), Status::TemporaryRedirect);\n    assert_eq!(response.headers().get(\"Location\").next(), Some(\"/redir/inner/\"));\n\n    let response = client.get(\"/redir/other\").dispatch();\n    assert_eq!(response.status(), Status::TemporaryRedirect);\n    assert_eq!(response.headers().get(\"Location\").next(), Some(\"/redir/other/\"));\n\n    let response = client.get(\"/redir_index/other\").dispatch();\n    assert_eq!(response.status(), Status::TemporaryRedirect);\n    assert_eq!(response.headers().get(\"Location\").next(), Some(\"/redir_index/other/\"));\n}\n\n#[test]\n#[should_panic]\nfn test_panic_on_missing_file() {\n    let _ = File::checked(static_root().join(\"missing_file\"));\n}\n\n#[test]\n#[should_panic]\nfn test_panic_on_missing_dir() {\n    let _ = Prefix::checked(static_root().join(\"missing_dir\"));\n}\n\n#[test]\n#[should_panic]\nfn test_panic_on_file_not_dir() {\n    let _ = Prefix::checked(static_root().join(\"index.html\"));\n}\n"
  },
  {
    "path": "core/lib/tests/flash-lazy-removes-issue-466.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::request::FlashMessage;\nuse rocket::response::Flash;\n\nconst FLASH_MESSAGE: &str = \"Hey! I'm a flash message. :)\";\n\n#[post(\"/\")]\nfn set() -> Flash<&'static str> {\n    Flash::success(\"This is the page.\", FLASH_MESSAGE)\n}\n\n#[get(\"/unused\")]\nfn unused(flash: Option<FlashMessage<'_>>) -> Option<()> {\n    flash.map(|_| ())\n}\n\n#[get(\"/use\")]\nfn used(flash: Option<FlashMessage<'_>>) -> Option<String> {\n    flash.map(|f| f.message().into())\n}\n\nmod flash_lazy_remove_tests {\n    use rocket::local::blocking::Client;\n    use rocket::http::Status;\n\n    #[test]\n    fn test() {\n        use super::*;\n\n        // Ensure the cookie's not there at first.\n        let client = Client::debug_with(routes![set, unused, used]).unwrap();\n        let response = client.get(\"/unused\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n\n        // Set the flash cookie.\n        client.post(\"/\").dispatch();\n\n        // Try once.\n        let response = client.get(\"/unused\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n\n        // Try again; should still be there.\n        let response = client.get(\"/unused\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n\n        // Now use it.\n        let response = client.get(\"/use\").dispatch();\n        assert_eq!(response.into_string(), Some(FLASH_MESSAGE.into()));\n\n        // Now it should be gone.\n        let response = client.get(\"/unused\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n\n        // Still gone.\n        let response = client.get(\"/use\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/form-validation-names.rs",
    "content": "use std::fmt::Debug;\n\nuse rocket::form::{Form, FromForm};\nuse rocket::form::error::{Error, Errors, ErrorKind};\n\n#[derive(Debug, FromForm)]\n#[allow(dead_code)]\nstruct Cat<'v> {\n    #[field(validate = len(5..))]\n    name: &'v str,\n    #[field(validate = starts_with(\"kitty\"))]\n    nick: &'v str,\n}\n\n#[derive(Debug, FromForm)]\n#[allow(dead_code)]\nstruct Dog<'v> {\n    #[field(validate = len(5..))]\n    name: &'v str,\n}\n\n#[derive(Debug, FromForm)]\n#[allow(dead_code)]\nstruct Person<'v> {\n    kitty: Cat<'v>,\n    #[field(validate = len(1..))]\n    cats: Vec<Cat<'v>>,\n    dog: Dog<'v>,\n}\n\nfn starts_with<'v, S: AsRef<str>>(string: S, prefix: &str) -> Result<(), Errors<'v>> {\n    if !string.as_ref().starts_with(prefix) {\n        Err(Error::validation(format!(\"must start with {:?}\", prefix)))?\n    }\n\n    Ok(())\n}\n\n#[track_caller]\nfn errors<'v, T: FromForm<'v> + Debug + 'v>(string: &'v str) -> Errors<'v> {\n    Form::<T>::parse(string).expect_err(\"expected an error\")\n}\n\n#[test]\nfn test_form_validation_context() {\n    use ErrorKind::*;\n\n    fn count<'a, K>(c: &Errors<'_>, n: &str, kind: K, fuzz: bool) -> usize\n        where K: Into<Option<ErrorKind<'a>>>\n    {\n        let kind = kind.into();\n        c.iter().filter(|e| {\n            let matches = (fuzz && e.is_for(n)) || (!fuzz && e.is_for_exactly(n));\n            let kinded = kind.as_ref().map(|k| k == &e.kind).unwrap_or(true);\n            matches && kinded\n        }).count()\n    }\n\n    fn fuzzy<'a, K>(c: &Errors<'_>, n: &str, kind: K) -> usize\n        where K: Into<Option<ErrorKind<'a>>>\n    {\n        count(c, n, kind, true)\n    }\n\n    fn exact<'a, K>(c: &Errors<'_>, n: &str, kind: K) -> usize\n        where K: Into<Option<ErrorKind<'a>>>\n    {\n        count(c, n, kind, false)\n    }\n\n    let c = errors::<Cat<'_>>(\"name=littlebobby\");\n    assert_eq!(exact(&c, \"nick\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"nick\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"nick\", None), 1);\n\n    let c = errors::<Person<'_>>(\"cats[0].name=Bob\");\n    assert_eq!(exact(&c, \"kitty\", None), 1);\n    assert_eq!(exact(&c, \"kitty\", Missing), 1);\n    assert_eq!(exact(&c, \"cats[0].nick\", None), 1);\n    assert_eq!(exact(&c, \"cats[0].nick\", Missing), 1);\n    assert_eq!(exact(&c, \"dog\", None), 1);\n    assert_eq!(exact(&c, \"dog\", Missing), 1);\n    assert_eq!(exact(&c, \"dog.name\", None), 0);\n    assert_eq!(exact(&c, \"kitty.name\", None), 0);\n    assert_eq!(exact(&c, \"kitty.nick\", None), 0);\n\n    assert_eq!(fuzzy(&c, \"kitty\", None), 1);\n    assert_eq!(fuzzy(&c, \"kitty.name\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"kitty.nick\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"cats[0].nick\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"dog.name\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"dog\", None), 1);\n\n    let c = errors::<Person<'_>>(\"cats[0].name=Bob&cats[0].nick=kit&kitty.name=Hi\");\n    assert_eq!(exact(&c, \"kitty.nick\", Missing), 1);\n    assert_eq!(exact(&c, \"kitty\", None), 0);\n    assert_eq!(exact(&c, \"dog\", Missing), 1);\n    assert_eq!(exact(&c, \"dog\", None), 1);\n    assert_eq!(exact(&c, \"cats[0].name\", None), 1);\n    assert_eq!(exact(&c, \"cats[0].name\", InvalidLength { min: Some(5), max: None }), 1);\n    assert_eq!(exact(&c, \"cats[0].nick\", None), 1);\n    assert_eq!(exact(&c, \"cats[0].nick\", Validation(\"must start with \\\"kitty\\\"\".into())), 1);\n\n    assert_eq!(fuzzy(&c, \"kitty.nick\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"kitty.nick\", None), 1);\n    assert_eq!(fuzzy(&c, \"kitty\", None), 0);\n    assert_eq!(fuzzy(&c, \"dog.name\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"dog\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"cats[0].nick\", None), 1);\n    assert_eq!(exact(&c, \"cats[0].name\", None), 1);\n\n    let c = errors::<Person<'_>>(\"kitty.name=Michael\");\n    assert_eq!(exact(&c, \"kitty.nick\", Missing), 1);\n    assert_eq!(exact(&c, \"dog\", Missing), 1);\n    assert_eq!(exact(&c, \"cats[0].name\", None), 0);\n    assert_eq!(exact(&c, \"cats[0].nick\", None), 0);\n\n    assert_eq!(exact(&c, \"cats\", None), 1);\n    assert_eq!(exact(&c, \"cats\", InvalidLength { min: Some(1), max: None }), 1);\n\n    assert_eq!(fuzzy(&c, \"kitty.nick\", Missing), 1);\n    assert_eq!(fuzzy(&c, \"kitty.nick\", None), 1);\n    assert_eq!(fuzzy(&c, \"dog\", None), 1);\n    assert_eq!(fuzzy(&c, \"dog.name\", Missing), 1);\n    assert_eq!(exact(&c, \"cats[0].name\", None), 0);\n    assert_eq!(exact(&c, \"cats[0].nick\", None), 0);\n\n    let c = errors::<Person<'_>>(\"kitty.name=Michael&kitty.nick=kittykat&dog.name=woofy\");\n    assert_eq!(c.iter().count(), 1);\n    assert_eq!(exact(&c, \"cats\", None), 1);\n    assert_eq!(exact(&c, \"cats\", InvalidLength { min: Some(1), max: None }), 1);\n    assert_eq!(fuzzy(&c, \"cats[0].name\", None), 1);\n}\n\n// #[derive(Debug, FromForm)]\n// struct Person<'v> {\n//     kitty: Cat<'v>,\n//     #[field(validate = len(1..))]\n//     cats: Vec<Cat<'v>>,\n//     dog: Dog<'v>,\n// }\n"
  },
  {
    "path": "core/lib/tests/form_method-issue-45.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::form::Form;\n\n#[derive(FromForm)]\nstruct FormData {\n    form_data: String,\n}\n\n#[patch(\"/\", data = \"<form_data>\")]\nfn patch(form_data: Form<FormData>) -> &'static str {\n    assert_eq!(\"Form data\", form_data.into_inner().form_data);\n    \"PATCH OK\"\n}\n\n#[route(\"/\", method = UPDATEREDIRECTREF, data = \"<form_data>\")]\nfn urr(form_data: Form<FormData>) -> &'static str {\n    assert_eq!(\"Form data\", form_data.into_inner().form_data);\n    \"UPDATEREDIRECTREF OK\"\n}\n\n#[route(\"/\", method = \"VERSION-CONTROL\", data = \"<form_data>\")]\nfn vc(form_data: Form<FormData>) -> &'static str {\n    assert_eq!(\"Form data\", form_data.into_inner().form_data);\n    \"VERSION-CONTROL OK\"\n}\n\nmod tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n    use rocket::http::{Status, ContentType, Method};\n\n    #[test]\n    fn method_eval() {\n        let client = Client::debug_with(routes![patch, urr, vc]).unwrap();\n        let response = client.post(\"/\")\n            .header(ContentType::Form)\n            .body(\"_method=patch&form_data=Form+data\")\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"PATCH OK\".into()));\n\n        let response = client.post(\"/\")\n            .header(ContentType::Form)\n            .body(\"_method=updateredirectref&form_data=Form+data\")\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"UPDATEREDIRECTREF OK\".into()));\n\n        let response = client.req(Method::UpdateRedirectRef, \"/\")\n            .header(ContentType::Form)\n            .body(\"form_data=Form+data\")\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"UPDATEREDIRECTREF OK\".into()));\n\n        let response = client.post(\"/\")\n            .header(ContentType::Form)\n            .body(\"_method=version-control&form_data=Form+data\")\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"VERSION-CONTROL OK\".into()));\n    }\n\n    #[test]\n    fn get_passes_through() {\n        let client = Client::debug_with(routes![patch, urr, vc]).unwrap();\n        let response = client.get(\"/\")\n            .header(ContentType::Form)\n            .body(\"_method=patch&form_data=Form+data\")\n            .dispatch();\n\n        assert_eq!(response.status(), Status::NotFound);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/form_value_decoding-issue-82.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::form::Form;\n\n#[post(\"/\", data = \"<form_data>\")]\nfn bug(form_data: Form<String>) -> String {\n    form_data.into_inner()\n}\n\nmod tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n    use rocket::http::ContentType;\n    use rocket::http::Status;\n\n    fn check_decoding(raw: &str, decoded: &str) {\n        let client = Client::debug_with(routes![bug]).unwrap();\n        let response = client.post(\"/\")\n            .header(ContentType::Form)\n            .body(format!(\"form_data={}\", raw))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(Some(decoded.to_string()), response.into_string());\n    }\n\n    #[test]\n    fn test_proper_decoding() {\n        check_decoding(\"password\", \"password\");\n        check_decoding(\"\", \"\");\n        check_decoding(\"+\", \" \");\n        check_decoding(\"%2B\", \"+\");\n        check_decoding(\"1+1\", \"1 1\");\n        check_decoding(\"1%2B1\", \"1+1\");\n        check_decoding(\"%3Fa%3D1%26b%3D2\", \"?a=1&b=2\");\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/form_value_from_encoded_str-issue-1425.rs",
    "content": "use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};\n\nuse rocket::http::RawStr;\nuse rocket::form::Form;\n\nmacro_rules! assert_from_form_field_eq {\n    ($string:literal as $T:ty, $expected:expr) => (\n        let value_str = RawStr::new(concat!(\"=\", $string));\n        let value = Form::<$T>::parse_encoded(value_str).unwrap();\n        assert_eq!(value, $expected);\n    )\n}\n\n#[test]\nfn test_from_form_value_encoded() {\n    assert_from_form_field_eq!(\n        \"127.0.0.1%3A80\" as SocketAddrV4,\n        SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80)\n    );\n\n    assert_from_form_field_eq!(\n        \"2001%3A0db8%3A85a3%3A0000%3A0000%3A8a2e%3A0370%3A7334\" as Ipv6Addr,\n        Ipv6Addr::new(0x2001, 0x0db8, 0x85a3, 0, 0, 0x8a2e, 0x0370, 0x7334)\n    );\n\n    assert_from_form_field_eq!(\n        \"%5B2001%3Adb8%3A%3A1%5D%3A8080\" as SocketAddrV6,\n        SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0)\n    );\n}\n"
  },
  {
    "path": "core/lib/tests/forward-includes-status-1560.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::http::Status;\nuse rocket::request::{self, Request, FromRequest};\n\nstruct Authenticated;\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for Authenticated {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n        if request.headers().contains(\"Authenticated\") {\n            request::Outcome::Success(Authenticated)\n        } else {\n            request::Outcome::Forward(Status::Unauthorized)\n        }\n    }\n}\n\nstruct TeapotForward;\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for TeapotForward {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(_: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n        request::Outcome::Forward(Status::ImATeapot)\n    }\n}\n\n#[get(\"/auth\")]\nfn auth(_name: Authenticated) -> &'static str {\n    \"Protected\"\n}\n\n#[get(\"/auth\", rank = 2)]\nfn public() -> &'static str {\n    \"Public\"\n}\n\n#[get(\"/auth\", rank = 3)]\nfn teapot(_teapot: TeapotForward) -> &'static str {\n    \"Protected\"\n}\n\n#[get(\"/need-auth\")]\nfn auth_needed(_auth: Authenticated) -> &'static str {\n    \"Have Auth\"\n}\n\n#[catch(401)]\nfn catcher() -> &'static str {\n    \"Custom Catcher\"\n}\n\nmod tests {\n    use super::*;\n\n    use rocket::routes;\n    use rocket::local::blocking::Client;\n    use rocket::http::Header;\n\n    #[test]\n    fn authorized_forwards() {\n        let client = Client::debug_with(routes![auth, public, auth_needed]).unwrap();\n\n        let response = client.get(\"/auth\")\n            .header(Header::new(\"Authenticated\", \"true\"))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string().unwrap(), \"Protected\");\n\n        let response = client.get(\"/auth\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string().unwrap(), \"Public\");\n\n        let response = client.get(\"/need-auth\")\n            .header(Header::new(\"Authenticated\", \"true\"))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string().unwrap(), \"Have Auth\");\n\n        let response = client.get(\"/need-auth\").dispatch();\n        assert_eq!(response.status(), Status::Unauthorized);\n        assert!(response.into_string().unwrap().contains(\"Rocket\"));\n    }\n\n    #[test]\n    fn unauthorized_custom_catcher() {\n        let rocket = rocket::build()\n            .mount(\"/\", routes![auth_needed])\n            .register(\"/\", catchers![catcher]);\n\n        let client = Client::debug(rocket).unwrap();\n        let response = client.get(\"/need-auth\").dispatch();\n        assert_eq!(response.status(), Status::Unauthorized);\n        assert_eq!(response.into_string().unwrap(), \"Custom Catcher\");\n    }\n\n    #[test]\n    fn use_last_forward() {\n        let client = Client::debug_with(routes![auth, teapot]).unwrap();\n        let response = client.get(\"/auth\").dispatch();\n        assert_eq!(response.status(), Status::ImATeapot);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/head_handling.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::http::Status;\nuse rocket::response::content::RawJson;\n\n#[get(\"/empty\")]\nfn empty() -> Status {\n    Status::NoContent\n}\n\n#[get(\"/\")]\nfn index() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[head(\"/other\")]\nfn other() -> RawJson<&'static str> {\n    RawJson(\"{ 'hi': 'hello' }\")\n}\n\nmod head_handling_tests {\n    use super::*;\n\n    use rocket::Route;\n    use rocket::local::blocking::Client;\n    use rocket::http::ContentType;\n\n    fn routes() -> Vec<Route> {\n        routes![index, empty, other]\n    }\n\n    #[test]\n    fn auto_head() {\n        let client = Client::debug_with(routes()).unwrap();\n        let response = client.head(\"/\").dispatch();\n\n        let content_type: Vec<_> = response.headers().get(\"Content-Type\").collect();\n        assert_eq!(content_type, vec![ContentType::Plain.to_string()]);\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.body().preset_size(), Some(13));\n        assert!(response.into_bytes().unwrap().is_empty());\n\n        let response = client.head(\"/empty\").dispatch();\n        assert_eq!(response.status(), Status::NoContent);\n        assert!(response.into_bytes().is_none());\n    }\n\n    #[test]\n    fn user_head() {\n        let client = Client::debug_with(routes()).unwrap();\n        let response = client.head(\"/other\").dispatch();\n\n        let content_type: Vec<_> = response.headers().get(\"Content-Type\").collect();\n        assert_eq!(content_type, vec![ContentType::JSON.to_string()]);\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.body().preset_size(), Some(17));\n        assert!(response.into_bytes().unwrap().is_empty());\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/http_serde.rs",
    "content": "use serde::{Serialize, Deserialize};\nuse figment::{Figment, providers::Serialized};\nuse pretty_assertions::assert_eq;\n\nuse rocket::{Config, uri};\nuse rocket::http::uri::{Absolute, Asterisk, Authority, Origin, Reference};\nuse rocket::http::{Method, Status};\n\n#[derive(PartialEq, Debug, Serialize, Deserialize)]\nstruct UriContainer<'a> {\n    asterisk: Asterisk,\n    origin: Origin<'a>,\n    authority: Authority<'a>,\n    absolute: Absolute<'a>,\n    reference: Reference<'a>,\n}\n\n#[derive(PartialEq, Debug, Serialize, Deserialize)]\nstruct UriContainerOwned {\n    asterisk: Asterisk,\n    origin: Origin<'static>,\n    authority: Authority<'static>,\n    absolute: Absolute<'static>,\n    reference: Reference<'static>,\n}\n\n#[derive(PartialEq, Debug, Serialize, Deserialize)]\nstruct MethodContainer {\n    mget: Method,\n    mput: Method,\n    mpost: Method,\n}\n\n#[derive(PartialEq, Debug, Serialize, Deserialize)]\nstruct StatusContainer {\n    a: Status,\n    b: Status,\n    c: Status,\n}\n\n#[test]\nfn uri_serde() {\n    figment::Jail::expect_with(|jail| {\n        jail.create_file(\"Rocket.toml\", r#\"\n            [default]\n            asterisk = \"*\"\n            origin = \"/foo/bar?baz\"\n            authority = \"user:pass@rocket.rs:80\"\n            absolute = \"https://rocket.rs/foo/bar\"\n            reference = \"https://rocket.rs:8000/index.html\"\n        \"#)?;\n\n        let uris: UriContainer<'_> = Config::figment().extract()?;\n        assert_eq!(uris, UriContainer {\n            asterisk: Asterisk,\n            origin: uri!(\"/foo/bar?baz\"),\n            authority: uri!(\"user:pass@rocket.rs:80\"),\n            absolute: uri!(\"https://rocket.rs/foo/bar\"),\n            reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n        });\n\n        let uris: UriContainerOwned = Config::figment().extract()?;\n        assert_eq!(uris, UriContainerOwned {\n            asterisk: Asterisk,\n            origin: uri!(\"/foo/bar?baz\"),\n            authority: uri!(\"user:pass@rocket.rs:80\"),\n            absolute: uri!(\"https://rocket.rs/foo/bar\"),\n            reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n        });\n\n        Ok(())\n    });\n}\n\n#[test]\nfn uri_serde_round_trip() {\n    let tmp = Figment::from(Serialized::defaults(UriContainer {\n        asterisk: Asterisk,\n        origin: uri!(\"/foo/bar?baz\"),\n        authority: uri!(\"user:pass@rocket.rs:80\"),\n        absolute: uri!(\"https://rocket.rs/foo/bar\"),\n        reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n    }));\n\n    let uris: UriContainer<'_> = tmp.extract().unwrap();\n    assert_eq!(uris, UriContainer {\n        asterisk: Asterisk,\n        origin: uri!(\"/foo/bar?baz\"),\n        authority: uri!(\"user:pass@rocket.rs:80\"),\n        absolute: uri!(\"https://rocket.rs/foo/bar\"),\n        reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n    });\n\n    let uris: UriContainerOwned = tmp.extract().unwrap();\n    assert_eq!(uris, UriContainerOwned {\n        asterisk: Asterisk,\n        origin: uri!(\"/foo/bar?baz\"),\n        authority: uri!(\"user:pass@rocket.rs:80\"),\n        absolute: uri!(\"https://rocket.rs/foo/bar\"),\n        reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n    });\n\n    let tmp = Figment::from(Serialized::defaults(UriContainerOwned {\n        asterisk: Asterisk,\n        origin: uri!(\"/foo/bar?baz\"),\n        authority: uri!(\"user:pass@rocket.rs:80\"),\n        absolute: uri!(\"https://rocket.rs/foo/bar\"),\n        reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n    }));\n\n    let uris: UriContainer<'_> = tmp.extract().unwrap();\n    assert_eq!(uris, UriContainer {\n        asterisk: Asterisk,\n        origin: uri!(\"/foo/bar?baz\"),\n        authority: uri!(\"user:pass@rocket.rs:80\"),\n        absolute: uri!(\"https://rocket.rs/foo/bar\"),\n        reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n    });\n\n    let uris: UriContainerOwned = tmp.extract().unwrap();\n    assert_eq!(uris, UriContainerOwned {\n        asterisk: Asterisk,\n        origin: uri!(\"/foo/bar?baz\"),\n        authority: uri!(\"user:pass@rocket.rs:80\"),\n        absolute: uri!(\"https://rocket.rs/foo/bar\"),\n        reference: uri!(\"https://rocket.rs:8000/index.html\").into(),\n    });\n}\n\n#[test]\nfn method_serde() {\n    figment::Jail::expect_with(|jail| {\n        jail.create_file(\"Rocket.toml\", r#\"\n            [default]\n            mget = \"GET\"\n            mput = \"PUT\"\n            mpost = \"post\"\n        \"#)?;\n\n        let methods: MethodContainer = Config::figment().extract()?;\n        assert_eq!(methods, MethodContainer {\n            mget: Method::Get,\n            mput: Method::Put,\n            mpost: Method::Post\n        });\n\n        let tmp = Figment::from(Serialized::defaults(methods));\n        let methods: MethodContainer = tmp.extract()?;\n        assert_eq!(methods, MethodContainer {\n            mget: Method::Get,\n            mput: Method::Put,\n            mpost: Method::Post\n        });\n\n        Ok(())\n    });\n}\n\n#[test]\nfn status_serde() {\n    figment::Jail::expect_with(|jail| {\n        jail.create_file(\"Rocket.toml\", r#\"\n            [default]\n            a = 500\n            b = 100\n            c = 404\n        \"#)?;\n\n        let statuses: StatusContainer = Config::figment().extract()?;\n        assert_eq!(statuses, StatusContainer {\n            a: Status::InternalServerError,\n            b: Status::Continue,\n            c: Status::NotFound\n        });\n\n        let tmp = Figment::from(Serialized::defaults(statuses));\n        let statuses: StatusContainer = tmp.extract()?;\n        assert_eq!(statuses, StatusContainer {\n            a: Status::InternalServerError,\n            b: Status::Continue,\n            c: Status::NotFound\n        });\n\n        jail.create_file(\"Rocket.toml\", r#\"\n            [default]\n            a = 99\n            b = 100\n            c = 404\n        \"#)?;\n\n        let statuses: Result<StatusContainer, _> = Config::figment().extract();\n        assert!(statuses.is_err());\n\n        jail.create_file(\"Rocket.toml\", r#\"\n            [default]\n            a = 500\n            b = 100\n            c = 600\n        \"#)?;\n\n        let statuses: Result<StatusContainer, _> = Config::figment().extract();\n        assert!(statuses.is_err());\n\n        Ok(())\n    });\n}\n"
  },
  {
    "path": "core/lib/tests/launch-inspect.rs",
    "content": "use rocket::fairing::AdHoc;\n\n#[rocket::async_test]\nasync fn test_inspectable_launch_state() -> Result<(), rocket::Error> {\n    let rocket = rocket::custom(rocket::Config::debug_default())\n        .attach(AdHoc::on_ignite(\"Add State\", |rocket| async {\n            rocket.manage(\"Hi!\")\n        }))\n        .ignite()\n        .await?;\n\n    let state = rocket.state::<&'static str>();\n    assert_eq!(state, Some(&\"Hi!\"));\n    Ok(())\n}\n\n#[rocket::async_test]\nasync fn test_inspectable_launch_state_in_liftoff() -> Result<(), rocket::Error> {\n    let rocket = rocket::custom(rocket::Config::debug_default())\n        .attach(AdHoc::on_ignite(\"Add State\", |rocket| async {\n            rocket.manage(\"Hi!\")\n        }))\n        .attach(AdHoc::on_ignite(\"Inspect State\", |rocket| async {\n            let state = rocket.state::<&'static str>();\n            assert_eq!(state, Some(&\"Hi!\"));\n            rocket\n        }))\n        .attach(AdHoc::on_liftoff(\"Inspect State\", |rocket| Box::pin(async move {\n            let state = rocket.state::<&'static str>();\n            assert_eq!(state, Some(&\"Hi!\"));\n        })))\n        .ignite()\n        .await?;\n\n    let state = rocket.state::<&'static str>();\n    assert_eq!(state, Some(&\"Hi!\"));\n    Ok(())\n}\n\n#[rocket::async_test]\nasync fn test_launch_state_is_well_ordered() -> Result<(), rocket::Error> {\n    let rocket = rocket::custom(rocket::Config::debug_default())\n        .attach(AdHoc::on_ignite(\"Inspect State Pre\", |rocket| async {\n            let state = rocket.state::<&'static str>();\n            assert_eq!(state, None);\n            rocket\n        }))\n        .attach(AdHoc::on_ignite(\"Add State\", |rocket| async {\n            rocket.manage(\"Hi!\")\n        }))\n        .attach(AdHoc::on_ignite(\"Inspect State\", |rocket| async {\n            let state = rocket.state::<&'static str>();\n            assert_eq!(state, Some(&\"Hi!\"));\n            rocket\n        }))\n        .ignite()\n        .await?;\n\n    let state = rocket.state::<&'static str>();\n    assert_eq!(state, Some(&\"Hi!\"));\n    Ok(())\n}\n\n#[should_panic]\n#[rocket::async_test]\nasync fn negative_test_launch_state() {\n    let _ = rocket::custom(rocket::Config::debug_default())\n        .attach(AdHoc::on_ignite(\"Add State\", |rocket| async {\n            rocket.manage(\"Hi!\")\n        }))\n        .attach(AdHoc::on_ignite(\"Inspect State\", |rocket| async {\n            let state = rocket.state::<&'static str>();\n            assert_ne!(state, Some(&\"Hi!\"));\n            rocket\n        }))\n        .ignite()\n        .await;\n}\n"
  },
  {
    "path": "core/lib/tests/limits.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::form::Form;\n\n#[post(\"/\", data = \"<form>\")]\nfn index(form: Form<String>) -> String {\n    form.into_inner()\n}\n\nmod limits_tests {\n    use rocket::{Rocket, Build};\n    use rocket::local::blocking::Client;\n    use rocket::http::{Status, ContentType};\n    use rocket::data::Limits;\n\n    fn rocket_with_forms_limit(limit: u64) -> Rocket<Build> {\n        let mut config = rocket::Config::debug_default();\n        config.limits = Limits::default().limit(\"form\", limit.into());\n        rocket::custom(config).mount(\"/\", routes![super::index])\n    }\n\n    #[test]\n    fn large_enough() {\n        let client = Client::debug(rocket_with_forms_limit(128)).unwrap();\n        let response = client.post(\"/\")\n            .body(\"value=Hello+world\")\n            .header(ContentType::Form)\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"Hello world\".into()));\n    }\n\n    #[test]\n    fn just_large_enough() {\n        let client = Client::debug(rocket_with_forms_limit(17)).unwrap();\n        let response = client.post(\"/\")\n            .body(\"value=Hello+world\")\n            .header(ContentType::Form)\n            .dispatch();\n\n        assert_eq!(response.into_string(), Some(\"Hello world\".into()));\n    }\n\n    #[test]\n    fn much_too_small() {\n        let client = Client::debug(rocket_with_forms_limit(4)).unwrap();\n        let response = client.post(\"/\")\n            .body(\"value=Hello+world\")\n            .header(ContentType::Form)\n            .dispatch();\n\n        assert_eq!(response.status(), Status::PayloadTooLarge);\n    }\n\n    #[test]\n    fn contracted() {\n        let client = Client::debug(rocket_with_forms_limit(10)).unwrap();\n        let response = client.post(\"/\")\n            .body(\"value=Hello+world\")\n            .header(ContentType::Form)\n            .dispatch();\n\n        assert_eq!(response.status(), Status::PayloadTooLarge);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/local-client-access-runtime-in-drop.rs",
    "content": "use rocket::local::blocking::Client;\n\nstruct SpawnBlockingOnDrop;\n\nimpl Drop for SpawnBlockingOnDrop {\n    fn drop(&mut self) {\n        rocket::tokio::task::spawn_blocking(|| ());\n    }\n}\n\n#[test]\nfn test_access_runtime_in_state_drop() {\n    Client::debug(rocket::build().manage(SpawnBlockingOnDrop)).unwrap();\n}\n"
  },
  {
    "path": "core/lib/tests/local-client-json.rs",
    "content": "#![cfg(feature = \"json\")]\n\n#[macro_use] extern crate rocket;\n\nuse rocket::serde::json::Json;\n\n#[get(\"/int\")] fn int() -> Json<i32> { Json(5) }\n#[get(\"/nil\")] fn nil() -> Json<()> { Json(()) }\n\n#[async_test]\nasync fn async_json_works() {\n    use rocket::local::asynchronous::Client;\n\n    let client = Client::debug_with(routes![int, nil]).await.unwrap();\n\n    let int0 = client.get(\"/int\").dispatch().await.into_json::<u32>().await;\n    let int1 = client.get(\"/int\").dispatch().await.into_json::<i32>().await;\n\n    assert_eq!(int0, Some(5));\n    assert_eq!(int1, Some(5));\n\n    let nil0 = client.get(\"/nil\").dispatch().await.into_json::<()>().await;\n    assert_eq!(nil0, Some(()));\n}\n"
  },
  {
    "path": "core/lib/tests/local-request-content-type-issue-505.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::{Request, Data};\nuse rocket::request::{self, FromRequest};\nuse rocket::outcome::IntoOutcome;\nuse rocket::http::Status;\n\nstruct HasContentType;\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for HasContentType {\n    type Error = ();\n\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        req.content_type().map(|_| HasContentType).or_forward(Status::NotFound)\n    }\n}\n\nuse rocket::data::{self, FromData};\n\n#[rocket::async_trait]\nimpl<'r> FromData<'r> for HasContentType {\n    type Error = ();\n\n    async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {\n        req.content_type().map(|_| HasContentType).or_forward((data, Status::NotFound))\n    }\n}\n\n#[post(\"/\")]\nfn rg_ct(ct: Option<HasContentType>) -> &'static str {\n    ct.map_or(\"Absent\", |_| \"Present\")\n}\n\n#[post(\"/data\", data = \"<_ct>\", rank = 1)]\nfn data_has_ct(_ct: HasContentType) -> &'static str {\n    \"Data Present\"\n}\n\n#[post(\"/data\", rank = 2)]\nfn data_no_ct() -> &'static str {\n    \"Data Absent\"\n}\n\nmod local_request_content_type_tests {\n    use super::*;\n\n    use rocket::{Rocket, Build};\n    use rocket::local::blocking::Client;\n    use rocket::http::ContentType;\n\n    fn rocket() -> Rocket<Build> {\n        rocket::build().mount(\"/\", routes![rg_ct, data_has_ct, data_no_ct])\n    }\n\n    #[test]\n    fn has_no_ct() {\n        let client = Client::debug(rocket()).unwrap();\n\n        let req = client.post(\"/\");\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Absent\".to_string()));\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Absent\".to_string()));\n        assert_eq!(req.dispatch().into_string(), Some(\"Absent\".to_string()));\n\n        let req = client.post(\"/data\");\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Data Absent\".to_string()));\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Data Absent\".to_string()));\n        assert_eq!(req.dispatch().into_string(), Some(\"Data Absent\".to_string()));\n    }\n\n    #[test]\n    fn has_ct() {\n        let client = Client::debug(rocket()).unwrap();\n\n        let req = client.post(\"/\").header(ContentType::JSON);\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Present\".to_string()));\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Present\".to_string()));\n        assert_eq!(req.dispatch().into_string(), Some(\"Present\".to_string()));\n\n        let req = client.post(\"/data\").header(ContentType::JSON);\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Data Present\".to_string()));\n        assert_eq!(req.clone().dispatch().into_string(), Some(\"Data Present\".to_string()));\n        assert_eq!(req.dispatch().into_string(), Some(\"Data Present\".to_string()));\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/local_request_private_cookie-issue-368.rs",
    "content": "#![cfg(feature = \"secrets\")]\n\nuse rocket::http::CookieJar;\n\n#[rocket::get(\"/\")]\nfn return_private_cookie(cookies: &CookieJar<'_>) -> Option<String> {\n    match cookies.get_private(\"cookie_name\") {\n        Some(cookie) => Some(cookie.value().into()),\n        None => None,\n    }\n}\n\nmod tests {\n    use super::*;\n    use rocket::routes;\n    use rocket::local::blocking::Client;\n    use rocket::http::Status;\n\n    #[test]\n    fn private_cookie_is_returned() {\n        let rocket = rocket::build().mount(\"/\", routes![return_private_cookie]);\n\n        let client = Client::debug(rocket).unwrap();\n        let req = client.get(\"/\").private_cookie((\"cookie_name\", \"cookie_value\"));\n        let response = req.dispatch();\n\n        assert_eq!(response.headers().get_one(\"Set-Cookie\"), None);\n        assert_eq!(response.into_string(), Some(\"cookie_value\".into()));\n    }\n\n    #[test]\n    fn regular_cookie_is_not_returned() {\n        let rocket = rocket::build().mount(\"/\", routes![return_private_cookie]);\n\n        let client = Client::debug(rocket).unwrap();\n        let req = client.get(\"/\").cookie((\"cookie_name\", \"cookie_value\"));\n        let response = req.dispatch();\n\n        assert_eq!(response.status(), Status::NotFound);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/many-cookie-jars-at-once.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::http::CookieJar;\n\n#[post(\"/\")]\nfn multi_add(jar_a: &CookieJar<'_>, jar_b: &CookieJar<'_>) {\n    jar_a.add((\"a\", \"v1\"));\n    jar_b.add((\"b\", \"v2\"));\n}\n\n#[get(\"/\")]\nfn multi_get(jar_a: &CookieJar<'_>, jar_b: &CookieJar<'_>, jar_c: &CookieJar<'_>) -> String {\n    let (a, a2, a3) = (jar_a.get(\"a\"), jar_b.get(\"a\"), jar_c.get(\"a\"));\n    let (b, b2, b3) = (jar_a.get(\"b\"), jar_b.get(\"b\"), jar_c.get(\"b\"));\n    assert_eq!(a, a2); assert_eq!(a2, a3);\n    assert_eq!(b, b2); assert_eq!(b2, b3);\n    format!(\"{}{}\", a.unwrap().value(), b.unwrap().value())\n}\n\n#[cfg(test)]\nmod many_cookie_jars_tests {\n    use super::*;\n    use rocket::{Rocket, Build};\n    use rocket::local::blocking::Client;\n\n    fn rocket() -> Rocket<Build> {\n        rocket::build().mount(\"/\", routes![multi_add, multi_get])\n    }\n\n    #[test]\n    fn test_multi_add() {\n        let client = Client::debug(rocket()).unwrap();\n        let response = client.post(\"/\").dispatch();\n        let cookies = response.cookies();\n        assert_eq!(cookies.iter().count(), 2);\n        assert_eq!(cookies.get(\"a\").unwrap().value(), \"v1\");\n        assert_eq!(cookies.get(\"b\").unwrap().value(), \"v2\");\n    }\n\n    #[test]\n    fn test_multi_get() {\n        let client = Client::debug(rocket()).unwrap();\n        let response = client.get(\"/\")\n            .cookie((\"a\", \"a_val\"))\n            .cookie((\"b\", \"hi!\"))\n            .dispatch();\n\n        assert_eq!(response.into_string().unwrap(), \"a_valhi!\");\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/mapped-base-issue-1262.rs",
    "content": "#[macro_use] extern crate rocket;\nuse rocket::{Rocket, Route, Build};\n\npub fn prepend(prefix: &str, route: Route) -> Route {\n    route.map_base(|base| format!(\"{}{}\", prefix, base)).unwrap()\n}\n\npub fn extend_routes(prefix: &str, routes: Vec<Route>) -> Vec<Route> {\n    routes.into_iter()\n        .map(|route| prepend(prefix, route))\n        .collect()\n}\n\nmod a {\n    #[get(\"/b/<id>\")]\n    fn b(id: u8) -> String { id.to_string() }\n\n    pub fn routes() -> Vec<rocket::Route> {\n        super::extend_routes(\"/a\", routes![b])\n    }\n}\n\nfn rocket() -> Rocket<Build> {\n    rocket::build().mount(\"/\", a::routes()).mount(\"/foo\", a::routes())\n}\n\nmod mapped_base_tests {\n    use rocket::local::blocking::Client;\n    use rocket::http::Status;\n\n    #[test]\n    fn only_prefix() {\n        let client = Client::debug(super::rocket()).unwrap();\n\n        let response = client.get(\"/a/b/3\").dispatch();\n        assert_eq!(response.into_string().unwrap(), \"3\");\n\n        let response = client.get(\"/a/b/239\").dispatch();\n        assert_eq!(response.into_string().unwrap(), \"239\");\n\n        let response = client.get(\"/b/239\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n    }\n\n    #[test]\n    fn prefix_and_base() {\n        let client = Client::debug(super::rocket()).unwrap();\n\n        let response = client.get(\"/foo/a/b/23\").dispatch();\n        assert_eq!(response.into_string().unwrap(), \"23\");\n\n        let response = client.get(\"/foo/a/b/99\").dispatch();\n        assert_eq!(response.into_string().unwrap(), \"99\");\n\n        let response = client.get(\"/foo/b/239\").dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/mount_point.rs",
    "content": "#[test]\n#[should_panic]\nfn bad_dynamic_mount() {\n    let _ = rocket::build().mount(\"<name>\", vec![]);\n}\n\n#[test]\nfn good_static_mount() {\n    let _ = rocket::build().mount(\"/abcdefghijkl_mno\", vec![]);\n}\n"
  },
  {
    "path": "core/lib/tests/msgpack_encoding.rs",
    "content": "#![cfg(feature = \"msgpack\")]\n\nuse std::borrow::Cow;\n\nuse rocket::{Rocket, Build};\nuse rocket::serde::msgpack::{self, MsgPack, Compact};\nuse rocket::local::blocking::Client;\n\n#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq)]\nstruct Person<'r> {\n    name: &'r str,\n    age: u8,\n    gender: Gender,\n}\n\n#[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq)]\nenum Gender {\n    Male,\n    Female,\n    NonBinary,\n}\n\n#[rocket::post(\"/named\", data = \"<person>\")]\nfn named(person: MsgPack<Person<'_>>) -> MsgPack<Person<'_>> {\n    person\n}\n\n#[rocket::post(\"/compact\", data = \"<person>\")]\nfn compact(person: MsgPack<Person<'_>>) -> Compact<Person<'_>> {\n    MsgPack(person.into_inner())\n}\n\nfn rocket() -> Rocket<Build> {\n    rocket::build().mount(\"/\", rocket::routes![named, compact])\n}\n\n// The object we're going to roundtrip through the API.\nconst OBJECT: Person<'static> = Person {\n    name: \"Cal\",\n    age: 17,\n    gender: Gender::NonBinary,\n};\n\n// [ \"Cal\", 17, \"NonBinary\" ]\nconst COMPACT_BYTES: &[u8] = &[\n    147, 163, 67, 97, 108, 17, 169, 78, 111, 110, 66, 105, 110, 97, 114, 121\n];\n\n// { \"name\": \"Cal\", \"age\": 17, \"gender\": \"NonBinary\" }\nconst NAMED_BYTES: &[u8] = &[\n    131, 164, 110, 97, 109, 101, 163, 67, 97, 108, 163, 97, 103, 101, 17, 166,\n    103, 101, 110, 100, 101, 114, 169, 78, 111, 110, 66, 105, 110, 97, 114, 121\n];\n\n#[test]\nfn check_roundtrip() {\n    let client = Client::debug(rocket()).unwrap();\n    let inputs: &[(&'static str, Cow<'static, [u8]>)] = &[\n        (\"objpack\", msgpack::to_vec(&OBJECT).unwrap().into()),\n        (\"named bytes\", NAMED_BYTES.into()),\n        (\"compact bytes\", COMPACT_BYTES.into()),\n    ];\n\n    for (name, input) in inputs {\n        let compact = client.post(\"/compact\").body(input).dispatch();\n        assert_eq!(compact.into_bytes().unwrap(), COMPACT_BYTES, \"{name} mismatch\");\n\n        let named = client.post(\"/named\").body(input).dispatch();\n        assert_eq!(named.into_bytes().unwrap(), NAMED_BYTES, \"{name} mismatch\");\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/multipart-limit.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::{Config, Build, Rocket};\nuse rocket::{data::Limits, form::Form};\nuse rocket::http::{ContentType, Status};\nuse ubyte::{ToByteUnit, ByteUnit};\n\n#[derive(FromForm)]\nstruct Data<'r> {\n    foo: Option<&'r str>,\n}\n\n#[rocket::post(\"/\", data = \"<form>\")]\nfn form<'r>(form: Form<Data<'r>>) -> &'r str {\n    form.foo.unwrap_or(\"missing\")\n}\n\nfn rocket_with_form_data_limit(limit: ByteUnit) -> Rocket<Build> {\n    rocket::custom(Config {\n        limits: Limits::default().limit(\"data-form\", limit),\n        ..Config::debug_default()\n    }).mount(\"/\", routes![form])\n}\n\n#[test]\nfn test_multipart_limit() {\n    use rocket::local::blocking::Client;\n\n    let body = &[\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"foo\"; filename=\"foo.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"hi\",\n        \"--X-BOUNDARY--\",\n        \"\",\n    ].join(\"\\r\\n\");\n\n    let client = Client::debug(rocket_with_form_data_limit(body.len().bytes())).unwrap();\n    let response = client.post(\"/\")\n        .header(\"multipart/form-data; boundary=X-BOUNDARY\".parse::<ContentType>().unwrap())\n        .body(body)\n        .dispatch();\n\n    assert_eq!(response.into_string().unwrap(), \"hi\");\n\n    let client = Client::debug(rocket_with_form_data_limit(body.len().bytes() - 1)).unwrap();\n    let response = client.post(\"/\")\n        .header(\"multipart/form-data; boundary=X-BOUNDARY\".parse::<ContentType>().unwrap())\n        .body(body)\n        .dispatch();\n\n    assert_eq!(response.status(), Status::PayloadTooLarge);\n}\n"
  },
  {
    "path": "core/lib/tests/nested-fairing-attaches.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse rocket::{Rocket, State, Build};\nuse rocket::fairing::AdHoc;\nuse rocket::http::Method;\n\n#[derive(Default)]\nstruct Counter {\n    attach: AtomicUsize,\n    get: AtomicUsize,\n}\n\n#[get(\"/\")]\nfn index(counter: &State<Counter>) -> String {\n    let attaches = counter.attach.load(Ordering::Relaxed);\n    let gets = counter.get.load(Ordering::Acquire);\n    format!(\"{}, {}\", attaches, gets)\n}\n\nfn rocket() -> Rocket<Build> {\n    rocket::build()\n        .mount(\"/\", routes![index])\n        .attach(AdHoc::on_ignite(\"Outer\", |rocket| async {\n            let counter = Counter::default();\n            counter.attach.fetch_add(1, Ordering::Relaxed);\n            let rocket = rocket.manage(counter)\n                .attach(AdHoc::on_request(\"Inner\", |req, _| {\n                    Box::pin(async move {\n                        if req.method() == Method::Get {\n                            let counter = req.rocket().state::<Counter>().unwrap();\n                            counter.get.fetch_add(1, Ordering::Release);\n                        }\n                    })\n                }));\n\n            rocket\n        }))\n}\n\nmod nested_fairing_attaches_tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n\n    #[test]\n    fn test_counts() {\n        let client = Client::debug(rocket()).unwrap();\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.into_string(), Some(\"1, 1\".into()));\n\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.into_string(), Some(\"1, 2\".into()));\n\n        client.get(\"/\").dispatch();\n        client.get(\"/\").dispatch();\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.into_string(), Some(\"1, 5\".into()));\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/on_launch_fairing_can_inspect_port.rs",
    "content": "use std::net::{SocketAddr, Ipv4Addr};\n\nuse rocket::config::Config;\nuse rocket::fairing::AdHoc;\nuse rocket::futures::channel::oneshot;\nuse rocket::listener::tcp::TcpListener;\n\n#[rocket::async_test]\nasync fn on_ignite_fairing_can_inspect_port() {\n    let (tx, rx) = oneshot::channel();\n    let rocket = rocket::custom(Config::debug_default())\n        .attach(AdHoc::on_liftoff(\"Send Port -> Channel\", move |rocket| {\n            Box::pin(async move {\n                let tcp = rocket.endpoints().find_map(|v| v.tcp());\n                tx.send(tcp.unwrap().port()).expect(\"send okay\");\n            })\n        }));\n\n    let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 0));\n    rocket::tokio::spawn(rocket.try_launch_on(TcpListener::bind(addr)));\n    assert_ne!(rx.await.unwrap(), 0);\n}\n"
  },
  {
    "path": "core/lib/tests/panic-handling.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::{Request, Rocket, Route, Catcher, Build, route, catcher};\nuse rocket::data::Data;\nuse rocket::http::{Method, Status};\nuse rocket::local::blocking::Client;\n\n#[get(\"/panic\")]\nfn panic_route() -> &'static str {\n    panic!(\"Panic in route\")\n}\n\n#[catch(404)]\nfn panic_catcher() -> &'static str {\n    panic!(\"Panic in catcher\")\n}\n\n#[catch(500)]\nfn ise() -> &'static str {\n    \"Hey, sorry! :(\"\n}\n\nfn pre_future_route<'r>(_: &'r Request<'_>, _: Data<'r>) -> route::BoxFuture<'r> {\n    panic!(\"hey now...\");\n}\n\nfn rocket() -> Rocket<Build> {\n    rocket::build()\n        .mount(\"/\", routes![panic_route])\n        .mount(\"/\", vec![Route::new(Method::Get, \"/pre\", pre_future_route)])\n}\n\n#[test]\nfn catches_route_panic() {\n    let rocket = rocket().register(\"/\", catchers![panic_catcher, ise]);\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/panic\").dispatch();\n    assert_eq!(response.status(), Status::InternalServerError);\n    assert_eq!(response.into_string().unwrap(), \"Hey, sorry! :(\");\n}\n\n#[test]\nfn catches_catcher_panic() {\n    let rocket = rocket().register(\"/\", catchers![panic_catcher, ise]);\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/noroute\").dispatch();\n    assert_eq!(response.status(), Status::InternalServerError);\n    assert_eq!(response.into_string().unwrap(), \"Hey, sorry! :(\");\n}\n\n#[test]\nfn catches_double_panic() {\n    #[catch(500)]\n    fn double_panic() {\n        panic!(\"so, so sorry...\")\n    }\n\n    let rocket = rocket().register(\"/\", catchers![panic_catcher, double_panic]);\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/noroute\").dispatch();\n    assert_eq!(response.status(), Status::InternalServerError);\n    assert!(response.into_string().unwrap().contains(\"Rocket\"));\n}\n\n#[test]\nfn catches_early_route_panic() {\n    let rocket = rocket().register(\"/\", catchers![panic_catcher, ise]);\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/pre\").dispatch();\n    assert_eq!(response.status(), Status::InternalServerError);\n    assert_eq!(response.into_string().unwrap(), \"Hey, sorry! :(\");\n}\n\n#[test]\nfn catches_early_catcher_panic() {\n    fn pre_future_catcher<'r>(_: Status, _: &'r Request<'_>) -> catcher::BoxFuture<'r> {\n        panic!(\"a panicking pre-future catcher\")\n    }\n\n    let rocket = rocket()\n        .register(\"/\", vec![Catcher::new(404, pre_future_catcher)])\n        .register(\"/\", catchers![ise]);\n\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/idontexist\").dispatch();\n    assert_eq!(response.status(), Status::InternalServerError);\n    assert_eq!(response.into_string().unwrap(), \"Hey, sorry! :(\");\n}\n"
  },
  {
    "path": "core/lib/tests/precise-content-type-matching.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[post(\"/\", format = \"application/json\")]\nfn specified() -> &'static str {\n    \"specified\"\n}\n\n#[post(\"/\", rank = 2)]\nfn unspecified() -> &'static str {\n    \"unspecified\"\n}\n\n#[post(\"/\", format = \"application/json\")]\nfn specified_json() -> &'static str {\n    \"specified_json\"\n}\n\n#[post(\"/\", format = \"text/html\")]\nfn specified_html() -> &'static str {\n    \"specified_html\"\n}\n\nmod tests {\n    use super::*;\n\n    use rocket::{Rocket, Build};\n    use rocket::local::blocking::Client;\n    use rocket::http::{Status, ContentType};\n\n    fn rocket() -> Rocket<Build> {\n        rocket::build()\n            .mount(\"/first\", routes![specified, unspecified])\n            .mount(\"/second\", routes![specified_json, specified_html])\n    }\n\n    macro_rules! check_dispatch {\n        ($mount:expr, $ct:expr, $body:expr) => (\n            let client = Client::debug(rocket()).unwrap();\n            let mut req = client.post($mount);\n            let ct: Option<ContentType> = $ct;\n            if let Some(ct) = ct {\n                req.add_header(ct);\n            }\n\n            let response = req.dispatch();\n            let status = response.status();\n            let body_str = response.into_string();\n            let body: Option<&'static str> = $body;\n            match body {\n                Some(string) => assert_eq!(body_str, Some(string.to_string())),\n                None => assert_eq!(status, Status::NotFound)\n            }\n        )\n    }\n\n    #[test]\n    fn exact_match_or_forward() {\n        check_dispatch!(\"/first\", Some(ContentType::JSON), Some(\"specified\"));\n        check_dispatch!(\"/first\", None, Some(\"unspecified\"));\n        check_dispatch!(\"/first\", Some(ContentType::HTML), Some(\"unspecified\"));\n    }\n\n    #[test]\n    fn exact_match_or_none() {\n        check_dispatch!(\"/second\", Some(ContentType::JSON), Some(\"specified_json\"));\n        check_dispatch!(\"/second\", Some(ContentType::HTML), Some(\"specified_html\"));\n        check_dispatch!(\"/second\", Some(ContentType::CSV), None);\n        check_dispatch!(\"/second\", None, None);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/raw-strings-multipart-files-1987.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::form::Form;\nuse rocket::http::ContentType;\nuse rocket::local::blocking::Client;\n\n#[derive(FromForm)]\nstruct Data<'r> {\n    foo: &'r str,\n    bar: &'r str,\n    baz: &'r str,\n}\n\n#[rocket::post(\"/\", data = \"<form>\")]\nfn form(form: Form<Data<'_>>) -> String {\n    form.foo.to_string() + form.bar + form.baz\n}\n\n#[test]\nfn test_multipart_raw_strings_from_files() {\n    let body = &[\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"foo\"; filename=\"foo.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"hi\",\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"bar\"; filename=\"bar.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"hey\",\n        \"--X-BOUNDARY\",\n        r#\"Content-Disposition: form-data; name=\"baz\"; filename=\"baz.txt\"\"#,\n        \"Content-Type: text/plain\",\n        \"\",\n        \"bye\",\n        \"--X-BOUNDARY--\",\n        \"\",\n    ].join(\"\\r\\n\");\n\n    let client = Client::debug_with(rocket::routes![form]).unwrap();\n    let response = client.post(\"/\")\n        .header(\"multipart/form-data; boundary=X-BOUNDARY\".parse::<ContentType>().unwrap())\n        .body(body)\n        .dispatch();\n\n    assert_eq!(response.into_string().unwrap(), \"hiheybye\");\n}\n"
  },
  {
    "path": "core/lib/tests/recursive-singleton-fairing.rs",
    "content": "use rocket::{Rocket, Build, Config};\nuse rocket::fairing::{self, Fairing, Info, Kind};\nuse rocket::error::ErrorKind;\n\nstruct Singleton(Kind, Kind, bool);\n\n#[rocket::async_trait]\nimpl Fairing for Singleton {\n    fn info(&self) -> Info {\n        Info {\n            name: \"Singleton\",\n            kind: self.0\n        }\n    }\n\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {\n        if self.2 {\n            Ok(rocket.attach(Singleton(self.1, self.1, false)))\n        } else {\n            Ok(rocket)\n        }\n    }\n}\n\n\n// Have => two `Singleton`s. This is okay; we keep the latter.\n#[rocket::async_test]\nasync fn recursive_singleton_ok() {\n    let result = rocket::custom(Config::debug_default())\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Singleton, false))\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Singleton, false))\n        .ignite()\n        .await;\n\n    assert!(result.is_ok(), \"{:?}\", result);\n\n    let result = rocket::custom(Config::debug_default())\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Singleton, false))\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Singleton, false))\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Singleton, false))\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Singleton, false))\n        .ignite()\n        .await;\n\n    assert!(result.is_ok(), \"{:?}\", result);\n}\n\n// Have a `Singleton` add itself `on_ignite()`. Since it already ran, the one it\n// adds can't be unique, so ensure we error in this case.\n#[rocket::async_test]\nasync fn recursive_singleton_bad() {\n    #[track_caller]\n    fn assert_err(error: rocket::Error) {\n        if let ErrorKind::FailedFairings(v) = error.kind() {\n            assert_eq!(v.len(), 1);\n            assert_eq!(v[0].name, \"Singleton\");\n        } else {\n            panic!(\"unexpected error: {:?}\", error);\n        }\n    }\n\n    let result = rocket::custom(Config::debug_default())\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Ignite | Kind::Singleton, true))\n        .ignite()\n        .await;\n\n    assert_err(result.unwrap_err());\n\n    let result = rocket::custom(Config::debug_default())\n        .attach(Singleton(Kind::Ignite | Kind::Singleton, Kind::Singleton, true))\n        .ignite()\n        .await;\n\n    assert_err(result.unwrap_err());\n\n    let result = rocket::custom(Config::debug_default())\n        .attach(Singleton(Kind::Ignite, Kind::Singleton, true))\n        .ignite()\n        .await;\n\n    assert_err(result.unwrap_err());\n}\n"
  },
  {
    "path": "core/lib/tests/redirect_from_catcher-issue-113.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::response::Redirect;\n\n#[catch(404)]\nfn not_found() -> Redirect {\n    Redirect::to(\"/\")\n}\n\nmod tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n    use rocket::http::Status;\n\n    #[test]\n    fn error_catcher_redirect() {\n        let client = Client::debug(rocket::build().register(\"/\", catchers![not_found])).unwrap();\n        let response = client.get(\"/unknown\").dispatch();\n\n        let location: Vec<_> = response.headers().get(\"location\").collect();\n        assert_eq!(response.status(), Status::SeeOther);\n        assert_eq!(location, vec![\"/\"]);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/replace-content-type-518.rs",
    "content": "use rocket::{Rocket, Build};\nuse rocket::{fairing::AdHoc, http::ContentType, local::blocking::Client};\n\n#[rocket::post(\"/\", data = \"<_data>\", format = \"json\")]\nfn index(_data: rocket::Data<'_>) -> &'static str { \"json\" }\n\n#[rocket::post(\"/\", data = \"<_data>\", rank = 2)]\nfn other_index(_data: rocket::Data<'_>) -> &'static str { \"other\" }\n\nfn rocket() -> Rocket<Build> {\n    rocket::build()\n        .mount(\"/\", rocket::routes![index, other_index])\n        .attach(AdHoc::on_request(\"Change CT\", |req, _| Box::pin(async move {\n            let need_ct = req.content_type().is_none();\n            if req.uri().path().starts_with(\"/add\") {\n                req.set_uri(rocket::uri!(index));\n                if need_ct { req.add_header(ContentType::JSON); }\n            } else if need_ct {\n                req.replace_header(ContentType::JSON);\n            }\n        })))\n}\n\n#[test]\nfn check_fairing_changes_content_type() {\n    let client = Client::debug(rocket()).unwrap();\n    let response = client.post(\"/\").header(ContentType::PNG).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"other\");\n\n    let response = client.post(\"/\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"json\");\n\n    let response = client.post(\"/add\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"json\");\n\n    let response = client.post(\"/add\").header(ContentType::HTML).dispatch();\n    assert_eq!(response.into_string().unwrap(), \"other\");\n}\n"
  },
  {
    "path": "core/lib/tests/responder_lifetime-issue-345.rs",
    "content": "#![allow(dead_code)] // This test is only here so that we can ensure it compiles.\n\n#[macro_use] extern crate rocket;\n\nuse rocket::{Request, State};\nuse rocket::response::{Responder, Result};\n\nstruct SomeState;\n\npub struct CustomResponder<'r, R> {\n    responder: R,\n    state: &'r SomeState,\n}\n\nimpl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for CustomResponder<'r, R> {\n    fn respond_to(self, req: &'r Request<'_>) -> Result<'o> {\n        self.responder.respond_to(req)\n    }\n}\n\n#[get(\"/unit_state\")]\nfn unit_state(state: &State<SomeState>) -> CustomResponder<'_, ()> {\n    CustomResponder { responder: (), state: &*state }\n}\n\n#[get(\"/string_state\")]\nfn string_state(state: &State<SomeState>) -> CustomResponder<'_, String> {\n    CustomResponder { responder: \"\".to_string(), state: &*state }\n}\n"
  },
  {
    "path": "core/lib/tests/route_guard.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse std::path::{Path, PathBuf};\nuse rocket::http::ext::Normalize;\nuse rocket::Route;\n\n#[get(\"/<path..>\")]\nfn files(route: &Route, path: PathBuf) -> String {\n    Path::new(&route.uri.base()).join(path).normalized_str().to_string()\n}\n\nmod route_guard_tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n\n    fn assert_path(client: &Client, path: &str) {\n        let res = client.get(path).dispatch();\n        assert_eq!(res.into_string(), Some(path.into()));\n    }\n\n    #[test]\n    fn check_mount_path() {\n        let rocket = rocket::build()\n            .mount(\"/first\", routes![files])\n            .mount(\"/second\", routes![files]);\n\n        let client = Client::debug(rocket).unwrap();\n        assert_path(&client, \"/first/some/path\");\n        assert_path(&client, \"/second/some/path\");\n        assert_path(&client, \"/first/second/b/c\");\n        assert_path(&client, \"/second/a/b/c\");\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/scoped-uri.rs",
    "content": "use rocket::{Rocket, Build};\nuse rocket::local::blocking::Client;\n\nmod inner {\n    use rocket::uri;\n\n    #[rocket::get(\"/\")]\n    pub fn hello() -> String {\n        format!(\"Hello! Try {}.\", uri!(super::hello_name(\"Rust 2018\")))\n    }\n}\n\n#[rocket::get(\"/<name>\")]\nfn hello_name(name: String) -> String {\n    format!(\"Hello, {}! This is {}.\", name, rocket::uri!(hello_name(&name)))\n}\n\nfn rocket() -> Rocket<Build> {\n    rocket::build()\n        .mount(\"/\", rocket::routes![hello_name])\n        .mount(\"/\", rocket::routes![inner::hello])\n}\n\n#[test]\nfn test_inner_hello() {\n    let client = Client::debug(rocket()).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert_eq!(response.into_string(), Some(\"Hello! Try /Rust%202018.\".into()));\n}\n\n#[test]\nfn test_hello_name() {\n    let client = Client::debug(rocket()).unwrap();\n    let response = client.get(\"/Rust%202018\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"Hello, Rust 2018! This is /Rust%202018.\");\n}\n"
  },
  {
    "path": "core/lib/tests/segments-issues-41-86.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::http::uri::{Segments, fmt::Path};\n\n#[get(\"/test/<path..>\")]\nfn test(path: Segments<'_, Path>) -> String {\n    path.collect::<Vec<_>>().join(\"/\")\n}\n\n#[get(\"/two/<path..>\")]\nfn two(path: Segments<'_, Path>) -> String {\n    path.collect::<Vec<_>>().join(\"/\")\n}\n\n#[get(\"/one/two/<path..>\")]\nfn one_two(path: Segments<'_, Path>) -> String {\n    path.collect::<Vec<_>>().join(\"/\")\n}\n\n#[get(\"/<path..>\", rank = 2)]\nfn none(path: Segments<'_, Path>) -> String {\n    path.collect::<Vec<_>>().join(\"/\")\n}\n\n#[get(\"/static/<user>/is/<path..>\")]\nfn dual(user: String, path: Segments<'_, Path>) -> String {\n    user + \"/is/\" + &path.collect::<Vec<_>>().join(\"/\")\n}\n\nmod tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n\n    #[test]\n    fn segments_works() {\n        let rocket = rocket::build()\n            .mount(\"/\", routes![test, two, one_two, none, dual])\n            .mount(\"/point\", routes![test, two, one_two, dual]);\n        let client = Client::debug(rocket).unwrap();\n\n        // We construct a path that matches each of the routes above. We ensure the\n        // prefix is stripped, confirming that dynamic segments are working.\n        for prefix in &[\"\", \"/test\", \"/two\", \"/one/two\",\n                        \"/point/test\", \"/point/two\", \"/point/one/two\",\n                        \"/static\", \"/point/static\"]\n        {\n            let path = \"this/is/the/path/we/want\";\n            let response = client.get(format!(\"{}/{}\", prefix, path)).dispatch();\n            assert_eq!(response.into_string(), Some(path.into()));\n        }\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/sentinel.rs",
    "content": "use rocket::{*, either::Either, error::ErrorKind::SentinelAborts};\n\n#[get(\"/two\")]\nfn two_states(_one: &State<u32>, _two: &State<String>) {}\n\n#[post(\"/one\", data = \"<s>\")]\nfn one_state<'r>(_three: &'r State<u8>, s: &'r str) -> &'r str { s }\n\n#[async_test]\nasync fn state_sentinel_works() {\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![two_states])\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 2));\n\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![two_states])\n        .manage(String::new())\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![two_states])\n        .manage(1 as u32)\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    let result = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![two_states])\n        .manage(String::new())\n        .manage(1 as u32)\n        .ignite().await;\n\n    assert!(result.is_ok());\n\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![one_state])\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    let result = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![one_state])\n        .manage(1 as u8)\n        .ignite().await;\n\n    assert!(result.is_ok());\n\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![one_state, two_states])\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 3));\n\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![one_state, two_states])\n        .manage(1 as u32)\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 2));\n\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![one_state, two_states])\n        .manage(1 as u8)\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 2));\n\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![one_state, two_states])\n        .manage(1 as u32)\n        .manage(1 as u8)\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    let result = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![one_state, two_states])\n        .manage(1 as u32)\n        .manage(1 as u8)\n        .manage(String::new())\n        .ignite().await;\n\n    assert!(result.is_ok());\n}\n\nstruct Data;\n\n#[crate::async_trait]\nimpl<'r> data::FromData<'r> for Data {\n    type Error = Error;\n    async fn from_data(_: &'r Request<'_>, _: data::Data<'r>) -> data::Outcome<'r, Self> {\n        unimplemented!()\n    }\n}\n\nimpl Sentinel for Data {\n    fn abort(rocket: &Rocket<Ignite>) -> bool {\n        rocket.state::<Data>().is_none()\n    }\n}\n\n#[post(\"/data\", data = \"<_data>\")]\nfn with_data(_data: Data) {}\n\n#[async_test]\nasync fn data_sentinel_works() {\n    let err = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![with_data])\n        .ignite().await\n        .unwrap_err();\n\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    let result = rocket::build()\n        .reconfigure(Config::debug_default())\n        .mount(\"/\", routes![with_data])\n        .manage(Data)\n        .ignite().await;\n\n    assert!(result.is_ok());\n}\n\n#[test]\nfn inner_sentinels_detected() {\n    use rocket::local::blocking::Client;\n\n    #[derive(Responder)]\n    struct MyThing<T>(T);\n\n    struct ResponderSentinel;\n\n    impl<'r, 'o: 'r> response::Responder<'r, 'o> for ResponderSentinel {\n        fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {\n            unimplemented!()\n        }\n    }\n\n    impl Sentinel for ResponderSentinel {\n        fn abort(_: &Rocket<Ignite>) -> bool {\n            true\n        }\n    }\n\n    #[get(\"/\")]\n    fn route() -> MyThing<ResponderSentinel> { todo!() }\n\n    let err = Client::debug_with(routes![route]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[derive(Responder)]\n    struct Inner<T>(T);\n\n    #[get(\"/\")]\n    fn inner() -> MyThing<Inner<ResponderSentinel>> { todo!() }\n\n    let err = Client::debug_with(routes![inner]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[get(\"/\")]\n    fn inner_either() -> Either<Inner<ResponderSentinel>, ResponderSentinel> { todo!() }\n\n    let err = Client::debug_with(routes![inner_either]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 2));\n\n    #[derive(Responder)]\n    struct Block<T>(T);\n\n    impl<T> Sentinel for Block<T> {\n        fn abort(_: &Rocket<Ignite>) -> bool {\n            false\n        }\n    }\n\n    #[get(\"/\")]\n    fn blocked() -> Block<ResponderSentinel> { todo!() }\n\n    Client::debug_with(routes![blocked]).expect(\"no sentinel errors\");\n\n    #[get(\"/a\")]\n    fn inner_b() -> Either<Inner<Block<ResponderSentinel>>, Block<ResponderSentinel>> {\n        todo!()\n    }\n\n    #[get(\"/b\")]\n    fn inner_b2() -> Either<Block<Inner<ResponderSentinel>>, Block<ResponderSentinel>> {\n        todo!()\n    }\n\n    Client::debug_with(routes![inner_b, inner_b2]).expect(\"no sentinel errors\");\n\n    #[get(\"/\")]\n    fn half_b() -> Either<Inner<ResponderSentinel>, Block<ResponderSentinel>> {\n        todo!()\n    }\n\n    let err = Client::debug_with(routes![half_b]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    use rocket::response::Responder;\n\n    #[get(\"/\")]\n    fn half_c<'r>() -> Either<\n        Inner<impl Responder<'r, 'static>>,\n        Result<ResponderSentinel, Inner<ResponderSentinel>>\n    > {\n        Either::Left(Inner(()))\n    }\n\n    let err = Client::debug_with(routes![half_c]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 2));\n\n    #[get(\"/\")]\n    fn half_d<'r>() -> Either<\n        Inner<impl Responder<'r, 'static>>,\n        Result<Block<ResponderSentinel>, Inner<ResponderSentinel>>\n    > {\n        Either::Left(Inner(()))\n    }\n\n    let err = Client::debug_with(routes![half_d]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    // The special `Result` implementation.\n    type MyResult = Result<ResponderSentinel, ResponderSentinel>;\n\n    #[get(\"/\")]\n    fn half_e<'r>() -> Either<Inner<impl Responder<'r, 'static>>, MyResult> {\n        Either::Left(Inner(()))\n    }\n\n    let err = Client::debug_with(routes![half_e]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    // Another specialized sentinel.\n\n    #[get(\"/\")] fn either_route() -> Either<ResponderSentinel, ResponderSentinel> { todo!() }\n    let err = Client::debug_with(routes![either_route]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[get(\"/\")] fn either_route2() -> Either<ResponderSentinel, ()> { todo!() }\n    let err = Client::debug_with(routes![either_route2]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[get(\"/\")] fn either_route3() -> Either<(), ResponderSentinel> { todo!() }\n    let err = Client::debug_with(routes![either_route3]).unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 1));\n\n    #[get(\"/\")] fn either_route4() -> Either<(), ()> { todo!() }\n    Client::debug_with(routes![either_route4]).expect(\"no sentinel error\");\n}\n\n#[async_test]\nasync fn known_macro_sentinel_works() {\n    use rocket::response::stream::{TextStream, ByteStream, ReaderStream};\n    use rocket::local::asynchronous::Client;\n    use rocket::tokio::io::AsyncRead;\n\n    #[derive(Responder)]\n    struct TextSentinel<'r>(&'r str);\n\n    impl Sentinel for TextSentinel<'_> {\n        fn abort(_: &Rocket<Ignite>) -> bool {\n            true\n        }\n    }\n\n    impl AsRef<str> for TextSentinel<'_> {\n        fn as_ref(&self) -> &str {\n            self.0\n        }\n    }\n\n    impl AsRef<[u8]> for TextSentinel<'_> {\n        fn as_ref(&self) -> &[u8] {\n            self.0.as_bytes()\n        }\n    }\n\n    impl AsyncRead for TextSentinel<'_> {\n        fn poll_read(\n            self: std::pin::Pin<&mut Self>,\n            _: &mut futures::task::Context<'_>,\n            _: &mut tokio::io::ReadBuf<'_>,\n        ) -> futures::task::Poll<std::io::Result<()>> {\n            futures::task::Poll::Ready(Ok(()))\n        }\n    }\n\n    #[get(\"/text\")]\n    fn text<'r>() -> TextStream![TextSentinel<'r>] {\n        TextStream!(yield TextSentinel(\"hi\");)\n    }\n\n    #[get(\"/<a>\")]\n    fn byte(a: &str) -> ByteStream![TextSentinel<'_>] {\n        ByteStream!(yield TextSentinel(a);)\n    }\n\n    #[get(\"/<_a>/<b>\")]\n    fn reader<'b>(_a: &str, b: &'b str) -> ReaderStream![TextSentinel<'b>] {\n        ReaderStream!(yield TextSentinel(b);)\n    }\n\n    macro_rules! UnknownStream {\n        ($t:ty) => (ReaderStream![$t])\n    }\n\n    #[get(\"/ignore\")]\n    fn ignore() -> UnknownStream![TextSentinel<'static>] {\n        ReaderStream!(yield TextSentinel(\"hi\");)\n    }\n\n    let err = Client::debug_with(routes![text, byte, reader, ignore]).await.unwrap_err();\n    assert!(matches!(err.kind(), SentinelAborts(vec) if vec.len() == 3));\n}\n"
  },
  {
    "path": "core/lib/tests/session-cookies-issue-1506.rs",
    "content": "#![cfg(feature = \"secrets\")]\n\nuse rocket::http::{CookieJar, Cookie};\n\n#[rocket::get(\"/\")]\nfn index(jar: &CookieJar<'_>) {\n    jar.add_private(Cookie::build((\"key\", \"value\")).expires(None));\n}\n\nmod test_session_cookies {\n    use super::*;\n    use rocket::local::blocking::Client;\n\n    #[test]\n    fn session_cookie_is_session() {\n        let rocket = rocket::build().mount(\"/\", rocket::routes![index]);\n        let client = Client::debug(rocket).unwrap();\n\n        let response = client.get(\"/\").dispatch();\n        let cookie = response.cookies().get_private(\"key\").unwrap();\n        assert_eq!(cookie.expires_datetime(), None);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/shield.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::Config;\nuse rocket::http::Status;\nuse rocket::local::blocking::{Client, LocalResponse};\nuse rocket::shield::*;\n\nuse time::Duration;\n\n#[get(\"/\")] fn hello() { }\n\nmacro_rules! assert_header {\n    ($response:ident, $name:expr, $value:expr) => {\n        match $response.headers().get_one($name) {\n            Some(value) => assert_eq!(value, $value),\n            None => panic!(\"missing header '{}' with value '{}'\", $name, $value)\n        }\n    };\n}\n\nmacro_rules! assert_no_header {\n    ($response:ident, $name:expr) => {\n        if let Some(value) = $response.headers().get_one($name) {\n            panic!(\"unexpected header: '{}={}\", $name, value);\n        }\n    };\n}\n\nmacro_rules! dispatch {\n    ($shield:expr, $closure:expr) => {{\n        let rocket = rocket::build().mount(\"/\", routes![hello]).attach($shield);\n        let client = Client::debug(rocket).unwrap();\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        $closure(response)\n    }}\n}\n\n#[test]\nfn default_shield() {\n    let client = Client::debug(rocket::build()).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert_header!(response, \"Permissions-Policy\", \"interest-cohort=()\");\n    assert_header!(response, \"X-Frame-Options\", \"SAMEORIGIN\");\n    assert_header!(response, \"X-Content-Type-Options\", \"nosniff\");\n\n    let client = Client::debug(rocket::custom(Config::debug_default())).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert_header!(response, \"Permissions-Policy\", \"interest-cohort=()\");\n    assert_header!(response, \"X-Frame-Options\", \"SAMEORIGIN\");\n    assert_header!(response, \"X-Content-Type-Options\", \"nosniff\");\n}\n\n#[test]\nfn shield_singleton() {\n    let rocket = rocket::build().attach(Shield::new());\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert_no_header!(response, \"Permissions-Policy\");\n    assert_no_header!(response, \"X-Frame-Options\");\n    assert_no_header!(response, \"X-Content-Type-Options\");\n\n    let rocket = rocket::custom(Config::debug_default()).attach(Shield::new());\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert_no_header!(response, \"Permissions-Policy\");\n    assert_no_header!(response, \"X-Frame-Options\");\n    assert_no_header!(response, \"X-Content-Type-Options\");\n}\n\n#[test]\nfn default_headers_test() {\n    dispatch!(Shield::default(), |response: LocalResponse<'_>| {\n        assert_header!(response, \"Permissions-Policy\", \"interest-cohort=()\");\n        assert_header!(response, \"X-Frame-Options\", \"SAMEORIGIN\");\n        assert_header!(response, \"X-Content-Type-Options\", \"nosniff\");\n    })\n}\n\n#[test]\nfn disable_headers_test() {\n    let shield = Shield::default().disable::<Permission>();\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"X-Frame-Options\", \"SAMEORIGIN\");\n        assert_header!(response, \"X-Content-Type-Options\", \"nosniff\");\n        assert_no_header!(response, \"Permissions-Policy\");\n    });\n\n    let shield = Shield::default().disable::<Frame>();\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"Permissions-Policy\", \"interest-cohort=()\");\n        assert_header!(response, \"X-Content-Type-Options\", \"nosniff\");\n        assert_no_header!(response, \"X-Frame-Options\");\n    });\n\n    let shield = Shield::default()\n        .disable::<Frame>()\n        .disable::<Permission>()\n        .disable::<NoSniff>();\n\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_no_header!(response, \"X-Frame-Options\");\n        assert_no_header!(response, \"Permissions-Policy\");\n        assert_no_header!(response, \"X-Content-Type-Options\");\n    });\n\n    dispatch!(Shield::new(), |response: LocalResponse<'_>| {\n        assert_no_header!(response, \"X-Frame-Options\");\n        assert_no_header!(response, \"Permissions-Policy\");\n        assert_no_header!(response, \"X-Content-Type-Options\");\n    });\n}\n\n#[test]\nfn additional_headers_test() {\n    let shield = Shield::default()\n        .enable(Hsts::default())\n        .enable(ExpectCt::default())\n        .enable(Referrer::default());\n\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(\n            response,\n            \"Strict-Transport-Security\",\n            format!(\"max-age={}\", Duration::days(365).whole_seconds())\n        );\n\n        assert_header!(\n            response,\n            \"Expect-CT\",\n            format!(\"max-age={}, enforce\", Duration::days(30).whole_seconds())\n        );\n\n        assert_header!(response, \"Referrer-Policy\", \"no-referrer\");\n    })\n}\n\n#[test]\nfn uri_test() {\n    let enforce_uri = uri!(\"https://rocket.rs\");\n    let shield = Shield::default()\n        .enable(ExpectCt::ReportAndEnforce(Duration::seconds(30), enforce_uri));\n\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"Expect-CT\",\n            \"max-age=30, enforce, report-uri=\\\"https://rocket.rs\\\"\");\n    });\n}\n\n#[test]\nfn prefetch_test() {\n    let shield = Shield::default().enable(Prefetch::default());\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"X-DNS-Prefetch-Control\", \"off\");\n    });\n\n    let shield = Shield::default().enable(Prefetch::Off);\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"X-DNS-Prefetch-Control\", \"off\");\n    });\n\n    let shield = Shield::default().enable(Prefetch::On);\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"X-DNS-Prefetch-Control\", \"on\");\n    });\n}\n\n#[test]\n#[should_panic]\nfn bad_uri_permission_test() {\n    let uri = uri!(\"http://:200\");\n    Permission::allowed(Feature::Usb, Allow::Origin(uri));\n}\n\n#[test]\n#[should_panic]\nfn bad_uri_permission_test2() {\n    let uri = uri!(\"http://:200\");\n    Permission::default().allow(Feature::Camera, Allow::Origin(uri));\n}\n\n#[test]\nfn permission_test() {\n    let shield = Shield::default().enable(Permission::default());\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"Permissions-Policy\", \"interest-cohort=()\");\n    });\n\n    let shield = Shield::default().enable(Permission::blocked(Feature::Usb));\n    dispatch!(shield, |response: LocalResponse<'_>| {\n        assert_header!(response, \"Permissions-Policy\", \"usb=()\");\n    });\n\n    let permission = Permission::blocked(Feature::Usb)\n        .block(Feature::Camera)\n        .block(Feature::WebShare);\n\n    let shield = Shield::default().enable(permission);\n    dispatch!(shield, |r: LocalResponse<'_>| {\n        assert_header!(r, \"Permissions-Policy\", \"usb=(), camera=(), web-share=()\");\n    });\n\n    let permission = Permission::blocked(Feature::Usb)\n        .allow(Feature::Camera, [Allow::Any, Allow::This])\n        .block(Feature::WebShare);\n\n    let shield = Shield::default().enable(permission);\n    dispatch!(shield, |r: LocalResponse<'_>| {\n        assert_header!(r, \"Permissions-Policy\", \"usb=(), camera=(*), web-share=()\");\n    });\n\n    let permission = Permission::blocked(Feature::Usb)\n        .allow(Feature::Camera, [Allow::This])\n        .block(Feature::WebShare);\n\n    let shield = Shield::default().enable(permission);\n    dispatch!(shield, |r: LocalResponse<'_>| {\n        assert_header!(r, \"Permissions-Policy\", \"usb=(), camera=(self), web-share=()\");\n    });\n\n    let uri = uri!(\"http://rocket.rs\");\n    let permission = Permission::allowed(Feature::Usb, Allow::Origin(uri))\n        .allow(Feature::Camera, [Allow::This])\n        .block(Feature::WebShare);\n\n    let shield = Shield::default().enable(permission);\n    dispatch!(shield, |r: LocalResponse<'_>| {\n        assert_header!(r, \"Permissions-Policy\",\n            \"usb=(\\\"http://rocket.rs\\\"), camera=(self), web-share=()\");\n    });\n\n    let origin1 = Allow::Origin(uri!(\"http://rocket.rs\"));\n    let origin2 = Allow::Origin(uri!(\"https://rocket.rs\"));\n    let shield = Shield::default()\n        .enable(Permission::allowed(Feature::Camera, [origin1, origin2]));\n\n    dispatch!(shield, |r: LocalResponse<'_>| {\n        assert_header!(r, \"Permissions-Policy\",\n            \"camera=(\\\"http://rocket.rs\\\" \\\"https://rocket.rs\\\")\");\n    });\n\n    let origin1 = Allow::Origin(uri!(\"http://rocket.rs\"));\n    let origin2 = Allow::Origin(uri!(\"https://rocket.rs\"));\n    let perm = Permission::allowed(Feature::Accelerometer, [origin1, origin2])\n        .block(Feature::Usb);\n\n    let shield = Shield::default().enable(perm);\n    dispatch!(shield, |r: LocalResponse<'_>| {\n        assert_header!(r, \"Permissions-Policy\",\n            \"accelerometer=(\\\"http://rocket.rs\\\" \\\"https://rocket.rs\\\"), usb=()\");\n    });\n}\n"
  },
  {
    "path": "core/lib/tests/shutdown-fairings.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};\n\nuse rocket::fairing::AdHoc;\n\n// Want to test:\n//\n//   * stalled connection + sleep in shutdown -> conn closed\n//   * stalled shutdown fairing stalls shutdown but not > grace + mercy\n//     - sleep < grace + mercy\n//     - sleep > grace + mercy\n\n#[derive(Default)]\nstruct Flags {\n    liftoff: AtomicBool,\n    shutdown: AtomicUsize\n}\n\n#[test]\nfn shutdown_fairing_runs() {\n    use rocket::local::blocking::Client;\n\n    let rocket = rocket::build()\n        .manage(Flags::default())\n        .attach(AdHoc::on_liftoff(\"Liftoff Flag\", |rocket| Box::pin(async move {\n            let flags = rocket.state::<Flags>().unwrap();\n            flags.liftoff.store(true, Ordering::SeqCst);\n        })))\n        .attach(AdHoc::on_shutdown(\"Shutdown Flag\", |rocket| Box::pin(async move {\n            let flags = rocket.state::<Flags>().unwrap();\n            flags.shutdown.fetch_add(1, Ordering::SeqCst);\n        })));\n\n    let client = Client::debug(rocket).unwrap();\n    let flags = client.rocket().state::<Flags>().unwrap();\n    assert!(flags.liftoff.load(Ordering::SeqCst));\n    assert_eq!(0, flags.shutdown.load(Ordering::SeqCst));\n\n    let rocket = client.terminate();\n    let flags = rocket.state::<Flags>().unwrap();\n    assert_eq!(1, flags.shutdown.load(Ordering::SeqCst));\n}\n\n#[async_test]\nasync fn async_shutdown_fairing_runs() {\n    use rocket::local::asynchronous::Client;\n\n    let rocket = rocket::build()\n        .manage(Flags::default())\n        .attach(AdHoc::on_liftoff(\"Liftoff Flag\", |rocket| Box::pin(async move {\n            let flags = rocket.state::<Flags>().unwrap();\n            flags.liftoff.store(true, Ordering::SeqCst);\n        })))\n        .attach(AdHoc::on_shutdown(\"Shutdown Flag\", |rocket| Box::pin(async move {\n            let flags = rocket.state::<Flags>().unwrap();\n            flags.shutdown.fetch_add(1, Ordering::SeqCst);\n        })));\n\n    let client = Client::debug(rocket).await.unwrap();\n    let flags = client.rocket().state::<Flags>().unwrap();\n    assert!(flags.liftoff.load(Ordering::SeqCst));\n    assert_eq!(0, flags.shutdown.load(Ordering::SeqCst));\n\n    let rocket = client.terminate().await;\n    let flags = rocket.state::<Flags>().unwrap();\n    assert_eq!(1, flags.shutdown.load(Ordering::SeqCst));\n}\n\n#[async_test]\nasync fn multiple_shutdown_fairing_runs() {\n    use rocket::local::asynchronous::Client;\n\n    let rocket = rocket::build()\n        .manage(Flags::default())\n        .attach(AdHoc::on_shutdown(\"Shutdown Flag 1\", |rocket| Box::pin(async move {\n            let flags = rocket.state::<Flags>().unwrap();\n            flags.shutdown.fetch_add(1, Ordering::SeqCst);\n        })))\n        .attach(AdHoc::on_shutdown(\"Shutdown Flag 2\", |rocket| Box::pin(async move {\n            let flags = rocket.state::<Flags>().unwrap();\n            flags.shutdown.fetch_add(1, Ordering::SeqCst);\n        })));\n\n    let client = Client::debug(rocket).await.unwrap();\n    let flags = client.rocket().state::<Flags>().unwrap();\n    assert_eq!(0, flags.shutdown.load(Ordering::SeqCst));\n\n    let rocket = client.terminate().await;\n    let flags = rocket.state::<Flags>().unwrap();\n    assert_eq!(2, flags.shutdown.load(Ordering::SeqCst));\n}\n\n#[async_test]\nasync fn async_slow_shutdown_doesnt_elongate_grace() {\n    use rocket::local::asynchronous::Client;\n\n    let mut config = rocket::Config::debug_default();\n    config.shutdown.grace = 1;\n    config.shutdown.mercy = 1;\n\n    let rocket = rocket::build()\n        .manage(Flags::default())\n        .reconfigure(config)\n        .attach(AdHoc::on_shutdown(\"Slow Shutdown\", |rocket| Box::pin(async move {\n            tokio::time::sleep(std::time::Duration::from_secs(4)).await;\n            let flags = rocket.state::<Flags>().unwrap();\n            flags.shutdown.fetch_add(1, Ordering::SeqCst);\n        })));\n\n    let client = Client::debug(rocket).await.unwrap();\n    let flags = client.rocket().state::<Flags>().unwrap();\n    assert_eq!(0, flags.shutdown.load(Ordering::SeqCst));\n\n    let start = std::time::Instant::now();\n    let rocket = client.terminate().await;\n    let elapsed = start.elapsed();\n\n    let flags = rocket.state::<Flags>().unwrap();\n    assert!(elapsed > std::time::Duration::from_secs(2));\n    assert!(elapsed < std::time::Duration::from_secs(5));\n    assert_eq!(1, flags.shutdown.load(Ordering::SeqCst));\n}\n\n#[test]\nfn background_tasks_dont_prevent_terminate() {\n    use rocket::local::blocking::Client;\n\n    #[get(\"/\")]\n    fn index() {\n        tokio::task::spawn(async {\n            tokio::time::sleep(std::time::Duration::from_secs(10)).await;\n        });\n\n        tokio::task::spawn_blocking(|| {\n            std::thread::sleep(std::time::Duration::from_secs(10));\n        });\n    }\n\n    let mut config = rocket::Config::debug_default();\n    config.shutdown.grace = 1;\n    config.shutdown.mercy = 1;\n\n    let rocket = rocket::build().reconfigure(config).mount(\"/\", routes![index]);\n\n    let client = Client::debug(rocket).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert!(response.status().class().is_success());\n    drop(response);\n    let _ = client.terminate();\n}\n"
  },
  {
    "path": "core/lib/tests/static/.hidden",
    "content": "Peek-a-boo.\n"
  },
  {
    "path": "core/lib/tests/static/index.html",
    "content": "Just a file here: index.html.\n"
  },
  {
    "path": "core/lib/tests/static/inner/.hideme",
    "content": "Oh no!\n"
  },
  {
    "path": "core/lib/tests/static/inner/goodbye",
    "content": "Thanks for coming!\n"
  },
  {
    "path": "core/lib/tests/static/inner/index.html",
    "content": "Inner index.html\n"
  },
  {
    "path": "core/lib/tests/static/other/hello.txt",
    "content": "Hi!\n"
  },
  {
    "path": "core/lib/tests/static/other/index.htm",
    "content": "Inner index.htm\n"
  },
  {
    "path": "core/lib/tests/strict_and_lenient_forms.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::form::{Form, Strict};\n\n#[derive(FromForm)]\nstruct MyForm<'r> {\n    field: &'r str,\n}\n\n#[post(\"/strict\", data = \"<form>\")]\nfn strict<'r>(form: Form<Strict<MyForm<'r>>>) -> &'r str {\n    form.field\n}\n\n#[post(\"/lenient\", data = \"<form>\")]\nfn lenient<'r>(form: Form<MyForm<'r>>) -> &'r str {\n    form.field\n}\n\nmod strict_and_lenient_forms_tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n    use rocket::http::{Status, ContentType};\n\n    const FIELD_VALUE: &str = \"just_some_value\";\n\n    fn client() -> Client {\n        Client::debug_with(routes![strict, lenient]).unwrap()\n    }\n\n    #[test]\n    fn test_strict_form() {\n        let client = client();\n        let response = client.post(\"/strict\")\n            .header(ContentType::Form)\n            .body(format!(\"field={}\", FIELD_VALUE))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string(), Some(FIELD_VALUE.into()));\n\n        let response = client.post(\"/strict\")\n            .header(ContentType::Form)\n            .body(format!(\"field={}&extra=whoops\", FIELD_VALUE))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::UnprocessableEntity);\n    }\n\n    #[test]\n    fn test_lenient_form() {\n        let client = client();\n        let response = client.post(\"/lenient\")\n            .header(ContentType::Form)\n            .body(format!(\"field={}\", FIELD_VALUE))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string(), Some(FIELD_VALUE.into()));\n\n        let response = client.post(\"/lenient\")\n            .header(ContentType::Form)\n            .body(format!(\"field={}&extra=whoops\", FIELD_VALUE))\n            .dispatch();\n\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string(), Some(FIELD_VALUE.into()));\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/timer-on-attach.rs",
    "content": "#[rocket::async_test]\nasync fn test_await_timer_inside_attach() {\n\n    async fn do_async_setup() {\n        // By using a timer or I/O resource, we ensure that do_async_setup will\n        // deadlock if no thread is able to tick the time or I/O drivers.\n        rocket::tokio::time::sleep(std::time::Duration::from_millis(100)).await;\n    }\n\n    let _ = rocket::build()\n        .attach(rocket::fairing::AdHoc::on_ignite(\"1\", |rocket| async {\n            do_async_setup().await;\n            rocket\n        }));\n}\n"
  },
  {
    "path": "core/lib/tests/tls-config-from-source-1503.rs",
    "content": "#![cfg(feature = \"tls\")]\n\nmacro_rules! relative {\n    ($path:expr) => {\n        std::path::Path::new(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/\", $path))\n    };\n}\n\n#[test]\nfn tls_config_from_source() {\n    use rocket::tls::TlsConfig;\n    use rocket::figment::{Figment, providers::Serialized};\n\n    let cert_path = relative!(\"examples/tls/private/cert.pem\");\n    let key_path = relative!(\"examples/tls/private/key.pem\");\n    let config = TlsConfig::from_paths(cert_path, key_path);\n\n    let tls: TlsConfig = Figment::from(Serialized::globals(config)).extract().unwrap();\n    assert_eq!(tls.certs().unwrap_left(), cert_path);\n    assert_eq!(tls.key().unwrap_left(), key_path);\n}\n"
  },
  {
    "path": "core/lib/tests/twice_managed_state.rs",
    "content": "struct A;\n\n#[test]\n#[should_panic]\nfn twice_managed_state() {\n    let _ = rocket::build().manage(A).manage(A);\n}\n"
  },
  {
    "path": "core/lib/tests/typed-uri-docs-redef-issue-1373.rs",
    "content": "#![allow(dead_code)] // This test is only here to ensure it compiles.\n#![allow(unused_variables)] // This test is only here to ensure it compiles.\n\nmod a {\n    /// Docs.\n    #[rocket::post(\"/typed_uris/<id>\")]\n    fn simple(id: i32) { }\n}\n\nmod b {\n    /// Docs.\n    #[rocket::post(\"/typed_uris/<id>\")]\n    fn simple(id: i32) { }\n}\n"
  },
  {
    "path": "core/lib/tests/unsound-local-request-1312.rs",
    "content": "use rocket::http::Header;\nuse rocket::local::blocking::Client;\n\n#[test]\nfn test_local_request_clone_soundness() {\n    let client = Client::debug_with(vec![]).unwrap();\n\n    // creates two LocalRequest instances that shouldn't share the same req\n    let r1 = client.get(\"/\").header(Header::new(\"key\", \"val1\"));\n    let mut r2 = r1.clone();\n\n    // save the iterator, which internally holds a slice\n    let mut iter = r1.inner().headers().get(\"key\");\n\n    // insert headers to force header map reallocation.\n    for i in 0..100 {\n        r2.add_header(Header::new(i.to_string(), i.to_string()));\n    }\n\n    // Replace the original key/val.\n    r2.add_header(Header::new(\"key\", \"val2\"));\n\n    // Heap massage: so we've got crud to print.\n    let _: Vec<usize> = vec![0, 0xcafebabe, 31337, 0];\n\n    // Ensure we're good.\n    let s = iter.next().unwrap();\n    println!(\"{}\", s);\n\n    // And that we've got the right data.\n    assert_eq!(r1.inner().headers().get(\"key\").collect::<Vec<_>>(), vec![\"val1\"]);\n    assert_eq!(r2.inner().headers().get(\"key\").collect::<Vec<_>>(), vec![\"val1\", \"val2\"]);\n}\n"
  },
  {
    "path": "core/lib/tests/untracked-vs-tracked.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::http::CookieJar;\n\n#[post(\"/\")]\nfn add(jar: &CookieJar<'_>) {\n    jar.add((\"name\", \"value\"));\n}\n\n#[get(\"/\")]\nfn get<'a>(jar: &'a CookieJar<'_>) -> Option<&'a str> {\n    jar.get(\"name\").map(|c| c.value())\n}\n\n#[cfg(test)]\nmod many_cookie_jars_tests {\n    use super::*;\n    use rocket::{Rocket, local::blocking::Client, Build};\n    use rocket::http::Status;\n\n    fn rocket() -> Rocket<Build> {\n        rocket::custom(rocket::Config::debug_default())\n            .mount(\"/\", routes![add, get])\n    }\n\n    #[test]\n    fn test_tracked() {\n        let client = Client::tracked(rocket()).unwrap();\n\n        assert_eq!(client.get(\"/\").dispatch().status(), Status::NotFound);\n        assert_eq!(client.post(\"/\").dispatch().status(), Status::Ok);\n\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string().unwrap(), \"value\");\n    }\n\n    #[test]\n    fn test_untracked() {\n        let client = Client::untracked(rocket()).unwrap();\n\n        assert_eq!(client.get(\"/\").dispatch().status(), Status::NotFound);\n        assert_eq!(client.post(\"/\").dispatch().status(), Status::Ok);\n        assert_eq!(client.get(\"/\").dispatch().status(), Status::NotFound);\n    }\n}\n"
  },
  {
    "path": "core/lib/tests/uri-percent-encoding-issue-808.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::{Rocket, Build};\nuse rocket::response::Redirect;\n\nconst NAME: &str = \"John[]|\\\\%@^\";\n\n#[get(\"/hello/<name>\")]\nfn hello(name: String) -> String {\n    format!(\"Hello, {}!\", name)\n}\n\n#[get(\"/raw\")]\nfn raw_redirect() -> Redirect {\n    Redirect::to(uri!(hello(NAME)))\n}\n\n#[get(\"/uri\")]\nfn uri_redirect() -> Redirect {\n    Redirect::to(uri!(hello(NAME)))\n}\n\nfn rocket() -> Rocket<Build> {\n    rocket::build().mount(\"/\", routes![hello, uri_redirect, raw_redirect])\n}\n\nmod tests {\n    use super::*;\n    use rocket::local::blocking::Client;\n    use rocket::http::Status;\n\n    #[test]\n    fn uri_percent_encoding_redirect() {\n        let expected_location = vec![\"/hello/John[]%7C%5C%25@%5E\"];\n        let client = Client::debug(rocket()).unwrap();\n\n        let response = client.get(\"/raw\").dispatch();\n        let location: Vec<_> = response.headers().get(\"location\").collect();\n        assert_eq!(response.status(), Status::SeeOther);\n        assert_eq!(&location, &expected_location);\n\n        let response = client.get(\"/uri\").dispatch();\n        let location: Vec<_> = response.headers().get(\"location\").collect();\n        assert_eq!(response.status(), Status::SeeOther);\n        assert_eq!(&location, &expected_location);\n    }\n\n    #[test]\n    fn uri_percent_encoding_get() {\n        let client = Client::debug(rocket()).unwrap();\n        let response = client.get(uri!(hello(NAME))).dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string().unwrap(), format!(\"Hello, {}!\", NAME));\n    }\n}\n"
  },
  {
    "path": "docs/LICENSE",
    "content": "                     GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "docs/guide/00-introduction.md",
    "content": "+++\nsummary = \"introduces Rocket and its philosophy\"\n+++\n\n# Introduction\n\nRocket is a web framework for Rust. If you'd like, you can think of Rocket as\nbeing a more flexible, friendly medley of [Rails](https://rubyonrails.org/),\n[Flask](https://palletsprojects.com/p/flask/),\n[Bottle](https://bottlepy.org/docs/dev/index.html), and\n[Yesod](https://www.yesodweb.com/). We prefer to think of Rocket as something\nnew. Rocket aims to be fast, easy, and flexible while offering guaranteed safety\nand security where it can. Importantly, Rocket also aims to be _fun_, and it\naccomplishes this by ensuring that you write as little code as needed to\naccomplish your task.\n\nThis guide introduces you to the core, intermediate, and advanced concepts of\nRocket. After reading this guide, you should find yourself being very\nproductive with Rocket.\n\n## Audience\n\nReaders are assumed to have a good grasp of the Rust programming language.\nReaders new to Rust are encouraged to read the [Rust\nBook](https://doc.rust-lang.org/book/). This guide also assumes a basic\nunderstanding of web application fundamentals, such as routing and HTTP. Mozilla\nprovides a good overview of these concepts in their [MDN web docs].\n\n[MDN web docs]: https://developer.mozilla.org/en-US/docs/Web/HTTP\n\n## Foreword\n\nRocket's design is centered around three core philosophies:\n\n  * **Security, correctness, and developer experience are paramount.**\n\n    The path of least resistance should lead you to the most secure, correct web\n    application, though security and correctness should not come at the cost of\n    a degraded developer experience. Rocket is easy to use while taking great\n    measures to ensure that your application is secure and correct without\n    cognitive overhead.\n\n  * **All request handling information should be typed and self-contained.**\n\n    Because the web and HTTP are themselves untyped (or _stringly_ typed, as\n    some call it), this means that something or someone has to convert strings\n    to native types. Rocket does this for you with zero programming overhead.\n    What's more, Rocket's request handling is **self-contained** with zero\n    global state: handlers are regular functions with regular arguments.\n\n  * **Decisions should not be forced.**\n\n    Templates, serialization, sessions, and just about everything else are all\n    pluggable, optional components. While Rocket has official support and\n    libraries for each of these, they are completely optional and swappable.\n\nThese three ideas dictate Rocket's interface, and you will find all of them\nembedded in Rocket's core features.\n"
  },
  {
    "path": "docs/guide/01-upgrading.md",
    "content": "+++\nsummary = \"a migration guide from Rocket v0.5 to v0.6\"\n+++\n\n# Upgrading\n\nThis a placeholder for an eventual migration guide from v0.5 to v0.6.\n\n## Getting Help\n\nIf you run into any issues upgrading, we encourage you to ask questions via\n[GitHub discussions] or via chat at [`#rocket:mozilla.org`] on Matrix. The\n[FAQ](../faq/) also provides answers to commonly asked questions.\n\n[GitHub discussions]: @github/discussions\n[`#rocket:mozilla.org`]: @chat\n"
  },
  {
    "path": "docs/guide/02-quickstart.md",
    "content": "+++\nsummary = \"the minimal steps to running your first Rocket application\"\n+++\n\n# Quickstart\n\nBefore you can start writing a Rocket application, you'll need to install the\nRust toolchain. We recommend using [rustup](https://rustup.rs/). If you don't\nhave Rust installed and would like extra guidance doing so, see [Getting\nStarted].\n\n## Running Examples\n\nThe absolute fastest way to start experimenting with Rocket is to clone the\n[Rocket repository](@github) and run the included examples in the `examples/`\ndirectory. For instance, the following set of commands runs the `hello` example:\n\n```sh\ngit clone https://github.com/rwf2/Rocket\ncd Rocket\ngit checkout master\ncd examples/hello\ncargo run\n```\n\nThere are numerous examples in the `examples/` directory. They can all be run\nwith `cargo run`.\n\n! note\n\n  The examples' `Cargo.toml` files will point to the locally cloned `rocket`\n  libraries. When copying the examples for your own use, you should modify the\n  `Cargo.toml` files as explained in the [Getting Started] guide.\n\n[Getting Started]: ../getting-started/\n"
  },
  {
    "path": "docs/guide/03-getting-started.md",
    "content": "+++\nsummary = \"a gentle introduction to running your first Rocket application\"\n+++\n\n# Getting Started\n\nLet's create and run our first Rocket application. We'll ensure we have a\ncompatible Rust toolchain installed, create a new Cargo project that depends on\nRocket, and then run the application.\n\n## Installing Rust\n\nRocket makes use of the latest Rust features. Because of this, we'll need a\nrecent release of Rust to run Rocket applications. If you already have a working\ninstallation of the latest Rust compiler, feel free to skip to the next section.\n\nTo install the latest version of Rust, we recommend using `rustup`. Install\n`rustup` by following the instructions on [its website](https://rustup.rs/).\nOnce `rustup` is installed, ensure the latest toolchain is installed by running\nthe command:\n\n```sh\nrustup default stable\n```\n\n! note: You may prefer to develop using the `nightly` channel.\n\n  The nightly Rust toolchain enables certain improved developer experiences,\n  such as better compile-time diagnostics, when developing with Rocket. You may\n  choose to develop on the nightly channel to take advantage of these improved\n  experiences. Note that all Rocket features are available across all Rust\n  channels.\n\n  To set the nightly toolchain as your default, run `rustup default nightly`.\n\n## Hello, world!\n\nLet's write our first Rocket application! Start by creating a new binary-based\nCargo project and changing into the new directory:\n\n```sh\ncargo new hello-rocket --bin\ncd hello-rocket\n```\n\nNow, add Rocket as a dependency in your `Cargo.toml`:\n\n```toml\n[dependencies]\nrocket = \"0.6.0-dev\"\n```\n\n! warning: Development versions must be _git_ dependencies.\n\n  Development versions, tagged with `-dev`, are not published. To depend on a\n  development version of Rocket, you'll need to point `Cargo.toml` to a Rocket\n  git repository. For example, with `######` replaced with a git commit hash:\n\n  ```toml\n  rocket = { git = \"https://github.com/rwf2/Rocket\", rev = \"######\" }\n  ```\n\nModify `src/main.rs` so that it contains the code for the Rocket `Hello, world!`\nprogram, reproduced below:\n\n```rust\n#[macro_use] extern crate rocket;\n\n#[get(\"/\")]\nfn index() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/\", routes![index])\n}\n```\n\nWe won't explain exactly what the program does now; we leave that for the rest\nof the guide. In short, it creates an `index` route, _mounts_ the route at the\n`/` path, and launches the application. Compile and run the program with `cargo\nrun`. You should see the following:\n\n```sh\n> cargo run\n🔧 Configured for debug.\n   >> address: 127.0.0.1\n   >> port: 8000\n   >> workers: [..]\n   >> keep-alive: 5s\n   >> limits: [..]\n   >> tls: disabled\n   >> temp dir: /tmp\n   >> log level: normal\n   >> cli colors: true\n🛰  Routes:\n   >> (index) GET /\n🚀 Rocket has launched from http://127.0.0.1:8000\n```\n\nVisit `http://localhost:8000` to see your first Rocket application in action!\n\n! tip: Don't like colors or emoji?\n\n  You can disable colors and emoji by setting the `ROCKET_CLI_COLORS`\n  environment variable to `0` or `false` when running a Rocket binary:\n  `ROCKET_CLI_COLORS=false cargo run`.\n"
  },
  {
    "path": "docs/guide/04-overview.md",
    "content": "+++\nsummary = \"an overview of Rocket's core concepts\"\n+++\n\n# Overview\n\nRocket provides primitives to build web servers and applications with Rust:\nRocket provides routing, pre-processing of requests, and post-processing of\nresponses; the rest is up to you. Your application code instructs Rocket on what\nto pre-process and post-process and fills the gaps between pre-processing and\npost-processing.\n\n## Lifecycle\n\nRocket's main task is to listen for incoming web requests, dispatch the request\nto the application code, and return a response to the client. We call the\nprocess that goes from request to response the \"lifecycle\". We summarize the\nlifecycle as the following sequence of steps:\n\n  1. **Routing**\n\n     Rocket parses an incoming HTTP request into native structures that your\n     code operates on indirectly. Rocket determines which request handler to\n     invoke by matching against route attributes declared in your application.\n\n  2. **Validation**\n\n     Rocket validates the incoming request against types and guards present in\n     the matched route. If validation fails, Rocket _forwards_ the request to\n     the next matching route or calls an _error handler_.\n\n  3. **Processing**\n\n     The request handler associated with the route is invoked with validated\n     arguments. This is the main business logic of an application. Processing\n     completes by returning a `Response`.\n\n  4. **Response**\n\n     The returned `Response` is processed. Rocket generates the appropriate HTTP\n     response and sends it to the client. This completes the lifecycle. Rocket\n     continues listening for requests, restarting the lifecycle for each\n     incoming request.\n\nThe remainder of this section details the _routing_ phase as well as additional\ncomponents needed for Rocket to begin dispatching requests to request handlers.\nThe sections following describe the request and response phases as well as other\ncomponents of Rocket.\n\n## Routing\n\nRocket applications are centered around routes and handlers. A _route_ is a\ncombination of:\n\n  * A set of parameters to match an incoming request against.\n  * A handler to process the request and return a response.\n\nA _handler_ is simply a function that takes an arbitrary number of arguments and\nreturns any arbitrary type.\n\nThe parameters to match against include static paths, dynamic paths, path\nsegments, forms, query strings, request format specifiers, and body data. Rocket\nuses attributes, which look like function decorators in other languages, to make\ndeclaring routes easy. Routes are declared by annotating a function, the\nhandler, with the set of parameters to match against. A complete route\ndeclaration looks like this:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/world\")]              // <- route attribute\nfn world() -> &'static str {  // <- request handler\n    \"hello, world!\"\n}\n```\n\nThis declares the `world` route to match against the static path `\"/world\"` on\nincoming `GET` requests. Instead of `#[get]`, we could have used `#[post]` or\n`#[put]` for other HTTP methods, or `#[catch]` for serving [custom error\npages](../requests/#error-catchers). Additionally, other route parameters may be\nnecessary when building more interesting applications. The\n[Requests](../requests/) chapter, which follows this one, has further details on\nrouting and error handling.\n\n! note: We prefer `#[macro_use]`, but you may prefer explicit imports.\n\n  Throughout this guide and the majority of Rocket's documentation, we import\n  `rocket` explicitly with `#[macro_use]` even though the Rust 2018 edition\n  makes explicitly importing crates optional. However, explicitly importing with\n  `#[macro_use]` imports macros globally, allowing you to use Rocket's macros\n  anywhere in your application without importing them explicitly.\n\n  You may instead prefer to import macros explicitly or refer to them with\n  absolute paths: `use rocket::get;` or `#[rocket::get]`.\n\n## Mounting\n\nBefore Rocket can dispatch requests to a route, the route needs to be _mounted_:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# #[get(\"/world\")]\n# fn world() -> &'static str {\n#     \"hello, world!\"\n# }\n\nrocket::build().mount(\"/hello\", routes![world]);\n```\n\nThe `mount` method takes as input:\n\n   1. A _base_ path to namespace a list of routes under, here, `/hello`.\n   2. A list of routes via the `routes!` macro: here, `routes![world]`, with\n      multiple routes: `routes![a, b, c]`.\n\nThis creates a new `Rocket` instance via the `build` function and mounts the\n`world` route to the `/hello` base path, making Rocket aware of the route.\n`GET` requests to `/hello/world` will be directed to the `world` function.\n\nThe `mount` method, like all other builder methods on `Rocket`, can be chained\nany number of times, and routes can be reused by mount points:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# #[get(\"/world\")]\n# fn world() -> &'static str {\n#     \"hello, world!\"\n# }\n\nrocket::build()\n    .mount(\"/hello\", routes![world])\n    .mount(\"/hi\", routes![world]);\n```\n\nBy mounting `world` to both `/hello` and `/hi`, requests to `\"/hello/world\"`\n_and_ `\"/hi/world\"` will be directed to the `world` function.\n\n! note: In many cases, the base path will simply be `\"/\"`.\n\n## Launching\n\nRocket begins serving requests after being _launched_, which starts a\nmulti-threaded asynchronous server and dispatches requests to matching routes as\nthey arrive.\n\nThere are two mechanisms by which a `Rocket` can be launched. The first and\npreferred approach is via the `#[launch]` route attribute, which generates a\n`main` function that sets up an async runtime and starts the server. With\n`#[launch]`, our complete _Hello, world!_ application looks like:\n\n```rust\n#[macro_use] extern crate rocket;\n\n#[get(\"/world\")]\nfn world() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/hello\", routes![world])\n}\n```\n\nRunning the application, the console shows:\n\n```sh\n> cargo run\n🔧 Configured for debug.\n   >> address: 127.0.0.1\n   >> port: 8000\n   >> workers: [..]\n   >> keep-alive: 5s\n   >> limits: [..]\n   >> tls: disabled\n   >> temp dir: /tmp\n   >> log level: normal\n   >> cli colors: true\n🛰  Routes:\n   >> (world) GET /hello/world\n🚀 Rocket has launched from http://127.0.0.1:8000\n```\n\n! tip: `#[launch]` infers the return type!\n\n  Special to Rocket's `#[launch]` attribute, the return type of a function\n  decorated with `#[launch]` is automatically inferred when the return type is\n  set to `_`. If you prefer, you can also set the return type explicitly to\n  `Rocket<Build>`.\n\nIf we visit `http://127.0.0.1:8000/hello/world`, we see `Hello, world!`, exactly\nas we expected.\n\n! note: This and other examples are on GitHub.\n\n  An expanded version of this example's complete crate, ready to `cargo run`,\n  can be found on [GitHub](@git/master/examples/hello). You can find dozens of other\n  complete examples, spanning all of Rocket's features, in the [GitHub examples\n  directory](@git/master/examples/).\n\nThe second approach uses the `#[rocket::main]` route attribute.\n`#[rocket::main]` _also_ generates a `main` function that sets up an async\nruntime but unlike `#[launch]`, allows _you_ to start the server:\n\n```rust,no_run\n# #[macro_use] extern crate rocket;\n#\n# #[get(\"/world\")]\n# fn world() -> &'static str {\n#     \"Hello, world!\"\n# }\n\n#[rocket::main]\nasync fn main() -> Result<(), rocket::Error> {\n    let _rocket = rocket::build()\n        .mount(\"/hello\", routes![world])\n        .launch()\n        .await?;\n\n    Ok(())\n}\n```\n\n`#[rocket::main]` is useful when a handle to the `Future` returned by `launch()`\nis desired, or when the return value of [`launch()`] is to be inspected. The\n[error handling example] for instance, inspects the return value.\n\n[`launch()`]: @api/master/rocket/struct.Rocket.html#method.launch\n[error handling example]: @git/master/examples/error-handling\n\n## Futures and Async\n\nRocket uses Rust [`Future`]s for concurrency. Asynchronous programming with\n`Future`s and `async/await` allows route handlers to perform wait-heavy I/O such\nas filesystem and network access while still allowing other requests to make\nprogress. For an overview of Rust `Future`s, see [Asynchronous Programming in\nRust](https://rust-lang.github.io/async-book/).\n\nIn general, you should prefer to use async-ready libraries instead of\nsynchronous equivalents inside Rocket applications.\n\n`async` appears in several places in Rocket:\n\n* [Routes] and [Error Catchers] can be `async fn`s. Inside an `async fn`, you\n  can `.await` `Future`s from Rocket or other libraries.\n* Several of Rocket's traits, such as [`FromData`] and [`FromRequest`], have\n  methods that return `Future`s.\n* [`Data`] and [`DataStream`], incoming request data, and `Response` and `Body`,\n  outgoing response data, are based on `tokio::io::AsyncRead` instead of\n  `std::io::Read`.\n\nYou can find async-ready libraries on [crates.io](https://crates.io) with the\n`async` tag.\n\n[`Future`]: @std/future/trait.Future.html\n[`Data`]: @api/master/rocket/struct.Data.html\n[`DataStream`]: @api/master/rocket/data/enum.DataStream.html\n[Routes]: ../requests/\n[Error Catchers]: ../requests/#error-catchers\n[`FromData`]: ../requests/#body-data\n[`FromRequest`]: ../requests/#request-guards\n\n! note\n\n  Rocket uses the tokio runtime. The runtime is started for you if you\n  use `#[launch]` or `#[rocket::main]`, but you can still `launch()` a Rocket\n  instance on a custom-built runtime by not using _either_ attribute.\n\n### Async Routes\n\nRocket makes it easy to use `async/await` in routes.\n\n```rust\n# #[macro_use] extern crate rocket;\nuse rocket::tokio::time::{sleep, Duration};\n\n#[get(\"/delay/<seconds>\")]\nasync fn delay(seconds: u64) -> String {\n    sleep(Duration::from_secs(seconds)).await;\n    format!(\"Waited for {} seconds\", seconds)\n}\n```\n\nFirst, notice that the route function is an `async fn`. This enables the use of\n`await` inside the handler. `sleep` is an asynchronous function, so we must\n`await` it.\n\n### Multitasking\n\nRust's `Future`s are a form of *cooperative multitasking*. In general, `Future`s\nand `async fn`s should only `.await` on operations and never block.  Some common\nexamples of blocking include locking non-`async` mutexes, joining threads, or\nusing non-`async` library functions (including those in `std`) that perform I/O.\n\nIf a `Future` or `async fn` blocks the thread, inefficient resource usage,\nstalls, or sometimes even deadlocks can occur.\n\nSometimes there is no good `async` alternative for a library or operation. If\nnecessary, you can convert a synchronous operation to an async one with\n[`tokio::task::spawn_blocking`]:\n\n```rust\n# #[macro_use] extern crate rocket;\nuse std::io;\n\nuse rocket::tokio::task::spawn_blocking;\n\n#[get(\"/blocking_task\")]\nasync fn blocking_task() -> io::Result<Vec<u8>> {\n    // In a real app, use rocket::fs::NamedFile or tokio::fs::File.\n    let vec = spawn_blocking(|| std::fs::read(\"data.txt\")).await\n        .map_err(|e| io::Error::new(io::ErrorKind::Interrupted, e))??;\n\n    Ok(vec)\n}\n```\n\n[`tokio::task::spawn_blocking`]: @tokio/task/fn.spawn_blocking.html\n"
  },
  {
    "path": "docs/guide/05-requests.md",
    "content": "+++\nsummary = \"handling request and body data: control-flow, parsing, validation\"\n+++\n\n# Requests\n\nTogether, a [`route`] attribute and function signature specify what must be true\nabout a request in order for the route's handler to be called. You've already\nseen an example of this in action:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n#[get(\"/world\")]\nfn handler() { /* .. */ }\n```\n\nThis route indicates that it only matches against `GET` requests to the `/world`\nroute. Rocket ensures that this is the case before `handler` is called. Of\ncourse, you can do much more than specify the method and path of a request.\nAmong other things, you can ask Rocket to automatically validate:\n\n  * The type of a dynamic path segment.\n  * The type of _several_ dynamic path segments.\n  * The type of incoming body data.\n  * The types of query strings, forms, and form values.\n  * The expected incoming or outgoing format of a request.\n  * Any arbitrary, user-defined security or validation policies.\n\nThe route attribute and function signature work in tandem to describe these\nvalidations. Rocket's code generation takes care of actually validating the\nproperties. This section describes how to ask Rocket to validate against all of\nthese properties and more.\n\n[`route`]: @api/master/rocket/attr.route.html\n\n## Methods\n\nA Rocket route attribute can either be method-specific, any one of `get`, `put`,\n`post`, `delete`, `head`, `patch`, or `options`, or the generic [`route`], which\nallows explicitly specifying any valid HTTP [`Method`] or no method at all, to\nmatch again _any_ method. Consider the following examples:\n\n  * Match a `POST` request to `/`:\n\n    ```rust\n    # use rocket::post;\n    #[post(\"/\")]\n    # fn handler() {}\n    ```\n\n  * Match a `PATCH` request to `/fix`:\n\n    ```rust\n    # use rocket::patch;\n    #[patch(\"/fix\")]\n    # fn handler() {}\n    ```\n\n  * Match a `PROPFIND` request to `/collection`:\n\n    ```rust\n    # use rocket::route;\n    #[route(\"/collection\", method = PROPFIND)]\n    # fn handler() {}\n    ```\n\n  * Match a `VERSION-CONTROL` request to `/collection`:\n\n    ```rust\n    # use rocket::route;\n    #[route(\"/resource\", method = \"VERSION-CONTROL\")]\n    # fn handler() {}\n    ```\n\n  * Match a request to `/page` with _any_ method:\n\n    ```rust\n    # use rocket::route;\n    #[route(\"/page\")]\n    # fn handler() {}\n    ```\n\nThe grammar for these attributes is defined formally in the [`route`] API docs.\n\n[`Method`]: @api/master/rocket/http/enum.Method.html\n\n### HEAD Requests\n\nRocket handles `HEAD` requests automatically when there exists a `GET` route\nthat would otherwise match. It does this by stripping the body from the\nresponse, if there is one. You can also specialize the handling of a `HEAD`\nrequest by declaring a route for it; Rocket won't interfere with `HEAD` requests\nyour application explicitly handles.\n\n### Reinterpreting\n\nBecause web browsers only support submitting HTML forms as `GET` or `POST` requests,\nRocket _reinterprets_ request methods under certain conditions. If a `POST`\nrequest contains a body of `Content-Type: application/x-www-form-urlencoded` and\nthe form's **first** field has the name `_method` and a valid HTTP method name\nas its value (such as `\"PUT\"`), that field's value is used as the method for the\nincoming request.  This allows Rocket applications to submit non-`POST` forms.\nThe [todo example](@git/master/examples/todo/static/index.html.tera#L47) makes use of this\nfeature to submit `PUT` and `DELETE` requests from a web form.\n\n## Dynamic Paths\n\nYou can declare path segments as dynamic by using angle brackets around variable\nnames in a route's path. For example, if we want to say _Hello!_ to anything,\nnot just the world, we can declare a route like so:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n#[get(\"/hello/<name>\")]\nfn hello(name: &str) -> String {\n    format!(\"Hello, {}!\", name)\n}\n```\n\nIf we were to mount the path at the root (`.mount(\"/\", routes![hello])`), then\nany request to a path with two non-empty segments, where the first segment is\n`hello`, will be dispatched to the `hello` route. For example, if we were to\nvisit `/hello/John`, the application would respond with `Hello, John!`.\n\nAny number of dynamic path segments are allowed. A path segment can be of any\ntype, including your own, as long as the type implements the [`FromParam`]\ntrait. We call these types _parameter guards_. Rocket implements `FromParam` for\nmany of the standard library types, as well as a few special Rocket types. For\nthe full list of provided implementations, see the [`FromParam` API docs].\nHere's a more complete route to illustrate varied usage:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n#[get(\"/hello/<name>/<age>/<cool>\")]\nfn hello(name: &str, age: u8, cool: bool) -> String {\n    if cool {\n        format!(\"You're a cool {} year old, {}!\", age, name)\n    } else {\n        format!(\"{}, we need to talk about your coolness.\", name)\n    }\n}\n```\n\n[`FromParam`]: @api/master/rocket/request/trait.FromParam.html\n[`FromParam` API docs]: @api/master/rocket/request/trait.FromParam.html\n\n### Multiple Segments\n\nYou can also match against multiple segments by using `<param..>` in a route\npath. The type of such parameters, known as _segments guards_, must implement\n[`FromSegments`]. A segments guard must be the final component of a path: any\ntext after a segments guard will result in a compile-time error.\n\nAs an example, the following route matches against all paths that begin with\n`/page`:\n\n```rust\n# use rocket::get;\nuse std::path::PathBuf;\n\n#[get(\"/page/<path..>\")]\nfn get_page(path: PathBuf) { /* ... */ }\n```\n\nThe path after `/page/` will be available in the `path` parameter, which may be\nempty for paths that are simply `/page`, `/page/`, `/page//`, and so on. The\n`FromSegments` implementation for `PathBuf` ensures that `path` cannot lead to\n[path traversal attacks]. With this, a safe and secure static file server can be\nimplemented in just 4 lines:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse std::path::{Path, PathBuf};\nuse rocket::fs::NamedFile;\n\n#[get(\"/<file..>\")]\nasync fn files(file: PathBuf) -> Option<NamedFile> {\n    NamedFile::open(Path::new(\"static/\").join(file)).await.ok()\n}\n```\n\n[path traversal attacks]: https://owasp.org/www-community/attacks/Path_Traversal\n\n! tip: Rocket makes it even _easier_ to serve static files!\n\n  If you need to serve static files from your Rocket application, consider using\n  [`FileServer`], which makes it as simple as:\n\n  ```rust\n  # #[macro_use] extern crate rocket;\n\n  use rocket::fs::FileServer;\n\n  #[launch]\n  fn rocket() -> _ {\n      rocket::build()\n           // serve files from `/www/static` at path `/public`\n          .mount(\"/public\", FileServer::new(\"/www/static\"))\n  }\n  ```\n\n[`FileServer`]: @api/master/rocket/fs/struct.FileServer.html\n[`FromSegments`]: @api/master/rocket/request/trait.FromSegments.html\n\n### Ignored Segments\n\nA component of a route can be fully ignored by using `<_>`, and multiple\ncomponents can be ignored by using `<_..>`. In other words, the wildcard name\n`_` is a dynamic parameter name that ignores that dynamic parameter. An ignored\nparameter must not appear in the function argument list. A segment declared as\n`<_>` matches anything in a single segment while segments declared as `<_..>`\nmatch any number of segments with no conditions.\n\nAs an example, the `foo_bar` route below matches any `GET` request with a\n3-segment URI that starts with `/foo/` and ends with `/bar`. The `everything`\nroute below matches _every_ GET request.\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/foo/<_>/bar\")]\nfn foo_bar() -> &'static str {\n    \"Foo _____ bar!\"\n}\n\n#[get(\"/<_..>\")]\nfn everything() -> &'static str {\n    \"Hey, you're here.\"\n}\n\n# // Ensure there are no collisions.\n# rocket_docs_tests::client(routes![foo_bar, everything]);\n```\n\n## Forwarding\n\nLet's take a closer look at this route attribute and signature pair from a\nprevious example:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n#[get(\"/hello/<name>/<age>/<cool>\")]\nfn hello(name: &str, age: u8, cool: bool) { /* ... */ }\n```\n\nWhat if `cool` isn't a `bool`? Or, what if `age` isn't a `u8`? When a parameter\ntype mismatch occurs, Rocket _forwards_ the request to the next matching route,\nif there is any. This continues until a route succeeds or fails, or there are no\nother matching routes to try. When there are no remaining routes, the [error\ncatcher](#error-catchers) associated with the status set by the last forwarding\nguard is called.\n\nRoutes are attempted in increasing _rank_ order. Every route has an associated\nrank. If one is not specified, Rocket chooses a default rank designed to avoid\ncollisions based on a route's _color_, detailed in the [next\nsection](#default-ranking), but a route's rank can also be manually set with the\n`rank` attribute. To illustrate, consider the following routes:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/user/<id>\")]\nfn user(id: usize) { /* ... */ }\n\n#[get(\"/user/<id>\", rank = 2)]\nfn user_int(id: isize) { /* ... */ }\n\n#[get(\"/user/<id>\", rank = 3)]\nfn user_str(id: &str) { /* ... */ }\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/\", routes![user, user_int, user_str])\n}\n```\n\nNotice the `rank` parameters in `user_int` and `user_str`. If we run this\napplication with the routes mounted at the root path, as is done in `rocket()`\nabove, requests to `/user/<id>` (such as `/user/123`, `/user/Bob`, and so on)\nwill be routed as follows:\n\n  1. The `user` route matches first. If the string at the `<id>` position is an\n     unsigned integer, then the `user` handler is called. If it is not, then the\n     request is forwarded to the next matching route: `user_int`.\n\n  2. The `user_int` route matches next. If `<id>` is a signed integer,\n     `user_int` is called. Otherwise, the request is forwarded.\n\n  3. The `user_str` route matches last. Since `<id>` is always a string, the\n     route always matches. The `user_str` handler is called.\n\n! note: A route's rank appears in **[brackets]** during launch.\n\n  You'll also find a route's rank logged in brackets during application launch:\n  `GET /user/<id> [3] (user_str)`.\n\nForwards can be _caught_ by using a `Result` or `Option` type. For example, if\nthe type of `id` in the `user` function was `Result<usize, &str>`, then `user`\nwould never forward. An `Ok` variant would indicate that `<id>` was a valid\n`usize`, while an `Err` would indicate that `<id>` was not a `usize`. The\n`Err`'s value would contain the string that failed to parse as a `usize`.\n\n! tip: It's not just forwards that can be caught!\n\n  In general, when any guard fails for any reason, including parameter guards,\n  you can use an `Option` or `Result` type in its place to catch the error.\n\nBy the way, if you were to omit the `rank` parameter in the `user_str` or\n`user_int` routes, Rocket would emit an error and abort launch, indicating that\nthe routes _collide_, or can match against similar incoming requests. The `rank`\nparameter resolves this collision.\n\n### Default Ranking\n\nIf a rank is not explicitly specified, Rocket assigns a default rank to a route.\nDefault ranks range from `-12` to `-1`. This differs from ranks that can be\nassigned manually in a route attribute, which must be positive numbers. The\ndefault rank prefers static segments over dynamic segments in both paths and\nqueries: the _more_ static a route's path and query are, the higher its\nprecedence.\n\nThere are three \"colors\" assignable to each path and query:\n\n  1. `static`, meaning all components are static\n  2. `partial`, meaning at least one component is dynamic\n  3. `wild`, meaning all components are dynamic\n\nAdditionally, a query may have _no_ color (`none`) if there is no query.\n\nStatic paths carry more weight than static queries. The same is true for partial\nand wild paths. This results in the following default ranking table:\n\n| path color | query color | default rank |\n|------------|-------------|--------------|\n| static     | static      | -12          |\n| static     | partial     | -11          |\n| static     | wild        | -10          |\n| static     | none        | -9           |\n| partial    | static      | -8           |\n| partial    | partial     | -7           |\n| partial    | wild        | -6           |\n| partial    | none        | -5           |\n| wild       | static      | -4           |\n| wild       | partial     | -3           |\n| wild       | wild        | -2           |\n| wild       | none        | -1           |\n\nRecall that _lower_ ranks have _higher_ precedence. As an example, consider this\napplication from before:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/foo/<_>/bar\")]\nfn foo_bar() { }\n\n#[get(\"/<_..>\")]\nfn everything() { }\n#\n# // Ensure there are no collisions.\n# rocket_docs_tests::client(routes![foo_bar, everything]);\n```\n\nDefault ranking ensures that `foo_bar`, with a \"partial\" path color, has higher\nprecedence than `everything` with a \"wild\" path color. This default ranking\nprevents what would have otherwise been a routing collision.\n\n## Request Guards\n\nRequest guards are one of Rocket's most powerful instruments. As the name might\nimply, a request guard protects a handler from being called erroneously based on\ninformation contained in an incoming request. More specifically, a request guard\nis a type that represents an arbitrary validation policy. The validation policy\nis implemented through the [`FromRequest`] trait. Every type that implements\n`FromRequest` is a request guard.\n\nRequest guards appear as inputs to handlers. An arbitrary number of request\nguards can appear as arguments in a route handler. Rocket will automatically\ninvoke the [`FromRequest`] implementation for request guards before calling the\nhandler. Rocket only dispatches requests to a handler when all of its guards\npass.\n\nFor instance, the following dummy handler makes use of three request guards,\n`A`, `B`, and `C`. An input can be identified as a request guard if it is not\nnamed in the route attribute.\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# type A = rocket::http::Method;\n# type B = A;\n# type C = A;\n\n#[get(\"/<param>\")]\nfn index(param: isize, a: A, b: B, c: C) { /* ... */ }\n```\n\nRequest guards always fire in left-to-right declaration order. In the example\nabove, the order will be `A` followed by `B` followed by `C`. Errors are\nshort-circuiting; if one guard fails, the remaining are not attempted. To learn\nmore about request guards and implementing them, see the [`FromRequest`]\ndocumentation.\n\n[`FromRequest`]: @api/master/rocket/request/trait.FromRequest.html\n[`CookieJar`]: @api/master/rocket/http/struct.CookieJar.html\n\n### Custom Guards\n\nYou can implement `FromRequest` for your own types. For instance, to protect a\n`sensitive` route from running unless an `ApiKey` is present in the request\nheaders, you might create an `ApiKey` type that implements `FromRequest` and\nthen use it as a request guard:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n# type ApiKey = rocket::http::Method;\n\n#[get(\"/sensitive\")]\nfn sensitive(key: ApiKey) { /* .. */ }\n```\n\nYou might also implement `FromRequest` for an `AdminUser` type that\nauthenticates an administrator using incoming cookies. Then, any handler with an\n`AdminUser` or `ApiKey` type in its argument list is assured to only be invoked\nif the appropriate conditions are met. Request guards centralize policies,\nresulting in a simpler, safer, and more secure applications.\n\n### Guard Transparency\n\nWhen a request guard type can only be created through its [`FromRequest`]\nimplementation, and the type is not `Copy`, the existence of a request guard\nvalue provides a _type-level proof_ that the current request has been validated\nagainst an arbitrary policy. This provides powerful means of protecting your\napplication against access-control violations by requiring data accessing\nmethods to _witness_ a proof of authorization via a request guard. We call the\nnotion of using a request guard as a witness _guard transparency_.\n\nAs a concrete example, the following application has a function,\n`health_records`, that returns all of the health records in a database. Because\nhealth records are sensitive information, they should only be accessible by\nsuper users. The `SuperUser` request guard authenticates and authorizes a super\nuser, and its `FromRequest` implementation is the only means by which a\n`SuperUser` can be constructed. By declaring the `health_records` function as\nfollows, access control violations against health records are guaranteed to be\nprevented at _compile-time_:\n\n```rust\n# type Records = ();\n# type SuperUser = ();\nfn health_records(user: &SuperUser) -> Records { /* ... */ }\n```\n\nThe reasoning is as follows:\n\n  1. The `health_records` function requires an `&SuperUser` type.\n  2. The only constructor for a `SuperUser` type is `FromRequest`.\n  3. Only Rocket can provide an active `&Request` to construct via `FromRequest`.\n  4. Thus, there must be a `Request` authorizing a `SuperUser` to call\n     `health_records`.\n\n! note\n\n  At the expense of a lifetime parameter in the guard type, guarantees can be\n  made even stronger by tying the lifetime of the `Request` passed to\n  `FromRequest` to the request guard, ensuring that the guard value always\n  corresponds to an _active_ request.\n\nWe recommend leveraging request guard transparency for _all_ data accesses.\n\n### Forwarding Guards\n\nRequest guards and forwarding are a powerful combination for enforcing policies.\nTo illustrate, we consider how a simple authorization system might be\nimplemented using these mechanisms.\n\nWe start with two request guards:\n\n  * `User`: A regular, authenticated user.\n\n    The `FromRequest` implementation for `User` checks that a cookie identifies\n    a user and returns a `User` value if so. If no user can be authenticated,\n    the guard forwards with a 401 Unauthorized status.\n\n  * `AdminUser`: A user authenticated as an administrator.\n\n    The `FromRequest` implementation for `AdminUser` checks that a cookie\n    identifies an _administrative_ user and returns an `AdminUser` value if so.\n    If no user can be authenticated, the guard forwards with a 401 Unauthorized\n    status.\n\nWe now use these two guards in combination with forwarding to implement the\nfollowing three routes, each leading to an administrative control panel at\n`/admin`:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# type Template = ();\n# type AdminUser = rocket::http::Method;\n# type User = rocket::http::Method;\n\nuse rocket::response::Redirect;\n\n#[get(\"/login\")]\nfn login() -> Template { /* .. */ }\n\n#[get(\"/admin\")]\nfn admin_panel(admin: AdminUser) -> &'static str {\n    \"Hello, administrator. This is the admin panel!\"\n}\n\n#[get(\"/admin\", rank = 2)]\nfn admin_panel_user(user: User) -> &'static str {\n    \"Sorry, you must be an administrator to access this page.\"\n}\n\n#[get(\"/admin\", rank = 3)]\nfn admin_panel_redirect() -> Redirect {\n    Redirect::to(uri!(login))\n}\n```\n\nThe three routes above encode authentication _and_ authorization. The\n`admin_panel` route only succeeds if an administrator is logged in. Only then is\nthe admin panel displayed. If the user is not an admin, the `AdminUser` guard\nwill forward. Since the `admin_panel_user` route is ranked next highest, it is\nattempted next. This route succeeds if there is _any_ user signed in, and an\nauthorization error message is displayed. Finally, if a user isn't signed in,\nthe `admin_panel_redirect` route is attempted. Since this route has no guards,\nit always succeeds. The user is redirected to a log in page.\n\n### Fallible Guards\n\nA failing or forwarding guard can be \"caught\" in handler, preventing it from\nfailing or forwarding, via the `Option<T>` and `Result<T, E>` guards. When a\nguard `T` fails or forwards, `Option<T>` will be `None`. If a guard `T` fails\nwith error `E`, `Result<T, E>` will be `Err(E)`.\n\nAs an example, for the `User` guard above, instead of allowing the guard to\nforward in `admin_panel_user`, we might want to detect it and handle it\ndynamically:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# type Template = ();\n# type AdminUser = rocket::http::Method;\n# type User = rocket::http::Method;\n# #[get(\"/login\")]\n# fn login() -> Template { /* .. */ }\n\nuse rocket::response::Redirect;\n\n#[get(\"/admin\", rank = 2)]\nfn admin_panel_user(user: Option<User>) -> Result<&'static str, Redirect> {\n    let user = user.ok_or_else(|| Redirect::to(uri!(login)))?;\n    Ok(\"Sorry, you must be an administrator to access this page.\")\n}\n```\n\nIf the `User` guard forwards or fails, the `Option` will be `None`. If it\nsucceeds, it will be `Some(User)`.\n\nFor guards that may fail (and not just forward), the `Result<T, E>` guard allows\nretrieving the error type `E` on error. As an example, when the\n[`mtls::Certificate`] type fails, it reports the reason in an [`mtls::Error`]\ntype. The value can be retrieved in a handler by using a `Result<Certificate,\nError>` guard:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::mtls;\n\n#[get(\"/login\")]\nfn login(cert: Result<mtls::Certificate, mtls::Error>) {\n    match cert {\n        Ok(cert) => { /* guard succeeded! value in `cert` */ },\n        Err(e) => { /* guard failed. error in `e` */ },\n    }\n}\n```\n\nIt's important to note that `Result<T, E>` forwards if `T` forwards. You can,\nhowever, chain both catching responders to determine if a guard `T` forwards or\nfails, and retrieve the error if it fails, with `Option<Result<T, E>>`:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::mtls;\n\n#[get(\"/login\")]\nfn login(cert: Option<Result<mtls::Certificate, mtls::Error>>) {\n    match cert {\n        Some(Ok(cert)) => { /* guard succeeded! value in `cert` */ },\n        Some(Err(e)) => { /* guard failed. error in `e` */ },\n        None => { /* guard forwarded */ },\n    }\n}\n```\n\n[`mtls::Certificate`]: @api/master/rocket/mtls/struct.Certificate.html\n[`mtls::Error`]: @api/master/rocket/mtls/enum.Error.html\n\n## Cookies\n\nA reference to a [`CookieJar`] is an important, built-in request guard: it\nallows you to get, set, and remove cookies. Because `&CookieJar` is a request\nguard, an argument of its type can simply be added to a handler:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\nuse rocket::http::CookieJar;\n\n#[get(\"/\")]\nfn index(cookies: &CookieJar<'_>) -> Option<String> {\n    cookies.get(\"message\").map(|crumb| format!(\"Message: {}\", crumb.value()))\n}\n```\n\nThis results in the incoming request's cookies being accessible from the\nhandler. The example above retrieves a cookie named `message`. Cookies can also\nbe set and removed using the `CookieJar` guard. The [cookies example] on GitHub\nillustrates further use of the `CookieJar` type to get and set cookies, while\nthe [`CookieJar`] documentation contains complete usage information.\n\n[cookies example]: @git/master/examples/cookies\n\n### Private Cookies\n\nCookies added via the [`CookieJar::add()`] method are set _in the clear._ In\nother words, the value set is visible to the client. For sensitive data, Rocket\nprovides _private_ cookies. Private cookies are similar to regular cookies\nexcept that they are encrypted using authenticated encryption, a form of\nencryption which simultaneously provides confidentiality, integrity, and\nauthenticity. Thus, private cookies cannot be inspected, tampered with, or\nmanufactured by clients. If you prefer, you can think of private cookies as\nbeing signed and encrypted.\n\nSupport for private cookies must be manually enabled via the `secrets` crate\nfeature:\n\n```toml\n## in Cargo.toml\nrocket = { version = \"0.6.0-dev\", features = [\"secrets\"] }\n```\n\nThe API for retrieving, adding, and removing private cookies is identical except\nthat most methods are suffixed with `_private`. These methods are:\n[`get_private`], [`add_private`], and [`remove_private`]. An example of their\nusage is below:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::http::{Cookie, CookieJar};\nuse rocket::response::{Flash, Redirect};\n\n/// Retrieve the user's ID, if any.\n#[get(\"/user_id\")]\nfn user_id(cookies: &CookieJar<'_>) -> Option<String> {\n    cookies.get_private(\"user_id\")\n        .map(|crumb| format!(\"User ID: {}\", crumb.value()))\n}\n\n/// Remove the `user_id` cookie.\n#[post(\"/logout\")]\nfn logout(cookies: &CookieJar<'_>) -> Flash<Redirect> {\n    cookies.remove_private(\"user_id\");\n    Flash::success(Redirect::to(\"/\"), \"Successfully logged out.\")\n}\n```\n\n[`CookieJar::add()`]: @api/master/rocket/http/struct.CookieJar.html#method.add\n\n### Secret Key\n\nTo encrypt private cookies, Rocket uses the 256-bit key specified in the\n`secret_key` configuration parameter. When compiled in debug mode, a fresh key\nis generated automatically. In release mode, Rocket requires you to set a secret\nkey if the `secrets` feature is enabled. Failure to do so results in a hard\nerror at launch time. The value of the parameter may either be a 256-bit base64\nor hex string or a 32-byte slice.\n\nGenerating a string suitable for use as a `secret_key` configuration value is\nusually done through tools like `openssl`. Using `openssl`, a 256-bit base64 key\ncan be generated with the command `openssl rand -base64 32`.\n\nFor more information on configuration, see the [Configuration] section of the\nguide.\n\n[`get_private`]: @api/master/rocket/http/struct.CookieJar.html#method.get_private\n[`add_private`]: @api/master/rocket/http/struct.CookieJar.html#method.add_private\n[`remove_private`]: @api/master/rocket/http/struct.CookieJar.html#method.remove_private\n[Configuration]: ../configuration/\n\n## Format\n\nA route can specify the data format it is willing to accept or respond with by\nusing the `format` route parameter. The value of the parameter is a string\nidentifying an HTTP media type or a shorthand variant. For instance, for JSON\ndata, the string `application/json` or simply `json` can be used.\n\nWhen a route indicates a payload-supporting method (`PUT`, `POST`, `DELETE`, and\n`PATCH`), the `format` route parameter instructs Rocket to check against the\n`Content-Type` header of the incoming request. Only requests where the\n`Content-Type` header matches the `format` parameter will match to the route.\n\nAs an example, consider the following route:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# type User = String;\n\n#[post(\"/user\", format = \"application/json\", data = \"<user>\")]\nfn new_user(user: User) { /* ... */ }\n```\n\nThe `format` parameter in the `post` attribute declares that only incoming\nrequests with `Content-Type: application/json` will match `new_user`. (The\n`data` parameter is described in the next section.) Shorthand is also supported\nfor the most common `format` arguments. Instead of using the full Content-Type,\n`format = \"application/json\"`, you can also write shorthands like `format =\n\"json\"`. For a full list of available shorthands, see the\n[`ContentType::parse_flexible()`] documentation.\n\nWhen a route indicates a non-payload-supporting method (`GET`, `HEAD`,\n`OPTIONS`) the `format` route parameter instructs Rocket to check against the\n`Accept` header of the incoming request. Only requests where the preferred media\ntype in the `Accept` header matches the `format` parameter will match to the\nroute.\n\nAs an example, consider the following route:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n# type User = ();\n\n#[get(\"/user/<id>\", format = \"json\")]\nfn user(id: usize) -> User { /* .. */ }\n```\n\nThe `format` parameter in the `get` attribute declares that only incoming\nrequests with `application/json` as the preferred media type in the `Accept`\nheader will match `user`. If instead the route had been declared as `post`,\nRocket would match the `format` against the `Content-Type` header of the\nincoming response.\n\n[`ContentType::parse_flexible()`]: @api/master/rocket/http/struct.ContentType.html#method.parse_flexible\n\n## Body Data\n\nBody data processing, like much of Rocket, is type directed. To indicate that a\nhandler expects body data, annotate it with `data = \"<param>\"`, where `param` is\nan argument in the handler. The argument's type must implement the [`FromData`]\ntrait. It looks like this, where `T` is assumed to implement `FromData`:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# type T = String;\n\n#[post(\"/\", data = \"<input>\")]\nfn new(input: T) { /* .. */ }\n```\n\nAny type that implements [`FromData`] is also known as _a data guard_.\n\n[`FromData`]: @api/master/rocket/data/trait.FromData.html\n\n### JSON\n\nThe [`Json<T>`](@api/master/rocket/serde/json/struct.Json.html) guard deserializes body\ndata as JSON. The only condition is that the generic type `T` implements the\n`Deserialize` trait from [`serde`](https://serde.rs).\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::serde::{Deserialize, json::Json};\n\n#[derive(Deserialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Task<'r> {\n    description: &'r str,\n    complete: bool\n}\n\n#[post(\"/todo\", data = \"<task>\")]\nfn new(task: Json<Task<'_>>) { /* .. */ }\n```\n\n! warning: Using Rocket's `serde` derive re-exports requires a bit more effort.\n\n  For convenience, Rocket re-exports `serde`'s `Serialize` and `Deserialize`\n  traits and derive macros from `rocket::serde`. However, due to Rust's limited\n  support for derive macro re-exports, using the re-exported derive macros\n  requires annotating structures with `#[serde(crate = \"rocket::serde\")]`. If\n  you'd like to avoid this extra annotation, you must depend on `serde` directly\n  via your crate's `Cargo.toml`:\n\n  ```toml\n  serde = { version = \"1.0\", features = [\"derive\"] }\n  ```\n\n  We always use the extra annotation in the guide, but you may prefer the\n  alternative.\n\nSee the [JSON example](@git/master/examples/serialization/src/json.rs) on GitHub for a\ncomplete example.\n\n! note: JSON support requires enabling Rocket's `json` feature flag.\n\n  Rocket intentionally places JSON support, as well support for other data\n  formats and features, behind feature flags. See [the api\n  docs](@api/master/rocket/#features) for a list of available features. The `json`\n  feature can be enabled in the `Cargo.toml`:\n\n  ```toml\n  rocket = { version = \"0.6.0-dev\", features = [\"json\"] }\n  ```\n\n### Temporary Files\n\nThe [`TempFile`] data guard streams data directly to a temporary file which can\nthen be persisted. It makes accepting file uploads trivial:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::fs::TempFile;\n\n#[post(\"/upload\", format = \"plain\", data = \"<file>\")]\nasync fn upload(mut file: TempFile<'_>) -> std::io::Result<()> {\n    # let permanent_location = \"/tmp/perm.txt\";\n    file.persist_to(permanent_location).await\n}\n```\n\n[`TempFile`]: @api/master/rocket/fs/enum.TempFile.html\n\n### Streaming\n\nSometimes you just want to handle incoming data directly. For example, you might\nwant to stream the incoming data to some sink. Rocket makes this as simple as\npossible via the [`Data`](@api/master/rocket/data/struct.Data.html) type:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::tokio;\n\nuse rocket::data::{Data, ToByteUnit};\n\n#[post(\"/debug\", data = \"<data>\")]\nasync fn debug(data: Data<'_>) -> std::io::Result<()> {\n    // Stream at most 512KiB of the body data to stdout.\n    data.open(512.kibibytes())\n        .stream_to(tokio::io::stdout())\n        .await?;\n\n    Ok(())\n}\n```\n\nThe route above accepts any `POST` request to the `/debug` path. At most 512KiB\nof the incoming is streamed out to `stdout`. If the upload fails, an error\nresponse is returned. The handler above is complete. It really is that simple!\n\n! note: Rocket requires setting limits when reading incoming data.\n\n  To aid in preventing DoS attacks, Rocket requires you to specify, as a\n  [`ByteUnit`](@api/master/rocket/data/struct.ByteUnit.html), the amount of data you're\n  willing to accept from the client when `open`ing a data stream. The\n  [`ToByteUnit`](@api/master/rocket/data/trait.ToByteUnit.html) trait makes specifying\n  such a value as idiomatic as `128.kibibytes()`.\n\n## Forms\n\nForms are one of the most common types of data handled in web applications, and\nRocket makes handling them easy. Rocket supports both `multipart` and\n`x-www-form-urlencoded` forms out of the box, enabled by the [`Form`] data guard\nand derivable [`FromForm`] trait.\n\nSay your application is processing a form submission for a new todo `Task`. The\nform contains two fields: `complete`, a checkbox, and `type`, a text field. You\ncan easily handle the form request in Rocket as follows:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::form::Form;\n\n#[derive(FromForm)]\nstruct Task<'r> {\n    complete: bool,\n    r#type: &'r str,\n}\n\n#[post(\"/todo\", data = \"<task>\")]\nfn new(task: Form<Task<'_>>) { /* .. */ }\n```\n\n[`Form`] is data guard as long as its generic parameter implements the\n[`FromForm`] trait. In the example, we've derived the `FromForm` trait\nautomatically for `Task`. `FromForm` can be derived for any structure whose\nfields implement [`FromForm`], or equivalently, [`FromFormField`].\n\nIf a `POST /todo` request arrives, the form data will automatically be parsed\ninto the `Task` structure. If the data that arrives isn't of the correct\nContent-Type, the request is forwarded. If the data doesn't parse or is simply\ninvalid, a customizable error is returned. As before, a forward or error can\nbe caught by using the `Option` and `Result` types:\n\n```rust\n# use rocket::{post, form::Form};\n# type Task<'r> = &'r str;\n\n#[post(\"/todo\", data = \"<task>\")]\nfn new(task: Option<Form<Task<'_>>>) { /* .. */ }\n```\n\n### Multipart\n\nMultipart forms are handled transparently, with no additional effort. Most\n`FromForm` types can parse themselves from the incoming data stream. For\nexample, here's a form and route that accepts a multipart file upload using\n[`TempFile`]:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::form::Form;\nuse rocket::fs::TempFile;\n\n#[derive(FromForm)]\nstruct Upload<'r> {\n    save: bool,\n    file: TempFile<'r>,\n}\n\n#[post(\"/upload\", data = \"<upload>\")]\nfn upload_form(upload: Form<Upload<'_>>) { /* .. */ }\n```\n\n[`Form`]: @api/master/rocket/form/struct.Form.html\n[`FromForm`]: @api/master/rocket/form/trait.FromForm.html\n[`FromFormField`]: @api/master/rocket/form/trait.FromFormField.html\n\n### Parsing Strategy\n\nRocket's `FromForm` parsing is _lenient_ by default: a `Form<T>` will parse\nsuccessfully from an incoming form even if it contains extra, duplicate, or\nmissing fields. Extras or duplicates are ignored -- no validation or parsing of\nthe fields occurs -- and missing fields are filled with defaults when available.\nTo change this behavior and make form parsing _strict_, use the\n[`Form<Strict<T>>`] data type, which emits errors if there are any extra or\nmissing fields, irrespective of defaults.\n\nYou can use a `Form<Strict<T>>` anywhere you'd use a `Form<T>`. Its generic\nparameter is also required to implement `FromForm`. For instance, we can simply\nreplace `Form<T>` with `Form<Strict<T>>` above to get strict parsing:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::form::{Form, Strict};\n\n# #[derive(FromForm)] struct Task<'r> { complete: bool, description: &'r str, }\n\n#[post(\"/todo\", data = \"<task>\")]\nfn new(task: Form<Strict<Task<'_>>>) { /* .. */ }\n```\n\n`Strict` can also be used to make individual fields strict while keeping the\noverall structure and remaining fields lenient:\n\n```rust\n# #[macro_use] extern crate rocket;\n# use rocket::form::{Form, Strict};\n\n#[derive(FromForm)]\nstruct Input {\n    required: Strict<bool>,\n    uses_default: bool\n}\n\n#[post(\"/\", data = \"<input>\")]\nfn new(input: Form<Input>) { /* .. */ }\n```\n\n[`Lenient`] is the _lenient_ analog to `Strict`, which forces parsing to be\nlenient. `Form` is lenient by default, so a `Form<Lenient<T>>` is redundant, but\n`Lenient` can be used to overwrite a strict parse as lenient:\n`Option<Lenient<T>>`.\n\n[`Form<Strict<T>>`]: @api/master/rocket/form/struct.Strict.html\n[`Lenient`]: @api/master/rocket/form/struct.Lenient.html\n\n### Defaults\n\nA form guard may specify a default value to use when a field is missing. The\ndefault value is used only when parsing is _lenient_. When _strict_, all errors,\nincluding missing fields, are propagated directly.\n\nSome types with defaults include `bool`, which defaults to `false`, useful for\ncheckboxes, `Option<T>`, which defaults to `None`, and [`form::Result`], which\ndefaults to `Err(Missing)` or otherwise collects errors in an `Err` of\n[`Errors<'_>`]. Defaulting guards can be used just like any other form guard:\n\n```rust\n# use rocket::form::FromForm;\nuse rocket::form::{self, Errors};\n\n#[derive(FromForm)]\nstruct MyForm<'v> {\n    maybe_string: Option<&'v str>,\n    ok_or_error: form::Result<'v, Vec<&'v str>>,\n    here_or_false: bool,\n}\n# rocket_docs_tests::assert_form_parses_ok!(MyForm, \"\");\n```\n\nThe default can be overridden or unset using the `#[field(default = expr)]`\nfield attribute. If `expr` is not literally `None`, the parameter sets the\ndefault value of the field to be `expr.into()`. If `expr` _is_ `None`, the\nparameter _unsets_ the default value of the field, if any.\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct MyForm {\n    // Set the default value to be `\"hello\"`.\n    //\n    // Note how an `&str` is automatically converted into a `String`.\n    #[field(default = \"hello\")]\n    greeting: String,\n    // Remove the default value of `false`, requiring all parses of `MyForm`\n    // to contain an `is_friendly` field.\n    #[field(default = None)]\n    is_friendly: bool,\n}\n```\n\nSee the [`FromForm` derive] documentation for full details on the `default`\nattribute parameter as well documentation on the more expressive `default_with`\nparameter option.\n\n[`Errors<'_>`]: @api/master/rocket/form/struct.Errors.html\n[`form::Result`]: @api/master/rocket/form/type.Result.html\n[`FromForm` derive]: @api/master/rocket/derive.FromForm.html\n\n### Field Renaming\n\nBy default, Rocket matches the name of an incoming form field to the name of a\nstructure field. While this behavior is typical, it may also be desired to use\ndifferent names for form fields and struct fields while still parsing as\nexpected. You can ask Rocket to look for a different form field for a given\nstructure field by using one or more `#[field(name = \"name\")]` or `#[field(name\n= uncased(\"name\")]` field annotation. The `uncased` variant case-insensitively\nmatches field names.\n\nAs an example, say that you're writing an application that receives data from an\nexternal service. The external service `POST`s a form with a field named\n`first-Name` which you'd like to write as `first_name` in Rust. Such a form\nstructure can be written as:\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct External<'r> {\n    #[field(name = \"first-Name\")]\n    first_name: &'r str\n}\n```\n\nIf you want to accept both `firstName` case-insensitively as well as\n`first_name` case-sensitively, you'll need to use two annotations:\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct External<'r> {\n    #[field(name = uncased(\"firstName\"))]\n    #[field(name = \"first_name\")]\n    first_name: &'r str\n}\n```\n\nThis will match any casing of `firstName` including `FirstName`, `firstname`,\n`FIRSTname`, and so on, but only match exactly on `first_name`.\n\nIf instead you wanted to match any of `first-name`, `first_name` or `firstName`,\nin each instance case-insensitively, you would write:\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct External<'r> {\n    #[field(name = uncased(\"first-name\"))]\n    #[field(name = uncased(\"first_name\"))]\n    #[field(name = uncased(\"firstname\"))]\n    first_name: &'r str\n}\n```\n\nCased and uncased renamings can be mixed and matched, and any number of\nrenamings is allowed. Rocket will emit an error at compile-time if field names\nconflict, preventing ambiguous parsing at runtime.\n\n### Ad-Hoc Validation\n\nFields of forms can be easily ad-hoc validated via the `#[field(validate)]`\nattribute. As an example, consider a form field `age: u16` which we'd like to\nensure is greater than `21`. The following structure accomplishes this:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[derive(FromForm)]\nstruct Person {\n    #[field(validate = range(21..))]\n    age: u16\n}\n```\n\nThe expression `range(21..)` is a call to [`form::validate::range`]. Rocket\npasses a borrow of the attributed field, here `self.age`, as the first parameter\nto the function call. The rest of the fields are pass as written in the\nexpression.\n\nAny function in the [`form::validate`] module can be called, and other fields of\nthe form can be passed in by using `self.$field` where `$field` is the name of\nthe field in the structure. You can also apply more than one validation to a\nfield by using multiple attributes. For example, the following form validates\nthat the value of the field `confirm` is equal to the value of the field `value`\nand that it doesn't contain `no`:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[derive(FromForm)]\nstruct Password<'r> {\n    #[field(name = \"password\")]\n    value: &'r str,\n    #[field(validate = eq(self.value))]\n    #[field(validate = omits(\"no\"))]\n    confirm: &'r str,\n}\n```\n\n[`form::validate`]: @api/master/rocket/form/validate/index.html\n[`form::validate::range`]: @api/master/rocket/form/validate/fn.range.html\n[`form::Result`]: @api/master/rocket/form/type.Result.html\n[`Errors<'_>`]: @api/master/rocket/form/error/struct.Errors.html\n\nIn reality, the expression after `validate =` can be _any_ expression as long as\nit evaluates to a value of type `Result<(), Errors<'_>>` (aliased by\n[`form::Result`]), where an `Ok` value means that validation was successful while\nan `Err` of [`Errors<'_>`] indicates the error(s) that occurred. For instance, if\nyou wanted to implement an ad-hoc Luhn validator for credit-card-like numbers,\nyou might write:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::time::Date;\nuse rocket::form::{self, Error};\n\n#[derive(FromForm)]\nstruct CreditCard {\n    #[field(validate = luhn(self.cvv, &self.expiration))]\n    number: u64,\n    #[field(validate = range(..9999))]\n    cvv: u16,\n    expiration: Date,\n}\n\nfn luhn<'v>(number: &u64, cvv: u16, exp: &Date) -> form::Result<'v, ()> {\n    # let valid = false;\n    if !valid {\n        Err(Error::validation(\"invalid credit card number\"))?;\n    }\n\n    Ok(())\n}\n```\n\nIf a field's validation doesn't depend on other fields (validation is _local_),\nit is validated prior to those fields that do. For `CreditCard`, `cvv` and\n`expiration` will be validated prior to `number`.\n\n### Wrapping Validators\n\nIf a particular validation is applied in more than one place, prefer creating a\ntype that encapsulates and represents the validated value. For example, if your\napplication often validates `age` fields, consider creating a custom `Age` form\nguard that always applies the validation:\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\n#[field(validate = range(18..150))]\nstruct Age(u16);\n```\n\nThis approach is also useful when a custom validator already exists in some\nother form. For instance, the following example leverages [`try_with`] and an\nexisting `FromStr` implementation on a `Token` type to validate a string:\n\n```rust\n# use rocket::form::FromForm;\n\n# impl FromStr for Token<'_> {\n#     type Err = &'static str;\n#     fn from_str(s: &str) -> Result<Self, Self::Err> { todo!() }\n# }\n\nuse std::str::FromStr;\n\n#[derive(FromForm)]\n#[field(validate = try_with(|s| Token::from_str(s)))]\nstruct Token<'r>(&'r str);\n```\n\n[`try_with`]: @api/master/rocket/form/validate/fn.try_with.html\n\n### Collections\n\nRocket's form support allows your application to express _any_ structure with\n_any_ level of nesting and collection, eclipsing the expressivity offered by any\nother web framework. To parse into these structures, Rocket separates a field's\nname into \"keys\" by the delimiters `.` and `[]`, each of which in turn is\nseparated into \"indices\" by `:`. In other words, a name has keys and a key has\nindices, each a strict subset of its parent. This is depicted in the example\nbelow with two form fields:\n\n```html\nfood.bart[bar:foo].blam[0_0][1000]=some-value&another_field=another_val\n|-------------------------------|   name\n|--| |--| |-----|  |--| |-|  |--|   keys\n|--| |--| |-| |-|  |--| |-|  |--|   indices\n```\n\nRocket _pushes_ form fields to `FromForm` types as they arrive. The type then\noperates on _one_ key (and all of its indices) at a time and _shifts_ to the\nnext `key`, from left-to-right, before invoking any other `FromForm` types with\nthe rest of the field. A _shift_ encodes a nested structure while indices allows\nfor structures that need more than one value to allow indexing.\n\n! note: A `.` after a `[]` is optional.\n\n  The form field name `a[b]c` is exactly equivalent to `a[b].c`. Likewise, the\n  form field name `.a` is equivalent to `a`.\n\n### Nesting\n\nForm structs can be nested:\n\n```rust\nuse rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct MyForm<'r> {\n    owner: Person<'r>,\n    pet: Pet<'r>,\n}\n\n#[derive(FromForm)]\nstruct Person<'r> {\n    name: &'r str\n}\n\n#[derive(FromForm)]\nstruct Pet<'r> {\n    name: &'r str,\n    #[field(validate = eq(true))]\n    good_pet: bool,\n}\n```\n\nTo parse into a `MyForm`, a form with the following fields must be submitted:\n\n  * `owner.name` - string\n  * `pet.name` - string\n  * `pet.good_pet` - boolean\n\nSuch a form, URL-encoded, may look like:\n\n```rust\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{assert_form_parses, assert_not_form_parses};\n# #[derive(FromForm, Debug, PartialEq)] struct MyForm { owner: Person, pet: Pet, }\n# #[derive(FromForm, Debug, PartialEq)] struct Person { name: String }\n# #[derive(FromForm, Debug, PartialEq)] struct Pet { name: String, good_pet: bool, }\n\n# assert_form_parses! { MyForm,\n\"owner.name=Bob&pet.name=Sally&pet.good_pet=on\",\n# \"owner.name=Bob&pet.name=Sally&pet.good_pet=yes\",\n# \"owner.name=Bob&pet.name=Sally&pet.good_pet=on\",\n# \"pet.name=Sally&owner.name=Bob&pet.good_pet=on\",\n# \"pet.name=Sally&pet.good_pet=on&owner.name=Bob\",\n# =>\n\n// ...which parses as this struct.\nMyForm {\n    owner: Person {\n        name: \"Bob\".into()\n    },\n    pet: Pet {\n        name: \"Sally\".into(),\n        good_pet: true,\n    }\n}\n# };\n```\n\nNote that `.` is used to separate each field. Identically, `[]` can be used in\nplace of or in addition to `.`:\n\n```rust\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{assert_form_parses, assert_not_form_parses};\n# #[derive(FromForm, Debug, PartialEq)] struct MyForm { owner: Person, pet: Pet, }\n# #[derive(FromForm, Debug, PartialEq)] struct Person { name: String }\n# #[derive(FromForm, Debug, PartialEq)] struct Pet { name: String, good_pet: bool, }\n\n// All of these are identical to the previous...\n# assert_form_parses! { MyForm,\n\"owner[name]=Bob&pet[name]=Sally&pet[good_pet]=on\",\n\"owner[name]=Bob&pet[name]=Sally&pet.good_pet=on\",\n\"owner.name=Bob&pet[name]=Sally&pet.good_pet=on\",\n\"pet[name]=Sally&owner.name=Bob&pet.good_pet=on\",\n# =>\n\n// ...and thus parse as this struct.\nMyForm {\n    owner: Person {\n        name: \"Bob\".into()\n    },\n    pet: Pet {\n        name: \"Sally\".into(),\n        good_pet: true,\n    }\n}\n# };\n```\n\nAny level of nesting is allowed.\n\n### Vectors\n\nA form can also contain sequences:\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct MyForm {\n    numbers: Vec<usize>,\n}\n```\n\nTo parse into a `MyForm`, a form with the following fields must be submitted:\n\n  * `numbers[$k]` - usize (or equivalently, `numbers.$k`)\n\n...where `$k` is the \"key\" used to determine whether to push the rest of the\nfield to the last element in the vector or create a new one. If the key is the\nsame as the previous key seen by the vector, then the field's value is pushed to\nthe last element. Otherwise, a new element is created. The actual value of `$k`\nis irrelevant: it is only used for comparison, has no semantic meaning, and is\nnot remembered by `Vec`. The special blank key is never equal to any other key.\n\nConsider the following examples.\n\n```rust\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{assert_form_parses, assert_not_form_parses};\n# #[derive(FromForm, PartialEq, Debug)] struct MyForm { numbers: Vec<usize>, }\n// These form strings...\n# assert_form_parses! { MyForm,\n\"numbers[]=1&numbers[]=2&numbers[]=3\",\n\"numbers[a]=1&numbers[b]=2&numbers[c]=3\",\n\"numbers[a]=1&numbers[b]=2&numbers[a]=3\",\n\"numbers[]=1&numbers[b]=2&numbers[c]=3\",\n\"numbers.0=1&numbers.1=2&numbers[c]=3\",\n\"numbers=1&numbers=2&numbers=3\",\n# =>\n\n// ...parse as this struct:\nMyForm {\n    numbers: vec![1 ,2, 3]\n}\n# };\n\n// These, on the other hand...\n# assert_form_parses! { MyForm,\n\"numbers[0]=1&numbers[0]=2&numbers[]=3\",\n\"numbers[]=1&numbers[b]=3&numbers[b]=2\",\n# =>\n\n// ...parse as this struct:\nMyForm {\n    numbers: vec![1, 3]\n}\n# };\n```\n\nYou might be surprised to see the last example,\n`\"numbers=1&numbers=2&numbers=3\"`, in the first list. This is equivalent to the\nprevious examples as the \"key\" seen by the `Vec` (everything after `numbers`) is\nempty. Thus, `Vec` pushes to a new `usize` for every field. `usize`, like all\ntypes that implement `FromFormField`, discard duplicate and extra fields when\nparsed leniently, keeping only the _first_ field.\n\n### Nesting in Vectors\n\nAny `FromForm` type can appear in a sequence:\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct MyForm {\n    name: String,\n    pets: Vec<Pet>,\n}\n\n#[derive(FromForm)]\nstruct Pet {\n    name: String,\n    #[field(validate = eq(true))]\n    good_pet: bool,\n}\n```\n\nTo parse into a `MyForm`, a form with the following fields must be submitted:\n\n  * `name` - string\n  * `pets[$k].name` - string\n  * `pets[$k].good_pet` - boolean\n\nExamples include:\n\n```rust\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{assert_form_parses, assert_not_form_parses};\n# #[derive(FromForm, Debug, PartialEq)] struct MyForm { name: String, pets: Vec<Pet>, }\n# #[derive(FromForm, Debug, PartialEq)] struct Pet { name: String, good_pet: bool, }\n// These form strings...\nassert_form_parses! { MyForm,\n\"name=Bob&pets[0].name=Sally&pets[0].good_pet=on\",\n\"name=Bob&pets[sally].name=Sally&pets[sally].good_pet=yes\",\n# =>\n\n// ...parse as this struct:\nMyForm {\n    name: \"Bob\".into(),\n    pets: vec![Pet { name: \"Sally\".into(), good_pet: true }],\n}\n# };\n\n// These, on the other hand, fail to parse:\n# assert_not_form_parses! { MyForm,\n\"name=Bob&pets[0].name=Sally&pets[1].good_pet=on\",\n\"name=Bob&pets[].name=Sally&pets[].good_pet=on\",\n# };\n```\n\n### Nested Vectors\n\nSince vectors are `FromForm` themselves, they can appear inside of vectors:\n\n```rust\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct MyForm {\n    v: Vec<Vec<usize>>,\n}\n```\n\nThe rules are exactly the same.\n\n```rust\n# use rocket::form::FromForm;\n# use rocket_docs_tests::assert_form_parses;\n# #[derive(FromForm, Debug, PartialEq)] struct MyForm { v: Vec<Vec<usize>>, }\n# assert_form_parses! { MyForm,\n\"v=1&v=2&v=3\" => MyForm { v: vec![vec![1], vec![2], vec![3]] },\n\"v[][]=1&v[][]=2&v[][]=3\" => MyForm { v: vec![vec![1], vec![2], vec![3]] },\n\"v[0][]=1&v[0][]=2&v[][]=3\" => MyForm { v: vec![vec![1, 2], vec![3]] },\n\"v[][]=1&v[0][]=2&v[0][]=3\" => MyForm { v: vec![vec![1], vec![2, 3]] },\n\"v[0][]=1&v[0][]=2&v[0][]=3\" => MyForm { v: vec![vec![1, 2, 3]] },\n\"v[0][0]=1&v[0][0]=2&v[0][]=3\" => MyForm { v: vec![vec![1, 3]] },\n\"v[0][0]=1&v[0][0]=2&v[0][0]=3\" => MyForm { v: vec![vec![1]] },\n# };\n```\n\n### Maps\n\nA form can also contain maps:\n\n```rust\n# use rocket::form::FromForm;\nuse std::collections::HashMap;\n\n#[derive(FromForm)]\nstruct MyForm {\n    ids: HashMap<String, usize>,\n}\n```\n\nTo parse into a `MyForm`, a form with the following fields must be submitted:\n\n  * `ids[$string]` - usize (or equivalently, `ids.$string`)\n\n...where `$string` is the \"key\" used to determine which value in the map to push\nthe rest of the field to. Unlike with vectors, the key _does_ have a semantic\nmeaning and _is_ remembered, so ordering of fields is inconsequential: a given\nstring `$string` always maps to the same element.\n\nAs an example, the following are equivalent and all parse to `{ \"a\" => 1, \"b\" =>\n2 }`:\n\n```rust\n# use std::collections::HashMap;\n#\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{map, assert_form_parses};\n#\n# #[derive(Debug, PartialEq, FromForm)]\n# struct MyForm {\n#     ids: HashMap<String, usize>,\n# }\n// These form strings...\n# assert_form_parses! { MyForm,\n\"ids[a]=1&ids[b]=2\",\n\"ids[b]=2&ids[a]=1\",\n\"ids[a]=1&ids[a]=2&ids[b]=2\",\n\"ids.a=1&ids.b=2\",\n# =>\n\n// ...parse as this struct:\nMyForm {\n    ids: map! {\n        \"a\" => 1usize,\n        \"b\" => 2usize,\n    }\n}\n# };\n```\n\nBoth the key and value of a `HashMap` can be any type that implements\n`FromForm`. Consider a value representing another structure:\n\n```rust\n# use std::collections::HashMap;\n\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct MyForm {\n    ids: HashMap<usize, Person>,\n}\n\n#[derive(FromForm)]\nstruct Person {\n    name: String,\n    age: usize\n}\n```\n\nTo parse into a `MyForm`, a form with the following fields must be submitted:\n\n  * `ids[$usize].name` - string\n  * `ids[$usize].age` - usize\n\nExamples include:\n\n```rust\n# use std::collections::HashMap;\n#\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{map, assert_form_parses};\n#\n\n# #[derive(FromForm, Debug, PartialEq)] struct MyForm { ids: HashMap<usize, Person>, }\n# #[derive(FromForm, Debug, PartialEq)] struct Person { name: String, age: usize }\n\n// These form strings...\n# assert_form_parses! { MyForm,\n\"ids[0]name=Bob&ids[0]age=3&ids[1]name=Sally&ids[1]age=10\",\n\"ids[0]name=Bob&ids[1]age=10&ids[1]name=Sally&ids[0]age=3\",\n\"ids[0]name=Bob&ids[1]name=Sally&ids[0]age=3&ids[1]age=10\",\n# =>\n\n// ...which parse as this struct:\nMyForm {\n    ids: map! {\n        0usize => Person { name: \"Bob\".into(), age: 3 },\n        1usize => Person { name: \"Sally\".into(), age: 10 },\n    }\n}\n# };\n```\n\nNow consider the following structure where both the key and value represent\nstructures:\n\n```rust\n# use std::collections::HashMap;\n\n# use rocket::form::FromForm;\n\n#[derive(FromForm)]\nstruct MyForm {\n    m: HashMap<Person, Pet>,\n}\n\n#[derive(FromForm, PartialEq, Eq, Hash)]\nstruct Person {\n    name: String,\n    age: usize\n}\n\n#[derive(FromForm)]\nstruct Pet {\n    wags: bool\n}\n```\n\n! warning: The `HashMap` key type, here `Person`, must implement `Eq + Hash`.\n\nSince the key is a collection, here `Person`, it must be built up from multiple\nfields. This requires being able to specify via the form field name that the\nfield's value corresponds to a key in the map. The is done with the syntax\n`k:$key` which indicates that the field corresponds to the `k`ey named `$key`.\nThus, to parse into a `MyForm`, a form with the following fields must be\nsubmitted:\n\n  * `m[k:$key].name` - string\n  * `m[k:$key].age` - usize\n  * `m[$key].wags` or `m[v:$key].wags`  - boolean\n\n! note: The syntax `v:$key` also exists.\n\n  The shorthand `m[$key]` is equivalent to `m[v:$key]`.\n\nNote that `$key` can be _anything_: it is simply a symbolic identifier for a\nkey/value pair in the map and has no bearing on the actual values that will be\nparsed into the map.\n\nExamples include:\n\n```rust\n# use std::collections::HashMap;\n#\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{map, assert_form_parses};\n#\n\n# #[derive(FromForm, Debug, PartialEq)] struct MyForm { m: HashMap<Person, Pet>, }\n# #[derive(FromForm, Debug, PartialEq, Eq, Hash)] struct Person { name: String, age: usize }\n# #[derive(FromForm, Debug, PartialEq)] struct Pet { wags: bool }\n\n// These form strings...\n# assert_form_parses! { MyForm,\n\"m[k:alice]name=Alice&m[k:alice]age=30&m[v:alice].wags=no\",\n\"m[k:alice]name=Alice&m[k:alice]age=30&m[alice].wags=no\",\n\"m[k:123]name=Alice&m[k:123]age=30&m[123].wags=no\",\n# =>\n\n// ...which parse as this struct:\nMyForm {\n    m: map! {\n        Person { name: \"Alice\".into(), age: 30 } => Pet { wags: false }\n    }\n}\n# };\n\n// While this longer form string...\n# assert_form_parses! { MyForm,\n\"m[k:a]name=Alice&m[k:a]age=40&m[a].wags=no&\\\nm[k:b]name=Bob&m[k:b]age=72&m[b]wags=yes&\\\nm[k:cat]name=Katie&m[k:cat]age=12&m[cat]wags=yes\",\n# =>\n\n// ...parses as this struct:\nMyForm {\n    m: map! {\n        Person { name: \"Alice\".into(), age: 40 } => Pet { wags: false },\n        Person { name: \"Bob\".into(), age: 72 } => Pet { wags: true },\n        Person { name: \"Katie\".into(), age: 12 } => Pet { wags: true },\n    }\n}\n# };\n```\n\n### Arbitrary Collections\n\n_Any_ collection can be expressed with any level of arbitrary nesting, maps, and\nsequences. Consider the extravagantly contrived type:\n\n```rust\nuse std::collections::{BTreeMap, HashMap};\n# use rocket::form::FromForm;\n\n#[derive(FromForm, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]\nstruct Person {\n    name: String,\n    age: usize\n}\n\n# type Foo =\nHashMap<Vec<BTreeMap<Person, usize>>, HashMap<usize, Person>>\n# ;\n# /*\n|-[k:$k1]-----------|------|------| |-[$k1]-----------------|\n     |---[$i]-------|------|------|         |-[k:$j]*|\n           |-[k:$k2]|------|                 ~~[$j]~~|name*|\n                    |-name*|                 ~~[$j]~~|age-*|\n                    |-age*-|\n           |~~~~~~~~~~~~~~~|v:$k2*|\n# */\n```\n\n! warning: The `BTreeMap` key type, here `Person`, must implement `Ord`.\n\nAs illustrated above with `*` marking terminals, we need the following form\nfields for this structure:\n\n  * `[k:$k1][$i][k:$k2]name` - string\n  * `[k:$k1][$i][k:$k2]age` - usize\n  * `[k:$k1][$i][$k2]` - usize\n  * `[$k1][k:$j]` - usize\n  * `[$k1][$j]name` - string\n  * `[$k1][$j]age` - string\n\nWhere we have the following symbolic keys:\n\n  * `$k1`: symbolic name of the top-level key\n  * `$i`: symbolic name of the vector index\n  * `$k2`: symbolic name of the sub-level  (`BTreeMap`) key\n  * `$j`: symbolic name and/or value top-level value's key\n\n```rust\n# use std::collections::BTreeMap;\n# use std::collections::HashMap;\n#\n# use rocket::form::FromForm;\n# use rocket_docs_tests::{map, bmap, assert_form_parses};\n# #[derive(FromForm, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]\n# struct Person { name: String, age: usize }\n\ntype Foo = HashMap<Vec<BTreeMap<Person, usize>>, HashMap<usize, Person>>;\n\n// This (long, contrived) form string...\n# assert_form_parses! { Foo,\n\"[k:top_key][i][k:sub_key]name=Bobert&\\\n[k:top_key][i][k:sub_key]age=22&\\\n[k:top_key][i][sub_key]=1337&\\\n[top_key][7]name=Builder&\\\n[top_key][7]age=99\",\n\n// We could also set the top-level value's key explicitly:\n// [top_key][k:7]=7\n# \"[k:top_key][i][k:sub_key]name=Bobert&\\\n# [k:top_key][i][k:sub_key]age=22&\\\n# [top_key][k:7]=7&\\\n# [k:top_key][i][sub_key]=1337&\\\n# [top_key][7]name=Builder&\\\n# [top_key][7]age=99\",\n# =>\n\n// ...parses as this (long, contrived) map:\nmap! {\n    vec![bmap! {\n        Person { name: \"Bobert\".into(), age: 22 } => 1337usize,\n    }]\n    =>\n    map! {\n        7usize => Person { name: \"Builder\".into(), age: 99 }\n    }\n}\n# };\n```\n\n### Context\n\nThe [`Contextual`] form guard acts as a proxy for any other form guard,\nrecording all submitted form values and produced errors and associating them\nwith their corresponding field name. `Contextual` is particularly useful for\nrendering forms with previously submitted values and errors associated with form\ninput.\n\nTo retrieve the context for a form, use `Form<Contextual<'_, T>>` as a data\nguard, where `T` implements `FromForm`. The `context` field contains the form's\n[`Context`]:\n\n```rust\n# use rocket::post;\n# type T = String;\n\nuse rocket::form::{Form, Contextual};\n\n#[post(\"/submit\", data = \"<form>\")]\nfn submit(form: Form<Contextual<'_, T>>) {\n    if let Some(ref value) = form.value {\n        // The form parsed successfully. `value` is the `T`.\n    }\n\n    // We can retrieve raw field values and errors.\n    let raw_id_value = form.context.field_value(\"id\");\n    let id_errors = form.context.field_errors(\"id\");\n}\n```\n\n`Context` is nesting-aware for errors. When `Context` is queried for errors for\na field named `foo.bar`, it returns errors for fields that are a prefix of\n`foo.bar`, namely `foo` and `foo.bar`. Similarly, if queried for errors for a\nfield named `foo.bar.baz`, errors for field `foo`, `foo.bar`, and `foo.bar.baz`\nwill be returned.\n\n`Context` serializes as a map, so it can be rendered in templates that require\n`Serialize` types. See [`Context`] for details about its serialization format.\nThe [forms example], too, makes use of form contexts, as well as every other\nforms feature.\n\n[`Contextual`]: @api/master/rocket/form/struct.Contextual.html\n[`Context`]: @api/master/rocket/form/struct.Context.html\n[forms example]: @git/master/examples/forms\n\n## Query Strings\n\nQuery strings are URL-encoded forms that appear in the URL of a request. Query\nparameters are declared like path parameters but otherwise handled like regular\nURL-encoded form fields. The table below summarizes the analogy:\n\n| Path Syntax | Query Syntax | Path Type Bound  | Query Type Bound |\n|-------------|--------------|------------------|------------------|\n| `<param>`   | `<param>`    | [`FromParam`]    | [`FromForm`]     |\n| `<param..>` | `<param..>`  | [`FromSegments`] | [`FromForm`]     |\n| `static`    | `static`     | N/A              | N/A              |\n\nBecause dynamic parameters are form types, they can be single values,\ncollections, nested collections, or anything in between, just like any other\nform field.\n\n### Static Parameters\n\nA request matches a route _iff_ its query string contains all of the static\nparameters in the route's query string. A route with a static parameter `param`\n(any UTF-8 text string) in a query will only match requests with that exact path\nsegment in its query string.\n\n! note: This is truly an _iff_!\n\n  Only the static parameters in query route string affect routing. Dynamic\n  parameters are allowed to be missing by default.\n\n\nFor example, the route below will match requests with path `/` and _at least_\nthe query segments `hello` and `cat=♥`:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/?hello&cat=♥\")]\nfn cats() -> &'static str {\n    \"Hello, kittens!\"\n}\n\n// The following GET requests match `cats`. `%E2%99%A5` is encoded `♥`.\n# let status = rocket_docs_tests::client(routes![cats]).get(\n\"/?cat=%E2%99%A5&hello\"\n# ).dispatch().status();\n# assert_eq!(status, rocket::http::Status::Ok);\n# let status = rocket_docs_tests::client(routes![cats]).get(\n\"/?hello&cat=%E2%99%A5\"\n# ).dispatch().status();\n# assert_eq!(status, rocket::http::Status::Ok);\n# let status = rocket_docs_tests::client(routes![cats]).get(\n\"/?dogs=amazing&hello&there&cat=%E2%99%A5\"\n# ).dispatch().status();\n# assert_eq!(status, rocket::http::Status::Ok);\n```\n\n### Dynamic Parameters\n\nA single dynamic parameter of `<param>` acts identically to a form field\ndeclared as `param`. In particular, Rocket will expect the query form to contain\na field with key `param` and push the shifted field to the `param` type. As with\nforms, default values are used when parsing fails. The example below illustrates\nthis with a single value `name`, a collection `color`, a nested form `person`,\nand an `other` value that will default to `None`:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[derive(Debug, PartialEq, FromFormField)]\nenum Color {\n    Red,\n    Blue,\n    Green\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct Pet<'r> {\n  name: &'r str,\n  age: usize,\n}\n\n#[derive(Debug, PartialEq, FromForm)]\nstruct Person<'r> {\n  pet: Pet<'r>,\n}\n\n#[get(\"/?<name>&<color>&<person>&<other>\")]\nfn hello(name: &str, color: Vec<Color>, person: Person<'_>, other: Option<usize>) {\n    assert_eq!(name, \"George\");\n    assert_eq!(color, [Color::Red, Color::Green, Color::Green, Color::Blue]);\n    assert_eq!(other, None);\n    assert_eq!(person, Person {\n      pet: Pet { name: \"Fi Fo Alex\", age: 1 }\n    });\n}\n\n// A request with these query segments matches as above.\n# let status = rocket_docs_tests::client(routes![hello]).get(\"/?\\\nname=George&\\\ncolor=red&\\\ncolor=green&\\\nperson.pet.name=Fi+Fo+Alex&\\\ncolor=green&\\\nperson.pet.age=1&\\\ncolor=blue&\\\nextra=yes\\\n# \").dispatch().status();\n# assert_eq!(status, rocket::http::Status::Ok);\n```\n\nNote that, like forms, parsing is field-ordering insensitive and lenient by\ndefault.\n\n### Trailing Parameter\n\nA trailing dynamic parameter of `<param..>` collects all of the query segments\nthat don't otherwise match a declared static or dynamic parameter. In other\nwords, the otherwise unmatched segments are pushed, unshifted, to the\n`<param..>` type:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::form::Form;\n\n#[derive(FromForm)]\nstruct User<'r> {\n    name: &'r str,\n    active: bool,\n}\n\n#[get(\"/?hello&<id>&<user..>\")]\nfn user(id: usize, user: User<'_>) {\n    assert_eq!(id, 1337);\n    assert_eq!(user.name, \"Bob Smith\");\n    assert_eq!(user.active, true);\n}\n\n// A request with these query segments matches as above.\n# let status = rocket_docs_tests::client(routes![user]).get(\"/?\\\nhello&\\\nname=Bob+Smith&\\\nid=1337&\\\nactive=yes\\\n# \").dispatch().status();\n# assert_eq!(status, rocket::http::Status::Ok);\n```\n\n## Error Catchers\n\nApplication processing is fallible. Errors arise from the following sources:\n\n  * A failing guard.\n  * A failing responder.\n  * A routing failure.\n\nIf any of these occur, Rocket returns an error to the client. To generate the\nerror, Rocket invokes the _catcher_ corresponding to the error's status code and\nscope. Catchers are similar to routes except in that:\n\n  1. Catchers are only invoked on error conditions.\n  2. Catchers are declared with the `catch` attribute.\n  3. Catchers are _registered_ with [`register()`] instead of [`mount()`].\n  4. Any modifications to cookies are cleared before a catcher is invoked.\n  5. Error catchers cannot invoke guards.\n  6. Error catchers should not fail to produce a response.\n  7. Catchers are scoped to a path prefix.\n\nTo declare a catcher for a given status code, use the [`catch`] attribute, which\ntakes a single integer corresponding to the HTTP status code to catch. For\ninstance, to declare a catcher for `404 Not Found` errors, you'd write:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::Request;\n\n#[catch(404)]\nfn not_found(req: &Request) { /* .. */ }\n```\n\nCatchers may take zero, one, or two arguments. If the catcher takes one\nargument, it must be of type [`&Request`]. It it takes two, they must be of type\n[`Status`] and [`&Request`], in that order. As with routes, the return type must\nimplement `Responder`. A concrete implementation may look like:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# use rocket::Request;\n\n#[catch(404)]\nfn not_found(req: &Request) -> String {\n    format!(\"Sorry, '{}' is not a valid path.\", req.uri())\n}\n```\n\nAlso as with routes, Rocket needs to know about a catcher before it is used to\nhandle errors. The process, known as \"registering\" a catcher, is similar to\nmounting a route: call the [`register()`] method with a list of catchers via the\n[`catchers!`] macro. The invocation to add the **404** catcher declared above\nlooks like:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# use rocket::Request;\n# #[catch(404)] fn not_found(req: &Request) { /* .. */ }\n\nfn main() {\n    rocket::build().register(\"/\", catchers![not_found]);\n}\n```\n\n### Scoping\n\nThe first argument to `register()` is a path to scope the catcher under called\nthe catcher's _base_. A catcher's base determines which requests it will handle\nerrors for. Specifically, a catcher's base must be a prefix of the erroring\nrequest for it to be invoked. When multiple catchers can be invoked, the catcher\nwith the longest base takes precedence.\n\nAs an example, consider the following application:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[catch(404)]\nfn general_not_found() -> &'static str {\n    \"General 404\"\n}\n\n#[catch(404)]\nfn foo_not_found() -> &'static str {\n    \"Foo 404\"\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .register(\"/\", catchers![general_not_found])\n        .register(\"/foo\", catchers![foo_not_found])\n}\n\n# let client = rocket::local::blocking::Client::debug(rocket()).unwrap();\n#\n# let response = client.get(\"/\").dispatch();\n# assert_eq!(response.into_string().unwrap(), \"General 404\");\n#\n# let response = client.get(\"/bar\").dispatch();\n# assert_eq!(response.into_string().unwrap(), \"General 404\");\n#\n# let response = client.get(\"/bar/baz\").dispatch();\n# assert_eq!(response.into_string().unwrap(), \"General 404\");\n#\n# let response = client.get(\"/foo\").dispatch();\n# assert_eq!(response.into_string().unwrap(), \"Foo 404\");\n#\n# let response = client.get(\"/foo/bar\").dispatch();\n# assert_eq!(response.into_string().unwrap(), \"Foo 404\");\n```\n\nSince there are no mounted routes, all requests will `404`. Any request whose\npath begins with `/foo` (i.e, `GET /foo`, `GET /foo/bar`, etc) will be handled\nby the `foo_not_found` catcher while all other requests will be handled by the\n`general_not_found` catcher.\n\n### Default Catchers\n\nA _default_ catcher is a catcher that handles _all_ status codes. They are\ninvoked as a fallback if no status-specific catcher is registered for a given\nerror. Declaring a default catcher is done with `#[catch(default)]` and must\nsimilarly be registered with [`register()`]:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::Request;\nuse rocket::http::Status;\n\n#[catch(default)]\nfn default_catcher(status: Status, request: &Request) { /* .. */ }\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().register(\"/\", catchers![default_catcher])\n}\n```\n\nCatchers with longer bases are preferred, even when there is a status-specific\ncatcher. In other words, a default catcher with a longer matching base than a\nstatus-specific catcher takes precedence.\n\n### Built-In Catcher\n\nRocket provides a built-in default catcher. It produces HTML or JSON, depending\non the value of the `Accept` header. As such, custom catchers only need to be\nregistered for custom error handling.\n\nThe [error handling example](@git/master/examples/error-handling) illustrates catcher use in\nfull, while the [`Catcher`] API documentation provides further details.\n\n[`catch`]: @api/master/rocket/attr.catch.html\n[`register()`]: @api/master/rocket/struct.Rocket.html#method.register\n[`mount()`]: @api/master/rocket/struct.Rocket.html#method.mount\n[`catchers!`]: @api/master/rocket/macro.catchers.html\n[`&Request`]: @api/master/rocket/struct.Request.html\n[`Status`]: @api/master/rocket/http/struct.Status.html\n[`Catcher`]: @api/master/rocket/catcher/struct.Catcher.html\n"
  },
  {
    "path": "docs/guide/06-responses.md",
    "content": "+++\nsummary = \"generating responses and using typed URIs\"\n+++\n\n# Responses\n\nYou may have noticed that the return type of a handler appears to be arbitrary,\nand that's because it is! A value of any type that implements the [`Responder`]\ntrait can be returned, including your own. In this section, we describe the\n`Responder` trait as well as several useful `Responder`s provided by Rocket.\nWe'll also briefly discuss how to implement your own `Responder`.\n\n[`Responder`]: @api/master/rocket/response/trait.Responder.html\n\n## Responder\n\nTypes that implement [`Responder`] know how to generate a [`Response`] from\ntheir values. A `Response` includes an HTTP status, headers, and body. The body\nmay either be _fixed-sized_ or _streaming_. The given `Responder` implementation\ndecides which to use. For instance, `String` uses a fixed-sized body, while\n`File` uses a streamed response. Responders may dynamically adjust their\nresponses according to the incoming `Request` they are responding to.\n\n[`Response`]: @api/master/rocket/response/struct.Response.html\n\n### Wrapping\n\nResponders compose by _wrapping_ (encapsulating) other responders. Naturally, we\ncall these _wrapping_ responders. A wrapping responder takes a response from an\nexisting responder `R`, modifies it, and then returns it. They typically have\nthe following shape:\n\n```rust\nstruct WrappingResponder<R>(R);\n```\n\nExamples include `Responder`s in the [`status` module], which override the\nstatus code of the wrapped `Responder`'s response, and `Responder`s in the\n[`content` module], which override the Content-Type.\n\nAs a concrete example, the [`Accepted`] wrapping responder sets the status to\n`202 - Accepted`. It can be used as follows:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::response::status;\n\n#[post(\"/<id>\")]\nfn new(id: usize) -> status::Accepted<String> {\n    // Modifies the response generated by `String` to have a status of `202`.\n    status::Accepted(format!(\"id: '{}'\", id))\n}\n```\n\nBecause wrapping responders are themselves responders, they too can be wrapped.\nThis is what allows responders to compose, enabling powerful combinations of\nsimple primitives to form more powerful abstractions. For example, combining the\n[`content::RawJson`] and [`status::Custom`] responders allows creating a\nresponse with a Content-Type of JSON and an arbitrary status code like `418 I'm\na teapot` from an `&'static str`:\n\n```rust\n# #[macro_use] extern crate rocket;\nuse rocket::http::Status;\nuse rocket::response::{content, status};\n\n#[get(\"/\")]\nfn json() -> status::Custom<content::RawJson<&'static str>> {\n    status::Custom(Status::ImATeapot, content::RawJson(\"{ \\\"hi\\\": \\\"world\\\" }\"))\n}\n```\n\n! warning: This is _not_ the same as [`serde::json::Json`]!\n\n! note: There are simpler alternatives for setting a status and content-types.\n\n  The built-in `(Status, R)` and `(ContentType, R)` wrapping responders\n  also override the `Status` and `Content-Type` of responses, respectively, and\n  may be simpler alternatives:\n\n  ```rust\n  # #[macro_use] extern crate rocket;\n  use rocket::http::{Status, ContentType};\n\n  #[get(\"/\")]\n  fn json() -> (Status, (ContentType, &'static str)) {\n      (Status::ImATeapot, (ContentType::JSON, \"{ \\\"hi\\\": \\\"world\\\" }\"))\n  }\n  ```\n\nComposition through wrapping is useful when you want to change one or two\nproperties of an existing response. For more complex use-cases, instead consider\nderiving a [custom responder]:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[derive(Responder)]\n#[response(status = 418, content_type = \"json\")]\nstruct RawTeapotJson(&'static str);\n\n#[get(\"/\")]\nfn json() -> RawTeapotJson {\n    RawTeapotJson(\"{ \\\"hi\\\": \\\"world\\\" }\")\n}\n```\n\n[`Accepted`]: @api/master/rocket/response/status/struct.Accepted.html\n[`content::RawJson`]: @api/master/rocket/response/content/struct.RawJson.html\n[`status::Custom`]: @api/master/rocket/response/status/struct.Custom.html\n[`serde::json::Json`]: @api/master/rocket/serde/json/struct.Json.html\n[custom responder]: #custom-responders\n[`status` module]: @api/master/rocket/response/status/\n[`content` module]: @api/master/rocket/response/content/\n\n### Errors\n\nResponders may fail instead of generating a response by returning an `Err` with\na status code. When this happens, Rocket forwards the request to the [error\ncatcher](../requests/#error-catchers) for that status code.\n\nIf an error catcher has been registered for the given status code, Rocket will\ninvoke it. The catcher creates and returns a response to the client. If no error\ncatcher has been registered and the error status code is one of the standard\nHTTP status code, a default error catcher will be used. Default error catchers\nreturn an HTML page with the status code and description. If there is no catcher\nfor a custom status code, Rocket uses the **500** error catcher to return a\nresponse.\n\n### Status\n\nWhile not encouraged, you can also forward a request to a catcher manually by\nreturning a [`Status`] directly. For instance, to forward to the catcher for\n**406: Not Acceptable**, you would write:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::http::Status;\n\n#[get(\"/\")]\nfn just_fail() -> Status {\n    Status::NotAcceptable\n}\n```\n\nThe response generated by `Status` depends on the status code itself. As\nindicated above, for error status codes (in range [400, 599]), `Status` forwards\nto the corresponding error catcher. The table below summarizes responses\ngenerated by `Status` for these and other codes:\n\n| Status Code Range | Response                              |\n|-------------------|---------------------------------------|\n| [400, 599]        | Forwards to catcher for given status. |\n| 100, [200, 205]   | Empty with given status.              |\n| All others.       | Invalid. Errors to `500` catcher.     |\n\n[`Status`]: @api/master/rocket/http/struct.Status.html\n\n## Custom Responders\n\nThe [`Responder`] trait documentation details how to implement your own custom\nresponders by explicitly implementing the trait. For most use cases, however,\nRocket makes it possible to automatically derive an implementation of\n`Responder`. In particular, if your custom responder wraps an existing\nresponder, headers, or sets a custom status or content-type, `Responder` can be\nautomatically derived:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::http::{Header, ContentType};\n# type OtherResponder = ();\n# type MyType = u8;\n\n#[derive(Responder)]\n#[response(status = 500, content_type = \"json\")]\nstruct MyResponder {\n    inner: OtherResponder,\n    // Override the Content-Type declared above.\n    header: ContentType,\n    more: Header<'static>,\n    #[response(ignore)]\n    unrelated: MyType,\n}\n```\n\nFor the example above, Rocket generates a `Responder` implementation that:\n\n  * Set the response's status to `500: Internal Server Error`.\n  * Sets the Content-Type to `application/json`.\n  * Adds the headers `self.header` and `self.more` to the response.\n  * Completes the response using `self.inner`.\n\nNote that the _first_ field is used as the inner responder while all remaining\nfields (unless ignored with `#[response(ignore)]`) are added as headers to the\nresponse. The optional `#[response]` attribute can be used to customize the\nstatus and content-type of the response. Because `ContentType` is itself a\nheader, you can also dynamically set a content-type by simply including a field\nof type [`ContentType`]. To set an HTTP status dynamically, leverage the\n`(Status, R: Responder)` responder:\n\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::http::{Header, Status};\n# type OtherResponder = ();\n\n#[derive(Responder)]\n#[response(content_type = \"json\")]\nstruct MyResponder {\n    inner: (Status, OtherResponder),\n    some_header: Header<'static>,\n}\n```\n\nYou can also use derive `Responder` for `enum`s, allowing dynamic selection of a\nresponder:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::http::{ContentType, Header, Status};\nuse rocket::fs::NamedFile;\n\n#[derive(Responder)]\nenum Error {\n    #[response(status = 500, content_type = \"json\")]\n    A(String),\n    #[response(status = 404)]\n    B(NamedFile, ContentType),\n    C {\n        inner: (Status, Option<String>),\n        header: ContentType,\n    }\n}\n```\n\nFor more on using the `Responder` derive, including details on how to use the\nderive to define generic responders, see the [`Responder` derive] documentation.\n\n[`Responder` derive]: @api/master/rocket/derive.Responder.html\n[`ContentType`]: @api/master/rocket/http/struct.ContentType.html\n\n## Implementations\n\nRocket implements `Responder` for many types in Rust's standard library\nincluding `String`, `&str`, `File`, `Option`, and `Result`. The [`Responder`]\ndocumentation describes these in detail, but we briefly cover a few here.\n\n### Strings\n\nThe `Responder` implementations for `&str` and `String` are straight-forward:\nthe string is used as a sized body, and the Content-Type of the response is set\nto `text/plain`. To get a taste for what such a `Responder` implementation looks\nlike, here's the implementation for `String`:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse std::io::Cursor;\n\nuse rocket::request::Request;\nuse rocket::response::{self, Response, Responder};\nuse rocket::http::ContentType;\n\n# struct String(std::string::String);\n#[rocket::async_trait]\nimpl<'r> Responder<'r, 'static> for String {\n    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {\n        Response::build()\n            .header(ContentType::Plain)\n            # /*\n            .sized_body(self.len(), Cursor::new(self))\n            # */\n            # .sized_body(self.0.len(), Cursor::new(self.0))\n            .ok()\n    }\n}\n```\n\nBecause of these implementations, you can directly return an `&str` or `String`\ntype from a handler:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n#[get(\"/string\")]\nfn handler() -> &'static str {\n    \"Hello there! I'm a string!\"\n}\n```\n\n### `Option`\n\n`Option` is a _wrapping_ responder: an `Option<T>` can only be returned when `T`\nimplements `Responder`. If the `Option` is `Some`, the wrapped responder is used\nto respond to the client. Otherwise, an error of **404 - Not Found** is returned\nto the client.\n\nThis implementation makes `Option` a convenient type to return when it is not\nknown until process-time whether content exists. For example, because of\n`Option`, we can implement a file server that returns a `200` when a file is\nfound and a `404` when a file is not found in just 4, idiomatic lines:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# use std::path::{Path, PathBuf};\nuse rocket::fs::NamedFile;\n\n#[get(\"/<file..>\")]\nasync fn files(file: PathBuf) -> Option<NamedFile> {\n    NamedFile::open(Path::new(\"static/\").join(file)).await.ok()\n}\n```\n\n### `Result`\n\n`Result` is another _wrapping_ responder: a `Result<T, E>` can only be returned\nwhen `T` implements `Responder` and `E` implements `Responder`.\n\nThe wrapped `Responder` in `Ok` or `Err`, whichever it might be, is used to\nrespond to the client. This means that the responder can be chosen dynamically\nat run-time, and two different kinds of responses can be used depending on the\ncircumstances. Revisiting our file server, for instance, we might wish to\nprovide more feedback to the user when a file isn't found. We might do this as\nfollows:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# use std::path::{Path, PathBuf};\nuse rocket::fs::NamedFile;\nuse rocket::response::status::NotFound;\n\n#[get(\"/<file..>\")]\nasync fn files(file: PathBuf) -> Result<NamedFile, NotFound<String>> {\n    let path = Path::new(\"static/\").join(file);\n    NamedFile::open(&path).await.map_err(|e| NotFound(e.to_string()))\n}\n```\n\n## Rocket Responders\n\nSome of Rocket's best features are implemented through responders. Among these\nare:\n\n  * [`NamedFile`] - Streams a file to the client; automatically sets the\n    Content-Type based on the file's extension.\n  * [`Redirect`] - Redirects the client to a different URI.\n  * [`content`] - Contains types that override the Content-Type of a response.\n  * [`status`] - Contains types that override the status code of a response.\n  * [`Flash`] - Sets a \"flash\" cookie that is removed when accessed.\n  * [`Json`] - Automatically serializes values into JSON.\n  * [`MsgPack`] - Automatically serializes values into MessagePack.\n  * [`Template`] - Renders a dynamic template using Handlebars, Tera or MiniJinja.\n\n[`status`]: @api/master/rocket/response/status/\n[`content`]: @api/master/rocket/response/content/\n[`response`]: @api/master/rocket/response/\n[`NamedFile`]: @api/master/rocket/fs/struct.NamedFile.html\n[`Redirect`]: @api/master/rocket/response/struct.Redirect.html\n[`Flash`]: @api/master/rocket/response/struct.Flash.html\n[`MsgPack`]: @api/master/rocket/serde/msgpack/struct.MsgPack.html\n[`Template`]: @api/master/rocket_dyn_templates/struct.Template.html\n\n### Async Streams\n\nThe [`stream`] responders allow serving potentially infinite [async `Stream`]s.\nA stream can be created from any async `Stream` or `AsyncRead` type, or via\ngenerator syntax using the [`stream!`] macro and its typed equivalents. Streams\nare the building blocks for unidirectional real-time communication. For\ninstance, the [`chat` example] uses an [`EventStream`] to implement a real-time,\nmulti-room chat application using Server-Sent Events (SSE).\n\nThe simplest version creates a [`ReaderStream`] from a single `AsyncRead` type.\nFor example, to stream from a TCP connection, we might write:\n\n```rust\n# use rocket::*;\nuse std::io;\nuse std::net::SocketAddr;\n\nuse rocket::tokio::net::TcpStream;\nuse rocket::response::stream::ReaderStream;\n\n#[get(\"/stream\")]\nasync fn stream() -> io::Result<ReaderStream![TcpStream]> {\n    let addr = SocketAddr::from(([127, 0, 0, 1], 9999));\n    let stream = TcpStream::connect(addr).await?;\n    Ok(ReaderStream::one(stream))\n}\n```\n\nStreams can also be created using generator syntax. The following example\nreturns an infinite [`TextStream`] that produces one `\"hello\"` every second:\n\n```rust\n# use rocket::get;\nuse rocket::tokio::time::{Duration, interval};\nuse rocket::response::stream::TextStream;\n\n/// Produce an infinite series of `\"hello\"`s, one per second.\n#[get(\"/infinite-hellos\")]\nfn hello() -> TextStream![&'static str] {\n    TextStream! {\n        let mut interval = interval(Duration::from_secs(1));\n        loop {\n            yield \"hello\";\n            interval.tick().await;\n        }\n    }\n}\n```\n\nSee the [`stream`] docs for full details on creating streams including notes on\nhow to detect and handle graceful shutdown requests.\n\n[`stream`]: @api/master/rocket/response/stream/index.html\n[`stream!`]: @api/master/rocket/response/stream/macro.stream.html\n[async `Stream`]: https://docs.rs/futures/0.3/futures/stream/trait.Stream.html\n[`ReaderStream`]: @api/master/rocket/response/stream/struct.ReaderStream.html\n[`TextStream`]: @api/master/rocket/response/stream/struct.TextStream.html\n[`EventStream`]: @api/master/rocket/response/stream/struct.EventStream.html\n[`chat` example]: @git/master/examples/chat\n\n### WebSockets\n\nEnabled by Rocket's support for [HTTP connection upgrades], the official\n[`rocket_ws`] crate implements first-class support for WebSockets. Working with\n`rocket_ws` to implement an echo server looks like this:\n\n```rust\n# use rocket::get;\nuse rocket_ws::{WebSocket, Stream};\n\n#[get(\"/echo\")]\nfn echo_compose(ws: WebSocket) -> Stream!['static] {\n    ws.stream(|io| io)\n}\n```\n\nAs with `async` streams, `rocket_ws` also supports using generator syntax for\nWebSocket messages:\n\n```rust\n# use rocket::get;\nuse rocket_ws::{WebSocket, Stream};\n\n#[get(\"/echo\")]\nfn echo_stream(ws: WebSocket) -> Stream!['static] {\n    Stream! { ws =>\n        for await message in ws {\n            yield message?;\n        }\n    }\n}\n```\n\nFor complete usage details, see the [`rocket_ws`] documentation.\n\n[HTTP connection upgrades]: @api/master/rocket/response/struct.Response.html#upgrading\n[`rocket_ws`]: @api/master/rocket_ws/\n\n### JSON\n\nThe [`Json`] responder in allows you to easily respond with well-formed JSON\ndata: simply return a value of type `Json<T>` where `T` is the type of a\nstructure to serialize into JSON. The type `T` must implement the [`Serialize`]\ntrait from [`serde`], which can be automatically derived.\n\nAs an example, to respond with the JSON value of a `Task` structure, we might\nwrite:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::serde::{Serialize, json::Json};\n\n#[derive(Serialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Task { /* .. */ }\n\n#[get(\"/todo\")]\nfn todo() -> Json<Task> {\n    Json(Task { /* .. */ })\n}\n```\n\n! note: You must enable Rocket's `json` crate feature to use the [`Json`] type.\n\nThe `Json` type serializes the structure into JSON, sets the Content-Type to\nJSON, and emits the serialized data in a fixed-sized body. If serialization\nfails, a **500 - Internal Server Error** is returned.\n\nThe [serialization example] provides further illustration.\n\n[`Json`]: @api/master/rocket/serde/json/struct.Json.html\n[`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html\n[`serde`]: https://serde.rs\n[serialization example]: @git/master/examples/serialization\n\n## Templates\n\nRocket has first-class templating support that works largely through a\n[`Template`] responder in the `rocket_dyn_templates` contrib library. To render\na template named \"index\", for instance, you might return a value of type\n`Template` as follows:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket_dyn_templates::Template;\n\n#[get(\"/\")]\nfn index() -> Template {\n    # /*\n    let context = /* object-like value */;\n    # */ let context = ();\n    Template::render(\"index\", &context)\n}\n```\n\nTemplates are rendered with the `render` method. The method takes in the name of\na template and a context to render the template with. The context can be any\ntype that implements `Serialize` and serializes into an `Object` value, such as\nstructs, `HashMaps`, and others.\n\nYou can also use [`context!`] to create ad-hoc templating contexts without\ndefining a new type:\n\n```rust\n# #[macro_use] extern crate rocket;\n# #[macro_use] extern crate rocket_dyn_templates;\n# fn main() {}\n\nuse rocket_dyn_templates::Template;\n\n#[get(\"/\")]\nfn index() -> Template {\n    Template::render(\"index\", context! {\n        foo: 123,\n    })\n}\n```\n\nTo render a template, it must first be registered. The `Template` fairing\nautomatically registers all discoverable templates when attached. The\n[Fairings](../fairings/) sections of the guide provides more information on\nfairings. To attach the template fairing, simply call\n`.attach(Template::fairing())` on an instance of `Rocket` as follows:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket_dyn_templates::Template;\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![/* .. */])\n        .attach(Template::fairing())\n}\n```\n\nRocket discovers templates in the [configurable] `template_dir` directory.\nTemplating support in Rocket is engine agnostic. The engine used to render a\ntemplate depends on the template file's extension. For example, if a file ends\nwith `.hbs`, Handlebars is used, while if a file ends with `.tera`, Tera is\nused.\n\n! note: The name of the template _does not_ include its extension.\n\n  For a template file named `index.html.tera`, call `render(\"index\")` and use\n  the name `\"index\"` in templates, i.e, `extends \"index\"` or `extends \"base\"`\n  for `base.html.tera`.\n\n[`context!`]: @api/master/rocket_dyn_templates/macro.context.html\n\n### Live Reloading\n\nWhen your application is compiled in `debug` mode (without the `--release` flag\npassed to `cargo`), templates are automatically reloaded when they are modified\non supported platforms. This means that you don't need to rebuild your\napplication to observe template changes: simply refresh! In release builds,\nreloading is disabled.\n\nThe [`Template`] API documentation contains more information about templates,\nincluding how to customize a template engine to add custom helpers and filters.\nThe [templating example](@git/master/examples/templating) uses Tera, Handlebars and MiniJinja\ntemplating to implement the same application.\n\n[configurable]: ../configuration/\n\n## Typed URIs\n\nRocket's [`uri!`] macro allows you to build URIs to routes in your application\nin a robust, type-safe, and URI-safe manner. Type or route parameter mismatches\nare caught at compile-time, and changes to route URIs are automatically\nreflected in the generated URIs.\n\nThe `uri!` macro returns an [`Origin`] structure with the URI of the supplied\nroute interpolated with the given values. Each value passed into `uri!` is\nrendered in its appropriate place in the URI using the [`UriDisplay`]\nimplementation for the value's type. The `UriDisplay` implementation ensures\nthat the rendered value is URI-safe.\n\nNote that `Origin` implements `Into<Uri>` (and by extension, `TryInto<Uri>`), so\nit can be converted into a [`Uri`] using `.into()` as needed and passed into\nmethods such as [`Redirect::to()`].\n\nFor example, given the following route:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n#[get(\"/<id>/<name>?<age>\")]\nfn person(id: Option<usize>, name: &str, age: Option<u8>) { /* .. */ }\n```\n\nURIs to `person` can be created as follows:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# #[get(\"/<id>/<name>?<age>\")]\n# fn person(id: Option<usize>, name: &str, age: Option<u8>) { /* .. */ }\n\n// with unnamed parameters, in route path declaration order\nlet mike = uri!(person(101, \"Mike Smith\", Some(28)));\nassert_eq!(mike.to_string(), \"/101/Mike%20Smith?age=28\");\n\n// with named parameters, order irrelevant\nlet mike = uri!(person(name = \"Mike\", id = 101, age = Some(28)));\nassert_eq!(mike.to_string(), \"/101/Mike?age=28\");\nlet mike = uri!(person(id = 101, age = Some(28), name = \"Mike\"));\nassert_eq!(mike.to_string(), \"/101/Mike?age=28\");\n\n// with a specific mount-point\nlet mike = uri!(\"/api\", person(id = 101, name = \"Mike\", age = Some(28)));\nassert_eq!(mike.to_string(), \"/api/101/Mike?age=28\");\n\n// with optional (defaultable) query parameters ignored\nlet mike = uri!(person(101, \"Mike\", _));\nassert_eq!(mike.to_string(), \"/101/Mike\");\nlet mike = uri!(person(id = 101, name = \"Mike\", age = _));\nassert_eq!(mike.to_string(), \"/101/Mike\");\n```\n\nRocket informs you of any mismatched parameters at compile-time:\n\n```rust,ignore\nerror: `person` route uri expects 3 parameters but 1 was supplied\n --> examples/uri/main.rs:7:26\n  |\n7 |     let x = uri!(person(\"Mike Smith\"));\n  |                         ^^^^^^^^^^^^\n  |\n  = note: expected parameters: id: Option <usize>, name: &str, age: Option <u8>\n```\n\nRocket also informs you of any type errors at compile-time:\n\n```rust,ignore\n --> examples/uri/src/main.rs:7:31\n  |\n7 |     let x = uri!(person(id = \"10\", name = \"Mike Smith\", age = Some(10)));\n  |                              ^^^^ `FromUriParam<Path, &str>` is not implemented for `usize`\n```\n\nWe recommend that you use `uri!` exclusively when constructing URIs to your\nroutes.\n\n### Ignorables\n\nAs illustrated in the previous above, query parameters can be ignored using `_`\nin place of an expression in a `uri!` invocation. The corresponding type in the\nroute URI must implement [`Ignorable`]. Ignored parameters are not interpolated\ninto the resulting `Origin`. Path parameters are not ignorable.\n\n### Deriving `UriDisplay`\n\nThe `UriDisplay` trait can be derived for custom types. For types that appear in\nthe path part of a URI, derive using [`UriDisplayPath`]; for types that appear\nin the query part of a URI, derive using [`UriDisplayQuery`].\n\nAs an example, consider the following form structure and route:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\nuse rocket::form::Form;\n\n#[derive(FromForm, UriDisplayQuery)]\nstruct UserDetails<'r> {\n    age: Option<usize>,\n    nickname: &'r str,\n}\n\n#[post(\"/user/<id>?<details..>\")]\nfn add_user(id: usize, details: UserDetails) { /* .. */ }\n```\n\nBy deriving using `UriDisplayQuery`, an implementation of `UriDisplay<Query>` is\nautomatically generated, allowing for URIs to `add_user` to be generated using\n`uri!`:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# use rocket::form::Form;\n\n# #[derive(FromForm, UriDisplayQuery)]\n# struct UserDetails<'r> {\n#     age: Option<usize>,\n#     nickname: &'r str,\n# }\n\n# #[post(\"/user/<id>?<details..>\")]\n# fn add_user(id: usize, details: UserDetails) { /* .. */ }\n\nlet link = uri!(add_user(120, UserDetails { age: Some(20), nickname: \"Bob\".into() }));\nassert_eq!(link.to_string(), \"/user/120?age=20&nickname=Bob\");\n```\n\n### Typed URI Parts\n\nThe [`Part`] trait categorizes types that mark a part of the URI as either a\n[`Path`] or a [`Query`]. Said another way, types that implement `Part` are\nmarker types that represent a part of a URI at the type-level. Traits such as\n[`UriDisplay`] and [`FromUriParam`] bound a generic parameter by `Part`: `P:\nPart`. This creates two instances of each trait: `UriDisplay<Query>` and\n`UriDisplay<Path>`, and `FromUriParam<Query>` and `FromUriParam<Path>`.\n\nAs the names might imply, the `Path` version of the traits is used when\ndisplaying parameters in the path part of the URI while the `Query` version is\nused when displaying parameters in the query part of the URI. These distinct\nversions of the traits exist exactly to differentiate, at the type-level, where\nin the URI a value is to be written to, allowing for type safety in the face of\ndifferences between the two locations. For example, while it is valid to use a\nvalue of `None` in the query part, omitting the parameter entirely, doing so is\n_not_ valid in the path part. By differentiating in the type system, both of\nthese conditions can be enforced appropriately through distinct implementations\nof `FromUriParam<Path>` and `FromUriParam<Query>`.\n\nThis division has an effect on how the `uri!` macro can be invoked. In query\nparts, for a route type of `Option<T>`, you _must_ supply a type of `Option`,\n`Result`, or an ignored `_` to the `uri!` invocation. By contrast, you _cannot_\nsupply such a type in the path part. This ensures that a valid URI is _always_\ngenerated.\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/<id>/<name>?<age>\")]\nfn person(id: Option<usize>, name: &str, age: Option<u8>) { /* .. */ }\n\n// Note that `id` is `Option<usize>` in the route, but `id` in `uri!` _cannot_\n// be an `Option`. `age`, on the other hand, _must_ be an `Option` (or `Result`\n// or `_`) as its in the query part and is allowed to be ignored.\nlet mike = uri!(person(id = 101, name = \"Mike\", age = Some(28)));\nassert_eq!(mike.to_string(), \"/101/Mike?age=28\");\n```\n\n### Conversions\n\n[`FromUriParam`] is used to perform a conversion for each value passed to `uri!`\nbefore it is displayed with `UriDisplay`. If a `T: FromUriParam<P, S>`\nimplementation exists for a type `T` for part URI part `P`, then a value of type\n`S` can be used in `uri!` macro for a route URI parameter declared with a type\nof `T` in part `P`. For example, the following implementation, provided by\nRocket, allows an `&str` to be used in a `uri!` invocation for route URI\nparameters declared as `String`:\n\n```rust\n# use rocket::http::uri::fmt::{FromUriParam, Part};\n# struct S;\n# type String = S;\nimpl<'a, P: Part> FromUriParam<P, &'a str> for String {\n    type Target = &'a str;\n#   fn from_uri_param(s: &'a str) -> Self::Target { \"hi\" }\n}\n```\n\nOther conversions to be aware of are:\n\n  * `&T` to `T`\n  * `&mut T` to `T`\n  * `String` to `&str`\n  * `&str` to `&Path`\n  * `&str` to `PathBuf`\n  * `T` to `Form<T>`\n\nThe following conversions only apply to path parts:\n\n  * `T` to `Option<T>`\n  * `T` to `Result<T, E>`\n\nThe following conversions are implemented only in query parts:\n\n  * `Option<T>` to `Result<T, E>` (for any `E`)\n  * `Result<T, E>` to `Option<T>` (for any `E`)\n\nConversions are transitive. That is, a conversion from `A -> B` and a conversion\n`B -> C` implies a conversion from `A -> C`. For instance, a value of type\n`&str` can be supplied when a value of type `Option<PathBuf>` is expected:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse std::path::PathBuf;\n\n#[get(\"/person/<id>/<details..>\")]\nfn person(id: usize, details: Option<PathBuf>) { /* .. */ }\n\nuri!(person(id = 100, details = \"a/b/c\"));\n```\n\nSee the [`FromUriParam`] documentation for further details.\n\n[`Origin`]: @api/master/rocket/http/uri/struct.Origin.html\n[`Part`]: @api/master/rocket/http/uri/fmt/trait.Part.html\n[`Uri`]: @api/master/rocket/http/uri/enum.Uri.html\n[`Redirect::to()`]: @api/master/rocket/response/struct.Redirect.html#method.to\n[`uri!`]: @api/master/rocket/macro.uri.html\n[`UriDisplay`]: @api/master/rocket/http/uri/fmt/trait.UriDisplay.html\n[`FromUriParam`]: @api/master/rocket/http/uri/fmt/trait.FromUriParam.html\n[`Path`]: @api/master/rocket/http/uri/fmt/enum.Path.html\n[`Query`]: @api/master/rocket/http/uri/fmt/enum.Query.html\n[`Ignorable`]: @api/master/rocket/http/uri/fmt/trait.Ignorable.html\n[`UriDisplayPath`]: @api/master/rocket/derive.UriDisplayPath.html\n[`UriDisplayQuery`]: @api/master/rocket/derive.UriDisplayQuery.html\n"
  },
  {
    "path": "docs/guide/07-state.md",
    "content": "+++\nsummary = \"managing application state and connecting to databases\"\n+++\n\n# State\n\nMany web applications have a need to maintain state. This can be as simple as\nmaintaining a counter for the number of visits or as complex as needing to\naccess job queues and multiple databases. Rocket provides the tools to enable\nthese kinds of interactions in a safe and simple manner.\n\n## Managed State\n\nThe enabling feature for maintaining state is _managed state_. Managed state, as\nthe name implies, is state that Rocket manages for your application. The state\nis managed on a per-type basis: Rocket will manage at most one value of a given\ntype.\n\nThe process for using managed state is simple:\n\n  1. Call `manage` on the `Rocket` instance corresponding to your application\n     with the initial value of the state.\n  2. Add a `&State<T>` type to any request handler, where `T` is the type of the\n     value passed into `manage`.\n\n! note: All managed state must be thread-safe.\n\n  Because Rocket automatically parallelizes your application, handlers can\n  concurrently access managed state. As a result, managed state must be\n  thread-safe. Thanks to Rust, this condition is checked at compile-time by\n  ensuring that the type of values you store in managed state implement `Send` +\n  `Sync`.\n\n\n### Adding State\n\nTo instruct Rocket to manage state for your application, call the\n[`manage`](@api/master/rocket/struct.Rocket.html#method.manage) method\non an instance of `Rocket`. For example, to ask Rocket to manage a `HitCount`\nstructure with an internal `AtomicUsize` with an initial value of `0`, we can\nwrite the following:\n\n```rust\nuse std::sync::atomic::AtomicUsize;\n\nstruct HitCount {\n    count: AtomicUsize\n}\n\nrocket::build().manage(HitCount { count: AtomicUsize::new(0) });\n```\n\nThe `manage` method can be called any number of times as long as each call\nrefers to a value of a different type. For instance, to have Rocket manage both\na `HitCount` value and a `Config` value, we can write:\n\n```rust\n# use std::sync::atomic::AtomicUsize;\n# struct HitCount { count: AtomicUsize }\n# type Config = &'static str;\n# let user_input = \"input\";\n\nrocket::build()\n    .manage(HitCount { count: AtomicUsize::new(0) })\n    .manage(Config::from(user_input));\n```\n\n### Retrieving State\n\nState that is being managed by Rocket can be retrieved via the\n[`&State`](@api/master/rocket/struct.State.html) type: a [request\nguard](../requests/#request-guards) for managed state. To use the request guard,\nadd a `&State<T>` type to any request handler, where `T` is the type of the\nmanaged state. For example, we can retrieve and respond with the current\n`HitCount` in a `count` route as follows:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# use std::sync::atomic::{AtomicUsize, Ordering};\n# struct HitCount { count: AtomicUsize }\n\nuse rocket::State;\n\n#[get(\"/count\")]\nfn count(hit_count: &State<HitCount>) -> String {\n    let current_count = hit_count.count.load(Ordering::Relaxed);\n    format!(\"Number of visits: {}\", current_count)\n}\n```\n\nYou can retrieve more than one `&State` type in a single route as well:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n\n# struct HitCount;\n# struct Config;\n# use rocket::State;\n\n#[get(\"/state\")]\nfn state(hit_count: &State<HitCount>, config: &State<Config>) { /* .. */ }\n```\n\n! warning\n\n  If you request a `&State<T>` for a `T` that is not `managed`, Rocket will\n  refuse to start your application. This prevents what would have been an\n  unmanaged state runtime error. Unmanaged state is detected at runtime through\n  [_sentinels_](@api/master/rocket/trait.Sentinel.html), so there are limitations. If a\n  limitation is hit, Rocket still won't call the offending route. Instead,\n  Rocket will log an error message and return a **500** error to the client.\n\nYou can find a complete example using the `HitCount` structure in the [state\nexample on GitHub](@git/master/examples/state) and learn more about the [`manage`\nmethod](@api/master/rocket/struct.Rocket.html#method.manage) and [`State`\ntype](@api/master/rocket/struct.State.html) in the API docs.\n\n### Within Guards\n\nBecause `State` is itself a request guard, managed state can be retrieved from\nanother request guard's implementation using either [`Request::guard()`] or\n[`Rocket::state()`]. In the following code example, the `Item` request guard\nretrieves `MyConfig` from managed state using both methods:\n\n```rust\nuse rocket::State;\nuse rocket::request::{self, Request, FromRequest};\nuse rocket::outcome::IntoOutcome;\nuse rocket::http::Status;\n\n# struct MyConfig { user_val: String };\nstruct Item<'r>(&'r str);\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for Item<'r> {\n    type Error = ();\n\n    async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        // Using `State` as a request guard. Use `inner()` to get an `'r`.\n        let outcome = request.guard::<&State<MyConfig>>().await\n            .map(|my_config| Item(&my_config.user_val));\n\n        // Or alternatively, using `Rocket::state()`:\n        let outcome = request.rocket().state::<MyConfig>()\n            .map(|my_config| Item(&my_config.user_val))\n            .or_forward(Status::InternalServerError);\n\n        outcome\n    }\n}\n```\n\n[`Request::guard()`]: @api/master/rocket/struct.Request.html#method.guard\n[`Rocket::state()`]: @api/master/rocket/struct.Rocket.html#method.state\n\n## Request-Local State\n\nWhile managed state is *global* and available application-wide, request-local\nstate is *local* to a given request, carried along with the request, and dropped\nonce the request is completed. Request-local state can be used whenever a\n`Request` is available, such as in a fairing, a request guard, or a responder.\n\nRequest-local state is *cached*: if data of a given type has already been\nstored, it will be reused. This is especially useful for request guards that\nmight be invoked multiple times during routing and processing of a single\nrequest, such as those that deal with authentication.\n\nAs an example, consider the following request guard implementation for\n`RequestId` that uses request-local state to generate and expose a unique\ninteger ID per request:\n\n```rust\n# #[macro_use] extern crate rocket;\n# fn main() {}\n# use std::sync::atomic::{AtomicUsize, Ordering};\n\nuse rocket::request::{self, Request, FromRequest};\n\n/// A global atomic counter for generating IDs.\nstatic ID_COUNTER: AtomicUsize = AtomicUsize::new(0);\n\n/// A type that represents a request's ID.\nstruct RequestId(pub usize);\n\n/// Returns the current request's ID, assigning one only as necessary.\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for &'r RequestId {\n    type Error = ();\n\n    async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n        // The closure passed to `local_cache` will be executed at most once per\n        // request: the first time the `RequestId` guard is used. If it is\n        // requested again, `local_cache` will return the same value.\n        request::Outcome::Success(request.local_cache(|| {\n            RequestId(ID_COUNTER.fetch_add(1, Ordering::Relaxed))\n        }))\n    }\n}\n\n#[get(\"/\")]\nfn id(id: &RequestId) -> String {\n    format!(\"This is request #{}.\", id.0)\n}\n```\n\nNote that, without request-local state, it would not be possible to:\n\n  1. Associate a piece of data, here an ID, directly with a request.\n  2. Ensure that a value is generated at most once per request.\n\nFor more examples, see the [`FromRequest` request-local state] documentation,\nwhich uses request-local state to cache expensive authentication and\nauthorization computations, and the [`Fairing`] documentation, which uses\nrequest-local state to implement request timing.\n\n[`FromRequest` request-local state]: @api/master/rocket/request/trait.FromRequest.html#request-local-state\n[`Fairing`]: @api/master/rocket/fairing/trait.Fairing.html#request-local-state\n\n## Databases\n\nRocket includes built-in, ORM-agnostic support for databases via\n[`rocket_db_pools`]. The library simplifies accessing one or more databases via\nconnection pools: data structures that maintain active database connections for\nuse in the application. Database configuration occurs via Rocket's regular\n[configuration](../configuration/) mechanisms.\n\nConnecting your Rocket application to a database using `rocket_db_pools` happens\nin three simple steps:\n\n1. Choose your database(s) from the [supported database driver list]. Add\n   `rocket_db_pools` as a dependency in `Cargo.toml` with respective database\n   driver feature(s) enabled:\n\n   ```toml\n   [dependencies.rocket_db_pools]\n   version = \"0.1.0\"\n   features = [\"sqlx_sqlite\"]\n   ```\n\n2. Choose a name for your database, here `sqlite_logs`. [Configure]  _at least_\n   a URL for the database under `databases.$name` (here, in `Rocket.toml`),\n   where `$name` is your choice of database name:\n\n   ```toml\n   [default.databases.sqlite_logs]\n   url = \"/path/to/database.sqlite\"\n   ```\n\n3. [Derive `Database`] for a unit `Type` (`Logs` here) which wraps the selected\n   driver's `Pool` type from the [supported database driver list]. Decorated the\n   struct with `#[database(\"$name\")]` with the `$name` from `2.`. Attach\n   `$Type::init()` to your application's `Rocket` to initialize the database\n   pool and use [`Connection<$Type>`] as a request guard to retrieve an active\n   database connection:\n\n   ```rust\n   #[macro_use] extern crate rocket;\n\n   use rocket_db_pools::{Database, Connection};\n   use rocket_db_pools::sqlx::{self, Row};\n\n   #[derive(Database)]\n   #[database(\"sqlite_logs\")]\n   struct Logs(sqlx::SqlitePool);\n\n   #[get(\"/<id>\")]\n   async fn read(mut db: Connection<Logs>, id: i64) -> Option<String> {\n       sqlx::query(\"SELECT content FROM logs WHERE id = ?\").bind(id)\n           .fetch_one(&mut **db).await\n           .and_then(|r| Ok(r.try_get(0)?))\n           .ok()\n   }\n\n   #[launch]\n   fn rocket() -> _ {\n       rocket::build().attach(Logs::init()).mount(\"/\", routes![read])\n   }\n   ```\n\nFor complete usage details, see [`rocket_db_pools`].\n\n[`rocket_db_pools`]: @api/master/rocket_db_pools/index.html\n[supported database driver list]: @api/master/rocket_db_pools/index.html#supported-drivers\n[database driver features]: @api/master/rocket_db_pools/index.html#supported-drivers\n[`Pool`]: @api/master/rocket_db_pools/index.html#supported-drivers\n[Configure]: @api/master/rocket_db_pools/index.html#configuration\n[Derive `Database`]: @api/master/rocket_db_pools/derive.Database.html\n[`Connection<$Type>`]: @api/master/rocket_db_pools/struct.Connection.html\n\n### Driver Features\n\nOnly the minimal features for each driver crate are enabled by\n`rocket_db_pools`. To use additional driver functionality exposed via its\ncrate's features, you'll need to depend on the crate directly with those\nfeatures enabled in `Cargo.toml`:\n\n```toml\n[dependencies.sqlx]\nversion = \"0.7\"\ndefault-features = false\nfeatures = [\"macros\", \"migrate\"]\n\n[dependencies.rocket_db_pools]\nversion = \"0.1.0\"\nfeatures = [\"sqlx_sqlite\"]\n```\n\n### Synchronous ORMs\n\nWhile [`rocket_db_pools`] provides support for `async` ORMs and should thus be\nthe preferred solution, Rocket also provides support for synchronous, blocking\nORMs like [Diesel] via the [`rocket_sync_db_pools`] library, which you may wish\nto explore. Usage is similar, but not identical, to `rocket_db_pools`. See the\ncrate docs for complete usage details.\n\n[`rocket_sync_db_pools`]: @api/master/rocket_sync_db_pools/index.html\n[diesel]: https://diesel.rs/\n\n### Examples\n\nFor examples of CRUD-like \"blog\" JSON APIs backed by a SQLite database driven by\neach of `sqlx`, `diesel`, and `rusqlite`, with migrations run automatically for\nthe former two drivers, see the [databases example](@git/master/examples/databases). The\n`sqlx` example uses `rocket_db_pools` while the `diesel` and `rusqlite` examples\nuse `rocket_sync_db_pools`.\n"
  },
  {
    "path": "docs/guide/08-fairings.md",
    "content": "+++\nsummary = \"Rocket's structured middleware\"\n+++\n\n# Fairings\n\nFairings are Rocket's approach to structured middleware. With fairings, your\napplication can hook into the request lifecycle to record or rewrite information\nabout incoming requests and outgoing responses.\n\n## Overview\n\nAny type that implements the [`Fairing`] trait is a _fairing_. Fairings hook\ninto Rocket's request lifecycle, receiving callbacks for events such as incoming\nrequests and outgoing responses. Rocket passes information about these events to\nthe fairing; the fairing can do what it wants with the information. This\nincludes rewriting requests or responses, recording information about the event,\nor doing nothing at all.\n\nRocket’s fairings are a lot like middleware from other frameworks, but they bear\na few key distinctions:\n\n  * Fairings **cannot** terminate or respond to an incoming request directly.\n  * Fairings **cannot** inject arbitrary, non-request data into a request.\n  * Fairings _can_ prevent an application from launching.\n  * Fairings _can_ inspect and modify the application's configuration.\n\nIf you are familiar with middleware from other frameworks, you may find yourself\nreaching for fairings instinctively. Before doing so, remember that Rocket\nprovides a rich set of mechanisms such as [request guards] and [data guards]\nthat can be used to solve problems in a clean, composable, and robust manner.\n\n! warning\n\n  As a general rule of thumb, only _globally applicable_ actions should be\n  effected through fairings. You should **_not_** use a fairing to implement\n  authentication or authorization (preferring to use a [request guard] instead)\n  _unless_ the authentication or authorization applies to all or the\n  overwhelming majority of the application. On the other hand, you _should_ use a\n  fairing to record timing and usage statistics or to enforce global security\n  policies.\n\n[`Fairing`]: @api/master/rocket/fairing/trait.Fairing.html\n[request guard]: ../requests/#request-guards\n[request guards]: ../requests/#request-guards\n[data guards]: ../requests/#body-data\n\n### Attaching\n\nFairings are registered with Rocket via the [`attach`] method on a [`Rocket`]\ninstance. Only when a fairing is attached will its callbacks fire. As an\nexample, the following snippet attached two fairings, `req_fairing` and\n`res_fairing`, to a new Rocket instance:\n\n```rust\n# use rocket::launch;\n#[launch]\nfn rocket() -> _ {\n    # let req_fairing = rocket::fairing::AdHoc::on_request(\"example\", |_, _| Box::pin(async {}));\n    # let res_fairing = rocket::fairing::AdHoc::on_response(\"example\", |_, _| Box::pin(async {}));\n    rocket::build()\n        .attach(req_fairing)\n        .attach(res_fairing)\n}\n```\n\nFairings are executed in the order in which they are attached: the first\nattached fairing has its callbacks executed before all others. A fairing can be\nattached any number of times. Except for [singleton fairings], all attached\ninstances are polled at runtime. Fairing callbacks may not be commutative; the\norder in which fairings are attached may be significant.\n\n[singleton fairings]: @api/master/rocket/fairing/trait.Fairing.html#singletons\n[`attach`]: @api/master/rocket/struct.Rocket.html#method.attach\n[`Rocket`]: @api/master/rocket/struct.Rocket.html\n\n### Callbacks\n\nThere are five events for which Rocket issues fairing callbacks. Each of these\nevents is briefly described below and in details in the [`Fairing`] trait docs:\n\n  * **Ignite (`on_ignite`)**\n\n    An ignite callback is called during [ignition] An ignite callback can\n    arbitrarily modify the `Rocket` instance being built. They are commonly\n    used to parse and validate configuration values, aborting on bad\n    configurations, and inserting the parsed value into managed state for later\n    retrieval.\n\n  * **Liftoff (`on_liftoff`)**\n\n    A liftoff callback is called immediately after a Rocket application has\n    launched. A liftoff callback can inspect the `Rocket` instance being\n    launched. A liftoff callback can be a convenient hook for launching services\n    related to the Rocket application being launched.\n\n  * **Request (`on_request`)**\n\n    A request callback is called just after a request is received. A request\n    callback can modify the request at will and peek into the incoming data. It\n    may not, however, abort or respond directly to the request; these issues are\n    better handled via request guards or via response callbacks.\n\n  * **Response (`on_response`)**\n\n    A response callback is called when a response is ready to be sent to the\n    client. A response callback can modify part or all of the response. As such,\n    a response fairing can be used to provide a response when the greater\n    application fails by rewriting **404** responses as desired. As another\n    example, response fairings can also be used to inject headers into all\n    outgoing responses.\n\n  * **Shutdown (`on_shutdown`)**\n\n    A shutdown callback is called when [shutdown is triggered]. At this point,\n    graceful shutdown has commenced but not completed; no new requests are\n    accepted but the application may still be actively serving existing\n    requests. All registered shutdown fairings are run concurrently; resolution\n    of all fairings is awaited before resuming shutdown.\n\n[ignition]: @api/master/rocket/struct.Rocket.html#method.ignite\n[shutdown is triggered]: @api/master/rocket/config/struct.Shutdown.html#triggers\n\n## Implementing\n\nRecall that a fairing is any type that implements the [`Fairing`] trait. A\n`Fairing` implementation has one required method: [`info`], which returns an\n[`Info`] structure. This structure is used by Rocket to assign a name to the\nfairing and determine the set of callbacks the fairing is registering for. A\n`Fairing` can implement any of the available callbacks: [`on_ignite`],\n[`on_liftoff`], [`on_request`], [`on_response`], and [`on_shutdown`]. Each\ncallback has a default implementation that does absolutely nothing.\n\n[`Info`]: @api/master/rocket/fairing/struct.Info.html\n[`info`]: @api/master/rocket/fairing/trait.Fairing.html#tymethod.info\n[`on_ignite`]: @api/master/rocket/fairing/trait.Fairing.html#method.on_ignite\n[`on_liftoff`]: @api/master/rocket/fairing/trait.Fairing.html#method.on_liftoff\n[`on_request`]: @api/master/rocket/fairing/trait.Fairing.html#method.on_request\n[`on_response`]: @api/master/rocket/fairing/trait.Fairing.html#method.on_response\n[`on_shutdown`]: @api/master/rocket/fairing/trait.Fairing.html#method.on_shutdown\n\n### Requirements\n\nA type implementing `Fairing` is required to be `Send + Sync + 'static`. This\nmeans that the fairing must be sendable across thread boundaries (`Send`),\nthread-safe (`Sync`), and have only static references, if any (`'static`). Note\nthat these bounds _do not_ prohibit a `Fairing` from holding state: the state\nneed simply be thread-safe and statically available or heap allocated.\n\n### Example\n\nAs an example, we want to record the number of `GET` and `POST` requests that\nour application has received. While we could do this with request guards and\nmanaged state, it would require us to annotate every `GET` and `POST` request\nwith custom types, polluting handler signatures. Instead, we can create a simple\nfairing that acts globally.\n\nThe code for a `Counter` fairing below implements exactly this. The fairing\nreceives a request callback, where it increments a counter on each `GET` and\n`POST` request. It also receives a response callback, where it responds to\nunrouted requests to the `/counts` path by returning the recorded number of\ncounts.\n\n```rust\nuse std::io::Cursor;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse rocket::{Request, Data, Response};\nuse rocket::fairing::{Fairing, Info, Kind};\nuse rocket::http::{Method, ContentType, Status};\n\nstruct Counter {\n    get: AtomicUsize,\n    post: AtomicUsize,\n}\n\n#[rocket::async_trait]\nimpl Fairing for Counter {\n    // This is a request and response fairing named \"GET/POST Counter\".\n    fn info(&self) -> Info {\n        Info {\n            name: \"GET/POST Counter\",\n            kind: Kind::Request | Kind::Response\n        }\n    }\n\n    // Increment the counter for `GET` and `POST` requests.\n    async fn on_request(&self, request: &mut Request<'_>, _: &mut Data<'_>) {\n        match request.method() {\n            Method::Get => self.get.fetch_add(1, Ordering::Relaxed),\n            Method::Post => self.post.fetch_add(1, Ordering::Relaxed),\n            _ => return\n        };\n    }\n\n    async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {\n        // Don't change a successful user's response, ever.\n        if response.status() != Status::NotFound {\n            return\n        }\n\n        // Rewrite the response to return the current counts.\n        if request.method() == Method::Get && request.uri().path() == \"/counts\" {\n            let get_count = self.get.load(Ordering::Relaxed);\n            let post_count = self.post.load(Ordering::Relaxed);\n            let body = format!(\"Get: {}\\nPost: {}\", get_count, post_count);\n\n            response.set_status(Status::Ok);\n            response.set_header(ContentType::Plain);\n            response.set_sized_body(body.len(), Cursor::new(body));\n        }\n    }\n}\n```\n\nThe complete example can be found in the [`Fairing`\ndocumentation](@api/master/rocket/fairing/trait.Fairing.html#example).\n\n## Ad-Hoc Fairings\n\nFor simpler cases, implementing the `Fairing` trait can be cumbersome. This is\nwhy Rocket provides the [`AdHoc`] type, which creates a fairing from a simple\nfunction or closure. Using the `AdHoc` type is easy: simply call the\n`on_ignite`, `on_liftoff`, `on_request`, `on_response`, or `on_shutdown`\nconstructors on `AdHoc` to create a fairing from a function or closure.\n\nAs an example, the code below creates a `Rocket` instance with two attached\nad-hoc fairings. The first, a liftoff fairing named \"Liftoff Printer\", prints a\nmessage indicating that the application has launched. The second named \"Put\nRewriter\", a request fairing, rewrites the method of all requests to be `PUT`.\n\n```rust\nuse rocket::fairing::AdHoc;\nuse rocket::http::Method;\n\nrocket::build()\n    .attach(AdHoc::on_liftoff(\"Liftoff Printer\", |_| Box::pin(async move {\n        println!(\"...annnddd we have liftoff!\");\n    })))\n    .attach(AdHoc::on_request(\"Put Rewriter\", |req, _| Box::pin(async move {\n        req.set_method(Method::Put);\n    })))\n    .attach(AdHoc::on_shutdown(\"Shutdown Printer\", |_| Box::pin(async move {\n        println!(\"...shutdown has commenced!\");\n    })));\n```\n\n[`AdHoc`]: @api/master/rocket/fairing/struct.AdHoc.html\n"
  },
  {
    "path": "docs/guide/09-testing.md",
    "content": "+++\nsummary = \"unit and integration testing with the built-in testing library\"\n+++\n\n# Testing\n\nEvery application should be well tested and understandable. Rocket provides the\ntools to perform unit and integration tests. It also provides a means to inspect\ncode generated by Rocket.\n\n## Local Dispatching\n\nRocket applications are tested by dispatching requests to a local instance of\n`Rocket`. The [`local`] module contains all of the structures necessary to do\nso. In particular, it contains a [`Client`] structure that is used to create\n[`LocalRequest`] structures that can be dispatched against a given [`Rocket`]\ninstance. Usage is straightforward:\n\n  1. Construct a `Rocket` instance that represents the application.\n\n     ```rust,no_run\n     let rocket = rocket::build();\n     # let _ = rocket;\n     ```\n\n  2. Construct a `Client` using the `Rocket` instance.\n\n     ```rust,no_run\n     # use rocket::local::blocking::Client;\n     # let rocket = rocket::build();\n     let client = Client::tracked(rocket).unwrap();\n     # let _ = client;\n     ```\n\n  3. Construct requests using the `Client` instance.\n\n     ```rust,no_run\n     # use rocket::local::blocking::Client;\n     # let rocket = rocket::build();\n     # let client = Client::tracked(rocket).unwrap();\n     let req = client.get(\"/\");\n     # let _ = req;\n     ```\n\n  4. Dispatch the request to retrieve the response.\n\n     ```rust,no_run\n     # use rocket::local::blocking::Client;\n     # let rocket = rocket::build();\n     # let client = Client::tracked(rocket).unwrap();\n     # let req = client.get(\"/\");\n     let response = req.dispatch();\n     # let _ = response;\n     ```\n\n[`local`]: @api/master/rocket/local/\n[`Client`]: @api/master/rocket/local/#client\n[`LocalRequest`]: @api/master/rocket/local/#localrequest\n[`Rocket`]: @api/master/rocket/struct.Rocket.html\n\n## Validating Responses\n\nA `dispatch` of a `LocalRequest` returns a [`LocalResponse`] which can be\ninspected for validity. During testing, the response is usually validated\nagainst expected properties. These includes things like the response HTTP\nstatus, the inclusion of headers, and expected body data.\n\n[`LocalResponse`] type provides methods to ease this sort of validation. We list\na few below:\n\n  * [`status`]: returns the HTTP status in the response.\n  * [`content_type`]: returns the Content-Type header in the response.\n  * [`headers`]: returns a map of all of the headers in the response.\n  * [`into_string`]: reads the body data into a `String`.\n  * [`into_bytes`]: reads the body data into a `Vec<u8>`.\n  * [`into_json`]: deserializes the body data on-the-fly as JSON.\n  * [`into_msgpack`]: deserializes the body data on-the-fly as MessagePack.\n\n[`LocalResponse`]: @api/master/rocket/local/blocking/struct.LocalResponse.html\n[`status`]: @api/master/rocket/local/blocking/struct.LocalResponse.html#method.status\n[`content_type`]: @api/master/rocket/local/blocking/struct.LocalResponse.html#method.content_type\n[`headers`]: @api/master/rocket/local/blocking/struct.LocalResponse.html#method.headers\n[`into_string`]: @api/master/rocket/local/blocking/struct.LocalResponse.html#method.into_string\n[`into_bytes`]: @api/master/rocket/local/blocking/struct.LocalResponse.html#method.into_bytes\n[`into_json`]: @api/master/rocket/local/blocking/struct.LocalResponse.html#method.into_json\n[`into_msgpack`]: @api/master/rocket/local/blocking/struct.LocalResponse.html#method.into_msgpack\n\nThese methods are typically used in combination with the `assert_eq!` or\n`assert!` macros as follows:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# use std::io::Cursor;\n# use rocket::Response;\n# use rocket::http::Header;\n#\n# #[derive(Responder)]\n# #[response(content_type = \"text\")]\n# struct Custom {\n#     body: &'static str,\n#     header: Header<'static>,\n# }\n#\n# #[get(\"/\")]\n# fn hello() -> Custom {\n#     Custom {\n#         body: \"Expected Body\",\n#         header: Header::new(\"X-Special\", \"\"),\n#     }\n# }\n\n# use rocket::local::blocking::Client;\nuse rocket::http::{ContentType, Status};\n\n# let rocket = rocket::build().mount(\"/\", routes![hello]);\n# let client = Client::debug(rocket).expect(\"valid rocket instance\");\nlet mut response = client.get(uri!(hello)).dispatch();\n\nassert_eq!(response.status(), Status::Ok);\nassert_eq!(response.content_type(), Some(ContentType::Plain));\nassert!(response.headers().get_one(\"X-Special\").is_some());\nassert_eq!(response.into_string().unwrap(), \"Expected Body\");\n```\n\n## Testing \"Hello, world!\"\n\nTo solidify an intuition for how Rocket applications are tested, we walk through\nhow to test the \"Hello, world!\" application below:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/\")]\nfn hello() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/\", routes![hello])\n}\n```\n\nNotice that we've separated the _creation_ of the `Rocket` instance from the\n_launch_ of the instance. As you'll soon see, this makes testing our application\neasier, less verbose, and less error-prone.\n\n### Setting Up\n\nFirst, we'll create a `test` module with the proper imports:\n\n```rust\n#[cfg(test)]\nmod test {\n    use super::rocket;\n    use rocket::local::blocking::Client;\n    use rocket::http::Status;\n\n    #[test]\n    fn hello_world() {\n        /* .. */\n    }\n}\n```\n\nYou can also move the body of the `test` module into its own file, say\n`tests.rs`, and then import the module into the main file using:\n\n```rust\n#[cfg(test)] mod tests;\n```\n\n### Testing\n\nTo test our \"Hello, world!\" application, we create a `Client` for our\n`Rocket` instance. It's okay to use methods like `expect` and `unwrap` during\ntesting: we _want_ our tests to panic when something goes wrong.\n\n```rust\n# #[rocket::launch]\n# fn rocket() -> _ {\n#     rocket::build().reconfigure(rocket::Config::debug_default())\n# }\n# use rocket::local::blocking::Client;\n\nlet client = Client::tracked(rocket()).expect(\"valid rocket instance\");\n```\n\nThen, we create a new `GET /` request and dispatch it, getting back our\napplication's response:\n\n```rust\n# use rocket::uri;\n# #[rocket::launch]\n# fn rocket() -> _ {\n#     rocket::build().reconfigure(rocket::Config::debug_default())\n# }\n\n# #[rocket::get(\"/\")]\n# fn hello() -> &'static str { \"Hello, world!\" }\n\n# use rocket::local::blocking::Client;\n# let client = Client::tracked(rocket()).expect(\"valid rocket instance\");\nlet mut response = client.get(uri!(hello)).dispatch();\n```\n\nFinally, we ensure that the response contains the information we expect it to.\nHere, we want to ensure two things:\n\n  1. The status is `200 OK`.\n  2. The body is the string \"Hello, world!\".\n\nWe do this by checking the `Response` object directly:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# #[get(\"/\")]\n# fn hello() -> &'static str { \"Hello, world!\" }\n\n# use rocket::local::blocking::Client;\nuse rocket::http::{ContentType, Status};\n#\n# let rocket = rocket::build().mount(\"/\", routes![hello]);\n# let client = Client::debug(rocket).expect(\"valid rocket instance\");\n# let mut response = client.get(uri!(hello)).dispatch();\n\nassert_eq!(response.status(), Status::Ok);\nassert_eq!(response.into_string(), Some(\"Hello, world!\".into()));\n```\n\nThat's it! Altogether, this looks like:\n\n```rust\n# #[macro_use] extern crate rocket;\n# use rocket::{Rocket, Build};\n\n#[get(\"/\")]\nfn hello() -> &'static str {\n    \"Hello, world!\"\n}\n\n\n# /*\n#[launch]\n# */\nfn rocket() -> Rocket<Build> {\n    rocket::build().mount(\"/\", routes![hello])\n}\n\n# /*\n#[cfg(test)]\n# */\nmod test {\n    use super::rocket;\n    use rocket::local::blocking::Client;\n    use rocket::http::Status;\n\n    # /*\n    #[test]\n    # */ pub\n    fn hello_world() {\n        # /*\n        let client = Client::tracked(rocket()).expect(\"valid rocket instance\");\n        # */\n        # let client = Client::debug(rocket()).expect(\"valid rocket instance\");\n        let mut response = client.get(uri!(super::hello)).dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string().unwrap(), \"Hello, world!\");\n    }\n}\n\n# fn main() { test::hello_world(); }\n```\n\nThe tests can be run with `cargo test`. You can find the full source code to\n[this example on GitHub](@git/master/examples/testing).\n\n## Asynchronous Testing\n\nYou may have noticed the use of a \"`blocking`\" API in these examples, even\nthough `Rocket` is an `async` web framework. In most situations, the `blocking`\ntesting API is easier to use and should be preferred. However, when concurrent\nexecution of two or more requests is required for the server to make progress,\nyou will need the more flexible `asynchronous` API; the `blocking` API is not\ncapable of dispatching multiple requests simultaneously. While synthetic, the\n[`async_required` `testing` example] uses an `async` barrier to demonstrate such\na case. For more information, see the [`rocket::local`] and\n[`rocket::local::asynchronous`] documentation.\n\n[`rocket::local`]: @api/master/rocket/local/index.html\n[`rocket::local::asynchronous`]: @api/master/rocket/local/asynchronous/index.html\n[`async_required` `testing` example]: @git/master/examples/testing/src/async_required.rs\n\n## Codegen Debug\n\nIt can be useful to inspect the code that Rocket's code generation is emitting,\nespecially when you get a strange type error. To have Rocket log the code that\nit is emitting to the console, set the `ROCKET_CODEGEN_DEBUG` environment\nvariable when compiling:\n\n```sh\nROCKET_CODEGEN_DEBUG=1 cargo build\n```\n\nDuring compilation, you should see output like:\n\n```rust,ignore\nnote: emitting Rocket code generation debug output\n  --> examples/hello/src/main.rs:14:1\n   |\n14 | #[get(\"/world\")]\n   | ^^^^^^^^^^^^^^^^\n   |\n   = note:\n    impl world {\n        fn into_info(self) -> rocket::StaticRouteInfo {\n            fn monomorphized_function<'_b>(\n                __req: &'_b rocket::request::Request<'_>,\n                __data: rocket::data::Data,\n            ) -> ::rocket::route::BoxFuture<'_b> {\n                ::std::boxed::Box::pin(async move {\n                    let ___responder = world();\n                    ::rocket::handler::Outcome::from(__req, ___responder)\n                })\n            }\n\n            ::rocket::StaticRouteInfo {\n                name: \"world\",\n                method: ::rocket::http::Method::Get,\n                path: \"/world\",\n                handler: monomorphized_function,\n                format: ::std::option::Option::None,\n                rank: ::std::option::Option::None,\n                sentinels: sentinels![&'static str],\n            }\n        }\n    }\n```\n\nThis corresponds to the facade request handler Rocket has generated for the\n`hello` route.\n"
  },
  {
    "path": "docs/guide/10-configuration.md",
    "content": "+++\nsummary = \"overview and customization of Rocket application configuration\"\n+++\n\n# Configuration\n\nRocket's configuration system is flexible. Based on [Figment](@figment), it\nallows you to configure your application the way _you_ want while also providing\na sensible set of defaults.\n\n## Overview\n\nRocket's configuration system is based on Figment's [`Provider`]s, types which\nprovide configuration data. Rocket's [`Config`] and [`Config::figment()`], as\nwell as Figment's [`Toml`] and [`Json`], are some examples of providers.\nProviders can be combined into a single [`Figment`] provider from which any\nconfiguration structure that implements [`Deserialize`] can be extracted.\n\nRocket expects to be able to extract a [`Config`] structure from the provider it\nis configured with. This means that no matter which configuration provider\nRocket is asked to use, it must be able to read the following configuration\nvalues:\n\n| key                  | kind               | description                                     | debug/release default         |\n|----------------------|--------------------|-------------------------------------------------|-------------------------------|\n| `address`            | `IpAddr`           | IP address to serve on.                         | `127.0.0.1`                   |\n| `port`               | `u16`              | Port to serve on.                               | `8000`                        |\n| `workers`*           | `usize`            | Number of threads to use for executing futures. | cpu core count                |\n| `max_blocking`*      | `usize`            | Limit on threads to start for blocking tasks.   | `512`                         |\n| `ident`              | `string`, `false`  | If and how to identify via the `Server` header. | `\"Rocket\"`                    |\n| `ip_header`          | `string`, `false`  | IP header to inspect to get [client's real IP]. | `\"X-Real-IP\"`                 |\n| `proxy_proto_header` | `string`, `false`  | Header identifying [client to proxy protocol].  | `None`                        |\n| `keep_alive`         | `u32`              | Keep-alive timeout seconds; disabled when `0`.  | `5`                           |\n| `log_level`          | [`LogLevel`]       | Max level to log. (off/normal/debug/critical)   | `normal`/`critical`           |\n| `cli_colors`         | [`CliColors`]      | Whether to use colors and emoji when logging.   | `\"auto\"`                      |\n| `secret_key`         | [`SecretKey`]      | Secret key for signing and encrypting values.   | `None`                        |\n| `tls`                | [`TlsConfig`]      | TLS configuration, if any.                      | `None`                        |\n| `limits`             | [`Limits`]         | Streaming read size limits.                     | [`Limits::default()`]         |\n| `limits.$name`       | `&str`/`uint`      | Read limit for `$name`.                         | form = \"32KiB\"                |\n| `ctrlc`              | `bool`             | Whether `ctrl-c` initiates a server shutdown.   | `true`                        |\n| `shutdown`*          | [`ShutdownConfig`] | Graceful shutdown configuration.                | [`ShutdownConfig::default()`] |\n\n\n<small>* Note: the `workers`, `max_blocking`, and `shutdown.force` configuration\nparameters are only read from the [default provider](#default-provider).</small>\n\n[client's real IP]: @api/master/rocket/request/struct.Request.html#method.real_ip\n[client to proxy protocol]: @api/master/rocket/request/struct.Request.html#method.proxy_proto\n\n### Profiles\n\nConfigurations can be arbitrarily namespaced by [`Profile`]s. Rocket's\n[`Config`] and [`Config::figment()`] providers automatically set the\nconfiguration profile to \"debug\" when compiled in \"debug\" mode and \"release\"\nwhen compiled in release mode, but you can arbitrarily name and set profiles to\nyour desire. For example, with the [default provider](#default-provider), you\ncan set the selected profile via `ROCKET_PROFILE`. This results in Rocket\npreferring the values in the `ROCKET_PROFILE` profile.\n\nIn addition to any profiles you declare, there are two meta-profiles, `default`\nand `global`, which can be used to provide values that apply to _all_ profiles.\nValues provided in a `default` profile are used as fall-back values when the\nselected profile doesn't contain a requested value, while values in the `global`\nprofile supplant any values with the same name in any profile.\n\n[`Provider`]: @figment/trait.Provider.html\n[`Profile`]: @figment/struct.Profile.html\n[`Config`]: @api/master/rocket/struct.Config.html\n[`Config::figment()`]: @api/master/rocket/struct.Config.html#method.figment\n[`Toml`]: @figment/providers/struct.Toml.html\n[`Json`]: @figment/providers/struct.Json.html\n[`Figment`]: @figment/struct.Figment.html\n[`Deserialize`]: @api/master/rocket/serde/trait.Deserialize.html\n[`LogLevel`]: @api/master/rocket/config/enum.LogLevel.html\n[`Limits`]: @api/master/rocket/data/struct.Limits.html\n[`Limits::default()`]: @api/master/rocket/data/struct.Limits.html#impl-Default-for-Limits\n[`SecretKey`]: @api/master/rocket/config/struct.SecretKey.html\n[`CliColors`]: @api/master/rocket/config/enum.CliColors.html\n[`TlsConfig`]: @api/master/rocket/tls/struct.TlsConfig.html\n[`ShutdownConfig`]: @api/master/rocket/shutdown/struct.ShutdownConfig.html\n[`ShutdownConfig::default()`]: @api/master/rocket/shutdown/struct.ShutdownConfig.html#fields\n\n## Default Provider\n\nRocket's default configuration provider is [`Config::figment()`]; this is the\nprovider that's used when calling [`rocket::build()`].\n\nThe default figment reads from and merges, at a per-key level, the following\nsources in ascending priority order:\n\n  1. [`Config::default()`], which provides default values for all parameters.\n  2. `Rocket.toml` _or_ TOML file path in `ROCKET_CONFIG` environment variable.\n  3. `ROCKET_` prefixed environment variables.\n\nThe selected profile is the value of the `ROCKET_PROFILE` environment variable,\nor if it is not set, \"debug\" when compiled in debug mode and \"release\" when\ncompiled in release mode. With the exception of `log_level`, which changes from\n`normal` in debug to `critical` in release, all of the default configuration\nvalues are the same in all profiles. What's more, all configuration values\n_have_ defaults, so no configuration is needed to get started.\n\nAs a result of `Config::figment()`, without any effort, Rocket can be configured\nvia a `Rocket.toml` file and/or via environment variables, the latter of which\ntake precedence over the former.\n\n[`Config::default()`]: @api/master/rocket/struct.Config.html#method.default\n\n### Rocket.toml\n\nRocket searches for `Rocket.toml` or the filename in a `ROCKET_CONFIG`\nenvironment variable starting at the current working directory. If it is not\nfound, the parent directory, its parent, and so on, are searched until the file\nis found or the root is reached. If the path set in `ROCKET_CONFIG` is absolute,\nno such search occurs and the set path is used directly.\n\nThe file is assumed to be _nested_, so each top-level key declares a profile and\nits values the value for the profile. The following is an example of what such a\nfile might look like:\n\n```toml\n## defaults for _all_ profiles\n[default]\naddress = \"0.0.0.0\"\nlimits = { form = \"64 kB\", json = \"1 MiB\" }\n\n## set only when compiled in debug mode, i.e, `cargo build`\n[debug]\nport = 8000\n## only the `json` key from `default` will be overridden; `form` will remain\nlimits = { json = \"10MiB\" }\n\n## set only when the `nyc` profile is selected\n[nyc]\nport = 9001\n\n## set only when compiled in release mode, i.e, `cargo build --release`\n[release]\nport = 9999\nip_header = false\nproxy_proto_header = \"X-Forwarded-Proto\"\n# NOTE: Don't (!) use this key! Generate your own and keep it private!\n#       e.g. via `head -c64 /dev/urandom | base64`\nsecret_key = \"hPrYyЭRiMyµ5sBB1π+CMæ1køFsåqKvBiQJxBVHQk=\"\n```\n\nThe following is a `Rocket.toml` file with all configuration options set for\ndemonstration purposes. You **do not** and _should not_ set a value for\nconfiguration options needlessly, preferring to use the default value when\nsensible.\n\n```toml\n[default]\naddress = \"127.0.0.1\"\nport = 8000\nworkers = 16\nmax_blocking = 512\nkeep_alive = 5\nident = \"Rocket\"\nip_header = \"X-Real-IP\" # set to `false` to disable\nproxy_proto_header = false # set to `false` (the default) to disable\nlog_level = \"normal\"\ntemp_dir = \"/tmp\"\ncli_colors = true\n# NOTE: Don't (!) use this key! Generate your own and keep it private!\n#       e.g. via `head -c64 /dev/urandom | base64`\nsecret_key = \"hPrYyЭRiMyµ5sBB1π+CMæ1køFsåqKvBiQJxBVHQk=\"\n\n[default.limits]\nform = \"64 kB\"\njson = \"1 MiB\"\nmsgpack = \"2 MiB\"\n\"file/jpg\" = \"5 MiB\"\n\n[default.tls]\ncerts = \"path/to/cert-chain.pem\"\nkey = \"path/to/key.pem\"\n\n[default.shutdown]\nctrlc = true\nsignals = [\"term\", \"hup\"]\ngrace = 5\nmercy = 5\n```\n\n### Environment Variables\n\nRocket reads all environment variable names prefixed with `ROCKET_` using the\nstring after the `_` as the name of a configuration value as the value of the\nparameter as the value itself. Environment variables take precedence over values\nin `Rocket.toml`. Values are parsed as loose form of TOML syntax. Consider the\nfollowing examples:\n\n```sh\nROCKET_FLOAT=3.14\nROCKET_ARRAY=[1,\"b\",3.14]\nROCKET_STRING=Hello\nROCKET_STRING=\"Hello There\"\n\nROCKET_KEEP_ALIVE=1\nROCKET_IDENT=Rocket\nROCKET_IDENT=\"Hello Rocket\"\nROCKET_IDENT=false\nROCKET_TLS={certs=\"abc\",key=\"foo/bar\"}\nROCKET_LIMITS={form=\"64 KiB\"}\n```\n\n## Configuration Parameters\n\n### Secret Key\n\nThe `secret_key` parameter configures a cryptographic key to use when encrypting\napplication values. In particular, the key is used to encrypt [private cookies],\nwhich are available only when the `secrets` crate feature is enabled.\n\nGenerating a string suitable for use as a `secret_key` configuration value is\nusually done through tools like `openssl`. Using `openssl`, a 256-bit base64 key\ncan be generated with the command `openssl rand -base64 32`.\n\nWhen compiled in debug mode, a fresh key is generated automatically. In release\nmode, Rocket requires you to set a secret key if the `secrets` feature is\nenabled. Failure to do so results in a hard error at launch time. The value of\nthe parameter may either be a 256-bit base64 or hex string or a slice of 32\nbytes.\n\n[private cookies]: ../requests/#private-cookies\n\n### Limits\n\nThe `limits` parameter configures the maximum amount of data Rocket will accept\nfor a given data type. The value is expected to be a dictionary table where each\nkey corresponds to a data type and each value corresponds to the maximum size in\nbytes Rocket should accept for that type. Rocket can parse both integers\n(`32768`) or SI unit based strings (`\"32KiB\"`) as limits.\n\nBy default, Rocket specifies a `32 KiB` limit for incoming forms. Since Rocket\nrequires specifying a read limit whenever data is read, external data guards may\nalso choose to have a configure limit via the `limits` parameter. The\n[`Json`](@api/master/rocket/serde/json/struct.Json.html) type, for instance, uses the\n`limits.json` parameter.\n\n### TLS\n\nRocket includes built-in, native support for TLS >= 1.2 (Transport Layer\nSecurity). To enable TLS support:\n\n  1. Enable the `tls` crate feature in `Cargo.toml`:\n\n   ```toml,ignore\n   [dependencies]\n   rocket = { version = \"0.6.0-dev\", features = [\"tls\"] }\n   ```\n\n  2. Configure a TLS certificate chain and private key via the `tls.key` and\n     `tls.certs` configuration parameters. With the default provider, this can\n     be done via `Rocket.toml` as:\n\n   ```toml,ignore\n   [default.tls]\n   key = \"path/to/key.pem\"     # Path or bytes to DER-encoded ASN.1 PKCS#1/#8 or SEC1 key.\n   certs = \"path/to/certs.pem\" # Path or bytes to DER-encoded X.509 TLS cert chain.\n   ```\n\nThe `tls` parameter is expected to be a dictionary that deserializes into a\n[`TlsConfig`] structure:\n\n| key                          | required  | type                                                          |\n|------------------------------|-----------|---------------------------------------------------------------|\n| `key`                        | **_yes_** | Path or bytes to DER-encoded ASN.1 PKCS#1/#8 or SEC1 key.     |\n| `certs`                      | **_yes_** | Path or bytes to DER-encoded X.509 TLS cert chain.            |\n| `ciphers`                    | no        | Array of [`CipherSuite`]s to enable.                          |\n| `prefer_server_cipher_order` | no        | Boolean for whether to [prefer server cipher suites].         |\n| `mutual`                     | no        | A map with [mutual TLS] configuration.                        |\n\n[`CipherSuite`]: @api/master/rocket/tls/enum.CipherSuite.html\n[prefer server cipher suites]: @api/master/rocket/tls/struct.TlsConfig.html#method.with_preferred_server_cipher_order\n[mutual TLS]: #mutual-tls\n\nWhen specified via TOML or other serialized formats, each [`CipherSuite`] is\nwritten as a string representation of the respective variant. For example,\n`CipherSuite::TLS_AES_256_GCM_SHA384` is `\"TLS_AES_256_GCM_SHA384\"`. In TOML,\nthe defaults (with an arbitrary `certs` and `key`) are written:\n\n```toml\n[default.tls]\ncerts = \"/ssl/cert.pem\"\nkey = \"/ssl/key.pem\"\nprefer_server_cipher_order = false\nciphers = [\n    \"TLS_CHACHA20_POLY1305_SHA256\",\n    \"TLS_AES_256_GCM_SHA384\",\n    \"TLS_AES_128_GCM_SHA256\",\n    \"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256\",\n    \"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256\",\n    \"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\",\n    \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\",\n    \"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\",\n    \"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\",\n]\n```\n\n### Mutual TLS\n\nRocket supports mutual TLS client authentication. Configuration works in concert\nwith the [`mtls`] module, which provides a request guard to validate, verify,\nand retrieve client certificates in routes.\n\nBy default, mutual TLS is disabled and client certificates are not required,\nvalidated or verified. To enable mutual TLS, the `mtls` feature must be\nenabled and support configured via the `tls.mutual` config parameter:\n\n  1. Enable the `mtls` crate feature in `Cargo.toml`:\n\n   ```toml,ignore\n   [dependencies]\n   rocket = { version = \"0.6.0-dev\", features = [\"mtls\"] }\n   ```\n\n   This implicitly enables the `tls` feature.\n\n  2. Configure a CA certificate chain via the `tls.mutual.ca_certs`\n     configuration parameter. With the default provider, this can be done via\n     `Rocket.toml` as:\n\n   ```toml,ignore\n   [default.tls.mutual]\n   ca_certs = \"path/to/ca_certs.pem\" # Path or bytes to DER-encoded X.509 TLS cert chain.\n   mandatory = true                  # when absent, defaults to false\n   ```\n\nThe `tls.mutual` parameter is expected to be a dictionary that deserializes into a\n[`MutualTls`] structure:\n\n| key         | required  | type                                                        |\n|-------------|-----------|-------------------------------------------------------------|\n| `ca_certs`  | **_yes_** | Path or bytes to DER-encoded X.509 TLS cert chain.          |\n| `mandatory` | no        | Boolean controlling whether the client _must_ authenticate. |\n\n[`MtlsConfig`]: @api/master/rocket/mtls/struct.MtlsConfig.html\n[`mtls`]: @api/master/rocket/mtls/index.html\n\nRocket reports if TLS and/or mTLS are enabled at launch time:\n\n```text\n🔧 Configured for debug.\n   ...\n   >> tls: enabled w/mtls\n```\n\nOnce mutual TLS is properly enabled, the [`mtls::Certificate`] request guard can\nbe used to retrieve validated, verified client certificates:\n\n```rust\n# #[macro_use] extern crate rocket;\nuse rocket::mtls::Certificate;\n\n#[get(\"/auth\")]\nfn auth(cert: Certificate<'_>) {\n    // This handler only runs when a valid certificate was presented.\n}\n```\n\nThe [TLS example](@git/master/examples/tls) illustrates a fully configured TLS server with\nmutual TLS.\n\n! warning: Rocket's built-in TLS supports only TLS 1.2 and 1.3.\n\n  This may not be suitable for production use requiring legacy support.\n\n[`mtls::Certificate`]: @api/master/rocket/mtls/struct.Certificate.html\n\n### Proxied TLS\n\nThe `proxy_proto_header` configuration parameter allows Rocket applications to\ndetermine when and if a client's initial connection was likely made in a secure\ncontext by examining the header with the configured name. The header's value is\nparsed into a [`ProxyProto`], retrievable via [`Request::proxy_proto()`].\n\nThat value is in-turn inspected to determine if the initial connection was\nsecure (i.e, made over TLS) and the outcome made available via\n[`Request::context_is_likely_secure()`]. The value returned by this method\ninfluences cookie defaults. In particular, if the method returns `true` (i.e,\nthe request context is likely secure), the `Secure` cookie flag is set by\ndefault when a cookie is added to a [`CookieJar`].\n\nTo enable this behaviour, configure the header as set by your reverse proxy or\nforwarding entity. For example, to set the header name to `X-Forwarded-Proto`\nvia a TOML file:\n\n```toml,ignore\nproxy_proto_header = \"X-Forwarded-Proto\"\n```\n\n[`Request::proxy_proto()`]: @api/master/rocket/request/struct.Request.html#method.proxy_proto\n[`ProxyProto`]: @api/master/rocket/http/enum.ProxyProto.html\n[`CookieJar`]: @api/master/rocket/http/struct.CookieJar.html\n[`Request::context_is_likely_secure()`]: @api/master/rocket/request/struct.Request.html#method.context_is_likely_secure\n\n### Crypto Providers\n\nRocket's TLS support, provided by [`rustls`], allows replacing the underlying\n[`CryptoProvider`] for cryptographic operations. By default, Rocket uses\n[`ring`] as its `CryptoProvider`, but applications can change the default by\n[installing] a different `CryptoProvider` before Rocket launches.\n\nFor example, to use `aws-lc-rs` instead of `ring`, first depend on `rustls`\ndirectly with the `aws_lc_rs` feature enabled:\n\n```toml\n[dependencies]\nrustls = { version = \"0.23\", features = [\"aws_lc_rs\"] }\n```\n\nThen, before the application starts, install the provider as the default:\n\n```rust,ignore\n# #[macro_use] extern crate rocket;\n\n#[launch]\nfn rocket() -> _ {\n    let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();\n    rocket::build()\n}\n```\n\nRocket will use the installed default whenever TLS is operational.\n\n[`rustls`]: @rustls\n[`CryptoProvider`]: @rustls/crypto/struct.CryptoProvider.html\n[`ring`]: @rustls/crypto/ring/index.html\n[installing]: @rustls/crypto/struct.CryptoProvider.html#method.install_default\n\n### Workers\n\nThe `workers` parameter sets the number of threads used for parallel task\nexecution; there is no limit to the number of concurrent tasks. Due to a\nlimitation in upstream async executers, unlike other values, the `workers`\nconfiguration value cannot be reconfigured or be configured from sources other\nthan those provided by [`Config::figment()`]. In other words, only the values\nset by the `ROCKET_WORKERS` environment variable or in the `workers` property of\n`Rocket.toml` will be considered - all other `workers` values are ignored.\n\nThe `max_blocking` parameter sets an upper limit on the number of threads the\nunderlying `async` runtime will spawn to execute potentially blocking,\nsynchronous tasks via [`spawn_blocking`] or equivalent. Similar to the `workers`\nparameter, `max_blocking` cannot be reconfigured or be configured from sources\nother than those provided by [`Config::figment()`]. Unlike `workers`, threads\ncorresponding to `max_blocking` are not always active and will exit if idling.\nIn general, the default value of `512` should not be changed unless physical or\nvirtual resources are scarce. Rocket only executes work on blocking threads when\nrequired such as when performing file system I/O via [`TempFile`] or wrapping\nsynchronous work via [`rocket_sync_db_pools`].\n\n[`spawn_blocking`]: @tokio/task/fn.spawn_blocking.html\n[`TempFile`]: @api/master/rocket/fs/enum.TempFile.html\n[`rocket_sync_db_pools`]: @api/master/rocket_sync_db_pools/index.html\n\n## Extracting Values\n\nYour application can extract any configuration that implements [`Deserialize`]\nfrom the configured provider, which is exposed via [`Rocket::figment()`]:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::serde::Deserialize;\n\n#[launch]\nfn rocket() -> _ {\n    let rocket = rocket::build();\n    let figment = rocket.figment();\n\n    #[derive(Deserialize)]\n    #[serde(crate = \"rocket::serde\")]\n    struct Config {\n        port: u16,\n        custom: Vec<String>,\n    }\n\n    // extract the entire config any `Deserialize` value\n    let config: Config = figment.extract().expect(\"config\");\n\n    // or a piece of it into any `Deserialize` value\n    let custom: Vec<String> = figment.extract_inner(\"custom\").expect(\"custom\");\n\n    rocket\n}\n```\n\nBoth values recognized by Rocket and values _not_ recognized by Rocket can be\nextracted. This means you can configure values recognized by your application in\nRocket's configuration sources directly. The next section describes how you can\ncustomize configuration sources by supplying your own `Provider`.\n\nBecause it is common to store configuration in managed state, Rocket provides an\n`AdHoc` fairing that 1) extracts a configuration from the configured provider,\n2) pretty prints any errors, and 3) stores the value in managed state:\n\n```rust\n# #[macro_use] extern crate rocket;\n# use rocket::serde::Deserialize;\n# #[derive(Deserialize)]\n# #[serde(crate = \"rocket::serde\")]\n# struct Config {\n#     port: u16,\n#     custom: Vec<String>,\n# }\n\nuse rocket::{State, fairing::AdHoc};\n\n#[get(\"/custom\")]\nfn custom(config: &State<Config>) -> String {\n    config.custom.get(0).cloned().unwrap_or(\"default\".into())\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![custom])\n        .attach(AdHoc::config::<Config>())\n}\n```\n\n[`Rocket::figment()`]: @api/master/rocket/struct.Rocket.html#method.figment\n\n## Custom Providers\n\nA custom provider can be set via [`rocket::custom()`], which replaces calls to\n[`rocket::build()`]. The configured provider can be built on top of\n[`Config::figment()`], [`Config::default()`], both, or neither. The\n[Figment](@figment) documentation has full details on instantiating existing\nproviders like [`Toml`] and [`Json`] as well as creating custom providers for\nmore complex cases.\n\n! note: You may need to depend on `figment` and `serde` directly.\n\n  Rocket reexports `figment` and `serde` from its crate root, so you can refer\n  to `figment` types via `rocket::figment` and `serde` types via\n  `rocket::serde`. However, Rocket does not enable all features from either\n  crate. As such, you may need to import crates directly:\n\n  `\n  figment = { version = \"0.10\", features = [\"env\", \"toml\", \"json\"] }\n  `\n\nAs a first example, we override configuration values at runtime by merging\nfigment's tuple providers with Rocket's default provider:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::data::{Limits, ToByteUnit};\n\n#[launch]\nfn rocket() -> _ {\n    let figment = rocket::Config::figment()\n        .merge((\"port\", 1111))\n        .merge((\"limits\", Limits::new().limit(\"json\", 2.mebibytes())));\n\n    rocket::custom(figment).mount(\"/\", routes![/* .. */])\n}\n```\n\nMore involved, consider an application that wants to use Rocket's defaults for\n[`Config`], but not its configuration sources, while allowing the application to\nbe configured via an `App.toml` file that uses top-level keys as profiles\n(`.nested()`), `APP_` environment variables as global overrides (`.global()`),\nand `APP_PROFILE` to configure the selected profile:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::serde::{Serialize, Deserialize};\nuse rocket::fairing::AdHoc;\n\nuse figment::{Figment, Profile, providers::{Format, Toml, Serialized, Env}};\n\n#[derive(Debug, Deserialize, Serialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Config {\n    app_value: usize,\n    /* and so on.. */\n}\n\nimpl Default for Config {\n    fn default() -> Config {\n        Config { app_value: 3, }\n    }\n}\n\n#[launch]\nfn rocket() -> _ {\n    let figment = Figment::from(rocket::Config::default())\n        .merge(Serialized::defaults(Config::default()))\n        .merge(Toml::file(\"App.toml\").nested())\n        .merge(Env::prefixed(\"APP_\").global())\n        .select(Profile::from_env_or(\"APP_PROFILE\", \"default\"));\n\n    rocket::custom(figment)\n        .mount(\"/\", routes![/* .. */])\n        .attach(AdHoc::config::<Config>())\n}\n```\n\nRocket will extract its configuration from the configured provider. This means\nthat if values like `port` and `address` are configured in `Config`, `App.toml`\nor `APP_` environment variables, Rocket will make use of them. The application\ncan also extract its configuration, done here via the `Adhoc::config()` fairing.\n\n[`rocket::custom()`]: @api/master/rocket/fn.custom.html\n[`rocket::build()`]: @api/master/rocket/fn.build.html\n"
  },
  {
    "path": "docs/guide/11-deploying.md",
    "content": "+++\nsummary = \"how to deploy a Rocket application to production\"\n+++\n\n# Deploying\n\nThis section describes deploying Rocket applications to production. It provides\na general overview as well as concrete, reusable examples for common deployment\nscenarios including [self-managed deployments], [containerization], and\n[fully-managed deployments].\n\n! note: Rocket does not endorse or prefer any particular tools or services.\n\n  Rocket does not endorse or prefer any specific tools or services mentioned in\n  this guide. They are mentioned in exposition only. Rocket is agnostic to its\n  deployment environment.\n\n[containerization]: #containerization\n[self-managed deployments]: #self-managed\n[fully-managed deployments]: #fully-managed\n\n## Overview\n\nFor any deployment, it's important to keep in mind:\n\n  1. **Configuration**\n\n     Minimally, Rocket will need to be configured to listen on the correct\n     **port** and **address**, typically port `80` or `8080` and address\n     `0.0.0.0`. Your deployment environment may have different requirements.\n     Recall that by default, you can set the address and port via the\n     environment variables `ROCKET_ADDRESS` and `ROCKET_PORT` as well as through\n     [many other means](../configuration).\n\n  2. **Asset Bundling**\n\n     If your application serves assets or leverages templates, you may need to\n     bundle those assets with your application binary. For example, if you serve\n     static assets from the `./static` directory and enable templates, you'll\n     need to ensure that those directories are present and **in the current\n     working directory** that your application binary starts in.\n\n     ```rust\n     # #[macro_use] extern crate rocket;\n\n     use rocket::fs::FileServer;\n     use rocket_dyn_templates::Template;\n\n     #[launch]\n     fn rocket() -> _ {\n         rocket::build()\n             .mount(\"/\", FileServer::new(\"./static\"))\n             .attach(Template::fairing())\n     }\n     ```\n\n     For the application above, assuming the `template_dir` configuration\n     parameter hasn't been changed, you'll need to ensure that the `static` and\n     `templates` directories are placed in the current working directory that\n     the application will start in. Otherwise, Rocket will refuse to launch.\n\n  3. **Load Balancing**\n\n     Rocket does not yet have robust support for [DDoS mitigation], so a\n     production deployment will require placing Rocket behind a load balancer or\n     reverse proxy that does. If you are deploying your Rocket application to\n     managed environments such as Kubernetes, Heroku, or Google Cloud Run, this\n     will be handled for you automatically. However, if you're deploying to a\n     self-managed environment such as a VPS, we recommend placing Rocket behind\n     a mature reverse proxy such as HAProxy or NGINX.\n\n  4. **Service Management**\n\n     As your application matures, you'll need to deploy updated versions to your\n     production environment, stopping the existing application and starting the\n     new one in its place. In a managed environment, you can likely rely on the\n     environment to provide these mechanisms. In a self-managed environment,\n     using a service manager like `systemd`, _in addition_ to a reverse proxy,\n     is recommended.\n\n     In either case, it's important to know that once a Rocket application has\n     started, it will run until [graceful shutdown] is initiated. Your\n     application should leverage Rocket's graceful shutdown mechanisms such as\n     the [`Shutdown`] future and [shutdown fairings] to clean-up resources\n     before terminating. You should also ensure that the graceful shutdown\n     configuration is aligned with your environment. For example, Kubernetes\n     issues a `SIGTERM` signal to initiate termination which Rocket listens for\n     by default, but other environments may send other signals which you might\n     need to enable as [triggers].\n\nThe following section addresses these concerns and more for common deployment\nscenarios.\n\n[DDoS mitigation]: @github/issues/1405\n[graceful shutdown]: @api/master/rocket/shutdown/struct.ShutdownConfig.html\n[`Shutdown`]: @api/master/rocket/struct.Shutdown.html\n[shutdown fairings]: @api/master/rocket/fairing/trait.Fairing.html#shutdown\n[triggers]: @api/master/rocket/shutdown/struct.ShutdownConfig.html#triggers\n\n## Common Scenarios\n\n### Self-Managed\n\nIn a _self-managed_ environment, you are typically responsible for all facets of\ndeployment and service management. In exchange, a self-managed environment\ntypically incurs the lowest financial cost.\n\nYou must decide whether you manage your Rocket application _directly_, by\ninstalling, configuring, and running a service manager, load balancer, and\nRocket application, or _indirectly_ by installing and configuring an application\nmanagement service like [kubernetes], [k3s], or [dokku]. Because indirect\nself-management typically revolves around [containerization], covered in the\nnext section, we focus on _direct_ self-management here.\n\n[kubernetes]: https://kubernetes.io/\n[k3s]: https://k3s.io/\n[dokku]: https://dokku.com/\n\nOur recommendation for a direct self-managed deployment is to:\n\n  - **Compile for the remote target (i.e, the VPS), bundle, and copy.**\n\n    Compile your application for the remote target and bundle the binary with\n    its assets. You may need to cross-compile for the remote target: we\n    recommend using [`cargo-zigbuild`]. Before cross-compiling, you'll also need\n    to install the Rust toolchain for the target.\n\n    The script below performs these steps, producing a gzipped archive ready to\n    be copied to a remote server.\n\n    ```sh\n    ## configure these for your environment\n    PKG=\"app\"                                    # cargo package name\n    TARGET=\"x86_64-unknown-linux-gnu\"            # remote target\n    ASSETS=(\"Rocket.toml\" \"static\" \"templates\")  # list of assets to bundle\n    BUILD_DIR=\"target/${TARGET}/release\"         # cargo build directory\n\n    ## ensure target toolchain is present\n    rustup target add $TARGET\n\n    ## cross-compile\n    cargo zigbuild --target $TARGET --release\n\n    ## bundle\n    tar -cvzf \"${PKG}.tar.gz\" \"${ASSETS[@]}\" -C \"${BUILD_DIR}\" \"${PKG}\"\n    ```\n\n  - **Run the application as a managed service.**\n\n    Once the bundle is at the remote server, use a service manager to start,\n    monitor, and stop the application. As an example, assuming the bundle\n    produced by the script above was extracted to `/www/pkg`, the following\n    `systemd` service file defines a service for the application:\n\n    ```ini\n    [Unit]\n    Description=Rocket Application\n    After=network.target\n\n    [Service]\n    Type=simple\n    WorkingDirectory=/www/pkg\n    ExecStart=/www/pkg/pkg\n    User=pkg\n    Group=pkg\n    Restart=always\n\n    [Install]\n    WantedBy=multi-user.target\n    ```\n\n    You'll want to modify the service file as needed. Consider particularly the\n    `User` and `Group`: that user/group will need to be authorized to access the\n    `WorkingDirectory`.\n\n    Write the service file to the `systemd` services directory (for example,\n    `/etc/systemd/system/pkg.service`). You can now interact with the service as\n    usual:\n\n    ```sh\n    systemctl [status,enable,start,stop,restart,disable] pkg\n    ```\n\n    If the service is running but the server doesn't appear to be responding,\n    ensure that you've set the address and port you expect in the `[default]`,\n    `[global]`, and/or `[production]` sections of `Rocket.toml` or via another\n    configuration source. For example, you may wish to set systemd `Service`\n    environment variables:\n\n    ```diff\n    [Service]\n    + Environment=ROCKET_ADDRESS=127.0.0.1\n    + Environment=ROCKET_PORT=8000\n    ```\n\n  - **Configure a reverse proxy for the application.**\n\n    Finally, configure a reverse proxy to serve requests to the running\n    application server. As an example, a simple NGINX reverse proxy\n    configuration file for the application above might look like:\n\n    ```conf\n    server {\n        listen 80;\n\n        location / {\n            proxy_pass http://127.0.0.1:8000;\n            proxy_set_header X-Real-IP $remote_addr;\n            proxy_set_header X-Forwarded-Proto $scheme;\n        }\n    }\n    ```\n\n    Note that we configure NGINX to forward the actual remote IP via the\n    `X-Real-IP` header, which Rocket uses by default via [`ip_header`].\n    Additionally, the scheme is forwarded via `X-Forwarded-Proto`, but it must\n    be explicitly configured via [`proxy_proto_header`] for Rocket to consider.\n\n[`cargo-zigbuild`]: https://github.com/rust-cross/cargo-zigbuild\n[`ip_header`]: @api/master/rocket/config/struct.Config.html#structfield.ip_header\n[`proxy_proto_header`]: @api/master/rocket/config/struct.Config.html#structfield.proxy_proto_header\n\n### Containerization\n\nIn a _containerization_ environment, you are responsible for writing a\n`Dockerfile` or `Containerfile` which you provide to an application platform.\nThe platform may be self-managed, as with [k3s] or [dokku], or fully-managed, as\nwith Google Cloud Run or Heroku.\n\nBelow you'll find an example of a `Dockerfile` that:\n\n  - Builds the application with the latest stable Rust compiler.\n  - Uses `--mount=type=cache` to avoid recompiling dependencies.\n  - Uses a second stage to create a slim (~100MiB), ready-to-deploy image with\n    only what's needed.\n  - Bundles all of an application's assets in the container.\n\n```dockerfile\nFROM docker.io/rust:1-slim-bookworm AS build\n\n## cargo package name: customize here or provide via --build-arg\nARG pkg=rocket-app\n\nWORKDIR /build\n\nCOPY . .\n\nRUN --mount=type=cache,target=/build/target \\\n    --mount=type=cache,target=/usr/local/cargo/registry \\\n    --mount=type=cache,target=/usr/local/cargo/git \\\n    set -eux; \\\n    cargo build --release; \\\n    objcopy --compress-debug-sections target/release/$pkg ./main\n\n################################################################################\n\nFROM docker.io/debian:bookworm-slim\n\nWORKDIR /app\n\n## copy the main binary\nCOPY --from=build /build/main ./\n\n## copy runtime assets which may or may not exist\nCOPY --from=build /build/Rocket.tom[l] ./\nCOPY --from=build /build/stati[c] ./static/\nCOPY --from=build /build/template[s] ./templates/\n\n## ensure the container listens globally on port 8080\nENV ROCKET_ADDRESS=0.0.0.0\nENV ROCKET_PORT=8080\n\nCMD ./main\n```\n\nYou will need to modify the `pkg` `ARG` or provide it via the command-line:\n\n```sh\ndocker build --build-arg pkg=cargo_package_name -t app  .\n```\n\nYou may also need to make the following changes:\n\n  * Add/remove/modify `ENV` variables as needed.\n  * Modify the expected `target/release/$pkg` directory.\n  * Add more assets to `COPY` to the final image.\n\nFinally, we recommend the following `.dockerignore` file to avoid copying\nunnecessary artifacts:\n\n```gitignore\ntarget\n.cargo\n**/*.sh\n**/*.tar.gz\n```\n\n### Fully-Managed\n\nIn a _fully-managed_ environment, you provide a service with your source code\nand instructions on how to build and run your application. The `Dockerfile` in\nthe [containerization] section, coupled with a configuration file that instructs\nthe service to build it, may be one such example.\n\nBecause the specifics on deploying to a fully-managed environment depend on the\nenvironment, we provide only the following general guidelines:\n\n  * **Ensure the address and port are set as required.**\n\n    Most environments require your application to listen on `0.0.0.0`. Ensure\n    `ROCKET_ADDRESS=0.0.0.0`.\n\n    Some environments require your application to listen on specific ports.\n    Remember to set the port as required. For example, if the service requires\n    your application to listen on a port provided by a `$PORT` environment\n    variable, set `ROCKET_PORT=$PORT` before starting your application.\n\n  * **Compile or run with `--release`.**\n\n    Ensure that you run `cargo` commands with `--release`. Besides compiling\n    with optimizations, compiling with `--release` sets the default\n    [configuration profile] to `release`.\n\n  * **Enable debug logging if the application misbehaves.**\n\n    The default log level in `--release` (the release profile) is `critical`.\n    This level may omit messages helpful in understanding application\n    misbehavior. To reenable those messages, set `ROCKET_LOG_LEVEL=debug`.\n\n[configuration profile]: ../configuration/#profiles\n"
  },
  {
    "path": "docs/guide/12-pastebin.md",
    "content": "+++\nsummary = \"step-by-step guide to creating a pastebin with Rocket\"\n+++\n\n# Pastebin Tutorial\n\nThis section of the guide is a tutorial intended to demonstrate how real-world\nRocket applications are crafted. We'll build a simple pastebin service that\nallows users to upload a file from any HTTP client, including `curl`. The\nservice will respond back with a URL to the uploaded file.\n\n! note: What's a pastebin?\n\n  A pastebin is a simple web application that allows users to upload a document\n  and later retrieve it via a special URL. They're often used to share code\n  snippets, configuration files, and error logs.\n\n## Finished Product\n\nA souped-up, completed version of the application you're about to build is\ndeployed live at [paste.rs](https://paste.rs). Feel free to play with the\napplication to get a feel for how it works. For example, to upload a text\ndocument named `test.txt`, you can run:\n\n```sh\ncurl --data-binary @test.txt https://paste.rs/\n# => https://paste.rs/IYu\n```\n\nThe finished product is composed of the following routes:\n\n  * `index` - `#[get(\"/\")]`\n\n    returns a simple HTML page with instructions about how to use the service\n\n  * `upload` - `#[post(\"/\")]`\n\n    accepts raw data in the body of the request and responds with a URL of a\n    page containing the body's content\n\n  * `retrieve` - `#[get(\"/<id>\")]`\n\n    retrieves the content for the paste with id `<id>`\n\n## Getting Started\n\nLet's get started! First, create a fresh Cargo binary project named\n`rocket-pastebin`:\n\n```sh\ncargo new --bin rocket-pastebin\ncd rocket-pastebin\n```\n\nThen add the usual Rocket dependencies to the `Cargo.toml` file:\n\n```toml\n[dependencies]\nrocket = \"0.6.0-dev\"\n```\n\nAnd finally, create a skeleton Rocket application to work off of in\n`src/main.rs`:\n\n```rust\n#[macro_use] extern crate rocket;\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n}\n```\n\nEnsure everything works by running the application:\n\n```sh\ncargo run\n```\n\nAt this point, we haven't declared any routes or handlers, so visiting any page\nwill result in Rocket returning a **404** error. Throughout the rest of the\ntutorial, we'll create the three routes and accompanying handlers.\n\n## Index\n\nThe first route we'll create is `index`. This is the page users will see when\nthey first visit the service. As such, the route should handle `GET /`. We\ndeclare the route and its handler by adding the `index` function below to\n`src/main.rs`:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n#[get(\"/\")]\nfn index() -> &'static str {\n    \"\n    USAGE\n\n      POST /\n\n          accepts raw data in the body of the request and responds with a URL of\n          a page containing the body's content\n\n      GET /<id>\n\n          retrieves the content for the paste with id `<id>`\n    \"\n}\n```\n\nThis declares the `index` route for requests to `GET /` as returning a static\nstring with the specified contents. Rocket will take the string and return it as\nthe body of a fully formed HTTP response with `Content-Type: text/plain`. You\ncan read more about how Rocket formulates responses in the [responses section]\nof the guide or at the [API documentation for the Responder\ntrait](@api/master/rocket/response/trait.Responder.html).\n\n[responses section]: ../responses/\n\nRemember that routes first need to be mounted before Rocket dispatches requests\nto them. To mount the `index` route, modify the main function so that it reads:\n\n```rust\n# #[macro_use] extern crate rocket;\n# #[get(\"/\")] fn index() { }\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/\", routes![index])\n}\n```\n\nYou should now be able to `cargo run` the application and visit the root path\n(`/`) to see the text.\n\n## Design\n\nBefore we continue, we'll need to make a few design decisions.\n\n  * **Where should pastes be stored?**\n\n    To keep things simple, we'll store uploaded pastes on the file system inside\n    of an `upload/` directory. Let's create that directory next to `src/` in our\n    project now:\n\n    ```sh\n    mkdir upload\n    ```\n\n    Our project tree now looks like:\n\n    ```sh\n    .\n    ├── Cargo.toml\n    ├── src\n    │   └── main.rs\n    └── upload\n    ```\n\n  * **What should we name the uploaded paste files?**\n\n    Similarly, we'll keep things simple by naming paste files a string of random\n    but readable characters. We'll call this random string the paste's \"ID\". To\n    represent, generate, and store the ID, we'll create a `PasteId` structure in\n    a new module file named `paste_id.rs` with the following contents:\n\n    ```rust\n    use std::borrow::Cow;\n    use std::path::{Path, PathBuf};\n\n    use rand::{self, Rng};\n\n    /// A _probably_ unique paste ID.\n    pub struct PasteId<'a>(Cow<'a, str>);\n\n    impl PasteId<'_> {\n        /// Generate a _probably_ unique ID with `size` characters. For readability,\n        /// the characters used are from the sets [0-9], [A-Z], [a-z]. The\n        /// probability of a collision depends on the value of `size` and the number\n        /// of IDs generated thus far.\n        pub fn new(size: usize) -> PasteId<'static> {\n            const BASE62: &[u8] = b\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n            let mut id = String::with_capacity(size);\n            let mut rng = rand::rng();\n            for _ in 0..size {\n                id.push(BASE62[rng.random_range(0..62)] as char);\n            }\n\n            PasteId(Cow::Owned(id))\n        }\n\n        /// Returns the path to the paste in `upload/` corresponding to this ID.\n        pub fn file_path(&self) -> PathBuf {\n            let root = concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/\", \"upload\");\n            Path::new(root).join(self.0.as_ref())\n        }\n    }\n    ```\n\n    We've given you the ID and path generation code for free. Our project tree\n    now looks like:\n\n    ```sh\n    .\n    ├── Cargo.toml\n    ├── src\n    │   ├── main.rs\n    │   └── paste_id.rs # new! contains `PasteId`\n    └── upload\n    ```\n\n    We'll import the new module and struct in `src/main.rs`, after the `extern\n    crate rocket`:\n\n    ```rust\n    # /*\n    mod paste_id;\n    # */ mod paste_id { pub struct PasteId; }\n\n    use paste_id::PasteId;\n    ```\n\n    You'll notice that our code to generate paste IDs uses the `rand` crate, so\n    we'll need to add it as a dependency in our `Cargo.toml` file:\n\n    ```toml\n    [dependencies]\n    ## existing Rocket dependencies...\n    rand = \"0.9\"\n    ```\n\n    Ensure that your application builds with the new code:\n\n    ```sh\n    cargo build\n    ```\n\n    You'll likely see many \"unused\" warnings for the new code we've added: that's\n    okay and expected. We'll be using the new code soon.\n\nWith these design decisions made, we're ready to continue writing our\napplication.\n\n## Retrieving Pastes\n\nWe'll proceed with a `retrieve` route which, given an `<id>`, will return the\ncorresponding paste if it exists or otherwise **404**. As we now know, that\nmeans we'll be reading the contents of the file corresponding to `<id>` in the\n`upload/` directory and return them to the user.\n\nHere's a first take at implementing the `retrieve` route. The route below takes\nin an `<id>` as a dynamic path element. The handler uses the `id` to construct a\npath to the paste inside `upload/`, and then attempts to open the file at that\npath, optionally returning the `File` if it exists. Rocket treats a `None`\n[Responder](@api/master/rocket/response/trait.Responder.html#provided-implementations)\nas a **404** error, which is exactly what we want to return when the requested\npaste doesn't exist.\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse std::path::Path;\nuse rocket::tokio::fs::File;\n\n#[get(\"/<id>\")]\nasync fn retrieve(id: &str) -> Option<File> {\n    let upload_dir = concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/\", \"upload\");\n    let filename = Path::new(upload_dir).join(id);\n    File::open(&filename).await.ok()\n}\n```\n\nMake sure that the route is mounted at the root path:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# #[get(\"/\")] fn index() {}\n# #[get(\"/<id>\")] fn retrieve(id: String) {}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/\", routes![index, retrieve])\n}\n```\n\nGive it a try! Create some fake pastes in the `upload/` directory, run the\napplication, and try to retrieve them by visiting the corresponding URL.\n\n### A Problem\n\nUnfortunately, there's a problem with this code. Can you spot the issue? The\n`&str` type in `retrieve` should tip you off! We've crafted a wonderful type to\nrepresent paste IDs but have ignored it!\n\nThe issue is that the _user_ controls the value of `id`, and as a result, can\ncoerce the service into opening files inside `upload/` that aren't meant to be\nopened. For instance, imagine that you later decide that a special file\n`upload/_credentials.txt` will store some important, private information. If the\nuser issues a `GET` request to `/_credentials.txt`, the server will read and\nreturn the `upload/_credentials.txt` file, leaking the sensitive information.\nThis is a big problem; it's known as the [full path disclosure\nattack](https://owasp.org/www-community/attacks/Full_Path_Disclosure), and\nRocket provides the tools to prevent this and other kinds of attacks from\nhappening.\n\n### The Solution\n\nTo prevent the attack, we need to _validate_ `id` before we use it. We do so by\nusing a type more specific than `&str` to represent IDs and then asking Rocket\nto validate the untrusted `id` input as that type. If validation fails, Rocket\nwill take care to not call our routes with bad input.\n\nTyped validation for dynamic parameters like `id` is implemented via the\n[`FromParam`] trait. Rocket uses `FromParam` to automatically validate and parse\ndynamic path parameters like `id`. We already have a type that represents valid\npaste IDs, `PasteId`, so we'll simply need to implement `FromParam` for\n`PasteId`.\n\nHere's the `FromParam` implementation for `PasteId` in `src/paste_id.rs`:\n\n[`FromParam`]: @api/master/rocket/request/trait.FromParam.html\n\n```rust\nuse rocket::request::FromParam;\n# use std::borrow::Cow;\n# pub struct PasteId<'a>(Cow<'a, str>);\n\n/// Returns an instance of `PasteId` if the path segment is a valid ID.\n/// Otherwise returns the invalid ID as the `Err` value.\nimpl<'a> FromParam<'a> for PasteId<'a> {\n    type Error = &'a str;\n\n    fn from_param(param: &'a str) -> Result<Self, Self::Error> {\n        param.chars().all(|c| c.is_ascii_alphanumeric())\n            .then(|| PasteId(param.into()))\n            .ok_or(param)\n    }\n}\n```\n\n! note: This implementation, while secure, could be improved.\n\n  Our `from_param` function is simplistic and could be improved by, for example,\n  checking that the length of the `id` is within some known bound, introducing\n  stricter character checks, checking for the existing of a paste file, and/or\n  potentially blacklisting sensitive files as needed.\n\nGiven this implementation, we can change the type of `id` in `retrieve` to\n`PasteId`. Rocket will then ensure that `<id>` represents a valid `PasteId`\nbefore calling the `retrieve` route, preventing the previous attack entirely:\n\n```rust\n# #[macro_use] extern crate rocket;\n\nuse rocket::tokio::fs::File;\n# use std::borrow::Cow;\n# use std::path::PathBuf;\n# use rocket::request::FromParam;\n# pub struct PasteId<'a>(Cow<'a, str>);\n# impl PasteId<'_> {\n#     pub fn new(size: usize) -> PasteId<'static> { todo!() }\n#     pub fn file_path(&self) -> PathBuf { todo!() }\n# }\n# impl<'a> FromParam<'a> for PasteId<'a> {\n#     type Error = &'a str;\n#     fn from_param(param: &'a str) -> Result<Self, Self::Error> { todo!() }\n# }\n\n#[get(\"/<id>\")]\nasync fn retrieve(id: PasteId<'_>) -> Option<File> {\n    File::open(id.file_path()).await.ok()\n}\n```\n\nNotice how much nicer this implementation is! And this time, it's secure.\n\nThe wonderful thing about using `FromParam` and other Rocket traits is that they\ncentralize policies. For instance, here, we've centralized the policy for valid\n`PasteId`s in dynamic parameters. At any point in the future, if other routes\nare added that require a `PasteId`, no further work has to be done: simply use\nthe type in the signature and Rocket takes care of the rest.\n\n\n## Uploading\n\nNow that we can retrieve pastes safely, it's time to actually store them. We'll\nwrite an `upload` route that, according to our design, takes a paste's contents\nand writes them to a file with a randomly generated ID inside of the `upload/`\ndirectory. It'll return a URL to the client for the paste corresponding to the\n`retrieve` route we just wrote.\n\n### Streaming Data\n\nTo stream the incoming paste data to a file, we'll make use of [`Data`], a [data\nguard] that represents an unopened stream to the incoming request body data.\nBefore we show you the code, you should attempt to write the route yourself.\nHere's a hint: one possible route and handler signature look like this:\n\n```rust\n# #[macro_use] extern crate rocket;\nuse rocket::Data;\n\n#[post(\"/\", data = \"<paste>\")]\nasync fn upload(paste: Data<'_>) -> std::io::Result<String> {\n    /* .. */\n    # Ok(\"\".into())\n}\n```\n\n[`Data`]: @api/master/rocket/data/struct.Data.html\n[data guard]: ../requests/#body-data\n\nYour code should:\n\n  1. Create a new `PasteId` of a length of your choosing.\n  2. Construct a path to the `PasteId` inside of `upload/`.\n  3. Stream the `Data` to the file at the constructed path.\n  4. Construct a URL for the `PasteId`.\n  5. Return the URL to the client.\n\n### Solution\n\nHere's our version:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n// We derive `UriDisplayPath` for `PasteId` in `paste_id.rs`:\n# use std::borrow::Cow;\n# use std::path::{Path, PathBuf};\n# use rocket::request::FromParam;\n\n#[derive(UriDisplayPath)]\npub struct PasteId<'a>(Cow<'a, str>);\n\n# impl PasteId<'_> {\n#     pub fn new(size: usize) -> PasteId<'static> { todo!() }\n#     pub fn file_path(&self) -> PathBuf { todo!() }\n# }\n#\n# impl<'a> FromParam<'a> for PasteId<'a> {\n#     type Error = &'a str;\n#     fn from_param(param: &'a str) -> Result<Self, Self::Error> { todo!() }\n# }\n// We implement the `upload` route in `main.rs`:\n\nuse rocket::data::{Data, ToByteUnit};\nuse rocket::http::uri::Absolute;\n# use rocket::tokio::fs::File;\n\n// In a real application, these would be retrieved dynamically from a config.\nconst ID_LENGTH: usize = 3;\nconst HOST: Absolute<'static> = uri!(\"http://localhost:8000\");\n# #[get(\"/\")] fn index() -> &'static str { \"\" }\n# #[get(\"/<id>\")] fn retrieve(id: PasteId<'_>) -> Option<File> { todo!() }\n\n#[post(\"/\", data = \"<paste>\")]\nasync fn upload(paste: Data<'_>) -> std::io::Result<String> {\n    let id = PasteId::new(ID_LENGTH);\n    paste.open(128.kibibytes()).into_file(id.file_path()).await?;\n    Ok(uri!(HOST, retrieve(id)).to_string())\n}\n```\n\nWe note the following Rocket APIs being used in our implementation:\n\n  * The [`kibibytes()`] method, which comes from the [`ToByteUnit`] trait.\n  * [`Data::open()`] to open [`Data`] as a [`DataStream`].\n  * [`DataStream::into_file()`] for writing the data stream into a file.\n  * The [`UriDisplayPath`] derive, allowing `PasteId` to be used in [`uri!`].\n  * The [`uri!`] macro to create type-safe, URL-safe URIs.\n\n[`Data::open()`]: @api/master/rocket/data/struct.Data.html#method.open\n[`Data`]: @api/master/rocket/data/struct.Data.html\n[`DataStream`]: @api/master/rocket/data/enum.DataStream.html\n[`DataStream::into_file()`]: @api/master/rocket/data/enum.DataStream.html#method.into_file\n[`uri!`]: @api/master/rocket/macro.uri.html\n[`kibibytes()`]: @api/master/rocket/data/trait.ToByteUnit.html#method.kibibytes\n[`ToByteUnit`]: @api/master/rocket/data/trait.ToByteUnit.html\n[`UriDisplayPath`]: @api/master/rocket/derive.UriDisplayPath.html\n\nEnsure that the route is mounted at the root path:\n\n```rust\n# #[macro_use] extern crate rocket;\n\n# #[get(\"/\")] fn index() {}\n# #[get(\"/<id>\")] fn retrieve(id: &str) {}\n# #[post(\"/\")] fn upload() {}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/\", routes![index, retrieve, upload])\n}\n```\n\nTest that your route works via `cargo run`. From a separate terminal, upload a\nfile using `curl` then retrieve the paste using the returned URL.\n\n```sh\n## in the project root\ncargo run\n\n## in a separate terminal\necho \"Hello, Rocket!\" | curl --data-binary @- http://localhost:8000\n## => http://localhost:8000/eGs\n\n## confirm we can retrieve the paste (replace with URL from above)\ncurl http://localhost:8000/eGs\n\n## we can check the contents of `upload/` as well\n<ctrl-c>     # kill running process\nls upload    # ensure the upload is there\ncat upload/* # ensure that contents are correct\n```\n\n## Conclusion\n\nThat's it! Ensure that all of your routes are mounted and test your application.\nYou've now written a simple (~75 line!) pastebin in Rocket! There are many\npotential improvements to this small application, and we encourage you to work\nthrough some of them to get a better feel for Rocket. Here are some ideas:\n\n  * Add a web form to the `index` where users can manually input new pastes.\n    Accept the form at `POST /`. Use `format` and/or `rank` to specify which of\n    the two `POST /` routes should be called.\n  * Support **deletion** of pastes by adding a new `DELETE /<id>` route. Use\n    `PasteId` to validate `<id>`.\n  * Indicate **partial uploads** with a **206** partial status code. If the user\n    uploads a paste that meets or exceeds the allowed limit, return a **206**\n    partial status code. Otherwise, return a **201** created status code.\n  * Set the `Content-Type` of the return value in `upload` and `retrieve` to\n    `text/plain`.\n  * **Return a unique \"key\"** after each upload and require that the key is\n    present and matches when doing deletion. Use one of Rocket's core traits to\n    do the key validation.\n  * Add a `PUT /<id>` route that allows a user with the key for `<id>` to\n    replace the existing paste, if any.\n  * Add a new route, `GET /<id>/<lang>` that syntax highlights the paste with ID\n    `<id>` for language `<lang>`. If `<lang>` is not a known language, do no\n    highlighting. Possibly validate `<lang>` with `FromParam`.\n  * Use the [`local` module](@api/master/rocket/local/) to write unit tests for your\n    pastebin.\n  * Dispatch a thread before `launch`ing Rocket in `main` that periodically\n    cleans up idling old pastes in `upload/`.\n\nYou can find the full source code for the [completed pastebin tutorial on\nGitHub](@git/master/examples/pastebin).\n"
  },
  {
    "path": "docs/guide/13-conclusion.md",
    "content": "+++\nsummary = \"next steps, and learning more about Rocket\"\n+++\n\n# Conclusion\n\nWe hope you agree that Rocket is a refreshing take on web frameworks. As with\nany software project, Rocket is _alive_. There are always things to improve, and\nwe're happy to take the best ideas. If you have something in mind, please\n[submit an issue](https://github.com/rwf2/Rocket/issues).\n\n## Getting Help\n\nIf you find yourself having trouble developing Rocket applications, you can get\nhelp via chat at [`#rocket:mozilla.org`] on Matrix. The [FAQ](../faq/) also\nprovides answers to commonly asked questions.\n\n[`#rocket:mozilla.org`]: @chat\n\n## What's next?\n\nThe best way to learn Rocket is to _build something_. It should be fun and easy,\nand there's always someone to help. Alternatively, you can read through the\n[Rocket examples](@git/master/examples) or the [Rocket source code](@git/master/core/lib/src).\nWhatever you decide to do next, we hope you have a blast!\n"
  },
  {
    "path": "docs/guide/14-faq.md",
    "content": "+++\nsummary = \"answers to frequently asked questions about Rocket and its usage\"\n+++\n\n{% macro faq(id) %}\n<details id=\"{{ id }}\">\n<summary>\n<a class=\"anchor\" href=\"#{{ id }}\" title=\"anchor\">#</a>\n{% endmacro %}\n\n{% macro answer() %}\n</summary>\n<div class=\"content\">\n{% endmacro %}\n\n{% macro endfaq() %}\n</div>\n</details>\n{% endmacro %}\n\n# FAQ\n\nBelow you'll find a collection of commonly asked questions and answers. If you\nhave suggestions for questions you'd like to see answered here, [comment on the\ndiscussion thread].\n\n[comment on the discussion thread]: https://github.com/rwf2/Rocket/discussions/1836\n\n## About Rocket\n\n{{ faq(\"monolithic\") }}\nIs Rocket a monolithic framework like Rails? Or is it more like Flask?\n{{ answer() }}\n\nNeither!\n\nRocket's core is small yet complete with respect to security and correctness. It\nmainly consists of:\n\n  * Guard traits like [`FromRequest`] and [`FromData`].\n  * Derive macros for all common traits.\n  * Attribute macros for routing.\n  * Thorough compile and launch-time checking.\n  * Zero-copy parsers and validators for common formats like multipart and SSE.\n  * Syntax sugar extensions for features like async streams and traits.\n  * Optional features for functionality like TLS, secrets, and so on.\n\nThe goal is for functionality like templating, sessions, ORMs, and so on to be\nimplemented entirely outside of Rocket while maintaining a first-class feel and\nexperience. Indeed, crates like [`rocket_dyn_templates`] and [`rocket_db_pools`]\ndo just this. As a result, Rocket is neither \"bare-bones\" nor is it a kitchen\nsink for all possible features.\n\nUnlike other frameworks, Rocket makes it its mission to help you avoid security\nand correctness blunders. It does this by including, out-of-the-box:\n\n  * A flexible, type-based [configuration](../configuration/) system.\n  * [Security and privacy headers](@api/master/rocket/shield/) by default.\n  * Zero-Copy RFC compliant [URI parsers](@api/master/rocket/http/uri).\n  * Safe, [typed URIs](@api/master/rocket/macro.uri.html) with compile-time checking.\n  * [Compile-time and launch-time route checking](@api/master/rocket/attr.route.html).\n  * A [testing framework](@api/master/rocket/local) with sync and `async` variants.\n  * Safe, exclusive access to fully decoded HTTP values.\n  * Mandatory [data limits](@api/master/rocket/data/struct.Limits.html) to prevent\n    trivial DoS attacks.\n\nOf course, this functionality comes at a compile-time cost (but notably, _not_\na runtime cost), impacting Rocket's clean build-time. For comparison, here's\nwhat a clean build of \"Hello, world!\" looks like for some Rust web frameworks:\n\n| Framework       | Dependencies | Build Time | Build w/ `sscache` |\n|-----------------|--------------|------------|--------------------|\n| Rocket 0.5      | 105          | 12s        | 5s                 |\n| Actix-Web 4.4.0 | 119          | 11s        | 4s                 |\n| Axum 0.6.20     | 78           | 10s        | 4s                 |\n\n<small>· Measurements taken on Apple Mac14,6 M2 Max, macOS 13, Rust 1.75. Best of 3.</small><br />\n<small>· Rocket includes features like graceful shutdown, HTTP/2 keepalive, SSE\nsupport, and static file serving that require additional deps in other frameworks.</small>\n\nOf course, iterative build-time is nearly identical for all frameworks, and the\ntime can be further reduced by using faster linkers like `lld`. We think the\ntrade-off is worth it. Rocket will never compromise security, correctness, or\nusability to \"win\" at benchmarks of any sort.\n\n[`rocket_dyn_templates`]: @api/master/rocket_dyn_templates/\n[`rocket_db_pools`]: @api/master/rocket_db_pools/\n{{ endfaq() }}\n\n\n{{ faq(\"compact\") }}\nI want a small and compact web framework. Is Rocket it?\n{{ answer() }}\nWe think so! See [\"Is Rocket a monolithic framework like Rails?\"](#monolithic)\n{{ endfaq() }}\n\n{{ faq(\"complete\") }}\nI want a web framework with all the bells and whistles. Is Rocket it?\n{{ answer() }}\nWe think so! See [\"Is Rocket a monolithic framework like Rails?\"](#monolithic)\n{{ endfaq() }}\n\n{{ faq(\"in-prod\") }}\nCan I use Rocket in production? Should I? It's only v0.x!\n{{ answer() }}\n\nWe **enthusiastically** recommend using Rocket in production, with the following\nnon-exhaustive list of caveats:\n\n  1. Run Rocket behind a reverse proxy like HAProxy or in a production load\n     balancing environment. Rocket (Hyper) doesn't employ any defenses against\n     DDoS attacks or certain DoS attacks which can be mitigated by an external\n     service.\n\n  2. Use a TLS termination proxy (perhaps from 1.) for zero-downtime certificate\n     rotation.\n\n  3. Properly configure your databases and database pools, especially with\n     respect to the pool size.\n\n  4. Ensure no blocking I/O happens outside of `spawn_blocking()` invocations.\n\nWhile Rocket _is_ still in the `0.x` phase, the version number is purely a\nstylistic choice. In fact, we consider Rocket to be the most mature web\nframework in the Rust ecosystem. To our knowledge, Rocket is the only Rust web\nframework that correctly implements:\n\n  * Server-Sent Events\n  * Graceful Shutdown\n  * Form Parsing with Arbitrarily Structure\n  * Zero-Copy, RFC Conforming URI Types\n  * Ambiguity-Free Routing\n  * Streamed Multipart Uploads\n\nIf you're coming from a different ecosystem, you should feel comfortable\nconsidering Rocket's `v0.x` as someone else's `vx.0`. Rust and Cargo's semver\npolicy, and Rocket's strict adherence to it, ensures that Rocket will _never_\nbreak your application when upgrading from `0.x.y` to `0.x.z`, where `z >= y`.\nFurthermore, we backport _all_ security and correctness patches to the previous\nmajor release (`0.{x-1}.y`), so your application remains secure if you need time\nto upgrade.\n\n{{ endfaq() }}\n\n{{ faq(\"performance\") }}\nIs Rocket slow? Is Rocket fast?\n{{ answer() }}\n\nRocket is pretty fast.\n\nA commonly repeated myth is that Rocket's great usability comes at the cost of\nruntime performance. _**This is false.**_ Rocket's usability derives largely\nfrom compile-time checks with _zero_ bearing on runtime performance.\n\nSo what about benchmarks? Well, benchmarking is _hard_, and besides often being\nconducted incorrectly<em>*</em>, often appear to say more than they do. So, when\nyou see a benchmark for \"Hello, world!\", you should know that the benchmark's\nrelevance doesn't extend far beyond those specific \"Hello, world!\" servers and\nthe specific way the measurement was taken. In other words, it provides _some_\nbaseline that is hard to extrapolate to real-world use-cases, _your_ use-case.\n\nNevertheless, here are some things you can consider as _generally_ true about\nRocket applications:\n\n  * They'll perform much, _much_ better than those written in scripting\n    languages like Python or Ruby.\n  * They'll perform much better than those written in VM or JIT languages like\n    JavaScript or Java.\n  * They'll perform a bit better than those written in compiled-to-native but\n    GC'd languages like Go.\n  * They'll perform competitively with those written in compiled-to-native,\n    non-GC'd languages like Rust or C.\n\nAgain, we emphasize _generally_ true. It is trivial to write a Rocket\napplication that is slower than a similar Python application.\n\nBesides a framework's _internal_ performance, you should also consider whether\nit enables your _application itself_ to perform well. Rocket takes great care to\nenable your application to perform as little work as possible through\nunique-to-Rocket features like [managed state], [request-local state], and\nzero-copy parsing and deserialization.\n\n<small>* A common mistake is to pit against Rocket's \"Hello, world!\" without\nnormalizing for response size, especially security headers.</small>\n\n[managed state]: ../state/#managed-state\n[request-local state]: ../state/#request-local-state\n{{ endfaq() }}\n\n{{ faq(\"showcase\") }}\nWhat are some examples of \"big\" apps written in Rocket?\n{{ answer() }}\n\nHere are some notable projects and websites in Rocket we're aware of:\n\n  * [Vaultwarden] - A BitWarden Server\n  * [Rust-Lang.org] - Rust Language Website\n  * [Plume] - Federated Blogging Engine\n  * [Hagrid] - OpenPGP KeyServer ([keys.openpgp.org](https://keys.openpgp.org/))\n  * [SourceGraph Syntax Highlighter] - Syntax Highlighting API\n  * [Revolt] - Open source user-first chat platform\n\n[Let us know] if you have a notable, public facing application written in Rocket\nyou'd like to see here!\n\n[Vaultwarden]: https://github.com/dani-garcia/vaultwarden\n[Conduit]: https://conduit.rs/\n[Rust-Lang.org]: https://www.rust-lang.org/\n[Plume]: https://github.com/Plume-org/Plume\n[Hagrid]: https://gitlab.com/keys.openpgp.org/hagrid\n[SourceGraph Syntax Highlighter]: https://github.com/sourcegraph/sourcegraph/tree/main/docker-images/syntax-highlighter\n[Let us know]: https://github.com/rwf2/Rocket/discussions/categories/show-and-tell\n[Revolt]: https://github.com/revoltchat/backend\n{{ endfaq() }}\n\n\n{{ faq(\"releases\") }}\nWhen will version `$y` be released? Why does it take so long?\n{{ answer() }}\n\nRocket represents an ecosystem-wide effort to create a web framework that\nenables writing web applications with unparalleled security, performance, and\nusability. From design to implementation to documentation, Rocket is carefully\ncrafted to ensure the greatest productivity and reliability with the fewest\nsurprises. Our goal is to make Rocket a compelling choice across _all_\nlanguages.\n\nAccomplishing this takes time, and our efforts extend to the entire ecosystem.\nFor example, work for Rocket v0.5 included:\n\n  * [Fixing correctness issues in `x509-parser`.](https://github.com/rusticata/x509-parser/pull/90)\n  * [Reporting multiple](https://github.com/bikeshedder/deadpool/issues/114)\n    [correctness issues](https://github.com/bikeshedder/deadpool/issues/113) in `deadpool`.\n  * [Fixing a major usability issue in `async-stream`.](https://github.com/tokio-rs/async-stream/pull/57)\n  * [Creating a brand new configuration library.](https://github.com/SergioBenitez/Figment)\n  * [Updating](https://github.com/rousan/multer-rs/pull/21),\n    [fixing](https://github.com/rousan/multer-rs/pull/29), and\n    [maintaining](https://github.com/rousan/multer-rs/commit/2758e778e6aa2785b737c82fe45e58026bea2f01) `multer`.\n  * [Significantly improving `async_trait` correctness and usability.](https://github.com/dtolnay/async-trait/pull/143)\n  * [Porting `Pattern` APIs to stable.](https://github.com/SergioBenitez/stable-pattern)\n  * [Porting macro diagnostics to stable.](https://github.com/SergioBenitez/proc-macro2-diagnostics)\n  * [Creating a brand new byte unit library.](https://github.com/SergioBenitez/ubyte)\n  * [Fixing a bug in `rustc`'s `libtest`.](https://github.com/rust-lang/rust/pull/78227)\n\nA version of Rocket is released whenever it is feature-complete and exceeds\nfeature, security, and usability parity with the previous version. As a result,\nspecifying a release date is nearly impossible. We are _always_ willing to delay\na release if these properties are not readily evident.\n\nWe know it can be frustrating, but we hope you'll agree that Rocket is worth the\nwait.\n{{ endfaq() }}\n\n## How To\n\n{{ faq(\"web-sockets\") }}\nCan I, and if so how, do I use WebSockets?\n{{ answer() }}\n\nYou can! WebSocket support is provided by the officially maintained\n[`rocket_ws`](@api/master/rocket_ws/) crate. You'll find all the docs you need\nthere.\n\nRocket _also_ supports [Server-Sent Events], which allows for real-time\n_unidirectional_ communication from the server to the client. The protocol is a\nbit simpler, and you may find SSE sufficient for your use-case. For instance,\nthe [chat example] uses SSE to implement a real-time, multiroom chat\napplication.\n\n[Server-Sent Events]: @api/master/rocket/response/stream/struct.EventStream.html\n[chat example]: @git/master/examples/chat\n{{ endfaq() }}\n\n{{ faq(\"global-state\") }}\nShould I use global state via something like `lazy_static!`?\n{{ answer() }}\n\nNo. Rocket's [managed state] provides a better alternative.\n\nWhile it may be convenient or comfortable to use global state, the downsides are\nnumerous. They include:\n\n  * The inability to test your application with different state.\n  * The inability to run your application on different threads with different\n    state.\n  * The inability to know the state a route accesses by looking at its\n    signature.\n\n[managed state]: ../state/#managed-state\n{{ endfaq() }}\n\n{{ faq(\"file-uploads\") }}\nHow do I handle file uploads? What is this \"multipart\" in my stream?\n{{ answer() }}\n\nFor a quick example on how to handle file uploads, see [multipart forms]. The\ngist is: use `Form<TempFile>` as a data guard.\n\nFile uploads are encoded and transmitted by the browser as [multipart] forms.\nThe raw stream, as seen by [`Data`] for example, thus contains the necessary\nmetadata to encode the form. Rocket's [`Form`] data guard can parse these form\nsubmissions into any type that implements [`FromForm`]. This includes types like\n[`TempFile`] which streams the decoded data to disk for persistence.\n\n[multipart]: https://datatracker.ietf.org/doc/html/rfc7578\n[multipart forms]: ../requests/#multipart\n[`DataField`]: @api/master/rocket/form/struct.DataField.html\n[`TempFile`]: @api/master/rocket/fs/enum.TempFile.html\n[`DataField`]: @api/master/rocket/data/struct.Data.html\n[`Form`]: @api/master/rocket/form/struct.Form.html\n[`FromForm`]: @api/master/rocket/form/trait.FromForm.html\n[`Data`]: @api/master/rocket/struct.Data.html\n{{ endfaq() }}\n\n{{ faq(\"raw-request\") }}\nHow do I get an `&Request` in a handler?\n{{ answer() }}\n\nYou don't!\n\nRocket's [philosophy] is that as much of the request should be validated and\nconverted into useful typed values _before_ being processed. Allowing a\n`Request` to be handled directly is incompatible with this idea.\n\nInstead, Rocket's handlers work through _guards_, reified as traits, which\nvalidate and extract parts of a request as needed. Rocket automatically invokes\nthese guards for you, so custom guards are write-once-use-everywhere. Rocket\nwon't invoke a handler with failing guards. This way, handlers only deal with\nfully validated, typed, secure values.\n\nRocket provides all of the guard implementations you would expect\nout-of-the-box, and you can implement your own, too. See the following:\n\n  * Parameter Guards: [`FromParam`]\n  * Multi-Segment Guards: [`FromSegments`]\n  * Data Guards: [`FromData`]\n  * Form Guards: [`FromForm`]\n  * Request Guards: [`FromRequest`]\n\n[philosophy]: ../introduction/#foreword\n[`FromParam`]: @api/master/rocket/request/trait.FromParam.html\n[`FromSegments`]: @api/master/rocket/request/trait.FromSegments.html\n[`FromData`]: @api/master/rocket/data/trait.FromData.html\n[`FromForm`]: @api/master/rocket/form/trait.FromForm.html\n[`FromRequest`]: @api/master/rocket/request/trait.FromRequest.html\n{{ endfaq() }}\n\n{{ faq(\"response-headers\") }}\nHow do I add a header to a response?\n{{ answer() }}\n\nThat depends on the header!\n\nAny \"transport\" headers (`Content-Length`, `Transfer-Encoding`, etc.) are\nautomatically set by Rocket and cannot be directly overridden for correctness\nreasons. The rest are set by a route's [`Responder`].\n\n**Status**\n\nRocket automatically sets a `Status` header for all responses. If a `Responder`\ndoesn't explicitly set a status, it defaults to `200`. Some responders, like\n`Option<T>`, do set a status. See [`Responder`] and the [`status`] module for\ndetails on setting a custom `Status` or overriding an existing one.\n\n**Content-Type**\n\nRocket automatically sets a `Content-Type` header for types it implements\n`Responder` for, so in the common case, there's nothing to do. This includes\ntypes like `&str`, `&[u8]`, `NamedFile`, and so on. The [`content`] module docs\ndetails setting a custom `Content-Type` or overriding an existing one.\n\n**Everything Else**\n\nTo add a custom header, you'll need a custom [`Responder`]. Not to worry!\n[`Responder` can be derived](@api/master/rocket/derive.Responder.html) in almost all\ncases. If a type for the header you want to add already exists, you can directly\nderive `Responder` for a struct that contains the header value, which adds the\nheader to the response:\n\n```rust\n# #[macro_use] extern crate rocket;\n# use rocket::http::Header;\n\n# type HeaderType = Header<'static>;\n\n# impl<T> From<T> for MyResponder<T> {\n#     fn from(inner: T) -> Self {\n#         MyResponder { inner, header: Header::new(\"X-My-Header\", \"some value\") }\n#     }\n# }\n\n#[derive(Responder)]\nstruct MyResponder<T> {\n    inner: T,\n    header: HeaderType,\n}\n\n#[get(\"/\")]\nfn with_header() -> MyResponder<&'static str> {\n    MyResponder::from(\"Hello, world!\")\n}\n```\n\nA `HeaderType` won't exist for custom headers, but you can define your own type.\nAs long as it implements `Into<Header>` for Rocket's [`Header`], the type can be\nused as a field in derived struct.\n\nAlternatively, you can always implement `Responder` directly. Make sure to\nleverage existing responders in your implementation. For example, _don't_\nserialize JSON manually. Instead, use the existing [`Json`] responder, like in\nthe example below:\n\n```rust\n# #[derive(rocket::serde::Serialize)]\n# #[serde(crate = \"rocket::serde\")]\n# struct Person { name: String, age: usize };\n\nuse rocket::request::Request;\nuse rocket::response::{self, Response, Responder};\nuse rocket::serde::json::Json;\n\nimpl<'r> Responder<'r, 'static> for Person {\n    fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {\n        Response::build_from(Json(&self).respond_to(req)?)\n            .raw_header(\"X-Person-Name\", self.name)\n            .raw_header(\"X-Person-Age\", self.age.to_string())\n            .ok()\n    }\n}\n```\n\n[`Responder`]: @api/master/rocket/response/trait.Responder.html\n[`content`]: @api/master/rocket/response/content/index.html\n[`status`]: @api/master/rocket/response/status/index.html\n[`Header`]: @api/master/rocket/http/struct.Header.html\n[`Json`]: @api/master/rocket/serde/json/struct.Json.html\n{{ endfaq() }}\n\n{{ faq(\"multiple-responses\") }}\nHow do I make one handler return different responses or status codes?\n{{ answer() }}\n\nIf you're returning _two_ different responses, use a `Result<T, E>` or an\n[`Either<A, B>`].\n\nIf you need to return _more_ than two kinds, [derive a custom `Responder`] `enum`:\n\n```rust\n# use rocket::response::Responder;\nuse rocket::fs::NamedFile;\nuse rocket::http::ContentType;\n\n#[derive(Responder)]\nenum Error<'r, T> {\n    #[response(status = 400)]\n    Unauthorized(T),\n    #[response(status = 404)]\n    NotFound(NamedFile),\n    #[response(status = 500)]\n    A(&'r str, ContentType),\n}\n```\n\n[`Either<A, B>`]: https://docs.rs/either/1/either/enum.Either.html\n[derive a custom `Responder`]: @api/master/rocket/derive.Responder.html\n{{ endfaq() }}\n\n{{ faq(\"automatic-reload\") }}\nHow do I make Rocket reload automatically when I change source code?\n{{ answer() }}\n\nIn debug mode, Rocket automatically reloads templates for you. So if all you\nneed is live template reloading, Rocket's got you covered.\n\nFor everything else, you'll need to use an external tool like [`cargo-watch`],\n[`watchexec`] or [`entr`]. With `cargo-watch`, you can automatically rebuild and\nrun a Rocket application by executing:\n\n```sh\ncargo watch -x run\n```\n\nTo only restart on successful compilations, see [this note].\n\n[`cargo-watch`]: https://github.com/watchexec/cargo-watch\n[`watchexec`]: https://github.com/watchexec/watchexec\n[`entr`]: http://eradman.com/entrproject/\n[this note]: https://github.com/watchexec/cargo-watch/tree/b75ce2c260874dea480f4accfd46ab28709ec56a#restarting-an-application-only-if-the-buildcheck-succeeds\n{{ endfaq() }}\n\n{{ faq(\"external-managed-state\") }}\nHow do I access managed state outside of a Rocket-related context?\n{{ answer() }}\n\nUse an `Arc`, like this:\n\n```rust\n# use rocket::*;\nuse std::sync::Arc;\n\n#[launch]\nfn rocket() -> _ {\n    # struct MyState;\n    let state = Arc::new(MyState);\n\n    let external = state.clone();\n    std::thread::spawn(move || {\n        let use_state = external;\n    });\n\n    rocket::build().manage(state)\n}\n```\n\n{{ endfaq() }}\n\n{{ faq(\"internal-server\") }}\nHow do I make Rocket a _part_ of my application as opposed to the whole thing?\n{{ answer() }}\n\nUse the `#[main]` attribute and manually call [`launch()`]:\n\n```rust,no_run\n#[rocket::main]\nasync fn main() {\n    # let should_start_server = false;\n    if should_start_server {\n        let result = rocket::build().launch().await;\n    } else {\n        // do something else\n    }\n}\n```\n\nThe cost to using the attribute is imperceptible and guarantees compatibility\nwith Rocket's async I/O.\n\n[`launch()`]: @api/master/rocket/struct.Rocket.html#method.launch\n{{ endfaq() }}\n\n## Debugging\n\n{{ faq(\"broken-example\") }}\nIs example `foo` broken? It doesn't work for me.\n{{ answer() }}\n\nAlmost certainly not.\n\nEvery example and code snippet you see in published documentation is tested by\nthe CI on every commit, and we only publish docs that pass the CI. Unless the CI\nenvironment is broken, the examples _cannot_ be wrong.\n\nCommon mistakes when running examples include:\n\n  * Looking at an example for version `y` but depending on version `x`. Select\n    the proper git tag!\n  * Looking at outdated examples on StackOverflow or Google. Check the\n    date/version!\n  * Not configuring the correct dependencies. See the example's `Cargo.toml`!\n{{ endfaq() }}\n\n{{ faq(\"unsat-bound\") }}\nThe trait bound `rocket::Responder` (`FromRequest`, etc.) is not satisfied.\n{{ answer() }}\n\nIf you're fairly certain a type implements a given Rocket trait but still get an\nerror like:\n\n```rust,ignore\nerror[E0277]: the trait bound `Foo: Responder<'_, '_>` is not satisfied\n--> src\\main.rs:4:20\n|\n4 | fn foo() -> Foo\n|             ^^^ the trait `Responder<'_, '_>` is not implemented for `Foo`\n|\n= note: required by `respond_to`\n```\n\n...then you're almost certainly depending, perhaps transitively, on _two\ndifferent versions_ of a single library. For example, you may be depending on\n`rocket` which depends on `time 0.3` while also depending directly on `time\n0.2`. Or you may depending on `rocket` from `crates.io` while depending on a\nlibrary that depends on `rocket` from `git`. A common instance of this mistake\nis to depend on a `contrib` library from git while also depending on a\n`crates.io` version of Rocket or vice-versa:\n\n```toml\nrocket = \"0.6.0-dev\"\nrocket_db_pools = { git = \"https://github.com/rwf2/Rocket.git\" }\n```\n\nThis is _never_ correct. If libraries or applications interact via types from a\ncommon library, those libraries or applications _must_ specify the _same_\nversion of that common library. This is because in Rust, types from two\ndifferent versions of a library or from different providers (like `git` vs.\n`crates.io`) are _always_ considered distinct, even if they have the same name.\nTherefore, even if a type implements a trait from one library, it _does not_\nimplement the trait from the other library (since it is considered to be a\n_different_, _distinct_ library). In other words, you can _never_ mix two\ndifferent published versions of Rocket, a published version and a `git` version,\nor two instances from different `git` revisions.\n{{ endfaq() }}\n"
  },
  {
    "path": "docs/guide/index.md",
    "content": "# The Rocket Programming Guide\n\nWelcome to Rocket!\n\nThis is the official guide for Rocket v0.6. It is designed to serve as a\nstarting point to writing web applications with Rocket and Rust. The guide is\nalso designed to be a reference for experienced Rocket developers. This guide is\nconversational in tone. For purely technical documentation with examples, see\nthe [API documentation](@api/master/rocket).\n\nThe guide is split into several sections, each with a focus on a different\naspect of Rocket. The sections are:\n\n================================================================================\n\n## Getting Help\n\nThe official community support channels are via Matrix chat on\n[`#rocket:mozilla.org`] and via [GitHub Discussions]. To join us on Matrix, we\nrecommend the browser-based [Element] client. The [FAQ](faq/) also provides\nanswers to commonly asked questions.\n\n[`#rocket:mozilla.org`]: @chat\n[GitHub Discussions]: https://github.com/rwf2/Rocket/discussions\n[Element]: https://chat.mozilla.org/#/room/#rocket:mozilla.org\n"
  },
  {
    "path": "docs/tests/Cargo.toml",
    "content": "[package]\nname = \"rocket_docs_tests\"\nversion = \"0.6.0-dev\"\nworkspace = \"../../\"\nedition = \"2021\"\npublish = false\n\n[lints]\nworkspace = true\n\n[dependencies]\nrocket = { path = \"../../core/lib\", features = [\"secrets\"] }\n\n[dev-dependencies]\nrocket = { path = \"../../core/lib\", features = [\"secrets\", \"json\", \"mtls\"] }\nfigment = { version = \"0.10.17\", features = [\"toml\", \"env\"] }\ntokio = { version = \"1\", features = [\"macros\", \"io-std\"] }\nrand = \"0.9\"\n\n[dev-dependencies.rocket_dyn_templates]\npath = \"../../contrib/dyn_templates\"\nfeatures = [\"tera\"]\n\n[dev-dependencies.rocket_db_pools]\npath = \"../../contrib/db_pools/lib\"\nfeatures = [\"sqlx_sqlite\"]\n\n[dev-dependencies.rocket_ws]\npath = \"../../contrib/ws\"\n"
  },
  {
    "path": "docs/tests/src/guide.rs",
    "content": "rocket::internal_guide_tests!(\"../guide/*.md\");\n"
  },
  {
    "path": "docs/tests/src/lib.rs",
    "content": "#[cfg(any(test, doctest))] mod guide;\n#[cfg(any(test, doctest))] mod readme;\n\n#[macro_export]\nmacro_rules! map {\n    ($($key:expr => $value:expr),* $(,)?) => ({\n        let mut map = std::collections::HashMap::new();\n        $(map.insert($key.into(), $value.into());)*\n        map\n    });\n}\n\n#[macro_export]\nmacro_rules! bmap {\n    ($($key:expr => $value:expr),* $(,)?) => ({\n        let mut map = std::collections::BTreeMap::new();\n        $(map.insert($key.into(), $value.into());)*\n        map\n    });\n}\n\n#[macro_export]\nmacro_rules! assert_form_parses {\n    ($T:ty, $form:expr => $value:expr) => (\n        match rocket::form::Form::<$T>::parse($form) {\n            Ok(v) => assert_eq!(v, $value, \"{}\", $form),\n            Err(e) => {\n                eprintln!(\"form failed to parse\\n> form: {:?}\\n> error: {:?}\", $form, e);\n                panic!(\"form parse error\");\n            }\n        }\n    );\n\n    ($T:ty, $($form:expr => $value:expr),+ $(,)?) => (\n        $(assert_form_parses!($T, $form => $value);)+\n    );\n\n    ($T:ty, $($form:expr),+ $(,)? => $value:expr) => (\n        $(assert_form_parses!($T, $form => $value);)+\n    );\n}\n\n#[macro_export]\nmacro_rules! assert_not_form_parses {\n    ($T:ty, $($form:expr),* $(,)?) => ($(\n        rocket::form::Form::<$T>::parse($form).unwrap_err();\n    )*);\n}\n\n#[macro_export]\nmacro_rules! assert_form_parses_ok {\n    ($T:ty, $($form:expr),* $(,)?) => ($(\n        rocket::form::Form::<$T>::parse($form).expect(\"form to parse\");\n    )*);\n}\n\npub fn client(routes: Vec<rocket::Route>) -> rocket::local::blocking::Client {\n    rocket::local::blocking::Client::debug_with(routes).unwrap()\n}\n"
  },
  {
    "path": "docs/tests/src/readme.rs",
    "content": "rocket::internal_guide_tests!(\"../../README.md\");\n"
  },
  {
    "path": "examples/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"config\",\n  \"cookies\",\n  \"databases\",\n  \"error-handling\",\n  \"fairings\",\n  \"forms\",\n  \"hello\",\n  \"manual-routing\",\n  \"responders\",\n  \"serialization\",\n  \"state\",\n  \"static-files\",\n  \"templating\",\n  \"testing\",\n  \"tls\",\n  \"upgrade\",\n\n  \"pastebin\",\n  \"todo\",\n  \"chat\",\n]\n"
  },
  {
    "path": "examples/README.md",
    "content": "# Rocket Examples\n\nThis directory contains projects showcasing Rocket's features.\n\n## Applications\n\n  * **[`pastebin`](./pastebin)**\n\n    A simple, API-only pastebin application, similar to https://paste.rs. Stores\n    pastes locally on the file system. Implements a custom parameter guard,\n    `PasteId`, to parse and validate paste identifiers.\n\n  * **[`todo`](./todo)**\n\n    A todo app with a web UI to add, delete, and mark/unmark items. Uses a\n    SQLite database driven by diesel. Runs migrations automatically at start-up.\n    Uses tera to render templates.\n\n  * **[`chat`](./chat)**\n\n    A real-time, multi-room chat application using Server-Sent Events (SSE) and\n    JavaScript's `EventSource`. Supports automatic reconnection with exponential\n    backoff and live connection status.\n\n## Feature Examples\n\n  * **[`config`](./config)** - Illustrates how to extract values from a Rocket\n    `Figment`, how to store and retrieve an application specific configuration\n    in managed state using `AdHoc::config()`, and how to set configuration\n    values in `Rocket.toml`.\n\n  * **[`cookies`](./cookies)** - Uses cookies to create a client-side message\n    box. Uses private cookies for a session-based authentication.\n\n  * **[`databases`](./databases)** - Implements a CRUD-like \"blog\" JSON API\n    backed by a SQLite database driven by each of `sqlx`, `diesel`, and\n    `rusqlite`. Runs migrations automatically for the former two drivers. Uses\n    `contrib` database support for all drivers (`rocket_db_pools` for the first;\n    `rocket_sync_db_pools` for the other latter two).\n\n  * **[`error-handling`](./error-handling)** - Exhibits the use of scoped\n    catchers; contains commented out lines that will cause a launch-time error\n    with code to custom-display the error.\n\n  * **[`fairings`](./fairings)** - Exemplifies creating a custom `Counter`\n    fairing and using `AdHoc` fairings.\n\n  * **[`forms`](./forms)** - Showcases all of Rocket's form support features\n    including multipart file uploads, ad-hoc validations, field renaming, and\n    use of form context for staged forms.\n\n  * **[`hello`](./hello)** - Basic example of Rocket's core features: route\n    declaration with path and query parameters, both simple and compound,\n    mounting, launching, testing, and returning simple responses. Also showcases\n    using UTF-8 in route declarations and responses.\n\n  * **[`manual-routing`](./manual-routing)** - An example eschewing Rocket's\n    codegen in favor of manual routing. This should be seen as last-ditch\n    effort, much like `unsafe` in Rust, as manual routing _also_ eschews many of\n    Rocket's automatic web security guarantees.\n\n  * **[`responders`](./responders)** - Illustrates the use of many of Rocket's\n    built-in responders: `Stream`, `Redirect`, `File`, `NamedFile`, `content`\n    for manually setting Content-Types, and `Either`. In the process, showcases\n    using `TempFile` for raw uploads. Also illustrates the creation of a custom,\n    derived `Responder`.\n\n  * **[`serialization`](./serialization)** - Showcases JSON and MessagePack\n    (de)serialization support by implementing a CRUD-like message API in JSON\n    and a simply read/echo API in MessagePack. Showcases UUID parsing support.\n\n  * **[`state`](./state)** - Illustrates the use of request-local state and\n    managed state. Uses request-local state to cache \"expensive\" per-request\n    operations. Uses managed state to implement a simple index hit counter. Also\n    uses managed state to store, retrieve, and push/pop from a concurrent queue.\n\n  * **[`static-files`](./static-files)** - Uses `FileServer` to serve static\n    files. Also creates a `second` manual yet safe version.\n\n  * **[`templating`](./templating)** - Illustrates using `contrib` `templates`\n    support with identical examples for handlebars and tera.\n\n  * **[`testing`](./testing)** - Uses Rocket's `local` libraries to test an\n    application. Showcases necessary use of the `async` `Client`. Note that all\n    examples contains tests, themselves serving as examples for how to test\n    Rocket applications.\n\n  * **[`tls`](./tls)** - Illustrates configuring TLS with a variety of key pair\n    kinds.\n\n  * **[`upgrade`](./upgrade)** - Uses the connection upgrade API to implement\n    WebSocket support using tungstenite.\n"
  },
  {
    "path": "examples/chat/Cargo.toml",
    "content": "[package]\nname = \"chat\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\", features = [\"json\"] }\n\n[dev-dependencies]\nrand = \"0.9\"\n"
  },
  {
    "path": "examples/chat/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\nuse rocket::{State, Shutdown};\nuse rocket::fs::{relative, FileServer};\nuse rocket::form::Form;\nuse rocket::response::stream::{EventStream, Event};\nuse rocket::serde::{Serialize, Deserialize};\nuse rocket::tokio::sync::broadcast::{channel, Sender, error::RecvError};\nuse rocket::tokio::select;\n\n#[derive(Debug, Clone, FromForm, Serialize, Deserialize)]\n#[cfg_attr(test, derive(PartialEq, UriDisplayQuery))]\n#[serde(crate = \"rocket::serde\")]\nstruct Message {\n    #[field(validate = len(..30))]\n    pub room: String,\n    #[field(validate = len(..20))]\n    pub username: String,\n    pub message: String,\n}\n\n/// Returns an infinite stream of server-sent events. Each event is a message\n/// pulled from a broadcast queue sent by the `post` handler.\n#[get(\"/events\")]\nasync fn events(queue: &State<Sender<Message>>, mut end: Shutdown) -> EventStream![] {\n    let mut rx = queue.subscribe();\n    EventStream! {\n        loop {\n            let msg = select! {\n                msg = rx.recv() => match msg {\n                    Ok(msg) => msg,\n                    Err(RecvError::Closed) => break,\n                    Err(RecvError::Lagged(_)) => continue,\n                },\n                _ = &mut end => break,\n            };\n\n            yield Event::json(&msg);\n        }\n    }\n}\n\n/// Receive a message from a form submission and broadcast it to any receivers.\n#[post(\"/message\", data = \"<form>\")]\nfn post(form: Form<Message>, queue: &State<Sender<Message>>) {\n    // A send 'fails' if there are no active subscribers. That's okay.\n    let _res = queue.send(form.into_inner());\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .manage(channel::<Message>(1024).0)\n        .mount(\"/\", routes![post, events])\n        .mount(\"/\", FileServer::new(relative!(\"static\")))\n}\n"
  },
  {
    "path": "examples/chat/src/tests.rs",
    "content": "use std::ops::Range;\n\nuse rand::{rng, Rng};\nuse rand::distr::Alphanumeric;\n\nuse rocket::http::{ContentType, Status};\nuse rocket::http::uri::fmt::{UriDisplay, Query};\nuse rocket::local::asynchronous::{Client, LocalResponse};\n\nuse rocket::tokio::{sync, join};\nuse rocket::tokio::io::{BufReader, AsyncBufReadExt};\nuse rocket::serde::json;\n\nuse super::*;\n\nasync fn send_message<'c>(client: &'c Client, message: &Message) -> LocalResponse<'c> {\n    client.post(uri!(post))\n        .header(ContentType::Form)\n        .body((message as &dyn UriDisplay<Query>).to_string())\n        .dispatch()\n        .await\n}\n\nfn gen_string(len: Range<usize>) -> String {\n    rng()\n        .sample_iter(&Alphanumeric)\n        .take(rng().random_range(len))\n        .map(char::from)\n        .collect()\n}\n\n#[async_test]\nasync fn messages() {\n    let client = Client::tracked(rocket()).await.unwrap();\n    let start_barrier = sync::Barrier::new(2);\n\n    let shutdown_message = Message {\n        room: \":control\".into(),\n        username: \":control\".into(),\n        message: \"shutdown\".into(),\n    };\n\n    // Generate somewhere between 75 and 100 messages.\n    let mut test_messages = vec![];\n    for _ in 0..rng().random_range(75..100) {\n        test_messages.push(Message {\n            room: gen_string(10..30),\n            username: gen_string(10..20),\n            message: gen_string(10..100),\n        })\n    }\n\n    let send_messages = async {\n        // Wait for the other task to start listening.\n        start_barrier.wait().await;\n\n        // Send all of the messages.\n        for message in &test_messages {\n            send_message(&client, message).await;\n        }\n\n        // Send the special \"shutdown\" message.\n        send_message(&client, &shutdown_message).await;\n    };\n\n    let receive_messages = async {\n        let response = client.get(uri!(events)).dispatch().await;\n\n        // We have the response stream. Let the receiver know to start sending.\n        start_barrier.wait().await;\n\n        let mut messages = vec![];\n        let mut reader = BufReader::new(response).lines();\n        while let Ok(Some(line)) = reader.next_line().await {\n            if !line.starts_with(\"data:\") {\n                continue;\n            }\n\n            let data: Message = json::from_str(&line[5..]).expect(\"message JSON\");\n            if data == shutdown_message {\n                // Test shutdown listening: this should end the stream.\n                client.rocket().shutdown().notify();\n                continue;\n            }\n\n            messages.push(data);\n        }\n\n        messages\n    };\n\n    let received_messages = join!(send_messages, receive_messages).1;\n    assert!(test_messages.len() >= 75);\n    assert_eq!(test_messages, received_messages);\n}\n\n#[async_test]\nasync fn bad_messages() {\n    // Generate a bunch of bad messages.\n    let mut bad_messages = vec![];\n    for _ in 0..rng().random_range(75..100) {\n        bad_messages.push(Message {\n            room: gen_string(30..40),\n            username: gen_string(20..30),\n            message: gen_string(10..100),\n        });\n    }\n\n    // Ensure they all result in a rejected request.\n    let client = Client::tracked(rocket()).await.unwrap();\n    for message in &bad_messages {\n        let response = send_message(&client, message).await;\n        assert_eq!(response.status(), Status::PayloadTooLarge);\n    }\n}\n"
  },
  {
    "path": "examples/chat/static/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Rocket Rooms</title>\n    <link rel=\"stylesheet\" href=\"/reset.css\">\n    <link rel=\"stylesheet\" href=\"/style.css\">\n    <script src=\"/script.js\" charset=\"utf-8\" defer></script>\n  </head>\n  <body>\n    <main>\n      <div id=\"sidebar\">\n        <div id=\"status\" class=\"pending\"></div>\n\n        <div id=\"room-list\">\n          <template id=\"room\">\n            <button class=\"room\"></button>\n          </template>\n        </div>\n\n        <form id=\"new-room\">\n          <input type=\"text\" name=\"name\" id=\"name\" autocomplete=\"off\"\n              placeholder=\"new room...\" maxlength=\"29\"></input>\n          <button type=\"submit\">+</button>\n        </form>\n      </div>\n\n      <div id=\"content\">\n\n        <div id=\"messages\">\n          <template id=\"message\">\n            <div class=\"message\">\n              <span class=\"username\"></span>\n              <span class=\"text\"></span>\n            </div>\n          </template>\n        </div>\n\n        <form id=\"new-message\">\n          <input type=\"text\" name=\"username\" id=\"username\" maxlength=\"19\"\n            placeholder=\"guest\" autocomplete=\"off\">\n          <input type=\"text\" name=\"message\" id=\"message\" autocomplete=\"off\"\n              placeholder=\"Send a message...\" autofocus>\n          <button type=\"submit\" id=\"send\">Send</button>\n        </form>\n      </div>\n    </main>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/chat/static/reset.css",
    "content": "html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe,button,input{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}\n"
  },
  {
    "path": "examples/chat/static/script.js",
    "content": "let roomListDiv = document.getElementById('room-list');\nlet messagesDiv = document.getElementById('messages');\nlet newMessageForm = document.getElementById('new-message');\nlet newRoomForm = document.getElementById('new-room');\nlet statusDiv = document.getElementById('status');\n\nlet roomTemplate = document.getElementById('room');\nlet messageTemplate = document.getElementById('message');\n\nlet messageField = newMessageForm.querySelector(\"#message\");\nlet usernameField = newMessageForm.querySelector(\"#username\");\nlet roomNameField = newRoomForm.querySelector(\"#name\");\n\nvar STATE = {\n  room: \"lobby\",\n  rooms: {},\n  connected: false,\n}\n\n// Generate a color from a \"hash\" of a string. Thanks, internet.\nfunction hashColor(str) {\n  let hash = 0;\n  for (var i = 0; i < str.length; i++) {\n    hash = str.charCodeAt(i) + ((hash << 5) - hash);\n    hash = hash & hash;\n  }\n\n  return `hsl(${hash % 360}, 100%, 70%)`;\n}\n\n// Add a new room `name` and change to it. Returns `true` if the room didn't\n// already exist and false otherwise.\nfunction addRoom(name) {\n  if (STATE[name]) {\n    changeRoom(name);\n    return false;\n  }\n\n  var node = roomTemplate.content.cloneNode(true);\n  var room = node.querySelector(\".room\");\n  room.addEventListener(\"click\", () => changeRoom(name));\n  room.textContent = name;\n  room.dataset.name = name;\n  roomListDiv.appendChild(node);\n\n  STATE[name] = [];\n  changeRoom(name);\n  return true;\n}\n\n// Change the current room to `name`, restoring its messages.\nfunction changeRoom(name) {\n  if (STATE.room == name) return;\n\n  var newRoom = roomListDiv.querySelector(`.room[data-name='${name}']`);\n  var oldRoom = roomListDiv.querySelector(`.room[data-name='${STATE.room}']`);\n  if (!newRoom || !oldRoom) return;\n\n  STATE.room = name;\n  oldRoom.classList.remove(\"active\");\n  newRoom.classList.add(\"active\");\n\n  messagesDiv.querySelectorAll(\".message\").forEach((msg) => {\n    messagesDiv.removeChild(msg)\n  });\n\n  STATE[name].forEach((data) => addMessage(name, data.username, data.message))\n}\n\n// Add `message` from `username` to `room`. If `push`, then actually store the\n// message. If the current room is `room`, render the message.\nfunction addMessage(room, username, message, push = false) {\n  if (push) {\n    STATE[room].push({ username, message })\n  }\n\n  if (STATE.room == room) {\n    var node = messageTemplate.content.cloneNode(true);\n    node.querySelector(\".message .username\").textContent = username;\n    node.querySelector(\".message .username\").style.color = hashColor(username);\n    node.querySelector(\".message .text\").textContent = message;\n    messagesDiv.appendChild(node);\n  }\n}\n\n// Subscribe to the event source at `uri` with exponential backoff reconnect.\nfunction subscribe(uri) {\n  var retryTime = 1;\n\n  function connect(uri) {\n    const events = new EventSource(uri);\n\n    events.addEventListener(\"message\", (ev) => {\n      console.log(\"raw data\", JSON.stringify(ev.data));\n      console.log(\"decoded data\", JSON.stringify(JSON.parse(ev.data)));\n      const msg = JSON.parse(ev.data);\n      if (!(\"message\" in msg) || !(\"room\" in msg) || !(\"username\" in msg)) return;\n      addMessage(msg.room, msg.username, msg.message, true);\n    });\n\n    events.addEventListener(\"open\", () => {\n      setConnectedStatus(true);\n      console.log(`connected to event stream at ${uri}`);\n      retryTime = 1;\n    });\n\n    events.addEventListener(\"error\", () => {\n      setConnectedStatus(false);\n      events.close();\n\n      let timeout = retryTime;\n      retryTime = Math.min(64, retryTime * 2);\n      console.log(`connection lost. attempting to reconnect in ${timeout}s`);\n      setTimeout(() => connect(uri), (() => timeout * 1000)());\n    });\n  }\n\n  connect(uri);\n}\n\n// Set the connection status: `true` for connected, `false` for disconnected.\nfunction setConnectedStatus(status) {\n  STATE.connected = status;\n  statusDiv.className = (status) ? \"connected\" : \"reconnecting\";\n}\n\n// Let's go! Initialize the world.\nfunction init() {\n  // Initialize some rooms.\n  addRoom(\"lobby\");\n  addRoom(\"rocket\");\n  changeRoom(\"lobby\");\n  addMessage(\"lobby\", \"Rocket\", \"Hey! Open another browser tab, send a message.\", true);\n  addMessage(\"rocket\", \"Rocket\", \"This is another room. Neat, huh?\", true);\n\n  // Set up the form handler.\n  newMessageForm.addEventListener(\"submit\", (e) => {\n    e.preventDefault();\n\n    const room = STATE.room;\n    const message = messageField.value;\n    const username = usernameField.value || \"guest\";\n    if (!message || !username) return;\n\n    if (STATE.connected) {\n      fetch(\"/message\", {\n        method: \"POST\",\n        body: new URLSearchParams({ room, username, message }),\n      }).then((response) => {\n        if (response.ok) messageField.value = \"\";\n      });\n    }\n  })\n\n  // Set up the new room handler.\n  newRoomForm.addEventListener(\"submit\", (e) => {\n    e.preventDefault();\n\n    const room = roomNameField.value;\n    if (!room) return;\n\n    roomNameField.value = \"\";\n    if (!addRoom(room)) return;\n\n    addMessage(room, \"Rocket\", `Look, your own \"${room}\" room! Nice.`, true);\n  })\n\n  // Subscribe to server-sent events.\n  subscribe(\"/events\");\n}\n\ninit();\n"
  },
  {
    "path": "examples/chat/static/style.css",
    "content": ":root {\n  --bg-dark: #242423;\n  --bg-light: #333533;\n  --fg-light: #E8EDDF;\n  --callout: rgb(255, 255, 102);\n  --callout-dark: #101010;\n}\n\n* {\n    font-size: 14px;\n}\n\nhtml, body, main {\n    background-color: var(--bg-dark);\n    color: #fff;\n    font-family: \"Inter\", Arial, Helvetica, sans-serif, \"Noto Color Emoji\";\n    font-weight: 400;\n    text-shadow: rgb(77, 81, 86) 0px 0px 0px;\n    height: 100%;\n}\n\nmain {\n    display: flex;\n}\n\nbutton:hover:not(.active) {\n    filter: brightness(1.15);\n    cursor: pointer;\n}\n\n#sidebar {\n    flex: 3 30%;\n    display: flex;\n    flex-direction: column;\n    overflow: auto;\n    background-color: var(--bg-light);\n}\n\n#room-list {\n    display: flex;\n    flex-direction: column;\n    overflow: auto;\n    flex: 1;\n}\n\n#sidebar button {\n    height: 40px;\n    margin-bottom: 1px;\n    background: var(--bg-light);\n    color: #fff;\n    overflow: hidden;\n}\n\n#sidebar button.active {\n    background: var(--bg-dark);\n    color: var(--callout);\n    font-weight: bold;\n    box-shadow: 0px 2px 2px rgba(0,0,0,0.9);\n    z-index: 10;\n}\n\n#content {\n    flex: 7 100%;\n    overflow: auto;\n    display: flex;\n    flex-direction: column;\n}\n\n.message {\n    display: flex;\n    flex-direction: column;\n    padding: 10px 0;\n}\n\n.message:last-child {\n    padding-bottom: 20px;\n}\n\n.message .username {\n    font-weight: bold;\n    padding-bottom: 5px;\n    color: var(--callout);\n}\n\n#messages {\n    padding: 10px 20px;\n    flex: 1;\n}\n\nform#new-message {\n    bottom: 0;\n    position: sticky;\n    flex: 0 0 auto;\n    width: 100%;\n}\n\nform {\n    display: flex;\n    border-top: 2px solid #242424;\n}\n\nform * {\n    height: 40px;\n    background: var(--fg-light);\n    color: var(--bg-dark);\n}\n\ninput {\n    padding: 0 10px;\n}\n\ninput:focus {\n    outline: 0;\n    filter: brightness(1.05);\n}\n\ninput#username {\n    text-align: right;\n    flex: 1 25%;\n    width: 25%;\n    border-right: 1px solid #303030;\n}\n\ninput#message {\n    flex: 10 100%;\n}\n\nform button {\n    padding: 0 10px;\n}\n\n#sidebar #new-room {\n    display: flex;\n    flex: 0 0 auto;\n    flex-direction: row;\n}\n\n#new-room input:focus, #new-room button:hover {\n    filter: brightness(1.2);\n}\n\n#new-room input {\n    flex: 8 80%;\n    width: 20%;\n    background-color: var(--callout-dark);\n    color: #fff;\n}\n\n#new-room button {\n    flex: 2 20%;\n    width: 20%;\n    background-color: var(--bg-dark);\n}\n\n#status {\n    padding: 5px 10px;\n    text-align: center;\n    font-size: 12px;\n}\n\n#status.pending::before {\n  content: \"status: connected\";\n}\n\n#status.pending {\n    background-color: yellow;\n    color: #000;\n}\n\n#status.connected::before {\n  content: \"status: connected\";\n}\n\n#status.connected {\n    background-color: green;\n    color: #fff;\n}\n\n#status.reconnecting::before {\n  content: \"status: reconnecting\";\n}\n\n#status.reconnecting {\n    background-color: red;\n    color: #fff;\n}\n"
  },
  {
    "path": "examples/config/Cargo.toml",
    "content": "[package]\nname = \"config\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\", features = [\"secrets\"] }\n"
  },
  {
    "path": "examples/config/Rocket.toml",
    "content": "# Except for the secret key, none of these are actually needed; Rocket has sane\n# defaults. We show all of them here explicitly for demonstrative purposes.\n\n[default.limits]\nforms = \"64 kB\"\njson = \"1 MiB\"\nmsgpack = \"2 MiB\"\n\"file/jpg\" = \"5 MiB\"\n\n[default]\nkey = \"a default app-key\"\nextra = false\nident = \"Rocket\"\nip_header = \"CF-Connecting-IP\"\n\n[debug]\naddress = \"127.0.0.1\"\nport = 8000\nworkers = 1\nkeep_alive = 0\nlog_level = \"info\"\nlog_format = \"pretty\"\n\n[release]\naddress = \"127.0.0.1\"\nport = 8000\nworkers = 12\nkeep_alive = 5\nlog_level = \"error\"\nlog_format = \"compact\"\n# NOTE: Don't (!) use this key! Generate your own and keep it private!\n#       e.g. via `head -c64 /dev/urandom | base64`\nsecret_key = \"hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk=\"\nkey = \"a release app-key\"\nextra = false\n"
  },
  {
    "path": "examples/config/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\nuse rocket::{State, Config};\nuse rocket::fairing::AdHoc;\nuse rocket::serde::Deserialize;\n\n#[derive(Debug, Deserialize)]\n#[serde(crate = \"rocket::serde\")]\n#[allow(dead_code)]\nstruct AppConfig {\n    key: String,\n    port: u16\n}\n\n#[get(\"/\")]\nfn read_config(rocket_config: &Config, app_config: &State<AppConfig>) -> String {\n    format!(\"{:#?}\\n{:#?}\", app_config, rocket_config)\n}\n\n// See Rocket.toml file. Running this server will print the config. Try running\n// with `ROCKET_PROFILE=release` manually by setting the environment variable\n// and automatically by compiling with `--release`.\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![read_config])\n        .attach(AdHoc::config::<AppConfig>())\n}\n"
  },
  {
    "path": "examples/config/src/tests.rs",
    "content": "use rocket::config::Config;\nuse rocket::trace::{Level, TraceFormat};\n\nasync fn test_config(profile: &str) {\n    let provider = Config::figment().select(profile);\n    let rocket = rocket::custom(provider).ignite().await.unwrap();\n    let config = rocket.config();\n    match profile {\n        \"debug\" => {\n            assert_eq!(config.workers, 1);\n            assert_eq!(config.keep_alive, 0);\n            assert_eq!(config.log_level, Some(Level::INFO));\n            assert_eq!(config.log_format, TraceFormat::Pretty);\n        }\n        \"release\" => {\n            assert_eq!(config.workers, 12);\n            assert_eq!(config.keep_alive, 5);\n            assert_eq!(config.log_level, Some(Level::ERROR));\n            assert_eq!(config.log_format, TraceFormat::Compact);\n            assert!(!config.secret_key.is_zero());\n        }\n        _ => {\n            panic!(\"Unknown profile: {}\", profile);\n        }\n    }\n}\n\n#[async_test]\nasync fn test_debug_config() {\n    test_config(\"debug\").await;\n}\n\n#[async_test]\nasync fn test_release_config() {\n    test_config(\"release\").await;\n}\n"
  },
  {
    "path": "examples/cookies/Cargo.toml",
    "content": "[package]\nname = \"cookies\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\", features = [\"secrets\"] }\n\n[dependencies.rocket_dyn_templates]\npath = \"../../contrib/dyn_templates\"\nfeatures = [\"handlebars\"]\n"
  },
  {
    "path": "examples/cookies/Rocket.toml",
    "content": "[default]\nsecret_key = \"itlYmFR2vYKrOmFhupMIn/hyB6lYCCTXz4yaQX89XVg=\"\ntemplate_dir = \"templates\"\n"
  },
  {
    "path": "examples/cookies/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\nmod session;\nmod message;\n\nuse rocket::response::content::RawHtml;\nuse rocket_dyn_templates::Template;\n\n#[get(\"/\")]\nfn index() -> RawHtml<&'static str> {\n    RawHtml(r#\"<a href=\"message\">Set a Message</a> or <a href=\"session\">Use Sessions</a>.\"#)\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .attach(Template::fairing())\n        .mount(\"/\", routes![index])\n        .mount(\"/message\", message::routes())\n        .mount(\"/session\", session::routes())\n}\n"
  },
  {
    "path": "examples/cookies/src/message.rs",
    "content": "use rocket::form::Form;\nuse rocket::response::Redirect;\nuse rocket::http::CookieJar;\nuse rocket_dyn_templates::{Template, context};\n\n#[macro_export]\nmacro_rules! message_uri {\n    ($($t:tt)*) => (rocket::uri!(\"/message\", $crate::message:: $($t)*))\n}\n\npub use message_uri as uri;\n\n#[post(\"/\", data = \"<message>\")]\nfn submit(cookies: &CookieJar<'_>, message: Form<&str>) -> Redirect {\n    cookies.add((\"message\", message.to_string()));\n    Redirect::to(uri!(index))\n}\n\n#[delete(\"/\")]\nfn delete(cookies: &CookieJar<'_>) -> Redirect {\n    cookies.remove(\"message\");\n    Redirect::to(uri!(index))\n}\n\n#[get(\"/\")]\nfn index(cookies: &CookieJar<'_>) -> Template {\n    let message = cookies.get(\"message\").map(|c| c.value());\n    let present = cookies.get(\"message\").is_some();\n    Template::render(\"message\", context! { present, message })\n}\n\npub fn routes() -> Vec<rocket::Route> {\n    routes![index, submit, delete]\n}\n"
  },
  {
    "path": "examples/cookies/src/session.rs",
    "content": "use rocket::outcome::IntoOutcome;\nuse rocket::request::{self, FlashMessage, FromRequest, Request};\nuse rocket::response::{Redirect, Flash};\nuse rocket::http::{CookieJar, Status};\nuse rocket::form::Form;\n\nuse rocket_dyn_templates::{Template, context};\n\n#[derive(FromForm)]\nstruct Login<'r> {\n    username: &'r str,\n    password: &'r str\n}\n\n#[derive(Debug)]\nstruct User(usize);\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for User {\n    type Error = std::convert::Infallible;\n\n    async fn from_request(request: &'r Request<'_>) -> request::Outcome<User, Self::Error> {\n        request.cookies()\n            .get_private(\"user_id\")\n            .and_then(|cookie| cookie.value().parse().ok())\n            .map(User)\n            .or_forward(Status::Unauthorized)\n    }\n}\n\n#[macro_export]\nmacro_rules! session_uri {\n    ($($t:tt)*) => (rocket::uri!(\"/session\", $crate::session:: $($t)*))\n}\n\npub use session_uri as uri;\n\n#[get(\"/\")]\nfn index(user: User) -> Template {\n    Template::render(\"session\", context! {\n        user_id: user.0,\n    })\n}\n\n#[get(\"/\", rank = 2)]\nfn no_auth_index() -> Redirect {\n    Redirect::to(uri!(login_page))\n}\n\n#[get(\"/login\")]\nfn login(_user: User) -> Redirect {\n    Redirect::to(uri!(index))\n}\n\n#[get(\"/login\", rank = 2)]\nfn login_page(flash: Option<FlashMessage<'_>>) -> Template {\n    Template::render(\"login\", flash)\n}\n\n#[post(\"/login\", data = \"<login>\")]\nfn post_login(jar: &CookieJar<'_>, login: Form<Login<'_>>) -> Result<Redirect, Flash<Redirect>> {\n    if login.username == \"Sergio\" && login.password == \"password\" {\n        jar.add_private((\"user_id\", \"1\"));\n        Ok(Redirect::to(uri!(index)))\n    } else {\n        Err(Flash::error(Redirect::to(uri!(login_page)), \"Invalid username/password.\"))\n    }\n}\n\n#[post(\"/logout\")]\nfn logout(jar: &CookieJar<'_>) -> Flash<Redirect> {\n    jar.remove_private(\"user_id\");\n    Flash::success(Redirect::to(uri!(login_page)), \"Successfully logged out.\")\n}\n\npub fn routes() -> Vec<rocket::Route> {\n    routes![index, no_auth_index, login, login_page, post_login, logout]\n}\n"
  },
  {
    "path": "examples/cookies/src/tests.rs",
    "content": "use super::{rocket, session, message};\nuse rocket::local::blocking::{Client, LocalResponse};\nuse rocket::http::{Status, Cookie, ContentType};\n\nfn user_id_cookie(response: &LocalResponse<'_>) -> Option<Cookie<'static>> {\n    let cookie = response.headers()\n        .get(\"Set-Cookie\")\n        .find(|v| v.starts_with(\"user_id\"))\n        .and_then(|val| Cookie::parse_encoded(val).ok());\n\n    cookie.map(|c| c.into_owned())\n}\n\nfn login(client: &Client, user: &str, pass: &str) -> Option<Cookie<'static>> {\n    let response = client.post(session::uri!(login))\n        .header(ContentType::Form)\n        .body(format!(\"username={}&password={}\", user, pass))\n        .dispatch();\n\n    user_id_cookie(&response)\n}\n\n#[test]\nfn redirect_logged_out_session() {\n    let client = Client::tracked(rocket()).unwrap();\n    let response = client.get(session::uri!(index)).dispatch();\n    assert_eq!(response.status(), Status::SeeOther);\n    assert_eq!(response.headers().get_one(\"Location\").unwrap(), &session::uri!(login));\n\n    let response = client.get(session::uri!(login_page)).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    let body = response.into_string().unwrap();\n    assert!(body.contains(\"Please login to continue.\"));\n}\n\n#[test]\nfn login_fails() {\n    let client = Client::tracked(rocket()).unwrap();\n    assert!(login(&client, \"Seergio\", \"password\").is_none());\n    assert!(login(&client, \"Sergio\", \"idontknow\").is_none());\n}\n\n#[test]\nfn login_logout_succeeds() {\n    let client = Client::tracked(rocket()).unwrap();\n    let login_cookie = login(&client, \"Sergio\", \"password\").expect(\"logged in\");\n\n    // Ensure we're logged in.\n    let response = client.get(session::uri!(index)).cookie(login_cookie.clone()).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    let body = response.into_string().unwrap();\n    assert!(body.contains(\"Logged in with user ID 1\"));\n\n    // One more.\n    let response = client.get(session::uri!(login)).cookie(login_cookie.clone()).dispatch();\n    assert_eq!(response.status(), Status::SeeOther);\n    assert_eq!(response.headers().get_one(\"Location\").unwrap(), &session::uri!(index));\n\n    // Logout.\n    let response = client.post(session::uri!(logout)).cookie(login_cookie).dispatch();\n    let cookie = user_id_cookie(&response).expect(\"logout cookie\");\n    assert!(cookie.value().is_empty());\n\n    // The user should be redirected back to the login page.\n    assert_eq!(response.status(), Status::SeeOther);\n    assert_eq!(response.headers().get_one(\"Location\").unwrap(), &session::uri!(login));\n\n    // The page should show the success message, and no errors.\n    let response = client.get(session::uri!(login)).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    let body = response.into_string().unwrap();\n    assert!(body.contains(\"success: Successfully logged out.\"));\n    assert!(!body.contains(\"Error\"));\n}\n\n#[test]\nfn test_message() {\n    let client = Client::tracked(rocket()).unwrap();\n\n    // Check that there's no message initially.\n    let response = client.get(message::uri!(index)).dispatch();\n    assert!(response.into_string().unwrap().contains(\"No message yet.\"));\n\n    // Now set a message; we should get a cookie back.\n    let response = client.post(message::uri!(submit))\n        .header(ContentType::Form)\n        .body(\"message=Hello from Rocket!\")\n        .dispatch();\n\n    let cookie_headers: Vec<_> = response.headers().get(\"Set-Cookie\").collect();\n    assert_eq!(cookie_headers.len(), 1);\n    assert!(cookie_headers[0].starts_with(\"message=Hello%20from%20Rocket!\"));\n    assert_eq!(response.headers().get_one(\"Location\").unwrap(), &message::uri!(index));\n    assert_eq!(response.status(), Status::SeeOther);\n\n    // Check that the message is reflected.\n    let response = client.get(message::uri!(index)).dispatch();\n    assert!(response.into_string().unwrap().contains(\"Hello from Rocket!\"));\n}\n"
  },
  {
    "path": "examples/cookies/templates/login.html.hbs",
    "content": "<!DOCTYPE html>\n<html>\n   <head>\n      <meta charset=\"utf-8\" />\n      <meta name=\"viewport\" content=\"width=device-width\" />\n      <title>Rocket: Sessions</title>\n   </head>\n   <body>\n      <h1>Rocket Session: Please Login</h1>\n\n     <p>Please login to continue.</p>\n\n      {{#if message}}\n         <p>{{#if kind}}{{kind}}: {{/if}}{{ message }}</p>\n      {{/if}}\n\n      <form action=\"/session/login\" method=\"post\" accept-charset=\"utf-8\">\n         <label for=\"username\">username</label>\n         <input type=\"text\" name=\"username\" id=\"username\" value=\"\" />\n         <label for=\"password\">password</label>\n         <input type=\"password\" name=\"password\" id=\"password\" value=\"\" />\n         <p><input type=\"submit\" value=\"login\"></p>\n      </form>\n\n      <a href=\"/\">Home</a>\n   </body>\n</html>\n"
  },
  {
    "path": "examples/cookies/templates/message.html.hbs",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width\" />\n    <title>Rocket: Cookie Message</title>\n  </head>\n  <body>\n    <h1>Rocket Cookie Message</h1>\n\n    <p>\n      {{#if present}}\n        {{#if message}}\n          <b>Message:</b> <i>{{message}}</i>\n        {{else}}\n          <b>Message:</b> <i>[empty message]</i>\n        {{/if}}\n      {{else}}\n        <b>No message yet.</b>\n      {{/if}}\n    </p>\n\n    <form id=\"set\" action=\"/message\" method=\"post\">\n      <textarea placeholder=\"Your message here...\" name=\"message\" rows=\"10\" cols=\"50\"></textarea>\n    </form>\n\n    <form id=\"delete\" action=\"/message\" method=\"post\">\n      <input type=\"hidden\" name=\"_method\" value=\"delete\" />\n    </form>\n\n    <p>\n      <input type=\"submit\" form=\"set\" value=\"Set Message\" />\n      <input type=\"submit\" form=\"delete\" value=\"Clear Message\" />\n    </p>\n\n    <a href=\"/\">Home</a>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/cookies/templates/session.html.hbs",
    "content": "<!DOCTYPE html>\n<html>\n   <head>\n      <meta charset=\"utf-8\" />\n      <meta name=\"viewport\" content=\"width=device-width\" />\n      <title>Rocket: Session Example</title>\n   </head>\n   <body>\n      <h1>Rocket Session Example</h1>\n      <p>Logged in with user ID {{ user_id }}.</p>\n      <form action=\"/session/logout\" method=\"post\" accept-charset=\"utf-8\">\n         <input type=\"submit\" name=\"logout\" id=\"logout\" value=\"logout\" />\n      </form>\n\n      <a href=\"/\">Home</a>\n   </body>\n</html>\n"
  },
  {
    "path": "examples/databases/.sqlx/query-11e3096becb72f427c8d3911ef4327afd9516143806981e11f8e34d069c14472.json",
    "content": "{\n  \"db_name\": \"SQLite\",\n  \"query\": \"SELECT id, title, text FROM posts WHERE id = ?\",\n  \"describe\": {\n    \"columns\": [\n      {\n        \"name\": \"id\",\n        \"ordinal\": 0,\n        \"type_info\": \"Integer\"\n      },\n      {\n        \"name\": \"title\",\n        \"ordinal\": 1,\n        \"type_info\": \"Text\"\n      },\n      {\n        \"name\": \"text\",\n        \"ordinal\": 2,\n        \"type_info\": \"Text\"\n      }\n    ],\n    \"parameters\": {\n      \"Right\": 1\n    },\n    \"nullable\": [\n      false,\n      false,\n      false\n    ]\n  },\n  \"hash\": \"11e3096becb72f427c8d3911ef4327afd9516143806981e11f8e34d069c14472\"\n}\n"
  },
  {
    "path": "examples/databases/.sqlx/query-4415c35941e52a981b10707fe2e1ceb0bad0e473701e51ef21ecb2973c76b4df.json",
    "content": "{\n  \"db_name\": \"SQLite\",\n  \"query\": \"SELECT id FROM posts\",\n  \"describe\": {\n    \"columns\": [\n      {\n        \"name\": \"id\",\n        \"ordinal\": 0,\n        \"type_info\": \"Integer\"\n      }\n    ],\n    \"parameters\": {\n      \"Right\": 0\n    },\n    \"nullable\": [\n      false\n    ]\n  },\n  \"hash\": \"4415c35941e52a981b10707fe2e1ceb0bad0e473701e51ef21ecb2973c76b4df\"\n}\n"
  },
  {
    "path": "examples/databases/.sqlx/query-668690acaca0a0c0b4ac306b14d82aa1bee940f0776fae3f9962639b78328858.json",
    "content": "{\n  \"db_name\": \"SQLite\",\n  \"query\": \"DELETE FROM posts\",\n  \"describe\": {\n    \"columns\": [],\n    \"parameters\": {\n      \"Right\": 0\n    },\n    \"nullable\": []\n  },\n  \"hash\": \"668690acaca0a0c0b4ac306b14d82aa1bee940f0776fae3f9962639b78328858\"\n}\n"
  },
  {
    "path": "examples/databases/.sqlx/query-79301b44b77802e0096efd73b1e9adac27b27a3cf7bf853af3a9f130b1684d91.json",
    "content": "{\n  \"db_name\": \"SQLite\",\n  \"query\": \"DELETE FROM posts WHERE id = ?\",\n  \"describe\": {\n    \"columns\": [],\n    \"parameters\": {\n      \"Right\": 1\n    },\n    \"nullable\": []\n  },\n  \"hash\": \"79301b44b77802e0096efd73b1e9adac27b27a3cf7bf853af3a9f130b1684d91\"\n}\n"
  },
  {
    "path": "examples/databases/.sqlx/query-bea4ef6e25064f6b383e854f8bc2770d89cfaf9859d0bfca78b2ca24627675b7.json",
    "content": "{\n  \"db_name\": \"SQLite\",\n  \"query\": \"INSERT INTO posts (title, text) VALUES (?, ?) RETURNING id\",\n  \"describe\": {\n    \"columns\": [\n      {\n        \"name\": \"id\",\n        \"ordinal\": 0,\n        \"type_info\": \"Integer\"\n      }\n    ],\n    \"parameters\": {\n      \"Right\": 2\n    },\n    \"nullable\": [\n      false\n    ]\n  },\n  \"hash\": \"bea4ef6e25064f6b383e854f8bc2770d89cfaf9859d0bfca78b2ca24627675b7\"\n}\n"
  },
  {
    "path": "examples/databases/Cargo.toml",
    "content": "[package]\nname = \"databases\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\", features = [\"json\"] }\ndiesel = { version = \"2\", features = [\"returning_clauses_for_sqlite_3_35\"] }\ndiesel_migrations = \"2\"\n\n[dependencies.sqlx]\nversion = \"0.8.0\"\ndefault-features = false\nfeatures = [\"macros\", \"migrate\"]\n\n[dependencies.rocket_db_pools]\npath = \"../../contrib/db_pools/lib/\"\nfeatures = [\"sqlx_sqlite\", \"diesel_mysql\"]\n\n[dependencies.rocket_sync_db_pools]\npath = \"../../contrib/sync_db_pools/lib/\"\nfeatures = [\"diesel_sqlite_pool\", \"sqlite_pool\"]\n"
  },
  {
    "path": "examples/databases/README.md",
    "content": "# Databases Example\n\nThis example makes use of SQLite and MySQL. You'll need `sqlite3` and a MySQL\nclient installed:\n\n  * **macOS:** `brew install sqlite mysql-client`\n  * **Debian**, **Ubuntu:** `apt-get install libsqlite3-dev libmysqlclient-dev`\n  * **Arch:** `pacman -S sqlite libmysqlclient`\n\n## API Implementation\n\nThis example implements a JSON-based HTTP API for a \"blog\" using several database drivers:\n\n  * `sqlx` (`/sqlx`, `sqlx.rs`)\n  * `rusqlite` (`/rusqlite`, `rusqlite.rs`)\n  * `diesel` (sqlite) (`/diesel`, `diesel_sqlite.rs`)\n  * `diesel-async` (mysql) (`/mysql`, `diesel_mysql.rs`)\n\nThe exposed API is succinctly described as follows, with\n[`httpie`](https://httpie.io/) CLI examples:\n\n  * `POST /driver`: create post via JSON with `title` and `text`; returns new\n    post JSON with new `id`\n\n        http http://127.0.0.1:8000/sqlx title=\"Title\" text=\"Hello, world.\"\n        > { \"id\": 2128, \"text\": \"Hello, world.\", \"title\": \"Title\" }\n\n  * `GET /driver`: returns JSON array of IDs for blog posts\n\n        http http://127.0.0.1:8000/sqlx\n        > [ 2128, 2129, 2130, 2131 ]\n\n  * `GET /driver/<id>`: returns a JSON object for the post with id `<id>`\n\n        http http://127.0.0.1:8000/sqlx/2128\n        > { \"id\": 2128, \"text\": \"Hello, world.\", \"title\": \"Title\" }\n\n  * `DELETE /driver`: delete all posts\n\n        http delete http://127.0.0.1:8000/sqlx\n\n  * `DELETE /driver/<id>`: delete post with id `<id>`\n\n        http delete http://127.0.0.1:8000/sqlx/4\n\n## Migrations\n\nDatabase migrations are stored in the respective `db/${driver}` directory.\n\n### `diesel`\n\nDiesel migrations are found in `db/diesel/migrations`. They are run\nautomatically. They can be run manually as well:\n\n```sh\ncargo install diesel_cli --no-default-features --features sqlite\nDATABASE_URL=\"db/diesel/db.sqlite\" diesel migration --migration-dir db/diesel/migrations redo\n```\n\n### `sqlx`\n\nsqlx migrations are found in `db/sqlx/migrations`. They are run automatically.\n\nQuery metadata for offline checking was prepared with the following commands:\n\n```sh\ncargo install sqlx-cli --no-default-features --features sqlite\nDATABASE_URL=\"sqlite:$(pwd)/db/sqlx/db.sqlite\" cargo sqlx prepare\n```\n"
  },
  {
    "path": "examples/databases/Rocket.toml",
    "content": "[default.databases.rusqlite]\nurl = \"file:rusqlite?mode=memory&cache=shared\"\n\n[default.databases.sqlx]\nurl = \"db/sqlx/db.sqlite\"\n\n[default.databases.diesel]\nurl = \"db/diesel/db.sqlite\"\ntimeout = 10\n\n[default.databases.diesel_mysql]\nurl = \"mysql://user:password@127.0.0.1/database\"\n"
  },
  {
    "path": "examples/databases/db/diesel/migrations/.gitkeep",
    "content": ""
  },
  {
    "path": "examples/databases/db/diesel/migrations/20210329150332_create_posts_table/down.sql",
    "content": "DROP TABLE posts;\n"
  },
  {
    "path": "examples/databases/db/diesel/migrations/20210329150332_create_posts_table/up.sql",
    "content": "CREATE TABLE posts (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    title VARCHAR NOT NULL,\n    text VARCHAR NOT NULL,\n    published BOOLEAN NOT NULL DEFAULT 0\n);\n"
  },
  {
    "path": "examples/databases/db/diesel/mysql-migrations/20210329150332_create_posts_table/down.sql",
    "content": "DROP TABLE posts;\n"
  },
  {
    "path": "examples/databases/db/diesel/mysql-migrations/20210329150332_create_posts_table/up.sql",
    "content": "CREATE TABLE posts (\n    id INTEGER AUTO_INCREMENT PRIMARY KEY,\n    title VARCHAR(255) NOT NULL,\n    text TEXT NOT NULL,\n    published BOOLEAN NOT NULL DEFAULT FALSE\n);\n"
  },
  {
    "path": "examples/databases/db/sqlx/migrations/20210331024424_create-posts-table.sql",
    "content": "CREATE TABLE posts (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    title VARCHAR NOT NULL,\n    text VARCHAR NOT NULL,\n    published BOOLEAN NOT NULL DEFAULT 0\n);\n"
  },
  {
    "path": "examples/databases/src/diesel_mysql.rs",
    "content": "use rocket::{Rocket, Build};\nuse rocket::fairing::AdHoc;\nuse rocket::response::{Debug, status::Created};\nuse rocket::serde::{Serialize, Deserialize, json::Json};\n\nuse rocket_db_pools::{Database, Connection};\nuse rocket_db_pools::diesel::{prelude::*, MysqlPool};\n\ntype Result<T, E = Debug<diesel::result::Error>> = std::result::Result<T, E>;\n\n#[derive(Database)]\n#[database(\"diesel_mysql\")]\nstruct Db(MysqlPool);\n\n#[derive(Debug, Clone, Deserialize, Serialize, Queryable, Insertable)]\n#[serde(crate = \"rocket::serde\")]\n#[diesel(table_name = posts)]\nstruct Post {\n    #[serde(skip_deserializing)]\n    id: Option<i64>,\n    title: String,\n    text: String,\n    #[serde(skip_deserializing)]\n    published: bool,\n}\n\ndiesel::table! {\n    posts (id) {\n        id -> Nullable<BigInt>,\n        title -> Text,\n        text -> Text,\n        published -> Bool,\n    }\n}\n\n#[post(\"/\", data = \"<post>\")]\nasync fn create(mut db: Connection<Db>, mut post: Json<Post>) -> Result<Created<Json<Post>>> {\n    diesel::define_sql_function!(fn last_insert_id() -> BigInt);\n\n    let post = db.transaction(|mut conn| Box::pin(async move {\n        diesel::insert_into(posts::table)\n            .values(&*post)\n            .execute(&mut conn)\n            .await?;\n\n        post.id = Some(posts::table\n            .select(last_insert_id())\n            .first(&mut conn)\n            .await?);\n\n        Ok::<_, diesel::result::Error>(post)\n    })).await?;\n\n    Ok(Created::new(\"/\").body(post))\n}\n\n#[get(\"/\")]\nasync fn list(mut db: Connection<Db>) -> Result<Json<Vec<Option<i64>>>> {\n    let ids = posts::table\n        .select(posts::id)\n        .load(&mut db)\n        .await?;\n\n    Ok(Json(ids))\n}\n\n#[get(\"/<id>\")]\nasync fn read(mut db: Connection<Db>, id: i64) -> Option<Json<Post>> {\n    posts::table\n        .filter(posts::id.eq(id))\n        .first(&mut db)\n        .await\n        .map(Json)\n        .ok()\n}\n\n#[delete(\"/<id>\")]\nasync fn delete(mut db: Connection<Db>, id: i64) -> Result<Option<()>> {\n    let affected = diesel::delete(posts::table)\n        .filter(posts::id.eq(id))\n        .execute(&mut db)\n        .await?;\n\n    Ok((affected == 1).then_some(()))\n}\n\n#[delete(\"/\")]\nasync fn destroy(mut db: Connection<Db>) -> Result<()> {\n    diesel::delete(posts::table).execute(&mut db).await?;\n    Ok(())\n}\n\nasync fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {\n    use rocket_db_pools::diesel::AsyncConnectionWrapper;\n    use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};\n\n    const MIGRATIONS: EmbeddedMigrations = embed_migrations!(\"db/diesel/mysql-migrations\");\n\n    let conn = Db::fetch(&rocket)\n        .expect(\"database is attached\")\n        .get().await\n        .unwrap_or_else(|e| {\n            span_error!(\"failed to connect to MySQL database\" => error!(\"{e}\"));\n            panic!(\"aborting launch\");\n        });\n\n    // `run_pending_migrations` blocks, so it must be run in `spawn_blocking`\n    rocket::tokio::task::spawn_blocking(move || {\n        let mut conn: AsyncConnectionWrapper<_> = conn.into();\n        conn.run_pending_migrations(MIGRATIONS).expect(\"diesel migrations\");\n    }).await.expect(\"diesel migrations\");\n\n    rocket\n}\n\npub fn stage() -> AdHoc {\n    AdHoc::on_ignite(\"Diesel MySQL Stage\", |rocket| async {\n        rocket.attach(Db::init())\n            .attach(AdHoc::on_ignite(\"Diesel Migrations\", run_migrations))\n            .mount(\"/mysql\", routes![list, read, create, delete, destroy])\n    })\n}\n"
  },
  {
    "path": "examples/databases/src/diesel_sqlite.rs",
    "content": "use rocket::{Rocket, Build};\nuse rocket::fairing::AdHoc;\nuse rocket::response::{Debug, status::Created};\nuse rocket::serde::{Serialize, Deserialize, json::Json};\n\nuse diesel::prelude::*;\n\n#[database(\"diesel\")]\nstruct Db(diesel::SqliteConnection);\n\ntype Result<T, E = Debug<diesel::result::Error>> = std::result::Result<T, E>;\n\n#[derive(Debug, Clone, Deserialize, Serialize, Queryable, Insertable)]\n#[serde(crate = \"rocket::serde\")]\n#[diesel(table_name = posts)]\nstruct Post {\n    #[serde(skip_deserializing)]\n    id: Option<i32>,\n    title: String,\n    text: String,\n    #[serde(skip_deserializing)]\n    published: bool,\n}\n\ntable! {\n    posts (id) {\n        id -> Nullable<Integer>,\n        title -> Text,\n        text -> Text,\n        published -> Bool,\n    }\n}\n\n#[post(\"/\", data = \"<post>\")]\nasync fn create(db: Db, mut post: Json<Post>) -> Result<Created<Json<Post>>> {\n    let post_value = post.clone();\n    let id: Option<i32> = db.run(move |conn| {\n        diesel::insert_into(posts::table)\n            .values(&*post_value)\n            .returning(posts::id)\n            .get_result(conn)\n    }).await?;\n\n    post.id = Some(id.expect(\"returning guarantees id present\"));\n    Ok(Created::new(\"/\").body(post))\n}\n\n#[get(\"/\")]\nasync fn list(db: Db) -> Result<Json<Vec<Option<i32>>>> {\n    let ids: Vec<Option<i32>> = db.run(move |conn| {\n        posts::table\n            .select(posts::id)\n            .load(conn)\n    }).await?;\n\n    Ok(Json(ids))\n}\n\n#[get(\"/<id>\")]\nasync fn read(db: Db, id: i32) -> Option<Json<Post>> {\n    db.run(move |conn| {\n        posts::table\n            .filter(posts::id.eq(id))\n            .first(conn)\n    }).await.map(Json).ok()\n}\n\n#[delete(\"/<id>\")]\nasync fn delete(db: Db, id: i32) -> Result<Option<()>> {\n    let affected = db.run(move |conn| {\n        diesel::delete(posts::table)\n            .filter(posts::id.eq(id))\n            .execute(conn)\n    }).await?;\n\n    Ok((affected == 1).then_some(()))\n}\n\n#[delete(\"/\")]\nasync fn destroy(db: Db) -> Result<()> {\n    db.run(move |conn| diesel::delete(posts::table).execute(conn)).await?;\n\n    Ok(())\n}\n\nasync fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {\n    use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};\n\n    const MIGRATIONS: EmbeddedMigrations = embed_migrations!(\"db/diesel/migrations\");\n\n    Db::get_one(&rocket).await\n        .expect(\"database connection\")\n        .run(|conn| { conn.run_pending_migrations(MIGRATIONS).expect(\"diesel migrations\"); })\n        .await;\n\n    rocket\n}\n\npub fn stage() -> AdHoc {\n    AdHoc::on_ignite(\"Diesel SQLite Stage\", |rocket| async {\n        rocket.attach(Db::fairing())\n            .attach(AdHoc::on_ignite(\"Diesel Migrations\", run_migrations))\n            .mount(\"/diesel\", routes![list, read, create, delete, destroy])\n    })\n}\n"
  },
  {
    "path": "examples/databases/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n#[macro_use] extern crate rocket_sync_db_pools;\n\n#[cfg(test)] mod tests;\n\nmod sqlx;\nmod diesel_sqlite;\nmod diesel_mysql;\nmod rusqlite;\n\nuse rocket::response::Redirect;\n\n#[get(\"/\")]\nfn index() -> Redirect {\n    Redirect::to(uri!(\"/sqlx\", sqlx::list()))\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![index])\n        .attach(sqlx::stage())\n        .attach(rusqlite::stage())\n        .attach(diesel_sqlite::stage())\n        .attach(diesel_mysql::stage())\n}\n"
  },
  {
    "path": "examples/databases/src/rusqlite.rs",
    "content": "use rocket::{Rocket, Build};\nuse rocket::fairing::AdHoc;\nuse rocket::serde::{Serialize, Deserialize, json::Json};\nuse rocket::response::{Debug, status::Created};\n\nuse rocket_sync_db_pools::rusqlite;\n\nuse self::rusqlite::params;\n\n#[database(\"rusqlite\")]\nstruct Db(rusqlite::Connection);\n\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Post {\n    #[serde(skip_deserializing, skip_serializing_if = \"Option::is_none\")]\n    id: Option<i64>,\n    title: String,\n    text: String,\n}\n\ntype Result<T, E = Debug<rusqlite::Error>> = std::result::Result<T, E>;\n\n#[post(\"/\", data = \"<post>\")]\nasync fn create(db: Db, mut post: Json<Post>) -> Result<Created<Json<Post>>> {\n    let item = post.clone();\n    let id = db.run(move |conn| {\n        conn.query_row(\"INSERT INTO posts (title, text) VALUES (?1, ?2) RETURNING id\",\n            params![item.title, item.text],\n            |r| r.get(0))\n    }).await?;\n\n    post.id = Some(id);\n    Ok(Created::new(\"/\").body(post))\n}\n\n#[get(\"/\")]\nasync fn list(db: Db) -> Result<Json<Vec<i64>>> {\n    let ids = db.run(|conn| {\n        conn.prepare(\"SELECT id FROM posts\")?\n            .query_map(params![], |row| row.get(0))?\n            .collect::<Result<Vec<i64>, _>>()\n    }).await?;\n\n    Ok(Json(ids))\n}\n\n#[get(\"/<id>\")]\nasync fn read(db: Db, id: i64) -> Option<Json<Post>> {\n    let post = db.run(move |conn| {\n        conn.query_row(\"SELECT id, title, text FROM posts WHERE id = ?1\", params![id],\n            |r| Ok(Post { id: Some(r.get(0)?), title: r.get(1)?, text: r.get(2)? }))\n    }).await.ok()?;\n\n    Some(Json(post))\n}\n\n#[delete(\"/<id>\")]\nasync fn delete(db: Db, id: i64) -> Result<Option<()>> {\n    let affected = db.run(move |conn| {\n        conn.execute(\"DELETE FROM posts WHERE id = ?1\", params![id])\n    }).await?;\n\n    Ok((affected == 1).then_some(()))\n}\n\n#[delete(\"/\")]\nasync fn destroy(db: Db) -> Result<()> {\n    db.run(move |conn| conn.execute(\"DELETE FROM posts\", params![])).await?;\n\n    Ok(())\n}\n\nasync fn init_db(rocket: Rocket<Build>) -> Rocket<Build> {\n    Db::get_one(&rocket).await\n        .expect(\"database mounted\")\n        .run(|conn| {\n            conn.execute(r#\"\n                CREATE TABLE posts (\n                    id INTEGER PRIMARY KEY AUTOINCREMENT,\n                    title VARCHAR NOT NULL,\n                    text VARCHAR NOT NULL,\n                    published BOOLEAN NOT NULL DEFAULT 0\n                )\"#, params![])\n        }).await\n        .expect(\"can init rusqlite DB\");\n\n    rocket\n}\n\npub fn stage() -> AdHoc {\n    AdHoc::on_ignite(\"Rusqlite Stage\", |rocket| async {\n        rocket.attach(Db::fairing())\n            .attach(AdHoc::on_ignite(\"Rusqlite Init\", init_db))\n            .mount(\"/rusqlite\", routes![list, create, read, delete, destroy])\n    })\n}\n"
  },
  {
    "path": "examples/databases/src/sqlx.rs",
    "content": "use rocket::{Rocket, Build, futures};\nuse rocket::fairing::{self, AdHoc};\nuse rocket::response::status::Created;\nuse rocket::serde::{Serialize, Deserialize, json::Json};\n\nuse rocket_db_pools::{Database, Connection};\n\nuse futures::{stream::TryStreamExt, future::TryFutureExt};\n\n#[derive(Database)]\n#[database(\"sqlx\")]\nstruct Db(sqlx::SqlitePool);\n\ntype Result<T, E = rocket::response::Debug<sqlx::Error>> = std::result::Result<T, E>;\n\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Post {\n    #[serde(skip_deserializing, skip_serializing_if = \"Option::is_none\")]\n    id: Option<i64>,\n    title: String,\n    text: String,\n}\n\n#[post(\"/\", data = \"<post>\")]\nasync fn create(mut db: Connection<Db>, mut post: Json<Post>) -> Result<Created<Json<Post>>> {\n    // NOTE: sqlx#2543, sqlx#1648 mean we can't use the pithier `fetch_one()`.\n    let results = sqlx::query!(\n            \"INSERT INTO posts (title, text) VALUES (?, ?) RETURNING id\",\n            post.title, post.text\n        )\n        .fetch(&mut **db)\n        .try_collect::<Vec<_>>()\n        .await?;\n\n    post.id = Some(results.first().expect(\"returning results\").id);\n    Ok(Created::new(\"/\").body(post))\n}\n\n#[get(\"/\")]\nasync fn list(mut db: Connection<Db>) -> Result<Json<Vec<i64>>> {\n    let ids = sqlx::query!(\"SELECT id FROM posts\")\n        .fetch(&mut **db)\n        .map_ok(|record| record.id)\n        .try_collect::<Vec<_>>()\n        .await?;\n\n    Ok(Json(ids))\n}\n\n#[get(\"/<id>\")]\nasync fn read(mut db: Connection<Db>, id: i64) -> Option<Json<Post>> {\n    sqlx::query!(\"SELECT id, title, text FROM posts WHERE id = ?\", id)\n        .fetch_one(&mut **db)\n        .map_ok(|r| Json(Post { id: Some(r.id), title: r.title, text: r.text }))\n        .await\n        .ok()\n}\n\n#[delete(\"/<id>\")]\nasync fn delete(mut db: Connection<Db>, id: i64) -> Result<Option<()>> {\n    let result = sqlx::query!(\"DELETE FROM posts WHERE id = ?\", id)\n        .execute(&mut **db)\n        .await?;\n\n    Ok((result.rows_affected() == 1).then_some(()))\n}\n\n#[delete(\"/\")]\nasync fn destroy(mut db: Connection<Db>) -> Result<()> {\n    sqlx::query!(\"DELETE FROM posts\").execute(&mut **db).await?;\n\n    Ok(())\n}\n\nasync fn run_migrations(rocket: Rocket<Build>) -> fairing::Result {\n    match Db::fetch(&rocket) {\n        Some(db) => match sqlx::migrate!(\"db/sqlx/migrations\").run(&**db).await {\n            Ok(_) => Ok(rocket),\n            Err(e) => {\n                error!(\"Failed to initialize SQLx database: {}\", e);\n                Err(rocket)\n            }\n        }\n        None => Err(rocket),\n    }\n}\n\npub fn stage() -> AdHoc {\n    AdHoc::on_ignite(\"SQLx Stage\", |rocket| async {\n        rocket.attach(Db::init())\n            .attach(AdHoc::try_on_ignite(\"SQLx Migrations\", run_migrations))\n            .mount(\"/sqlx\", routes![list, create, read, delete, destroy])\n    })\n}\n"
  },
  {
    "path": "examples/databases/src/tests.rs",
    "content": "use rocket::fairing::AdHoc;\nuse rocket::local::blocking::Client;\nuse rocket::serde::{Serialize, Deserialize};\nuse rocket::http::Status;\n\n#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Post {\n    title: String,\n    text: String,\n}\n\nfn test(base: &str, stage: AdHoc) {\n    // Number of posts we're going to create/read/delete.\n    const N: usize = 20;\n\n    // NOTE: If we had more than one test running concurrently that dispatches\n    // DB-accessing requests, we'd need transactions or to serialize all tests.\n    let client = Client::tracked(rocket::build().attach(stage)).unwrap();\n\n    // Clear everything from the database.\n    assert_eq!(client.delete(base).dispatch().status(), Status::Ok);\n    assert_eq!(client.get(base).dispatch().into_json::<Vec<i64>>(), Some(vec![]));\n\n    // Add some random posts, ensure they're listable and readable.\n    for i in 1..=N{\n        let title = format!(\"My Post - {}\", i);\n        let text = format!(\"Once upon a time, at {}'o clock...\", i);\n        let post = Post { title: title.clone(), text: text.clone() };\n\n        // Create a new post.\n        let response = client.post(base).json(&post).dispatch().into_json::<Post>();\n        assert_eq!(response.unwrap(), post);\n\n        // Ensure the index shows one more post.\n        let list = client.get(base).dispatch().into_json::<Vec<i64>>().unwrap();\n        assert_eq!(list.len(), i);\n\n        // The last in the index is the new one; ensure contents match.\n        let last = list.last().unwrap();\n        let response = client.get(format!(\"{}/{}\", base, last)).dispatch();\n        assert_eq!(response.into_json::<Post>().unwrap(), post);\n    }\n\n    // Now delete all of the posts.\n    for _ in 1..=N {\n        // Get a valid ID from the index.\n        let list = client.get(base).dispatch().into_json::<Vec<i64>>().unwrap();\n        let id = list.first().expect(\"have post\");\n\n        // Delete that post.\n        let response = client.delete(format!(\"{}/{}\", base, id)).dispatch();\n        assert_eq!(response.status(), Status::Ok);\n    }\n\n    // Ensure they're all gone.\n    let list = client.get(base).dispatch().into_json::<Vec<i64>>().unwrap();\n    assert!(list.is_empty());\n\n    // Trying to delete should now 404.\n    let response = client.delete(format!(\"{}/{}\", base, 1)).dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n}\n\n#[test]\nfn test_sqlx() {\n    test(\"/sqlx\", crate::sqlx::stage())\n}\n\n#[test]\nfn test_diesel() {\n    test(\"/diesel\", crate::diesel_sqlite::stage())\n}\n\n#[test]\nfn test_rusqlite() {\n    test(\"/rusqlite\", crate::rusqlite::stage())\n}\n"
  },
  {
    "path": "examples/error-handling/Cargo.toml",
    "content": "[package]\nname = \"error-handling\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n"
  },
  {
    "path": "examples/error-handling/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\nuse rocket::{Rocket, Request, Build};\nuse rocket::response::{content, status};\nuse rocket::http::Status;\n\n#[get(\"/hello/<name>/<age>\")]\nfn hello(name: &str, age: i8) -> String {\n    format!(\"Hello, {} year old named {}!\", age, name)\n}\n\n#[get(\"/<code>\")]\nfn forced_error(code: u16) -> Status {\n    Status::new(code)\n}\n\n#[catch(404)]\nfn general_not_found() -> content::RawHtml<&'static str> {\n    content::RawHtml(r#\"\n        <p>Hmm... What are you looking for?</p>\n        Say <a href=\"/hello/Sergio/100\">hello!</a>\n    \"#)\n}\n\n#[catch(404)]\nfn hello_not_found(req: &Request<'_>) -> content::RawHtml<String> {\n    content::RawHtml(format!(\"\\\n        <p>Sorry, but '{}' is not a valid path!</p>\\\n        <p>Try visiting /hello/&lt;name&gt;/&lt;age&gt; instead.</p>\",\n        req.uri()))\n}\n\n#[catch(default)]\nfn sergio_error() -> &'static str {\n    \"I...don't know what to say.\"\n}\n\n#[catch(default)]\nfn default_catcher(status: Status, req: &Request<'_>) -> status::Custom<String> {\n    let msg = format!(\"{} ({})\", status, req.uri());\n    status::Custom(status, msg)\n}\n\n#[allow(dead_code)]\n#[get(\"/unmanaged\")]\nfn unmanaged(_u8: &rocket::State<u8>, _string: &rocket::State<String>) { }\n\nfn rocket() -> Rocket<Build> {\n    rocket::build()\n        // .mount(\"/\", routes![hello, hello]) // uncomment this to get an error\n        // .mount(\"/\", routes![unmanaged]) // uncomment this to get a sentinel error\n        .mount(\"/\", routes![hello, forced_error])\n        .register(\"/\", catchers![general_not_found, default_catcher])\n        .register(\"/hello\", catchers![hello_not_found])\n        .register(\"/hello/Sergio\", catchers![sergio_error])\n}\n\n#[rocket::main]\nasync fn main() {\n    if let Err(e) = rocket().launch().await {\n        println!(\"Whoops! Rocket didn't launch!\");\n        // We drop the error to get a Rocket-formatted panic.\n        drop(e);\n    };\n}\n"
  },
  {
    "path": "examples/error-handling/src/tests.rs",
    "content": "use rocket::local::blocking::Client;\nuse rocket::http::Status;\n\n#[test]\nfn test_hello() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    let (name, age) = (\"Arthur\", 42);\n    let uri = format!(\"/hello/{}/{}\", name, age);\n    let response = client.get(uri).dispatch();\n\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.into_string().unwrap(), super::hello(name, age));\n}\n\n#[test]\nfn forced_error() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    let request = client.get(\"/404\");\n    let expected = super::general_not_found();\n    let response = request.dispatch();\n    assert_eq!(response.status(), Status::NotFound);\n    assert_eq!(response.into_string().unwrap(), expected.0);\n\n    let request = client.get(\"/405\");\n    let expected = super::default_catcher(Status::MethodNotAllowed, request.inner());\n    let response = request.dispatch();\n    assert_eq!(response.status(), Status::MethodNotAllowed);\n    assert_eq!(response.into_string().unwrap(), expected.1);\n\n    let request = client.get(\"/533\");\n    let expected = super::default_catcher(Status::new(533), request.inner());\n    let response = request.dispatch();\n    assert_eq!(response.status(), Status::new(533));\n    assert_eq!(response.into_string().unwrap(), expected.1);\n\n    let request = client.get(\"/700\");\n    let expected = super::default_catcher(Status::InternalServerError, request.inner());\n    let response = request.dispatch();\n    assert_eq!(response.status(), Status::InternalServerError);\n    assert_eq!(response.into_string().unwrap(), expected.1);\n}\n\n#[test]\nfn test_hello_invalid_age() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    for path in &[\"Ford/-129\", \"Trillian/128\"] {\n        let request = client.get(format!(\"/hello/{}\", path));\n        let expected = super::default_catcher(Status::UnprocessableEntity, request.inner());\n        let response = request.dispatch();\n        assert_eq!(response.status(), Status::UnprocessableEntity);\n        assert_eq!(response.into_string().unwrap(), expected.1);\n    }\n\n    {\n        let path = &\"foo/bar/baz\";\n        let request = client.get(format!(\"/hello/{}\", path));\n        let expected = super::hello_not_found(request.inner());\n        let response = request.dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n        assert_eq!(response.into_string().unwrap(), expected.0);\n    }\n}\n\n#[test]\nfn test_hello_sergio() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    for path in &[\"oops\", \"-129\"] {\n        let request = client.get(format!(\"/hello/Sergio/{}\", path));\n        let expected = super::sergio_error();\n        let response = request.dispatch();\n        assert_eq!(response.status(), Status::UnprocessableEntity);\n        assert_eq!(response.into_string().unwrap(), expected);\n    }\n\n    for path in &[\"foo/bar\", \"/foo/bar/baz\"] {\n        let request = client.get(format!(\"/hello/Sergio/{}\", path));\n        let expected = super::sergio_error();\n        let response = request.dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n        assert_eq!(response.into_string().unwrap(), expected);\n    }\n}\n"
  },
  {
    "path": "examples/fairings/Cargo.toml",
    "content": "[package]\nname = \"fairings\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n"
  },
  {
    "path": "examples/fairings/Rocket.toml",
    "content": "[global]\ntoken = 123\n"
  },
  {
    "path": "examples/fairings/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse std::io::Cursor;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse std::sync::Arc;\n\nuse rocket::{Rocket, Request, State, Data, Build};\nuse rocket::fairing::{self, AdHoc, Fairing, Info, Kind};\nuse rocket::trace::Trace;\nuse rocket::http::Method;\n\nstruct Token(i64);\n\n#[cfg(test)] mod tests;\n\n#[derive(Default, Clone)]\nstruct Counter {\n    get: Arc<AtomicUsize>,\n    post: Arc<AtomicUsize>,\n}\n\n#[rocket::async_trait]\nimpl Fairing for Counter {\n    fn info(&self) -> Info {\n        Info {\n            name: \"GET/POST Counter\",\n            kind: Kind::Ignite | Kind::Request\n        }\n    }\n\n    async fn on_ignite(&self, rocket: Rocket<Build>) -> fairing::Result {\n        #[get(\"/counts\")]\n        fn counts(counts: &State<Counter>) -> String {\n            let get_count = counts.get.load(Ordering::Relaxed);\n            let post_count = counts.post.load(Ordering::Relaxed);\n            format!(\"Get: {}\\nPost: {}\", get_count, post_count)\n        }\n\n        Ok(rocket.manage(self.clone()).mount(\"/\", routes![counts]))\n    }\n\n    async fn on_request(&self, request: &mut Request<'_>, _: &mut Data<'_>) {\n        if request.method() == Method::Get {\n            self.get.fetch_add(1, Ordering::Relaxed);\n        } else if request.method() == Method::Post {\n            self.post.fetch_add(1, Ordering::Relaxed);\n        }\n    }\n}\n\n#[put(\"/\")]\nfn hello() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[get(\"/token\")]\nfn token(token: &State<Token>) -> String {\n    format!(\"{}\", token.0)\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![hello, token])\n        .attach(Counter::default())\n        .attach(AdHoc::try_on_ignite(\"Token State\", |rocket| async {\n            info!(\"adding token managed state\");\n            match rocket.figment().extract_inner(\"token\") {\n                Ok(value) => Ok(rocket.manage(Token(value))),\n                Err(_) => Err(rocket)\n            }\n        }))\n        .attach(AdHoc::on_liftoff(\"Liftoff Message\", |_| Box::pin(async move {\n            info!(\"We have liftoff!\");\n        })))\n        .attach(AdHoc::on_request(\"PUT Rewriter\", |req, _| {\n            Box::pin(async move {\n                if req.uri().path() == \"/\" {\n                    span_info!(\"PUT rewriter\" => {\n                        req.trace_info();\n                        info!(\"changing method to `PUT`\");\n                        req.set_method(Method::Put);\n                        req.trace_info();\n                    })\n                }\n            })\n        }))\n        .attach(AdHoc::on_response(\"Response Rewriter\", |req, res| {\n            Box::pin(async move {\n                if req.uri().path() == \"/\" {\n                    info!(\"rewriting response body\");\n                    res.set_sized_body(None, Cursor::new(\"Hello, fairings!\"));\n                }\n            })\n        }))\n}\n"
  },
  {
    "path": "examples/fairings/src/tests.rs",
    "content": "use super::rocket;\nuse rocket::local::blocking::Client;\n\n#[test]\nfn rewrite_get_put() {\n    let client = Client::tracked(rocket()).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert_eq!(response.into_string(), Some(\"Hello, fairings!\".into()));\n}\n\n#[test]\nfn counts() {\n    let client = Client::tracked(rocket()).unwrap();\n\n    // Issue 1 GET request.\n    client.get(\"/\").dispatch();\n\n    // Check the GET count, taking into account _this_ GET request.\n    let response = client.get(\"/counts\").dispatch();\n    assert_eq!(response.into_string(), Some(\"Get: 2\\nPost: 0\".into()));\n\n    // Issue 1 more GET request and a POST.\n    client.get(\"/\").dispatch();\n    client.post(\"/\").dispatch();\n\n    // Check the counts.\n    let response = client.get(\"/counts\").dispatch();\n    assert_eq!(response.into_string(), Some(\"Get: 4\\nPost: 1\".into()));\n}\n\n#[test]\nfn token() {\n    let client = Client::tracked(rocket()).unwrap();\n\n    // Ensure the token is '123', which is what we have in `Rocket.toml`.\n    let res = client.get(\"/token\").dispatch();\n    assert_eq!(res.into_string(), Some(\"123\".into()));\n}\n"
  },
  {
    "path": "examples/forms/Cargo.toml",
    "content": "[package]\nname = \"forms\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n\n[dependencies.rocket_dyn_templates]\npath = \"../../contrib/dyn_templates\"\nfeatures = [\"tera\"]\n"
  },
  {
    "path": "examples/forms/Rocket.toml",
    "content": "[default]\nlimits.data-form = \"2MiB\"\ntemplate_dir = \"templates/\"\n"
  },
  {
    "path": "examples/forms/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::time::Date;\nuse rocket::http::{Status, ContentType};\nuse rocket::form::{Form, Contextual, FromForm, FromFormField, Context};\nuse rocket::fs::{FileServer, TempFile, relative};\n\nuse rocket_dyn_templates::Template;\n\n#[derive(Debug, FromForm)]\nstruct Password<'v> {\n    #[field(validate = len(6..))]\n    #[field(validate = eq(self.second))]\n    #[allow(unused)]\n    first: &'v str,\n    #[allow(unused)]\n    #[field(validate = eq(self.first))]\n    second: &'v str,\n}\n\n#[derive(Debug, FromFormField)]\nenum Rights {\n    Public,\n    Reserved,\n    Exclusive,\n}\n\n#[derive(Debug, FromFormField)]\nenum Category {\n    Biology,\n    Chemistry,\n    Physics,\n    #[field(value = \"CS\")]\n    ComputerScience,\n}\n\n#[derive(Debug, FromForm)]\n#[allow(dead_code)]\nstruct Submission<'v> {\n    #[field(validate = len(1..))]\n    title: &'v str,\n    date: Date,\n    #[field(validate = len(1..=250))]\n    r#abstract: &'v str,\n    #[field(validate = ext(ContentType::PDF))]\n    file: TempFile<'v>,\n    #[field(validate = len(1..))]\n    category: Vec<Category>,\n    rights: Rights,\n    ready: bool,\n}\n\n#[derive(Debug, FromForm)]\n#[allow(dead_code)]\nstruct Account<'v> {\n    #[field(validate = len(1..))]\n    name: &'v str,\n    password: Password<'v>,\n    #[field(validate = contains('@').or_else(msg!(\"invalid email address\")))]\n    email: &'v str,\n}\n\n#[derive(Debug, FromForm)]\n#[allow(dead_code)]\nstruct Submit<'v> {\n    account: Account<'v>,\n    submission: Submission<'v>,\n}\n\n#[get(\"/\")]\nfn index() -> Template {\n    Template::render(\"index\", &Context::default())\n}\n\n// NOTE: We use `Contextual` here because we want to collect all submitted form\n// fields to re-render forms with submitted values on error. If you have no such\n// need, do not use `Contextual`. Use the equivalent of `Form<Submit<'_>>`.\n#[post(\"/\", data = \"<form>\")]\nfn submit<'r>(form: Form<Contextual<'r, Submit<'r>>>) -> (Status, Template) {\n    let template = match form.value {\n        Some(ref submission) => {\n            println!(\"submission: {:#?}\", submission);\n            Template::render(\"success\", &form.context)\n        }\n        None => Template::render(\"index\", &form.context),\n    };\n\n    (form.context.status(), template)\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![index, submit])\n        .attach(Template::fairing())\n        .mount(\"/\", FileServer::new(relative!(\"/static\")))\n}\n"
  },
  {
    "path": "examples/forms/src/tests.rs",
    "content": "use std::fmt;\nuse super::{rocket, FormInput, FormOption};\n\nuse rocket::local::blocking::Client;\nuse rocket::http::ContentType;\n\nimpl fmt::Display for FormOption {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            FormOption::A => write!(f, \"a\"),\n            FormOption::B => write!(f, \"b\"),\n            FormOption::C => write!(f, \"c\"),\n        }\n    }\n}\n\nmacro_rules! assert_form_eq {\n    ($client:expr, $form_str:expr, $expected:expr) => {{\n        let res = $client.post(\"/\")\n            .header(ContentType::Form)\n            .body($form_str)\n            .dispatch();\n\n        assert_eq!(res.into_string(), Some($expected));\n    }};\n}\n\nmacro_rules! assert_valid_form {\n    ($client:expr, $input:expr) => {{\n        let f = format!(\"checkbox={}&number={}&type={}&password={}&textarea={}&select={}\",\n                $input.checkbox, $input.number, $input.radio, $input.password,\n                $input.text_area, $input.select);\n        assert_form_eq!($client, &f, format!(\"{:?}\", $input));\n    }};\n}\n\nmacro_rules! assert_valid_raw_form {\n    ($client:expr, $form_str:expr, $input:expr) => {{\n        assert_form_eq!($client, $form_str, format!(\"{:?}\", $input));\n    }};\n}\n\n#[test]\nfn test_good_forms() {\n    let client = Client::tracked(rocket()).unwrap();\n    let mut input = FormInput {\n        checkbox: true,\n        number: 310,\n        radio: FormOption::A,\n        password: \"beep\".into(),\n        text_area: \"bop\".to_string(),\n        select: FormOption::B\n    };\n\n    assert_valid_form!(&client, &input);\n\n    input.checkbox = false;\n    assert_valid_form!(&client, &input);\n\n    input.number = 0;\n    assert_valid_form!(&client, &input);\n    input.number = 120;\n    assert_valid_form!(&client, &input);\n    input.number = 133;\n    assert_valid_form!(&client, &input);\n\n    input.radio = FormOption::B;\n    assert_valid_form!(&client, &input);\n    input.radio = FormOption::C;\n    assert_valid_form!(&client, &input);\n\n    input.password = \"\".into();\n    assert_valid_form!(&client, &input);\n    input.password = \"----90138490285u2o3hndslkv\".into();\n    assert_valid_form!(&client, &input);\n    input.password = \"hi\".into();\n    assert_valid_form!(&client, &input);\n\n    input.text_area = \"\".to_string();\n    assert_valid_form!(&client, &input);\n    input.text_area = \"----90138490285u2o3hndslkv\".to_string();\n    assert_valid_form!(&client, &input);\n    input.text_area = \"hey\".to_string();\n    assert_valid_form!(&client, &input);\n\n    input.select = FormOption::A;\n    assert_valid_form!(&client, &input);\n    input.select = FormOption::C;\n    assert_valid_form!(&client, &input);\n\n    // checkbox need not be present; defaults to false; accepts 'on' and 'off'\n    assert_valid_raw_form!(&client,\n                          \"number=133&type=c&password=hi&textarea=hey&select=c\",\n                          &input);\n\n    assert_valid_raw_form!(&client,\n                          \"checkbox=off&number=133&type=c&password=hi&textarea=hey&select=c\",\n                          &input);\n\n    input.checkbox = true;\n    assert_valid_raw_form!(&client,\n                          \"checkbox=on&number=133&type=c&password=hi&textarea=hey&select=c\",\n                          &input);\n}\n\nmacro_rules! assert_invalid_form {\n    ($client:expr, $vals:expr) => {{\n        let vals = $vals;\n        let s = format!(\"checkbox={}&number={}&type={}&password={}&textarea={}&select={}\",\n                        vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]);\n        assert_form_eq!($client, &s, format!(\"Invalid form input: {}\", s));\n        *vals = [\"true\", \"1\", \"a\", \"hi\", \"hey\", \"b\"];\n    }};\n}\n\nmacro_rules! assert_invalid_raw_form {\n    ($client:expr, $form_str:expr) => {{\n        assert_form_eq!($client, $form_str, format!(\"Invalid form input: {}\", $form_str));\n    }};\n}\n\n#[test]\nfn check_semantically_invalid_forms() {\n    let client = Client::tracked(rocket()).unwrap();\n    let mut form_vals = [\"true\", \"1\", \"a\", \"hi\", \"hey\", \"b\"];\n\n    form_vals[0] = \"not true\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[0] = \"bing\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[0] = \"true0\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[0] = \" false\";\n    assert_invalid_form!(&client, &mut form_vals);\n\n    form_vals[1] = \"-1\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[1] = \"1e10\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[1] = \"-1-1\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[1] = \"NaN\";\n    assert_invalid_form!(&client, &mut form_vals);\n\n    form_vals[2] = \"A?\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[2] = \" B\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[2] = \"d\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[2] = \"100\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[2] = \"\";\n    assert_invalid_form!(&client, &mut form_vals);\n\n    // password and textarea are always valid, so we skip them\n    form_vals[5] = \"A.\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[5] = \"b \";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[5] = \"d\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[5] = \"-a\";\n    assert_invalid_form!(&client, &mut form_vals);\n    form_vals[5] = \"\";\n    assert_invalid_form!(&client, &mut form_vals);\n\n    // now forms with missing fields\n    assert_invalid_raw_form!(&client, \"number=10&type=a&password=hi&textarea=hey\");\n    assert_invalid_raw_form!(&client, \"number=10&radio=a&password=hi&textarea=hey&select=b\");\n    assert_invalid_raw_form!(&client, \"number=10&password=hi&select=b\");\n    assert_invalid_raw_form!(&client, \"number=10&select=b\");\n    assert_invalid_raw_form!(&client, \"password=hi&select=b\");\n    assert_invalid_raw_form!(&client, \"password=hi\");\n    assert_invalid_raw_form!(&client, \"\");\n}\n\n#[test]\nfn check_structurally_invalid_forms() {\n    let client = Client::tracked(rocket()).unwrap();\n    assert_invalid_raw_form!(&client, \"==&&&&&&==\");\n    assert_invalid_raw_form!(&client, \"a&=b\");\n    assert_invalid_raw_form!(&client, \"=\");\n}\n\n#[test]\nfn check_bad_utf8() {\n    let client = Client::tracked(rocket()).unwrap();\n    unsafe {\n        let bad_str = std::str::from_utf8_unchecked(b\"a=\\xff\");\n        assert_form_eq!(&client, bad_str, \"Form input was invalid UTF-8.\".into());\n    }\n}\n"
  },
  {
    "path": "examples/forms/templates/index.html.tera",
    "content": "{% import \"macros\" as m %}\n\n<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <title>Rocket Form Example</title>\n    <link rel=\"stylesheet\" href=\"/chota.min.css\">\n    <style>\n      .container {\n        max-width: 800px;\n        margin: 0 auto;\n        padding: 20px 10px;\n      }\n\n      h1 {\n          margin: 10px 0;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <h1>Form Example</h1>\n\n      {% if errors | length > 0 %}\n          <div class=\"row\">\n            <div class=\"col\">\n              <small class=\"text-error\">\n                error: {{ errors | length }} field{{ errors | length | pluralize }}\n                failed to validate\n              </small>\n            </div>\n          </div>\n      {% endif %}\n\n      <form action=\"/\" method=\"post\" enctype=\"multipart/form-data\">\n        <fieldset>\n          <legend>About You</legend>\n          <div class=\"row\">\n            <div class=\"col\">\n                {{ m::input(label=\"Name\", type=\"text\", name=\"account.name\") }}\n                <!-- required -->\n            </div>\n            <div class=\"col\">\n            {{ m::input(label=\"Email Address\", type=\"text\", name=\"account.email\") }}\n              <!-- required pattern=\".*@.*\"/> -->\n            </div>\n          </div>\n\n          <div class=\"row\">\n            <div class=\"col\">\n              {{ m::input(label=\"Password\", type=\"password\", name=\"account.password.first\") }}\n              <!--   required minlength=\"6\" value=\"\" /> -->\n            </div>\n\n            <div class=\"col\">\n\n            {{\n                m::input(label=\"Confirm Password\",\n                type=\"password\",\n                name=\"account.password.second\")\n            }}\n\n              <!--   required minlength=\"6\" value=\"\" /> -->\n            </div>\n          </div>\n        </fieldset>\n\n        <fieldset>\n          <legend>Metadata</legend>\n\n          <div class=\"row\">\n            <div class=\"col\">\n            {{ m::input(label=\"Title\", type=\"text\", name=\"submission.title\") }}\n              <!-- required -->\n            </div>\n          </div>\n\n          <div class=\"row\">\n            <div class=\"col\">\n            {{ m::input(label=\"Publish Date\", type=\"date\", name=\"submission.date\") }}\n              <!-- <input type=\"date\" name=\"submission.date\" id=\"date\" value=\"2020&#45;12&#45;26\"> -->\n            </div>\n\n            <div class=\"col\">\n            {{\n                m::select(\n                    label=\"Rights Assignment\",\n                    name=\"submission.rights\",\n                    options=[\"Public\", \"Reserved\", \"Exclusive\"]\n                )\n            }}\n            </div>\n          </div>\n\n          <div class=\"row\">\n            <div class=\"col\">\n              <label>Applicable Categories</label>\n              <br />\n              {{ m::checkbox(name=\"submission.category\", label=\"Biology\", value=\"Biology\") }}\n              <br />\n              {{ m::checkbox(name=\"submission.category\", label=\"Chemistry\", value=\"Chemistry\") }}\n              <br />\n              {{ m::checkbox(name=\"submission.category\", label=\"Physics\", value=\"Physics\") }}\n              <br />\n              {{ m::checkbox(name=\"submission.category\", label=\"CS\", value=\"CS\") }}\n            </div>\n          </div>\n\n        </fieldset>\n\n        <fieldset>\n          <legend>Contents</legend>\n\n            {{\n                m::textarea(\n                    label=\"Abstract\",\n                    name=\"submission.abstract\",\n                    placeholder=\"Your abstract, max 250 characters...\",\n                    max=250\n                )\n            }}\n\n          {{\n              m::input(\n                  label=\"File to Upload (PDF, max 1MiB)\",\n                  type=\"file\",\n                  name=\"submission.file\"\n              )\n          }}\n\n          <!-- <input type=\"file\" name=\"submission.file\" id=\"file\" required accept=\".pdf\"> -->\n\n          <div class=\"row\">\n            <div class=\"col\">\n                {{ m::checkbox(name=\"submission.ready\", label=\"Submission is ready for review.\") }}\n            </div>\n          </div>\n\n        </fieldset>\n\n        <br />\n        <input type=\"submit\" value=\"Submit\" class=\"is-full-width\" />\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/forms/templates/macros.html.tera",
    "content": "{% macro value_for(name) %}\n    {%- if name in values -%}\n        {{- values | get(key=name) | first -}}\n    {%- endif -%}\n{% endmacro value_for %}\n\n{% macro errors_for(name) %}\n    {%- if name in errors -%}\n        {% set field_errors = errors | get(key=name) %}\n        {% for error in field_errors %}\n            <p class=\"text-error is-marginless\">{{ error.msg }}</p>\n        {% endfor %}\n    {%- endif -%}\n{% endmacro errors_for %}\n\n{% macro input(type, label, name, value=\"\") %}\n    <label for=\"{{ name }}\">{{ label }}</label>\n    <input type=\"{{ type }}\"\n           name=\"{{ name }}\"\n           id=\"{{ name }}\"\n           value='{{ self::value_for(name=name) }}'\n           {% if name in errors %} class=\"error\" {% endif %}\n    />\n\n    {{ self::errors_for(name=name) }}\n{% endmacro input %}\n\n{% macro checkbox(name, label, value=\"yes\") %}\n    <label {% if name in errors %} class=\"bd-error\" {% endif %}>\n    <input type=\"checkbox\" name=\"{{ name }}\" value={{ value }}\n    {% if name in values %}\n        {% set field_values = values | get(key=name) %}\n        {% if field_values is containing(value) %}\n            checked\n        {% endif %}\n    {% endif %}\n    >\n        {{ label }}\n    </label>\n{% endmacro checkbox %}\n\n{% macro textarea(label, name, placeholder=\"\", max=250) %}\n    <label for=\"{{ name }}\">{{ label }}</label>\n    <textarea placeholder=\"{{ placeholder }}\"\n        name=\"{{ name }}\" id=\"{{ name }}\" rows=\"8\" cols=\"40\"\n        {% if name in errors %} class=\"error\" {% endif %}\n    >\n        {{- self::value_for(name=name) -}}\n    </textarea>\n\n    {{ self::errors_for(name=name) }}\n{% endmacro textarea %}\n\n{% macro select(label, name, options) %}\n    <label for=\"{{ name }}\">{{ label }}</label>\n    <select name=\"{{ name }}\" id=\"{{ name }}\">\n        {% for value in options %}\n            <option value=\"{{ value }}\"\n                {% if self::value_for(name=name) == value %} selected {% endif %}\n            >{{ value }}</option>\n        {% endfor %}\n    </select>\n{% endmacro select %}\n"
  },
  {
    "path": "examples/forms/templates/success.html.tera",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <title>Rocket Form Example</title>\n    <link rel=\"stylesheet\" href=\"/chota.min.css\">\n    <style>\n      .container {\n        max-width: 800px;\n        margin: 0 auto;\n        padding: 20px 10px;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n    <h1>Success!</h1>\n\n      <h3>Submission Data</h3>\n\n      <ul>\n          {% for key, value in values %}\n              <li><strong>{{ key }}</strong> - {{ value }}</li>\n          {% endfor %}\n      </ul>\n\n      <a href=\"/\">&lt; Submit Another</a>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/hello/Cargo.toml",
    "content": "[package]\nname = \"hello\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n"
  },
  {
    "path": "examples/hello/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\n#[derive(FromFormField)]\nenum Lang {\n    #[field(value = \"en\")]\n    English,\n    #[field(value = \"ru\")]\n    #[field(value = \"ру\")]\n    Russian\n}\n\n#[derive(FromForm)]\nstruct Options<'r> {\n    emoji: bool,\n    name: Option<&'r str>,\n}\n\n// Try visiting:\n//   http://127.0.0.1:8000/hello/world\n#[get(\"/world\")]\nfn world() -> &'static str {\n    \"Hello, world!\"\n}\n\n// Try visiting:\n//   http://127.0.0.1:8000/hello/мир\n#[get(\"/мир\")]\nfn mir() -> &'static str {\n    \"Привет, мир!\"\n}\n\n// Try visiting:\n//   http://127.0.0.1:8000/wave/Rocketeer/100\n#[get(\"/<name>/<age>\", rank = 2)]\nfn wave(name: &str, age: u8) -> String {\n    format!(\"👋 Hello, {} year old named {}!\", age, name)\n}\n\n// Note: without the `..` in `opt..`, we'd need to pass `opt.emoji`, `opt.name`.\n//\n// Try visiting:\n//   http://127.0.0.1:8000/?emoji\n//   http://127.0.0.1:8000/?name=Rocketeer\n//   http://127.0.0.1:8000/?lang=ру\n//   http://127.0.0.1:8000/?lang=ру&emoji\n//   http://127.0.0.1:8000/?emoji&lang=en\n//   http://127.0.0.1:8000/?name=Rocketeer&lang=en\n//   http://127.0.0.1:8000/?emoji&name=Rocketeer\n//   http://127.0.0.1:8000/?name=Rocketeer&lang=en&emoji\n//   http://127.0.0.1:8000/?lang=ru&emoji&name=Rocketeer\n#[get(\"/?<lang>&<opt..>\")]\nfn hello(lang: Option<Lang>, opt: Options<'_>) -> String {\n    let mut greeting = String::new();\n    if opt.emoji {\n        greeting.push_str(\"👋 \");\n    }\n\n    match lang {\n        Some(Lang::Russian) => greeting.push_str(\"Привет\"),\n        Some(Lang::English) => greeting.push_str(\"Hello\"),\n        None => greeting.push_str(\"Hi\"),\n    }\n\n    if let Some(name) = opt.name {\n        greeting.push_str(\", \");\n        greeting.push_str(name);\n    }\n\n    greeting.push('!');\n    greeting\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![hello])\n        .mount(\"/hello\", routes![world, mir])\n        .mount(\"/wave\", routes![wave])\n}\n"
  },
  {
    "path": "examples/hello/src/tests.rs",
    "content": "use rocket::local::blocking::Client;\nuse rocket::http::{RawStr, Status};\n\n#[test]\nfn hello() {\n    let langs = &[\"\", \"ru\", \"%D1%80%D1%83\", \"en\", \"unknown\"];\n    let ex_lang = &[\"Hi\", \"Привет\", \"Привет\", \"Hello\", \"Hi\"];\n\n    let emojis = &[\"\", \"on\", \"true\", \"false\", \"no\", \"yes\", \"off\"];\n    let ex_emoji = &[\"\", \"👋 \", \"👋 \", \"\", \"\", \"👋 \", \"\"];\n\n    let names = &[\"\", \"Bob\", \"Bob+Smith\"];\n    let ex_name = &[\"!\", \", Bob!\", \", Bob Smith!\"];\n\n    let client = Client::tracked(super::rocket()).unwrap();\n    for n in 0..(langs.len() * emojis.len() * names.len()) {\n        let i = n / (emojis.len() * names.len());\n        let j = n % (emojis.len() * names.len()) / names.len();\n        let k = n % (emojis.len() * names.len()) % names.len();\n\n        let (lang, ex_lang) = (langs[i], ex_lang[i]);\n        let (emoji, ex_emoji) = (emojis[j], ex_emoji[j]);\n        let (name, ex_name) = (names[k], ex_name[k]);\n        let expected = format!(\"{}{}{}\", ex_emoji, ex_lang, ex_name);\n\n        let q = |name, s: &str| match s.is_empty() {\n            true => \"\".into(),\n            false => format!(\"&{}={}\", name, s)\n        };\n\n        let uri = format!(\"/?{}{}{}\", q(\"lang\", lang), q(\"emoji\", emoji), q(\"name\", name));\n        let response = client.get(uri).dispatch();\n        assert_eq!(response.into_string().unwrap(), expected);\n\n        let uri = format!(\"/?{}{}{}\", q(\"emoji\", emoji), q(\"name\", name), q(\"lang\", lang));\n        let response = client.get(uri).dispatch();\n        assert_eq!(response.into_string().unwrap(), expected);\n    }\n}\n\n#[test]\nfn hello_world() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let response = client.get(\"/hello/world\").dispatch();\n    assert_eq!(response.into_string(), Some(\"Hello, world!\".into()));\n}\n\n#[test]\nfn hello_mir() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let response = client.get(\"/hello/%D0%BC%D0%B8%D1%80\").dispatch();\n    assert_eq!(response.into_string(), Some(\"Привет, мир!\".into()));\n}\n\n#[test]\nfn wave() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    for &(name, age) in &[(\"Bob%20Smith\", 22), (\"Michael\", 80), (\"A\", 0), (\"a\", 127)] {\n        let uri = format!(\"/wave/{}/{}\", name, age);\n        let real_name = RawStr::new(name).percent_decode_lossy();\n        let expected = format!(\"👋 Hello, {} year old named {}!\", age, real_name);\n        let response = client.get(uri).dispatch();\n        assert_eq!(response.into_string().unwrap(), expected);\n\n        for bad_age in &[\"1000\", \"-1\", \"bird\"] {\n            let bad_uri = format!(\"/wave/{}/{}\", name, bad_age);\n            let response = client.get(bad_uri).dispatch();\n            assert_eq!(response.status(), Status::UnprocessableEntity);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/manual-routing/Cargo.toml",
    "content": "[package]\nname = \"manual_routes\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n"
  },
  {
    "path": "examples/manual-routing/Rocket.toml",
    "content": "[global]\nport = 8000\n"
  },
  {
    "path": "examples/manual-routing/src/main.rs",
    "content": "#[cfg(test)]\nmod tests;\n\nuse rocket::{Request, Route, Catcher, route, catcher};\nuse rocket::data::{Data, ToByteUnit};\nuse rocket::http::{Status, Method::{Get, Post}};\nuse rocket::response::{Responder, status::Custom};\nuse rocket::outcome::{try_outcome, IntoOutcome};\nuse rocket::tokio::fs::File;\n\nfn forward<'r>(_req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {\n    Box::pin(async move { route::Outcome::forward(data, Status::NotFound) })\n}\n\nfn hi<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {\n    route::Outcome::from(req, \"Hello!\").pin()\n}\n\nfn name<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {\n    let param = req.param::<&'r str>(0)\n        .and_then(Result::ok)\n        .unwrap_or(\"unnamed\");\n\n    route::Outcome::from(req, param).pin()\n}\n\nfn echo_url<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {\n    let param_outcome = req.param::<&str>(1)\n        .and_then(Result::ok)\n        .or_error(Status::BadRequest);\n\n    Box::pin(async move {\n        route::Outcome::from(req, try_outcome!(param_outcome))\n    })\n}\n\nfn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {\n    Box::pin(async move {\n        if !req.content_type().map_or(false, |ct| ct.is_plain()) {\n            println!(\"    => Content-Type of upload must be text/plain. Ignoring.\");\n            return route::Outcome::error(Status::BadRequest);\n        }\n\n        let path = req.rocket().config().temp_dir.relative().join(\"upload.txt\");\n        let file = File::create(path).await;\n        if let Ok(file) = file {\n            if let Ok(n) = data.open(2.mebibytes()).stream_to(file).await {\n                return route::Outcome::from(req, format!(\"OK: {} bytes uploaded.\", n));\n            }\n\n            println!(\"    => Failed copying.\");\n            route::Outcome::error(Status::InternalServerError)\n        } else {\n            println!(\"    => Couldn't open file: {:?}\", file.unwrap_err());\n            route::Outcome::error(Status::InternalServerError)\n        }\n    })\n}\n\nfn get_upload<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {\n    let path = req.rocket().config().temp_dir.relative().join(\"upload.txt\");\n    route::Outcome::from(req, std::fs::File::open(path).ok()).pin()\n}\n\nfn not_found_handler<'r>(_: Status, req: &'r Request) -> catcher::BoxFuture<'r> {\n    let responder = Custom(Status::NotFound, format!(\"Couldn't find: {}\", req.uri()));\n    Box::pin(async move { responder.respond_to(req) })\n}\n\n#[derive(Clone)]\nstruct CustomHandler {\n    data: &'static str\n}\n\nimpl CustomHandler {\n    fn routes(data: &'static str) -> Vec<Route> {\n        vec![Route::new(Get, \"/<id>\", Self { data })]\n    }\n}\n\n#[rocket::async_trait]\nimpl route::Handler for CustomHandler {\n    async fn handle<'r>(&self, req: &'r Request<'_>, data: Data<'r>) -> route::Outcome<'r> {\n        let self_data = self.data;\n        let id = req.param::<&str>(0)\n            .and_then(Result::ok)\n            .or_forward((data, Status::NotFound));\n\n        route::Outcome::from(req, format!(\"{} - {}\", self_data, try_outcome!(id)))\n    }\n}\n\n#[rocket::launch]\nfn rocket() -> _ {\n    let always_forward = Route::ranked(1, Get, \"/\", forward);\n    let hello = Route::ranked(2, Get, \"/\", hi);\n\n    let echo = Route::new(Get, \"/echo/<str>\", echo_url);\n    let name = Route::new(Get, \"/<name>\", name);\n    let post_upload = Route::new(Post, \"/\", upload);\n    let get_upload = Route::new(Get, \"/\", get_upload);\n\n    let not_found_catcher = Catcher::new(404, not_found_handler);\n\n    rocket::build()\n        .mount(\"/\", vec![always_forward, hello, echo])\n        .mount(\"/upload\", vec![get_upload, post_upload])\n        .mount(\"/hello\", vec![name.clone()])\n        .mount(\"/hi\", vec![name])\n        .mount(\"/custom\", CustomHandler::routes(\"some data here\"))\n        .register(\"/\", vec![not_found_catcher])\n}\n"
  },
  {
    "path": "examples/manual-routing/src/tests.rs",
    "content": "use super::*;\nuse rocket::local::blocking::Client;\nuse rocket::http::ContentType;\n\nfn test(uri: &str, content_type: ContentType, status: Status, body: String) {\n    let client = Client::tracked(rocket()).unwrap();\n    let response = client.get(uri).header(content_type).dispatch();\n    assert_eq!(response.status(), status);\n    assert_eq!(response.into_string(), Some(body));\n}\n\n#[test]\nfn test_forward() {\n    test(\"/\", ContentType::Plain, Status::Ok, \"Hello!\".to_string());\n}\n\n#[test]\nfn test_name() {\n    for &name in &[(\"John\"), (\"Mike\"), (\"Angela\")] {\n        let uri = format!(\"/hello/{}\", name);\n        test(&uri, ContentType::Plain, Status::Ok, name.to_string());\n    }\n}\n\n#[test]\nfn test_echo() {\n    let uri = \"/echo/echo%20this%20text\".to_string();\n    test(&uri, ContentType::Plain, Status::Ok, \"echo this text\".into());\n}\n\n#[test]\nfn test_upload() {\n    let client = Client::tracked(rocket()).unwrap();\n    let expected_body = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, \\\n                         sed do eiusmod tempor incididunt ut labore et dolore \\\n                         magna aliqua\".to_string();\n\n    // Upload the body.\n    let response = client.post(\"/upload\")\n        .header(ContentType::Plain)\n        .body(&expected_body)\n        .dispatch();\n\n    assert_eq!(response.status(), Status::Ok);\n\n    // Ensure we get back the same body.\n    let response = client.get(\"/upload\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.into_string(), Some(expected_body));\n}\n\n#[test]\nfn test_not_found() {\n    let uri = \"/wrong_address\";\n    let expected_body = format!(\"Couldn't find: {}\", uri);\n    test(uri, ContentType::Plain, Status::NotFound, expected_body);\n}\n"
  },
  {
    "path": "examples/pastebin/Cargo.toml",
    "content": "[package]\nname = \"pastebin\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\nrand = \"0.9\"\n"
  },
  {
    "path": "examples/pastebin/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)]\nmod tests;\nmod paste_id;\n\nuse std::io;\n\nuse rocket::data::{Data, ToByteUnit};\nuse rocket::http::uri::Absolute;\nuse rocket::response::content::RawText;\nuse rocket::tokio::fs::{self, File};\n\nuse paste_id::PasteId;\n\n// In a real application, these would be retrieved dynamically from a config.\nconst HOST: Absolute<'static> = uri!(\"http://localhost:8000\");\nconst ID_LENGTH: usize = 3;\n\n#[post(\"/\", data = \"<paste>\")]\nasync fn upload(paste: Data<'_>) -> io::Result<String> {\n    let id = PasteId::new(ID_LENGTH);\n    paste.open(128.kibibytes()).into_file(id.file_path()).await?;\n    Ok(uri!(HOST, retrieve(id)).to_string())\n}\n\n#[get(\"/<id>\")]\nasync fn retrieve(id: PasteId<'_>) -> Option<RawText<File>> {\n    File::open(id.file_path()).await.map(RawText).ok()\n}\n\n#[delete(\"/<id>\")]\nasync fn delete(id: PasteId<'_>) -> Option<()> {\n    fs::remove_file(id.file_path()).await.ok()\n}\n\n#[get(\"/\")]\nfn index() -> &'static str {\n    \"\n    USAGE\n\n      POST /\n\n          accepts raw data in the body of the request and responds with a URL of\n          a page containing the body's content\n\n          EXAMPLE: curl --data-binary @file.txt http://localhost:8000\n\n      GET /<id>\n\n          retrieves the content for the paste with id `<id>`\n    \"\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build().mount(\"/\", routes![index, upload, delete, retrieve])\n}\n"
  },
  {
    "path": "examples/pastebin/src/paste_id.rs",
    "content": "use std::borrow::Cow;\nuse std::path::{Path, PathBuf};\n\nuse rand::Rng;\nuse rocket::request::FromParam;\n\n/// A _probably_ unique paste ID.\n#[derive(UriDisplayPath)]\npub struct PasteId<'a>(Cow<'a, str>);\n\nimpl PasteId<'_> {\n    /// Generate a _probably_ unique ID with `size` characters. For readability,\n    /// the characters used are from the sets [0-9], [A-Z], [a-z]. The\n    /// probability of a collision depends on the value of `size` and the number\n    /// of IDs generated thus far.\n    pub fn new(size: usize) -> PasteId<'static> {\n        const BASE62: &[u8] = b\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n        let mut id = String::with_capacity(size);\n        let mut rng = rand::rng();\n        for _ in 0..size {\n            id.push(BASE62[rng.random_range(0..62)] as char);\n        }\n\n        PasteId(Cow::Owned(id))\n    }\n\n    /// Returns the path to the paste in `upload/` corresponding to this ID.\n    pub fn file_path(&self) -> PathBuf {\n        let root = concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/\", \"upload\");\n        Path::new(root).join(self.0.as_ref())\n    }\n}\n\n/// Returns an instance of `PasteId` if the path segment is a valid ID.\n/// Otherwise returns the invalid ID as the `Err` value.\nimpl<'a> FromParam<'a> for PasteId<'a> {\n    type Error = &'a str;\n\n    fn from_param(param: &'a str) -> Result<Self, Self::Error> {\n        param.chars().all(|c| c.is_ascii_alphanumeric())\n            .then(|| PasteId(param.into()))\n            .ok_or(param)\n    }\n}\n"
  },
  {
    "path": "examples/pastebin/src/tests.rs",
    "content": "use super::{rocket, index, PasteId};\nuse rocket::local::blocking::Client;\nuse rocket::http::{Status, ContentType};\nuse rocket::request::FromParam;\n\nfn extract_id(from: &str) -> Option<String> {\n    from.rfind('/').map(|i| &from[(i + 1)..]).map(|s| s.trim_end().to_string())\n}\n\n#[test]\nfn check_index() {\n    let client = Client::tracked(rocket()).unwrap();\n\n    // Ensure the index returns what we expect.\n    let response = client.get(uri!(super::index)).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.content_type(), Some(ContentType::Plain));\n    assert_eq!(response.into_string(), Some(index().into()))\n}\n\nfn upload_paste(client: &Client, body: &str) -> String {\n    let response = client.post(uri!(super::upload)).body(body).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    assert_eq!(response.content_type(), Some(ContentType::Plain));\n    extract_id(&response.into_string().unwrap()).unwrap()\n}\n\nfn download_paste(client: &Client, id: &str) -> Option<String> {\n    let id = PasteId::from_param(id).expect(\"valid ID\");\n    let response = client.get(uri!(super::retrieve(id))).dispatch();\n    if response.status().class().is_success() {\n        Some(response.into_string().unwrap())\n    } else {\n        None\n    }\n}\n\nfn delete_paste(client: &Client, id: &str) {\n    let id = PasteId::from_param(id).expect(\"valid ID\");\n    let response = client.delete(uri!(super::delete(id))).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n}\n\n#[test]\nfn pasting() {\n    let client = Client::tracked(rocket()).unwrap();\n\n    // Do a trivial upload, just to make sure it works.\n    let body_1 = \"Hello, world!\";\n    let id_1 = upload_paste(&client, body_1);\n    assert_eq!(download_paste(&client, &id_1).unwrap(), body_1);\n\n    // Make sure we can keep getting that paste.\n    assert_eq!(download_paste(&client, &id_1).unwrap(), body_1);\n    assert_eq!(download_paste(&client, &id_1).unwrap(), body_1);\n    assert_eq!(download_paste(&client, &id_1).unwrap(), body_1);\n\n    // Upload some unicode.\n    let body_2 = \"こんにちは\";\n    let id_2 = upload_paste(&client, body_2);\n    assert_eq!(download_paste(&client, &id_2).unwrap(), body_2);\n\n    // Make sure we can get both pastes.\n    assert_eq!(download_paste(&client, &id_1).unwrap(), body_1);\n    assert_eq!(download_paste(&client, &id_2).unwrap(), body_2);\n    assert_eq!(download_paste(&client, &id_1).unwrap(), body_1);\n    assert_eq!(download_paste(&client, &id_2).unwrap(), body_2);\n\n    // Now a longer upload.\n    let body_3 = \"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed\n        do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim\n        ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n        aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit\n        in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui\n        officia deserunt mollit anim id est laborum.\";\n\n    let id_3 = upload_paste(&client, body_3);\n    assert_eq!(download_paste(&client, &id_3).unwrap(), body_3);\n    assert_eq!(download_paste(&client, &id_1).unwrap(), body_1);\n    assert_eq!(download_paste(&client, &id_2).unwrap(), body_2);\n\n    // Delete everything we uploaded.\n    delete_paste(&client, &id_1);\n    assert!(download_paste(&client, &id_1).is_none());\n\n    delete_paste(&client, &id_2);\n    assert!(download_paste(&client, &id_2).is_none());\n\n    delete_paste(&client, &id_3);\n    assert!(download_paste(&client, &id_3).is_none());\n}\n"
  },
  {
    "path": "examples/responders/Cargo.toml",
    "content": "[package]\nname = \"responders\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\nparking_lot = \"0.12\"\n"
  },
  {
    "path": "examples/responders/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\n/****************** `Result`, `Option` `NameFile` Responder *******************/\n\nuse std::{io, env};\n\nuse rocket::Config;\nuse rocket::data::Capped;\nuse rocket::fs::{NamedFile, TempFile};\nuse rocket::tokio::fs;\n\n// Upload your `big_file.dat` by POSTing it to /upload.\n// try `curl --data-binary @file.txt http://127.0.0.1:8000/stream/file`\nconst FILENAME: &str = \"big_file.dat\";\n\n// This is a *raw* file upload, _not_ a multipart upload!\n#[post(\"/file\", data = \"<file>\")]\nasync fn upload(mut file: Capped<TempFile<'_>>, config: &Config) -> io::Result<String> {\n    file.persist_to(config.temp_dir.relative().join(FILENAME)).await?;\n    Ok(format!(\"{} bytes at {}\", file.n.written, file.path().unwrap().display()))\n}\n\n#[get(\"/file\")]\nasync fn file(config: &Config) -> Option<NamedFile> {\n    NamedFile::open(config.temp_dir.relative().join(FILENAME)).await.ok()\n}\n\n#[delete(\"/file\")]\nasync fn delete(config: &Config) -> Option<()> {\n    fs::remove_file(config.temp_dir.relative().join(FILENAME)).await.ok()\n}\n\n/***************************** `Stream` Responder *****************************/\n\nuse rocket::tokio::select;\nuse rocket::tokio::time::{self, Duration};\nuse rocket::futures::stream::{repeat, StreamExt};\n\nuse rocket::Shutdown;\nuse rocket::response::stream::{TextStream, EventStream, Event};\n\n#[get(\"/stream/hi\")]\nfn many_his() -> TextStream![&'static str] {\n    TextStream(repeat(\"hi\").take(100))\n}\n\n#[get(\"/stream/hi/<n>\")]\nfn one_hi_per_ms(mut shutdown: Shutdown, n: u8) -> TextStream![&'static str] {\n    TextStream! {\n        let mut interval = time::interval(Duration::from_millis(n.into()));\n        loop {\n            select! {\n                _ = interval.tick() => yield \"hi\",\n                _ = &mut shutdown => {\n                    yield \"goodbye\";\n                    break;\n                }\n            };\n        }\n    }\n}\n\n#[get(\"/progress\", rank = 2)]\nfn progress_page() -> RawHtml<&'static str> {\n    RawHtml(r#\"\n          <script type=\"text/javascript\">\n            const evtSource = new EventSource(\"progress\");\n            evtSource.addEventListener(\"progress\", (event) => {\n                const el = document.getElementById(\"prog\");\n                el.textContent = event.data + \"%\";\n            });\n            evtSource.addEventListener(\"done\", (_) => {\n                const el = document.getElementById(\"prog\");\n                el.textContent = \"done\";\n                evtSource.close()\n            });\n        </script>\n\n        <p id=\"prog\"></p>\n    \"#)\n}\n\n#[get(\"/progress\", format = \"text/event-stream\", rank = 1)]\nfn progress_stream() -> EventStream![] {\n    let stream = EventStream! {\n        let mut interval = time::interval(Duration::from_secs(1));\n\n        for count in 0..100 {\n            interval.tick().await;\n            yield Event::data(count.to_string()).event(\"progress\");\n        }\n\n        yield Event::data(\"\").event(\"done\");\n    };\n\n    stream.heartbeat(Duration::from_secs(3))\n}\n\n/***************************** `Redirect` Responder ***************************/\n\nuse rocket::response::Redirect;\n\n#[get(\"/redir\")]\nfn redir_root() -> Redirect {\n    Redirect::to(uri!(redir_login))\n}\n\n#[get(\"/redir/login\")]\nfn redir_login() -> &'static str {\n    \"Hi! Please log in before continuing.\"\n}\n\n#[get(\"/redir/<name>\")]\nfn maybe_redir(name: &str) -> Result<&'static str, Redirect> {\n    match name {\n        \"Sergio\" => Ok(\"Hello, Sergio!\"),\n        _ => Err(Redirect::to(uri!(redir_login))),\n    }\n}\n\n/***************************** `content` Responders ***************************/\n\nuse rocket::Request;\nuse rocket::response::content;\n\n// NOTE: This example explicitly uses the `RawJson` type from\n// `response::content` for demonstration purposes. In a real application,\n// _always_ prefer to use `rocket::serde::json::Json` instead!\n\n// In a `GET` request and all other non-payload supporting request types, the\n// preferred media type in the Accept header is matched against the `format` in\n// the route attribute. Because the client can use non-specific media types like\n// `*/*` in `Accept`, these first two routes would collide without `rank`.\n#[get(\"/content\", format = \"xml\", rank = 1)]\nfn xml() -> content::RawXml<&'static str> {\n    content::RawXml(\"<payload>I'm here</payload>\")\n}\n\n#[get(\"/content\", format = \"json\", rank = 2)]\nfn json() -> content::RawJson<&'static str> {\n    content::RawJson(r#\"{ \"payload\": \"I'm here\" }\"#)\n}\n\n#[catch(404)]\nfn not_found(request: &Request<'_>) -> content::RawHtml<String> {\n    let html = match request.format() {\n        Some(ref mt) if !(mt.is_xml() || mt.is_html()) => {\n            format!(\"<p>'{}' requests are not supported.</p>\", mt)\n        }\n        _ => format!(\"<p>Sorry, '{}' is an invalid path! Try \\\n                 /hello/&lt;name&gt;/&lt;age&gt; instead.</p>\",\n                 request.uri())\n    };\n\n    content::RawHtml(html)\n}\n\n/******************************* `Either` Responder ***************************/\n\nuse rocket::either::Either;\nuse rocket::response::content::{RawJson, RawMsgPack};\nuse rocket::http::uncased::AsUncased;\n\n// NOTE: In a real application, we'd use `Json` and `MsgPack` from\n// `rocket::serde`, which perform automatic serialization of responses and\n// automatically set the `Content-Type`.\n#[get(\"/content/<kind>\")]\nfn json_or_msgpack(kind: &str) -> Either<RawJson<&'static str>, RawMsgPack<&'static [u8]>> {\n    if kind.as_uncased() == \"msgpack\" {\n        Either::Right(RawMsgPack(&[162, 104, 105]))\n    } else {\n        Either::Left(RawJson(\"\\\"hi\\\"\"))\n    }\n}\n\n/******************************* Custom Responder *****************************/\n\nuse std::borrow::Cow;\n\nuse rocket::response::content::RawHtml;\n\n#[derive(Responder)]\nenum StoredData {\n    File(Option<NamedFile>),\n    String(Cow<'static, str>),\n    Bytes(Vec<u8>),\n    #[response(status = 401)]\n    NotAuthorized(RawHtml<&'static str>),\n}\n\n#[derive(FromFormField, UriDisplayQuery)]\nenum Kind {\n    File,\n    String,\n    Bytes\n}\n\n#[get(\"/custom?<kind>\")]\nasync fn custom(kind: Option<Kind>) -> StoredData {\n    match kind {\n        Some(Kind::File) => {\n            let path = env::temp_dir().join(FILENAME);\n            StoredData::File(NamedFile::open(path).await.ok())\n        },\n        Some(Kind::String) => StoredData::String(\"Hey, I'm some data.\".into()),\n        Some(Kind::Bytes) => StoredData::Bytes(vec![72, 105]),\n        None => StoredData::NotAuthorized(RawHtml(\"No no no!\"))\n    }\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![many_his, one_hi_per_ms, file, upload, delete])\n        .mount(\"/\", routes![progress_stream, progress_page])\n        .mount(\"/\", routes![redir_root, redir_login, maybe_redir])\n        .mount(\"/\", routes![xml, json, json_or_msgpack])\n        .mount(\"/\", routes![custom])\n        .register(\"/\", catchers![not_found])\n}\n"
  },
  {
    "path": "examples/responders/src/tests.rs",
    "content": "use rocket::local::blocking::Client;\nuse rocket::http::Status;\n\n/****************************** `File` Responder ******************************/\n\n// We use a lock to synchronize between tests so FS operations don't race.\nstatic FS_LOCK: parking_lot::Mutex<()> = parking_lot::const_mutex(());\n\n#[test]\nfn test_file() {\n    const CONTENTS: &str = \"big_file contents...not so big here\";\n\n    // Take the lock so we exclusively access the FS.\n    let _lock = FS_LOCK.lock();\n\n    // Create the 'big_file'\n    let client = Client::tracked(super::rocket()).unwrap();\n    let response = client.post(uri!(super::upload)).body(CONTENTS).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    assert!(response.into_string().unwrap().contains(&CONTENTS.len().to_string()));\n\n    // Get the big file contents, hopefully.\n    let res = client.get(uri!(super::file)).dispatch();\n    assert_eq!(res.into_string(), Some(CONTENTS.into()));\n\n    // Delete it.\n    let response = client.delete(uri!(super::delete)).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n}\n\n/***************************** `Stream` Responder *****************************/\n\n#[test]\nfn test_many_his() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let res = client.get(uri!(super::many_his)).dispatch();\n\n    // Check that we have exactly 100 `hi`s.\n    let bytes = res.into_bytes().unwrap();\n    assert_eq!(bytes.len(), 200);\n    assert!(bytes.chunks(2).all(|b| b == b\"hi\"));\n}\n\n#[async_test]\nasync fn test_one_hi_per_second() {\n    use rocket::local::asynchronous::Client;\n    use rocket::tokio::time::{self, Instant, Duration};\n    use rocket::tokio::{self, select};\n\n    // Listen for 1 second at 1 `hi` per 250ms, see if we get ~4 `hi`'s, then\n    // send a shutdown() signal, meaning we should get a `goodbye`.\n    let client = Client::tracked(super::rocket()).await.unwrap();\n    let response = client.get(uri!(super::one_hi_per_ms(250))).dispatch().await;\n    let response = response.into_string();\n    let timer = time::sleep(Duration::from_secs(1));\n\n    tokio::pin!(timer, response);\n    let start = Instant::now();\n    let response = loop {\n        select! {\n            _ = &mut timer => {\n                client.rocket().shutdown().notify();\n                timer.as_mut().reset(Instant::now() + Duration::from_millis(100));\n                if start.elapsed() > Duration::from_secs(2) {\n                    panic!(\"responder did not terminate with shutdown\");\n                }\n            }\n            response = &mut response => break response.unwrap(),\n        }\n    };\n\n    match &*response {\n        \"hihihigoodbye\" | \"hihihihigoodbye\" | \"hihihihihigoodbye\" => { /* ok */ },\n        s => panic!(\"unexpected response from infinite responder: {}\", s)\n    }\n}\n\n/***************************** `Redirect` Responder ***************************/\n\n#[test]\nfn test_redir_root() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let response = client.get(uri!(super::redir_root)).dispatch();\n\n    assert!(response.body().is_none());\n    assert_eq!(response.status(), Status::SeeOther);\n    for h in response.headers().iter() {\n        match h.name.as_str() {\n            \"Location\" => assert_eq!(h.value.as_ref(), &uri!(super::redir_login)),\n            \"Content-Length\" => assert_eq!(h.value.parse::<i32>().unwrap(), 0),\n            _ => { /* let these through */ }\n        }\n    }\n}\n\n#[test]\nfn test_login() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let r = client.get(uri!(super::redir_login)).dispatch();\n    assert_eq!(r.into_string().unwrap(), \"Hi! Please log in before continuing.\");\n\n    for name in &[\"Bob\", \"Charley\", \"Joe Roger\"] {\n        let r = client.get(uri!(super::maybe_redir(name))).dispatch();\n        assert_eq!(r.status(), Status::SeeOther);\n    }\n\n    let r = client.get(uri!(super::maybe_redir(\"Sergio\"))).dispatch();\n    assert_eq!(r.status(), Status::Ok);\n    assert_eq!(r.into_string().unwrap(), \"Hello, Sergio!\");\n}\n\n/***************************** `content` Responders ***************************/\n\nuse rocket::http::{Accept, ContentType};\n\n#[test]\nfn test_xml() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let r = client.get(uri!(super::xml)).header(Accept::XML).dispatch();\n    assert_eq!(r.content_type().unwrap(), ContentType::XML);\n    assert_eq!(r.into_string().unwrap(), \"<payload>I'm here</payload>\");\n\n    // Purposefully use the \"xml\" URL to illustrate `format` handling.\n    let r = client.get(uri!(super::xml)).header(Accept::JSON).dispatch();\n    assert_eq!(r.content_type().unwrap(), ContentType::JSON);\n    assert_eq!(r.into_string().unwrap(), r#\"{ \"payload\": \"I'm here\" }\"#);\n\n    let r = client.get(uri!(super::xml)).header(Accept::CSV).dispatch();\n    assert_eq!(r.status(), Status::NotFound);\n    assert!(r.into_string().unwrap().contains(\"not supported\"));\n\n    let r = client.get(\"/content/i/dont/exist\").header(Accept::HTML).dispatch();\n    assert_eq!(r.content_type().unwrap(), ContentType::HTML);\n    assert!(r.into_string().unwrap().contains(\"invalid path\"));\n}\n\n/******************************* `Either` Responder ***************************/\n\n#[test]\nfn test_either() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let r = client.get(uri!(super::json_or_msgpack(\"json\"))).dispatch();\n    assert_eq!(r.content_type().unwrap(), ContentType::JSON);\n    assert_eq!(r.into_string().unwrap(), \"\\\"hi\\\"\");\n\n    let r = client.get(uri!(super::json_or_msgpack(\"msgpack\"))).dispatch();\n    assert_eq!(r.content_type().unwrap(), ContentType::MsgPack);\n    assert_eq!(r.into_bytes().unwrap(), &[162, 104, 105]);\n}\n\n/******************************** Custom Responder ****************************/\n\nuse super::Kind;\n\n#[test]\nfn test_custom() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let r = client.get(uri!(super::custom(Some(Kind::String)))).dispatch();\n    assert_eq!(r.into_string().unwrap(), \"Hey, I'm some data.\");\n\n    let r = client.get(uri!(super::custom(Some(Kind::Bytes)))).dispatch();\n    assert_eq!(r.into_string().unwrap(), \"Hi\");\n\n    let r = client.get(uri!(super::custom(_))).dispatch();\n    assert_eq!(r.status(), Status::Unauthorized);\n    assert_eq!(r.content_type().unwrap(), ContentType::HTML);\n    assert_eq!(r.into_string().unwrap(), \"No no no!\");\n\n    // Take the lock so we exclusively access the FS.\n    let _lock = FS_LOCK.lock();\n\n    // Create the 'big_file'.\n    const CONTENTS: &str = \"custom file contents!\";\n    let response = client.post(uri!(super::upload)).body(CONTENTS).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n\n    // Fetch it using `custom`.\n    let r = client.get(uri!(super::custom(Some(Kind::File)))).dispatch();\n    assert_eq!(r.into_string(), Some(CONTENTS.into()));\n\n    // Delete it.\n    let r = client.delete(uri!(super::delete)).dispatch();\n    assert_eq!(r.status(), Status::Ok);\n}\n"
  },
  {
    "path": "examples/serialization/Cargo.toml",
    "content": "[package]\nname = \"serialization\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies.rocket]\npath = \"../../core/lib\"\nfeatures = [\"json\", \"msgpack\", \"uuid\"]\n"
  },
  {
    "path": "examples/serialization/src/json.rs",
    "content": "use std::borrow::Cow;\n\nuse rocket::State;\nuse rocket::tokio::sync::Mutex;\nuse rocket::serde::json::{Json, Value, json};\nuse rocket::serde::{Serialize, Deserialize};\n\n// The type to represent the ID of a message.\ntype Id = usize;\n\n// We're going to store all of the messages here. No need for a DB.\ntype MessageList = Mutex<Vec<String>>;\ntype Messages<'r> = &'r State<MessageList>;\n\n#[derive(Serialize, Deserialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Message<'r> {\n    id: Option<Id>,\n    message: Cow<'r, str>\n}\n\n#[post(\"/\", format = \"json\", data = \"<message>\")]\nasync fn new(message: Json<Message<'_>>, list: Messages<'_>) -> Value {\n    let mut list = list.lock().await;\n    let id = list.len();\n    list.push(message.message.to_string());\n    json!({ \"status\": \"ok\", \"id\": id })\n}\n\n#[put(\"/<id>\", format = \"json\", data = \"<message>\")]\nasync fn update(id: Id, message: Json<Message<'_>>, list: Messages<'_>) -> Option<Value> {\n    match list.lock().await.get_mut(id) {\n        Some(existing) => {\n            *existing = message.message.to_string();\n            Some(json!({ \"status\": \"ok\" }))\n        }\n        None => None\n    }\n}\n\n#[get(\"/<id>\", format = \"json\")]\nasync fn get(id: Id, list: Messages<'_>) -> Option<Json<Message<'_>>> {\n    let list = list.lock().await;\n\n    Some(Json(Message {\n        id: Some(id),\n        message: list.get(id)?.to_string().into(),\n    }))\n}\n\n#[catch(404)]\nfn not_found() -> Value {\n    json!({\n        \"status\": \"error\",\n        \"reason\": \"Resource was not found.\"\n    })\n}\n\npub fn stage() -> rocket::fairing::AdHoc {\n    rocket::fairing::AdHoc::on_ignite(\"JSON\", |rocket| async {\n        rocket.mount(\"/json\", routes![new, update, get])\n            .register(\"/json\", catchers![not_found])\n            .manage(MessageList::new(vec![]))\n    })\n}\n"
  },
  {
    "path": "examples/serialization/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\nmod json;\nmod msgpack;\nmod uuid;\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .attach(json::stage())\n        .attach(msgpack::stage())\n        .attach(uuid::stage())\n}\n"
  },
  {
    "path": "examples/serialization/src/msgpack.rs",
    "content": "use rocket::serde::{Serialize, Deserialize, msgpack::MsgPack};\n\n#[derive(Serialize, Deserialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Message<'r> {\n    id: usize,\n    message: &'r str\n}\n\n#[get(\"/<id>\", format = \"msgpack\")]\nfn get(id: usize) -> MsgPack<Message<'static>> {\n    MsgPack(Message { id, message: \"Hello, world!\", })\n}\n\n#[post(\"/\", data = \"<data>\", format = \"msgpack\")]\nfn echo(data: MsgPack<Message<'_>>) -> &str {\n    data.message\n}\n\npub fn stage() -> rocket::fairing::AdHoc {\n    rocket::fairing::AdHoc::on_ignite(\"MessagePack\", |rocket| async {\n        rocket.mount(\"/msgpack\", routes![echo, get])\n    })\n}\n"
  },
  {
    "path": "examples/serialization/src/tests.rs",
    "content": "use rocket::local::blocking::Client;\nuse rocket::http::{Status, ContentType, Accept};\nuse rocket::serde::{Serialize, Deserialize, uuid::Uuid};\n\n#[derive(Debug, PartialEq, Serialize, Deserialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Message {\n    id: Option<usize>,\n    message: String\n}\n\nimpl Message {\n    fn new(message: impl Into<String>) -> Self {\n        Message { message: message.into(), id: None }\n    }\n\n    fn with_id(mut self, id: usize) -> Self {\n        self.id = Some(id);\n        self\n    }\n}\n\n#[test]\nfn json_bad_get_put() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    // Try to get a message with an ID that doesn't exist.\n    let res = client.get(\"/json/99\").header(ContentType::JSON).dispatch();\n    assert_eq!(res.status(), Status::NotFound);\n\n    let body = res.into_string().unwrap();\n    assert!(body.contains(\"error\"));\n    assert!(body.contains(\"Resource was not found.\"));\n\n    // Try to get a message with an invalid ID.\n    let res = client.get(\"/json/hi\").header(ContentType::JSON).dispatch();\n    assert_eq!(res.status(), Status::UnprocessableEntity);\n\n    // Try to put a message without a proper body.\n    let res = client.put(\"/json/80\").header(ContentType::JSON).dispatch();\n    assert_eq!(res.status(), Status::BadRequest);\n\n    // Try to put a message with a semantically invalid body.\n    let res = client.put(\"/json/0\")\n        .header(ContentType::JSON)\n        .body(r#\"{ \"dogs?\": \"love'em!\" }\"#)\n        .dispatch();\n\n    assert_eq!(res.status(), Status::UnprocessableEntity);\n\n    // Try to put a message for an ID that doesn't exist.\n    let res = client.put(\"/json/80\")\n        .json(&Message::new(\"hi\"))\n        .dispatch();\n\n    assert_eq!(res.status(), Status::NotFound);\n}\n\n#[test]\nfn json_post_get_put_get() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    // Create/read/update/read a few messages.\n    for id in 0..10 {\n        let uri = format!(\"/json/{}\", id);\n\n        // Check that a message with doesn't exist.\n        let res = client.get(&uri).header(ContentType::JSON).dispatch();\n        assert_eq!(res.status(), Status::NotFound);\n\n        // Add a new message. This should be ID 0.\n        let message = Message::new(format!(\"Hello, JSON {}!\", id));\n        let res = client.post(\"/json\").json(&message).dispatch();\n        assert_eq!(res.status(), Status::Ok);\n\n        // Check that the message exists with the correct contents.\n        let res = client.get(&uri).header(Accept::JSON).dispatch();\n        assert_eq!(res.status(), Status::Ok);\n        assert_eq!(res.into_json::<Message>().unwrap(), message.with_id(id));\n\n        // Change the message contents.\n        let message = Message::new(\"Bye bye, world!\");\n        let res = client.put(&uri).json(&message).dispatch();\n        assert_eq!(res.status(), Status::Ok);\n\n        // Check that the message exists with the updated contents.\n        let res = client.get(&uri).header(Accept::JSON).dispatch();\n        assert_eq!(res.status(), Status::Ok);\n        assert_eq!(res.into_json::<Message>().unwrap(), message.with_id(id));\n    }\n}\n\n#[test]\nfn msgpack_get() {\n    let client = Client::tracked(super::rocket()).unwrap();\n    let res = client.get(\"/msgpack/1\").header(ContentType::MsgPack).dispatch();\n    assert_eq!(res.status(), Status::Ok);\n    assert_eq!(res.content_type(), Some(ContentType::MsgPack));\n\n    // Check that the message is `[1, \"Hello, world!\"]`\n    let msg = Message::new(\"Hello, world!\").with_id(1);\n    assert_eq!(res.into_msgpack::<Message>().unwrap(), msg);\n}\n\n#[test]\nfn msgpack_post() {\n    // Dispatch request with a message of `[2, \"Goodbye, world!\"]`.\n    let client = Client::tracked(super::rocket()).unwrap();\n    let res = client.post(\"/msgpack\")\n        .msgpack(&Message::new(\"Goodbye, world!\").with_id(2))\n        .dispatch();\n\n    assert_eq!(res.status(), Status::Ok);\n    assert_eq!(res.into_string().unwrap(), \"Goodbye, world!\");\n}\n\n#[test]\nfn uuid() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    let pairs = &[\n        (\"7f205202-7ba1-4c39-b2fc-3e630722bf9f\", \"We found: Lacy\"),\n        (\"4da34121-bc7d-4fc1-aee6-bf8de0795333\", \"We found: Bob\"),\n        (\"ad962969-4e3d-4de7-ac4a-2d86d6d10839\", \"We found: George\"),\n        (\"e18b3a5c-488f-4159-a240-2101e0da19fd\",\n            \"Missing person for UUID: e18b3a5c-488f-4159-a240-2101e0da19fd\"),\n    ];\n\n    for (uuid, response) in pairs {\n        let uuid = Uuid::parse_str(uuid).unwrap();\n        let res = client.get(uri!(super::uuid::people(uuid))).dispatch();\n        assert_eq!(res.into_string().unwrap(), *response);\n    }\n\n    let res = client.get(\"/people/not-a-uuid\").dispatch();\n    assert_eq!(res.status(), Status::UnprocessableEntity);\n}\n"
  },
  {
    "path": "examples/serialization/src/uuid.rs",
    "content": "use std::collections::HashMap;\n\nuse rocket::State;\nuse rocket::serde::uuid::Uuid;\n\n// A small people mapping in managed state for the sake of this example. In a\n// real application this would be a database.\nstruct People(HashMap<Uuid, &'static str>);\n\n#[get(\"/people/<id>\")]\nfn people(id: Uuid, people: &State<People>) -> Result<String, String> {\n    people.0.get(&id)\n        .map(|person| format!(\"We found: {}\", person))\n        .ok_or_else(|| format!(\"Missing person for UUID: {}\", id))\n}\n\npub fn stage() -> rocket::fairing::AdHoc {\n    // Seed the \"database\".\n    let mut map = HashMap::new();\n    map.insert(\"7f205202-7ba1-4c39-b2fc-3e630722bf9f\".parse().unwrap(), \"Lacy\");\n    map.insert(\"4da34121-bc7d-4fc1-aee6-bf8de0795333\".parse().unwrap(), \"Bob\");\n    map.insert(\"ad962969-4e3d-4de7-ac4a-2d86d6d10839\".parse().unwrap(), \"George\");\n\n    rocket::fairing::AdHoc::on_ignite(\"UUID\", |rocket| async {\n        rocket\n            .manage(People(map))\n            .mount(\"/\", routes![people])\n    })\n}\n"
  },
  {
    "path": "examples/state/Cargo.toml",
    "content": "[package]\nname = \"state\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\nflume = \"0.11\"\n"
  },
  {
    "path": "examples/state/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\n#[cfg(test)] mod tests;\n\nmod request_local;\nmod managed_hit_count;\nmod managed_queue;\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .attach(request_local::stage())\n        .attach(managed_hit_count::stage())\n        .attach(managed_queue::stage())\n}\n"
  },
  {
    "path": "examples/state/src/managed_hit_count.rs",
    "content": "use std::sync::atomic::{AtomicUsize, Ordering};\n\nuse rocket::State;\nuse rocket::response::content::RawHtml;\nuse rocket::fairing::AdHoc;\n\nstruct HitCount(AtomicUsize);\n\n#[get(\"/\")]\nfn index(hit_count: &State<HitCount>) -> RawHtml<String> {\n    let count = hit_count.0.fetch_add(1, Ordering::Relaxed) + 1;\n    RawHtml(format!(\"Your visit is recorded!<br /><br />Visits: {}\", count))\n}\n\npub fn stage() -> AdHoc {\n    AdHoc::on_ignite(\"Managed Hit Count\", |rocket| async {\n        rocket.mount(\"/count\", routes![index])\n            .manage(HitCount(AtomicUsize::new(0)))\n    })\n}\n"
  },
  {
    "path": "examples/state/src/managed_queue.rs",
    "content": "use rocket::State;\nuse rocket::fairing::AdHoc;\nuse rocket::http::Status;\n\nstruct Tx(flume::Sender<String>);\nstruct Rx(flume::Receiver<String>);\n\n#[put(\"/push?<event>\")]\nfn push(event: String, tx: &State<Tx>) -> Result<(), Status> {\n    tx.0.try_send(event).map_err(|_| Status::ServiceUnavailable)\n}\n\n#[get(\"/pop\")]\nfn pop(rx: &State<Rx>) -> Option<String> {\n    rx.0.try_recv().ok()\n}\n\npub fn stage() -> AdHoc {\n    AdHoc::on_ignite(\"Managed Queue\", |rocket| async {\n        let (tx, rx) = flume::bounded(32);\n        rocket.mount(\"/queue\", routes![push, pop])\n            .manage(Tx(tx))\n            .manage(Rx(rx))\n    })\n}\n"
  },
  {
    "path": "examples/state/src/request_local.rs",
    "content": "use std::sync::atomic::{AtomicUsize, Ordering};\n\nuse rocket::State;\nuse rocket::outcome::{Outcome, try_outcome};\nuse rocket::request::{self, FromRequest, Request};\nuse rocket::fairing::AdHoc;\n\n#[derive(Default, Debug)]\npub struct Atomics {\n    pub uncached: AtomicUsize,\n    pub cached: AtomicUsize,\n}\n\nstruct Guard1;\nstruct Guard2;\nstruct Guard3;\nstruct Guard4;\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for Guard1 {\n    type Error = ();\n\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        let atomics = try_outcome!(req.guard::<&State<Atomics>>().await);\n        atomics.uncached.fetch_add(1, Ordering::Relaxed);\n        req.local_cache(|| {\n            atomics.cached.fetch_add(1, Ordering::Relaxed)\n        });\n\n        Outcome::Success(Guard1)\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for Guard2 {\n    type Error = ();\n\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        try_outcome!(req.guard::<Guard1>().await);\n        Outcome::Success(Guard2)\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for Guard3 {\n    type Error = ();\n\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        let atomics = try_outcome!(req.guard::<&State<Atomics>>().await);\n        atomics.uncached.fetch_add(1, Ordering::Relaxed);\n        req.local_cache_async(async {\n            atomics.cached.fetch_add(1, Ordering::Relaxed)\n        }).await;\n\n        Outcome::Success(Guard3)\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for Guard4 {\n    type Error = ();\n\n    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {\n        try_outcome!(Guard3::from_request(req).await);\n        Outcome::Success(Guard4)\n    }\n}\n\n#[get(\"/1-2\")]\nfn one_two(_g1: Guard1, _g2: Guard2, state: &State<Atomics>) -> String {\n    format!(\"{:#?}\", state)\n}\n\n#[get(\"/3-4\")]\nfn three_four(_g3: Guard3, _g4: Guard4, state: &State<Atomics>) -> String {\n    format!(\"{:#?}\", state)\n}\n\n#[get(\"/1-2-3-4\")]\nfn all(\n    _g1: Guard1,\n    _g2: Guard2,\n    _g3: Guard3,\n    _g4: Guard4,\n    state: &State<Atomics>\n) -> String {\n    format!(\"{:#?}\", state)\n}\n\npub fn stage() -> AdHoc {\n    AdHoc::on_ignite(\"Request Local State\", |rocket| async {\n        rocket.manage(Atomics::default())\n            .mount(\"/req-local\", routes![one_two, three_four, all])\n    })\n}\n"
  },
  {
    "path": "examples/state/src/tests.rs",
    "content": "use rocket::local::blocking::Client;\nuse rocket::http::Status;\n\n#[test]\nfn test_count() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    fn get_count(client: &Client) -> usize {\n        let response = client.get(\"/count\").dispatch().into_string().unwrap();\n        let count = response.split(' ').last().unwrap();\n        count.parse().unwrap()\n    }\n\n    // Count starts at 0; our hit is the first.\n    for i in 1..128 {\n        assert_eq!(get_count(&client), i);\n    }\n}\n\n// Cargo runs each test in parallel on different threads. We use all of these\n// tests below to show (and assert) that state is managed per-Rocket instance.\n#[test] fn test_count_parallel() { test_count() }\n#[test] fn test_count_parallel_2() { test_count() }\n#[test] fn test_count_parallel_3() { test_count() }\n#[test] fn test_count_parallel_4() { test_count() }\n#[test] fn test_count_parallel_5() { test_count() }\n#[test] fn test_count_parallel_6() { test_count() }\n#[test] fn test_count_parallel_7() { test_count() }\n#[test] fn test_count_parallel_8() { test_count() }\n#[test] fn test_count_parallel_9() { test_count() }\n\n#[test]\nfn test_queue_push_pop() {\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    let response = client.put(\"/queue/push?event=test1\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n\n    let response = client.get(\"/queue/pop\").dispatch();\n    assert_eq!(response.into_string().unwrap(), \"test1\");\n\n    client.put(\"/queue/push?event=POP!%20...goes+\").dispatch();\n    client.put(\"/queue/push?event=the+weasel\").dispatch();\n    let r1 = client.get(\"/queue/pop\").dispatch().into_string().unwrap();\n    let r2 = client.get(\"/queue/pop\").dispatch().into_string().unwrap();\n    assert_eq!(r1 + &r2, \"POP! ...goes the weasel\");\n}\n\n#[test]\nfn test_request_local_state() {\n    use super::request_local::Atomics;\n    use std::sync::atomic::Ordering;\n\n    let client = Client::tracked(super::rocket()).unwrap();\n\n    client.get(\"/req-local/1-2\").dispatch();\n    let atomics = client.rocket().state::<Atomics>().unwrap();\n    assert_eq!(atomics.uncached.load(Ordering::Relaxed), 2);\n    assert_eq!(atomics.cached.load(Ordering::Relaxed), 1);\n\n    client.get(\"/req-local/1-2\").dispatch();\n    let atomics = client.rocket().state::<Atomics>().unwrap();\n    assert_eq!(atomics.uncached.load(Ordering::Relaxed), 4);\n    assert_eq!(atomics.cached.load(Ordering::Relaxed), 2);\n\n    client.get(\"/req-local/1-2-3-4\").dispatch();\n    let atomics = client.rocket().state::<Atomics>().unwrap();\n    assert_eq!(atomics.uncached.load(Ordering::Relaxed), 8);\n    assert_eq!(atomics.cached.load(Ordering::Relaxed), 3);\n}\n"
  },
  {
    "path": "examples/static-files/Cargo.toml",
    "content": "[package]\nname = \"static-files\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n"
  },
  {
    "path": "examples/static-files/src/main.rs",
    "content": "#[cfg(test)] mod tests;\n\nuse rocket::fs::{FileServer, relative};\n\n// If we wanted or needed to serve files manually, we'd use `NamedFile`. Always\n// prefer to use `FileServer`!\nmod manual {\n    use std::path::{PathBuf, Path};\n    use rocket::fs::NamedFile;\n\n    #[rocket::get(\"/second/<path..>\")]\n    pub async fn second(path: PathBuf) -> Option<NamedFile> {\n        let mut path = Path::new(super::relative!(\"static\")).join(path);\n        if path.is_dir() {\n            path.push(\"index.html\");\n        }\n\n        NamedFile::open(path).await.ok()\n    }\n}\n\n#[rocket::launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", rocket::routes![manual::second])\n        .mount(\"/\", FileServer::new(relative!(\"static\")))\n}\n"
  },
  {
    "path": "examples/static-files/src/tests.rs",
    "content": "use std::fs::File;\nuse std::io::Read;\n\nuse rocket::local::blocking::Client;\nuse rocket::http::Status;\n\nuse super::rocket;\n\n#[track_caller]\nfn test_query_file<T> (path: &str, file: T, status: Status)\n    where T: Into<Option<&'static str>>\n{\n    let client = Client::tracked(rocket()).unwrap();\n    let response = client.get(path).dispatch();\n    assert_eq!(response.status(), status);\n\n    let body_data = response.into_bytes();\n    if let Some(filename) = file.into() {\n        let expected_data = read_file_content(filename).expect(filename);\n        assert!(body_data.map_or(false, |s| s == expected_data));\n    }\n}\n\nfn read_file_content(path: &str) -> std::io::Result<Vec<u8>> {\n    let mut file_content = vec![];\n    let mut fp = File::open(path)?;\n    fp.read_to_end(&mut file_content)?;\n    Ok(file_content)\n}\n\n#[test]\nfn test_index_html() {\n    test_query_file(\"/\", \"static/index.html\", Status::Ok);\n    test_query_file(\"/?v=1\", \"static/index.html\", Status::Ok);\n    test_query_file(\"/?this=should&be=ignored\", \"static/index.html\", Status::Ok);\n    test_query_file(\"/second/\", \"static/index.html\", Status::Ok);\n    test_query_file(\"/second/?v=1\", \"static/index.html\", Status::Ok);\n}\n\n#[test]\nfn test_hidden_index_html() {\n    test_query_file(\"/hidden/\", \"static/hidden/index.html\", Status::Ok);\n    test_query_file(\"//hidden//\", \"static/hidden/index.html\", Status::Ok);\n    test_query_file(\"/second/hidden\", \"static/hidden/index.html\", Status::Ok);\n    test_query_file(\"/second/hidden/\", \"static/hidden/index.html\", Status::Ok);\n    test_query_file(\"/second/hidden///\", \"static/hidden/index.html\", Status::Ok);\n}\n\n#[test]\nfn test_hidden_file() {\n    test_query_file(\"/hidden/hi.txt\", \"static/hidden/hi.txt\", Status::Ok);\n    test_query_file(\"/second/hidden/hi.txt\", \"static/hidden/hi.txt\", Status::Ok);\n    test_query_file(\"/hidden/hi.txt?v=1\", \"static/hidden/hi.txt\", Status::Ok);\n    test_query_file(\"/hidden/hi.txt?v=1&a=b\", \"static/hidden/hi.txt\", Status::Ok);\n    test_query_file(\"/second/hidden/hi.txt?v=1&a=b\", \"static/hidden/hi.txt\", Status::Ok);\n}\n\n#[test]\nfn test_icon_file() {\n    test_query_file(\"/rocket-icon.jpg\", \"static/rocket-icon.jpg\", Status::Ok);\n    test_query_file(\"/second/rocket-icon.jpg\", \"static/rocket-icon.jpg\", Status::Ok);\n}\n\n#[test]\nfn test_invalid_path() {\n    test_query_file(\"/hidden\", None, Status::TemporaryRedirect);\n    test_query_file(\"/thou_shalt_not_exist\", None, Status::NotFound);\n    test_query_file(\"/thou/shalt/not/exist\", None, Status::NotFound);\n    test_query_file(\"/thou/shalt/not/exist?a=b&c=d\", None, Status::NotFound);\n}\n"
  },
  {
    "path": "examples/static-files/static/hidden/hi.txt",
    "content": "You found me! :o\n"
  },
  {
    "path": "examples/static-files/static/hidden/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <title>Hmm...</title>\n  </head>\n  <body>\n    👀\n  </body>\n</html>\n"
  },
  {
    "path": "examples/static-files/static/index.html",
    "content": "<h1>Hello, world!</h1>\n\n<a href=\"rocket-icon.jpg\">\n  <img src=\"rocket-icon.jpg\" alt=\"A rocket icon.\" height=200 width=200 />\n</a>\n"
  },
  {
    "path": "examples/templating/Cargo.toml",
    "content": "[package]\nname = \"templating\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n\n# in your application, you should enable only the template engine(s) used\n[dependencies.rocket_dyn_templates]\npath = \"../../contrib/dyn_templates\"\nfeatures = [\"tera\", \"handlebars\", \"minijinja\"]\n"
  },
  {
    "path": "examples/templating/Rocket.toml",
    "content": "[default]\ntemplate_dir = \"templates\"\n"
  },
  {
    "path": "examples/templating/src/hbs.rs",
    "content": "use rocket::Request;\nuse rocket::response::Redirect;\n\nuse rocket_dyn_templates::{Template, handlebars, context};\n\nuse self::handlebars::{Handlebars, JsonRender};\n\n#[get(\"/\")]\npub fn index() -> Redirect {\n    Redirect::to(uri!(\"/hbs\", hello(name = \"Your Name\")))\n}\n\n#[get(\"/hello/<name>\")]\npub fn hello(name: &str) -> Template {\n    Template::render(\"hbs/index\", context! {\n        title: \"Hello\",\n        name: Some(name),\n        items: vec![\"One\", \"Two\", \"Three\"],\n    })\n}\n\n#[get(\"/about\")]\npub fn about() -> Template {\n    Template::render(\"hbs/about.html\", context! {\n        title: \"About\",\n        parent: \"hbs/layout\",\n    })\n}\n\n#[catch(404)]\npub fn not_found(req: &Request<'_>) -> Template {\n    Template::render(\"hbs/error/404\", context! {\n        uri: req.uri()\n    })\n}\n\nfn wow_helper(\n    h: &handlebars::Helper<'_>,\n    _: &handlebars::Handlebars,\n    _: &handlebars::Context,\n    _: &mut handlebars::RenderContext<'_, '_>,\n    out: &mut dyn handlebars::Output\n) -> handlebars::HelperResult {\n    if let Some(param) = h.param(0) {\n        out.write(\"<b><i>\")?;\n        out.write(&param.value().render())?;\n        out.write(\"</b></i>\")?;\n    }\n\n    Ok(())\n}\n\npub fn customize(hbs: &mut Handlebars) {\n    hbs.register_helper(\"wow\", Box::new(wow_helper));\n    hbs.register_template_string(\"hbs/about.html\", r#\"\n        {{#*inline \"page\"}}\n\n        <section id=\"about\">\n          <h1>About - Here's another page!</h1>\n        </section>\n\n        {{/inline}}\n        {{> hbs/layout}}\n    \"#).expect(\"valid HBS template\");\n}\n"
  },
  {
    "path": "examples/templating/src/main.rs",
    "content": "#[macro_use]\nextern crate rocket;\n\nmod hbs;\nmod minijinja;\nmod tera;\n\n#[cfg(test)]\nmod tests;\n\nuse rocket::response::content::RawHtml;\nuse rocket_dyn_templates::Template;\n\n#[get(\"/\")]\nfn index() -> RawHtml<&'static str> {\n    RawHtml(\n        r#\"See <a href=\"tera\">Tera</a>,\n        <a href=\"hbs\">Handlebars</a>,\n        or <a href=\"minijinja\">MiniJinja</a>.\"#,\n    )\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![index])\n        .mount(\"/tera\", routes![tera::index, tera::hello, tera::about])\n        .mount(\"/hbs\", routes![hbs::index, hbs::hello, hbs::about])\n        .mount(\n            \"/minijinja\",\n            routes![minijinja::index, minijinja::hello, minijinja::about],\n        )\n        .register(\"/hbs\", catchers![hbs::not_found])\n        .register(\"/tera\", catchers![tera::not_found])\n        .register(\"/minijinja\", catchers![minijinja::not_found])\n        .attach(Template::custom(|engines| {\n            hbs::customize(&mut engines.handlebars);\n            tera::customize(&mut engines.tera);\n            minijinja::customize(&mut engines.minijinja);\n        }))\n}\n"
  },
  {
    "path": "examples/templating/src/minijinja.rs",
    "content": "use rocket::response::Redirect;\nuse rocket::Request;\n\nuse rocket_dyn_templates::{context, minijinja::Environment, Template};\n\n// use self::minijinja::;\n\n#[get(\"/\")]\npub fn index() -> Redirect {\n    Redirect::to(uri!(\"/minijinja\", hello(name = \"Your Name\")))\n}\n\n#[get(\"/hello/<name>\")]\npub fn hello(name: &str) -> Template {\n    Template::render(\n        \"minijinja/index\",\n        context! {\n            title: \"Hello\",\n            name: Some(name),\n            items: vec![\"One\", \"Two\", \"Three\"],\n        },\n    )\n}\n\n#[get(\"/about\")]\npub fn about() -> Template {\n    Template::render(\n        \"minijinja/about.html\",\n        context! {\n            title: \"About\",\n        },\n    )\n}\n\n#[catch(404)]\npub fn not_found(req: &Request<'_>) -> Template {\n    println!(\"Handling 404 for URI: {}\", req.uri());\n\n    Template::render(\n        \"minijinja/error/404\",\n        context! {\n            uri: req.uri()\n        },\n    )\n}\n\npub fn customize(env: &mut Environment) {\n    env.add_template(\n        \"minijinja/about.html\",\n        r#\"\n        {% extends \"minijinja/layout\" %}\n\n        {% block page %}\n            <section id=\"about\">\n                <h1>About - Here's another page!</h1>\n            </section>\n        {% endblock %}\n    \"#,\n    )\n    .expect(\"valid Jinja2 template\");\n}\n"
  },
  {
    "path": "examples/templating/src/tera.rs",
    "content": "use rocket::Request;\nuse rocket::response::Redirect;\n\nuse rocket_dyn_templates::{Template, tera::Tera, context};\n\n#[get(\"/\")]\npub fn index() -> Redirect {\n    Redirect::to(uri!(\"/tera\", hello(name = \"Your Name\")))\n}\n\n#[get(\"/hello/<name>\")]\npub fn hello(name: &str) -> Template {\n    Template::render(\"tera/index\", context! {\n        title: \"Hello\",\n        name: Some(name),\n        items: vec![\"One\", \"Two\", \"Three\"],\n    })\n}\n\n#[get(\"/about\")]\npub fn about() -> Template {\n    Template::render(\"tera/about.html\", context! {\n        title: \"About\",\n    })\n}\n\n#[catch(404)]\npub fn not_found(req: &Request<'_>) -> Template {\n    Template::render(\"tera/error/404\", context! {\n        uri: req.uri()\n    })\n}\n\npub fn customize(tera: &mut Tera) {\n    tera.add_raw_template(\"tera/about.html\", r#\"\n        {% extends \"tera/base\" %}\n\n        {% block content %}\n            <section id=\"about\">\n              <h1>About - Here's another page!</h1>\n            </section>\n        {% endblock content %}\n    \"#).expect(\"valid Tera template\");\n}\n"
  },
  {
    "path": "examples/templating/src/tests.rs",
    "content": "use super::rocket;\n\nuse rocket::http::{RawStr, Status, Method::*};\nuse rocket::local::blocking::Client;\nuse rocket_dyn_templates::{Template, context};\n\nfn test_root(kind: &str) {\n    // Check that the redirect works.\n    let client = Client::tracked(rocket()).unwrap();\n    for method in &[Get, Head] {\n        let response = client.req(*method, format!(\"/{}\", kind)).dispatch();\n        assert_eq!(response.status(), Status::SeeOther);\n        assert!(response.body().is_none());\n\n        let location = response.headers().get_one(\"Location\").unwrap();\n        assert_eq!(location, format!(\"/{}/hello/Your%20Name\", kind));\n    }\n\n    // Check that other request methods are not accepted (and instead caught).\n    for method in &[Post, Put, Delete, Options, Trace, Connect, Patch] {\n        let context = context! { uri: format!(\"/{}\", kind) };\n        let expected = Template::show(client.rocket(), format!(\"{}/error/404\", kind), &context);\n\n        let response = client.req(*method, format!(\"/{}\", kind)).dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n        assert_eq!(response.into_string(), expected);\n    }\n}\n\nfn test_name(base: &str) {\n    // Check that the /hello/<name> route works.\n    let client = Client::tracked(rocket()).unwrap();\n    let response = client.get(format!(\"/{}/hello/Jack%20Daniels\", base)).dispatch();\n    assert_eq!(response.status(), Status::Ok);\n    assert!(response.into_string().unwrap().contains(\"Hi Jack Daniels!\"));\n}\n\nfn test_404(base: &str) {\n    // Check that the error catcher works.\n    let client = Client::tracked(rocket()).unwrap();\n    for bad_path in &[\"/hello\", \"/foo/bar\", \"/404\"] {\n        let path = format!(\"/{}{}\", base, bad_path);\n        let escaped_path = RawStr::new(&path).html_escape().to_lowercase();\n\n        let response = client.get(&path).dispatch();\n        assert_eq!(response.status(), Status::NotFound);\n        let response = response.into_string().unwrap().to_lowercase();\n\n        assert!(response.contains(base));\n        assert! {\n            response.contains(&format!(\"{} does not exist\", path))\n                || response.contains(&format!(\"{} does not exist\", escaped_path))\n        };\n    }\n}\n\nfn test_about(base: &str) {\n    let client = Client::tracked(rocket()).unwrap();\n    let response = client.get(format!(\"/{}/about\", base)).dispatch();\n    assert!(response.into_string().unwrap().contains(\"About - Here's another page!\"));\n}\n\n#[test]\nfn test_index() {\n    let client = Client::tracked(rocket()).unwrap();\n    let response = client.get(\"/\").dispatch().into_string().unwrap();\n    assert!(response.contains(\"Tera\"));\n    assert!(response.contains(\"Handlebars\"));\n    assert!(response.contains(\"MiniJinja\"));\n}\n\n#[test]\nfn hbs() {\n    test_root(\"hbs\");\n    test_name(\"hbs\");\n    test_404(\"hbs\");\n    test_about(\"hbs\");\n}\n\n#[test]\nfn tera() {\n    test_root(\"tera\");\n    test_name(\"tera\");\n    test_404(\"tera\");\n    test_about(\"tera\");\n}\n\n#[test]\nfn minijinja() {\n    test_root(\"minijinja\");\n    test_name(\"minijinja\");\n    test_404(\"minijinja\");\n    test_about(\"minijinja\");\n}"
  },
  {
    "path": "examples/templating/templates/hbs/error/404.html.hbs",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>404 - hbs</title>\n  </head>\n  <body>\n    <h1>404: Hey! There's nothing here.</h1>\n    The page at {{ uri }} does not exist!\n  </body>\n</html>\n"
  },
  {
    "path": "examples/templating/templates/hbs/footer.html.hbs",
    "content": "<footer>\n  <a href=\"/\">Home</a>\n</footer>\n"
  },
  {
    "path": "examples/templating/templates/hbs/index.html.hbs",
    "content": "{{#*inline \"page\"}}\n\n<section id=\"hello\">\n  <h1>Hi {{ name }}!</h1>\n  <h3>Here are your items:</h3>\n  <ul>\n    {{#each items}}\n      <li>{{ this }}</li>\n    {{/each}}\n  </ul>\n</section>\n\n<section id=\"custom-helper\">\n  <p>Try going to <a href=\"/hbs/hello/Your%20Name\">/hbs/hello/Your Name</a>.</p>\n  <p>Also, check {{ wow \"this\" }} (custom helper) out!</p>\n</section>\n\n{{/inline}}\n{{> hbs/layout}}\n"
  },
  {
    "path": "examples/templating/templates/hbs/layout.html.hbs",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Rocket Example - {{ title }}</title>\n  </head>\n  <body>\n    {{> hbs/nav}}\n    {{~> page}}\n    {{> hbs/footer}}\n  </body>\n</html>\n"
  },
  {
    "path": "examples/templating/templates/hbs/nav.html.hbs",
    "content": "<a href=\"/hbs/hello/Unknown\">Hello</a> | <a href=\"/hbs/about\">About</a>\n"
  },
  {
    "path": "examples/templating/templates/minijinja/error/404.html.j2",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>404 - minijinja</title>\n  </head>\n  <body>\n    <h1>404: Hey! There's nothing here.</h1>\n    The page at {{ uri }} does not exist!\n  </body>\n</html>\n"
  },
  {
    "path": "examples/templating/templates/minijinja/footer.html.j2",
    "content": "<footer>\n  <a href=\"/\">Home</a>\n</footer>\n"
  },
  {
    "path": "examples/templating/templates/minijinja/index.html.j2",
    "content": "{% extends \"minijinja/layout\" %}\n\n{% block page %}\n    <section id=\"hello\">\n      <h1>Hi {{ name }}!</h1>\n      <h3>Here are your items:</h3>\n      <ul>\n        {% for item in items %}\n          <li>{{ item }}</li>\n        {% endfor %}\n      </ul>\n    </section>\n\n    <section id=\"custom-helper\">\n      <p>Try going to <a href=\"/minijinja/hello/Your%20Name\">/minijinja/hello/Your Name</a>.</p>\n    </section>\n{% endblock %}\n"
  },
  {
    "path": "examples/templating/templates/minijinja/layout.html.j2",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Rocket Example - {{ title }}</title>\n  </head>\n  <body>\n    {% include \"minijinja/nav\" %}\n    {% block page %}{% endblock %}\n    {% include \"minijinja/footer\" %}\n  </body>\n</html>\n"
  },
  {
    "path": "examples/templating/templates/minijinja/nav.html.j2",
    "content": "<a href=\"/minijinja/hello/Unknown\">Hello</a> | <a href=\"/minijinja/about\">About</a>\n"
  },
  {
    "path": "examples/templating/templates/tera/base.html.tera",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Tera Demo - {{ title }}</title>\n  </head>\n  <body>\n    {% include \"tera/nav\" %}\n\n    {% block content %}{% endblock content %}\n\n      <footer>\n        <a href=\"/\">Home</a>\n      </footer>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/templating/templates/tera/error/404.html.tera",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>404 - tera</title>\n  </head>\n  <body>\n    <h1>404: Hey! There's nothing here.</h1>\n    The page at {{ uri }} does not exist!\n  </body>\n</html>\n"
  },
  {
    "path": "examples/templating/templates/tera/index.html.tera",
    "content": "{% extends \"tera/base\" %}\n\n{% block content %}\n    <h1>Hi {{ name }}!</h1>\n    <h3>Here are your items:</h3>\n    <ul>\n        {% for s in items %}\n            <li>{{ s }}</li>\n        {% endfor %}\n    </ul>\n\n    <p>Try going to <a href=\"/tera/hello/Your%20Name\">/tera/hello/Your Name</a></p>\n{% endblock content %}\n"
  },
  {
    "path": "examples/templating/templates/tera/nav.html.tera",
    "content": "<a href=\"/tera/hello/Unknown\">Hello</a> | <a href=\"/tera/about\">About</a>\n"
  },
  {
    "path": "examples/testing/Cargo.toml",
    "content": "[package]\nname = \"testing\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\n"
  },
  {
    "path": "examples/testing/src/async_required.rs",
    "content": "use rocket::{Rocket, State, Build};\nuse rocket::fairing::AdHoc;\nuse rocket::tokio::sync::Barrier;\n\n#[get(\"/barrier\")]\nasync fn rendezvous(barrier: &State<Barrier>) -> &'static str {\n    println!(\"Waiting for second task...\");\n    barrier.wait().await;\n    \"Rendezvous reached.\"\n}\n\npub fn rocket() -> Rocket<Build> {\n    rocket::build()\n        .mount(\"/\", routes![rendezvous])\n        .attach(AdHoc::on_ignite(\"Add Channel\", |rocket| async {\n            rocket.manage(Barrier::new(2))\n        }))\n}\n\n#[cfg(test)]\nmod test {\n    use super::rocket;\n    use rocket::http::Status;\n\n    #[rocket::async_test]\n    async fn test_rendezvous() {\n        use rocket::local::asynchronous::Client;\n\n        let client = Client::tracked(rocket()).await.unwrap();\n        let req = client.get(\"/barrier\");\n\n        let (r1, r2) = rocket::tokio::join!(req.clone().dispatch(), req.dispatch());\n        assert_eq!(r1.status(), r2.status());\n        assert_eq!(r1.status(), Status::Ok);\n\n        let (s1, s2) = (r1.into_string().await, r2.into_string().await);\n        assert_eq!(s1, s2);\n        assert_eq!(s1.unwrap(), \"Rendezvous reached.\");\n    }\n}\n"
  },
  {
    "path": "examples/testing/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\nmod async_required;\n\n#[get(\"/\")]\nfn hello() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[launch]\nfn rocket() -> _ {\n    async_required::rocket().mount(\"/\", routes![hello])\n}\n\n#[cfg(test)]\nmod test {\n    use super::rocket;\n    use rocket::http::Status;\n\n    #[test]\n    fn test_hello() {\n        use rocket::local::blocking::Client;\n\n        let client = Client::tracked(rocket()).unwrap();\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.status(), Status::Ok);\n        assert_eq!(response.into_string(), Some(\"Hello, world!\".into()));\n    }\n}\n"
  },
  {
    "path": "examples/tls/Cargo.toml",
    "content": "[package]\nname = \"tls\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\", features = [\"tls\", \"mtls\", \"secrets\", \"http3-preview\"] }\nyansi = \"1.0.1\"\n\n[target.'cfg(unix)'.dependencies]\nrustls = { version = \"0.23\", features = [\"aws_lc_rs\"] }\n"
  },
  {
    "path": "examples/tls/Rocket.toml",
    "content": "# The certificate key pairs used here were generated with openssl via the\n# 'private/gen_certs.sh' script.\n#\n# These certificates are self-signed. As such, you will need to trust them\n# directly for your browser to show connections as secure. You should NEVER use\n# these certificate/key pairs. They are here for DEMONSTRATION PURPOSES ONLY.\n\n[default]\nlog_format = \"compact\"\n\n[default.tls]\ncerts = \"private/rsa_sha256_cert.pem\"\nkey = \"private/rsa_sha256_key.pem\"\n\n[default.tls.mutual]\nca_certs = \"private/ca_cert.pem\"\nmandatory = false\n\n[rsa_sha256.tls]\ncerts = \"private/rsa_sha256_cert.pem\"\nkey = \"private/rsa_sha256_key.pem\"\n\n[ecdsa_nistp256_sha256_pkcs8.tls]\ncerts = \"private/ecdsa_nistp256_sha256_cert.pem\"\nkey = \"private/ecdsa_nistp256_sha256_key_pkcs8.pem\"\n\n[ecdsa_nistp384_sha384_pkcs8.tls]\ncerts = \"private/ecdsa_nistp384_sha384_cert.pem\"\nkey = \"private/ecdsa_nistp384_sha384_key_pkcs8.pem\"\n\n[ecdsa_nistp521_sha512_pkcs8.tls]\ncerts = \"private/ecdsa_nistp521_sha512_cert.pem\"\nkey = \"private/ecdsa_nistp521_sha512_key_pkcs8.pem\"\n\n[ecdsa_nistp256_sha256_sec1.tls]\ncerts = \"private/ecdsa_nistp256_sha256_cert.pem\"\nkey = \"private/ecdsa_nistp256_sha256_key_sec1.pem\"\n\n[ecdsa_nistp384_sha384_sec1.tls]\ncerts = \"private/ecdsa_nistp384_sha384_cert.pem\"\nkey = \"private/ecdsa_nistp384_sha384_key_sec1.pem\"\n\n[ed25519.tls]\ncerts = \"private/ed25519_cert.pem\"\nkey = \"private/ed25519_key.pem\"\n"
  },
  {
    "path": "examples/tls/private/ca_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIFbzCCA1egAwIBAgIURX345HUrWikAysSTFd8xoV5GSIYwDQYJKoZIhvcNAQEL\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx\nMDcwNzIzMzMzM1owRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQK\nDAlSb2NrZXQgQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEAybxw0cVrq8yn9W9xRDHdci8rnA5CxPcxAyM5\ny5LCFOV/tTY0IZgrmegRLo4blmz8QNiFta9Ydt7zsm7XUTm6BhJ7TkOUAcfP7eSv\n3jNEIEJQLU+k5SepV7pwFPRjUr6+a7yypS2xXAkDEVoyvzsuKYwzj+x6HvDuVhOF\n2zv4Kk0sLfS/3UelMdilKa5VBCL/WMEXaCpb7/BMUUwn868LVU8E9+1H6uDQMxKo\nZH1mH98yeFODjzM9Ko6n2ghXx8qbe+wab4mSHn/SPgFnDFU+ujyPXIQqrS4PSQW3\n5lkCn70hOw2K+8LHDBmgxOLk2Jb8o8PJWX6v346dlRcZr9VzMqCyKvEf1i5oT2hg\nNZrkDdUOgyMZeq6H7pQpSxSFSMtkaombSm816V0rg7/sXwS66KyaYJY7x8eYEpgd\nGuQKXkyIwp687TGLul97amoy/J3jIDnQOuf/YEcdyHCKojh20E5AERC4sCg6l+qs\n5Nbol7jZclzBFf+70JOsUFmCfVYd5e0LKWdYV9UhYABc3yQqJyzy/eyihWihUNZU\nLXStjd+XIkhKs+b7uKaBp1poFfgjpdboxmREyppWexua1t0eAReBgMU43bEGoy+B\niWoTFjyeQijd6M++npzsqwknYyv+7VjX3EfijyTFgIpZUL196PTJ5SGJMf7eJmaG\nBO0g2W0CAwEAAaNTMFEwHQYDVR0OBBYEFEQDJSPSVPCilnYHVWae8w99S0KTMB8G\nA1UdIwQYMBaAFEQDJSPSVPCilnYHVWae8w99S0KTMA8GA1UdEwEB/wQFMAMBAf8w\nDQYJKoZIhvcNAQELBQADggIBACCArR/ArOyoh97Pgie37miFJEJNtAe+ApzhDevh\n11P0Vn5hbu+dR7vftCJ7e+0u0irbPgfdxuW3IpEDgL+fttqCIRdAT6MTKLiUmrVS\nx0fQJqC4Hw4o+bIeRsaNAfB/SAEvOxBbyu5szOFak1r/sXVs4vzBINIF3NdtbNtj\nBhac0Fiy/+DlfTHJSRGvzYo+GljXHkrG02mF4aOWx9x97y/6UzbLqHJPINgyAIlN\nts29QIHVNtQQyUN292xC1F4TSrBNB+GziGt3XZ8YEASCkMEnIvs3Lpzsjjm9TrkE\nW/b9ee3C6RWg+RW3pokORMM7Q/lSOMWUmPrzI7CBCKaQUNN9g+iimLkPyp386sCS\nzXJDd0OKb0xkpxhrauEvzNfEJxGDQbxs8s598ZofhVo9ehdmmXcJAw/zUZjHSrI2\nPW+vHJ4kslBmKtH1oyAW3zYiFyYYPu4ohkeSrq8z8351upxwJUm4m/ndByXTrPwz\nYj6dEHaysjoRl0wOJgQ7G2ikw1QtWja2apJN9Q66i98vEDmtoEyOqOLMSjKjFL7c\nsSJ6vAittYtIziIeMK7E8lDc1rtzMT5MOAoTriVyIGBgHFs96YOoL0Vi5QmVtQtc\n8dkFUapFAUj8pREVxnJoLGose/FxBvF2FQZ5Sb25pyTPAeXk7y56noF78nusiVSF\nxRjI\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/tls/private/ca_key.pem",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIJKgIBAAKCAgEAybxw0cVrq8yn9W9xRDHdci8rnA5CxPcxAyM5y5LCFOV/tTY0\nIZgrmegRLo4blmz8QNiFta9Ydt7zsm7XUTm6BhJ7TkOUAcfP7eSv3jNEIEJQLU+k\n5SepV7pwFPRjUr6+a7yypS2xXAkDEVoyvzsuKYwzj+x6HvDuVhOF2zv4Kk0sLfS/\n3UelMdilKa5VBCL/WMEXaCpb7/BMUUwn868LVU8E9+1H6uDQMxKoZH1mH98yeFOD\njzM9Ko6n2ghXx8qbe+wab4mSHn/SPgFnDFU+ujyPXIQqrS4PSQW35lkCn70hOw2K\n+8LHDBmgxOLk2Jb8o8PJWX6v346dlRcZr9VzMqCyKvEf1i5oT2hgNZrkDdUOgyMZ\neq6H7pQpSxSFSMtkaombSm816V0rg7/sXwS66KyaYJY7x8eYEpgdGuQKXkyIwp68\n7TGLul97amoy/J3jIDnQOuf/YEcdyHCKojh20E5AERC4sCg6l+qs5Nbol7jZclzB\nFf+70JOsUFmCfVYd5e0LKWdYV9UhYABc3yQqJyzy/eyihWihUNZULXStjd+XIkhK\ns+b7uKaBp1poFfgjpdboxmREyppWexua1t0eAReBgMU43bEGoy+BiWoTFjyeQijd\n6M++npzsqwknYyv+7VjX3EfijyTFgIpZUL196PTJ5SGJMf7eJmaGBO0g2W0CAwEA\nAQKCAgEAtaXTJF+SYuBlwA73u0L3NfCZYOxKXNaDsGKQkOh1j6FSi9XhvPorEGsw\nxW26E4nQ3YbZZs4bZvW8E0fQ41eKVBtiIgehhrTnWjrXzMj2p+FuFk6nmJtM1SyP\n7Z5crM4J4jLH3Qm2sLuAoqhIF37vQwP2DbsN/zxMLv9nQQ/Pli9k/4BpHpN7gNWl\nalGKRa5JpB5BuE6j9/m0jmN3eel81/TN8XwbjLefYM2FCO8M/NfZtxTj2hZ2FhLb\nuuxWNhUOSdg/uXzzMDlCEwjqQ+WiFMmhANoVH1jg9IyMmYI+ZZ1EBctdAPLSjeep\npn7zNr9FfyQ08jurmy3sYKmrPHODRFKGOHwgdu2KQ8HfxVdPiF/If+smaeb4A0LE\npZWbQfVI9SCEnDytq+KPZm0acwO+Wtngc5Gr1x3qbglg5UKp3bi1ncPMSb6H/ZiM\nvi/Wjur/bVQhB11N9XTYlQ96Od9fIcO1abY2iw7bCz5HfXO+Zvg/hqC83zm5UccP\nmTueDpxbZH0myE3BVUMZrliy42l2OTs1S1QGqFgPEnkOgTgaOK0EjZqcR+UDouxL\nj7Z1EzOYT18v185JLvXEcao9A5jGDc5xGcHD8Ryc1DW6OlE+IIJT7Wc9aHTuuLf5\neICdn81/vg4lzaWgF1bYmXBLLMNmb28RzpwTQKTQNUhFCWUaWWECggEBAOsYTI4s\nCfnj1TW9PV0rfktCZRgC1rxXF+0UBEC0dTnaKrG2iQpFttZEaPUvMObm93EqEI9m\nCSuYGbkmRrm8nUdA/MtjmPWMCNhNw1IOvVeV1xGowDACbxO7oAYKVIZUTTlUdNy0\nq6Z2u+kDXzDu9ipHzbASI9vvdJhG/WXpQKskY6ZbUFyqA6Bu9oZbEnIqNZmSIkBR\nPS4rhuzZtomJmYu9AR0/WUn5XFsLkMHzoYmTXGLfpWKzbpKZPXIdEmK1zFgEGz1U\nq9wqljFaOOdTduesH7LyK5VzEALHtMaExP7beVCOB2gl60KuCYWWKgmsyl+S4VV0\n00eYnIp3BsQNEoUCggEBANuswuuIAtuBiOY2iT1ovVo0KlkPtBUYmaDm0DQJgJKS\nqMk6M4EelCTAFTTfeiwsMg+UFmyEAFM5gnLEHNyolcMfKlbbKxH53v+ZqVAcBwKr\nE1/En419afacGnArgPHGm3MvC5Zh9+Bx/kfv+93t9VMA7lTNhX8RF1ZiDl00scik\nthWmvo4Jwp1mJR0uneXdPnI+1NtAlTk3s+q7ceEXYQYX+Mz8C/PHca2MtRzB0sM4\niwxzv46h3GAVmm9wcPtzr8ocLn0YUGMeA3JGosuRM167GgkAzWUFY3pHmIrW2QF6\nC459jVlAEdSDcNrB5+ejzJ1+1JKEVcvcewRCUJtaw8kCggEAeLWnSTCPhsFWzhr2\nkQot9JKIucVrYJUPcelfLaH6ttOwLENfJekZsfa6NXofj89zqaVBj3+CoeGdA5YF\npoST9OwHYJ8pAJsAR5/V9CIhUgFbxnNxCrWVNvqVdcSEFdzfMdqNjm0t3XEFluTm\nUYfA2YC4ufj2dI0EvtNkdJlJXRZ4HAiywIGDDzMqXV4RoJDPqKSB9ahA054Bz0cS\nFJiUQE2xbsUCIZtpsk3D6/IeNTd2rkXK81zSH2+TPy5yLEDQRTkGi30YKRmsuHZs\n1UnjuZyFQipZ+ohz5hmIVo4BYCJsrdHfN7iQjVIzDWZG+2S/HEecb3ZmrVJMvkPT\nM4LKyQKCAQEAoULLvHeWEWmgA8/ZI5l2F3ff9o1Ol4X9kV6fTPQEzJSZD0+Ia6r0\n+Z2Ac9XyK+ctwL3nUDX+vxmip3lL7rhbaGfCfwxZK9MQXvaAkmxgwRaxHEaNEiMU\n3JJv3hQxjktL5lyM1xKIEt3b2xdS//Ile49dZieRblwvk5xcCxQZxr8TZAWKMV78\n3OsVJ70G8K1foCJ7w5A/e0dm7lQ4HxM4iG6kmGYWqBirXMnEUp3+iI1DlhqKbrxn\nuKljO5eBeTXNwEK75d0pdfmcchFkhKfM3CfhzuYl4Zj5E9TnKFTb7PeY8Ds+vlwI\nOsda21wpT6SxGpT2m7BGA2eRbuj3n3Qb8QKCAQEAy6eU4AraTCo6ak9V2LfEThXx\nwX04r/XyaqaS1SjAkVSXyfbZLxj0kz9Kc4YXG6h/YFrQYdQUIrFM1rfDZOvYXkGn\ncDv5NEc+9XP5UNM5BHVir3v/kRsDuZb9Wi543n9cDOEwAKRcRzrYzqPZaY+ZRef+\nmCl88yKEElw8Odhay+8+GaU47R0LFaMeb7ZlD36VNh+d090E3MvVUFfMJ+920d6U\nlnY8l91Vqsq9ZnNoVDyVlMLB938fSs3Yg08NsZ/VXshaBMXxH/C9St/fegbvwzAl\nGn4o5X2V2NY07r+qiD7VA1PTuHt6E9c8dvOWcpbikbSo018jYFSquUWNUzzLwQ==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/private/client.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCu68//dEJZTfUb\ng6lKo0AkcjWevKMtZVpO6YnBCQ+7J0d1U0p7OCN+bisCx0nXvzDO6VxDgWEcnG44\nIR03qYVihq+C1r/96I+6chKIqK0LI2WhXvJ/sXnzz1feFyBYoz/oSM6QndcjUV83\nR8nzp1+eefuTDjuhcCddAk8fU5fJ9OLd7B2sKit8ZLHdHwqlZSWU32sS12xEjP//\nTjazNzP137KVa/KKVvRu2xYlRWHRmR1zY8trSy1795GIdv7198nF2i+0oS4k0PrF\nLzIUYgr1fCZr3QYjLK7mErSpkXUk5FoEhApmWo9iGLOOWv3HUSC8yCgdcIcauK8N\nzTqz2iORAgMBAAECggEAEeG3d1+U3M5Jt/tYq3GkQAA7l7OkYXf9UxiFZZTIj+hZ\nt2vBWcwJDNwJoj9p6W1OebMveb3YhfU+lexaBp5aLWf5ZJW8NiJidxFBmx4rOnqZ\njB/0XbYbR8pdgC27DR9QjC134x7PpyOivo2kiTewtbcLTyLjA64/HT9RhAamphWA\naGNex/imFfrWObHg9BNTtfMDekfsOwHOIgbWS/TvdJaVbUzOphZZLmM3mOG/VROG\nBIlDS7mfIO1/YHCE88vfRD3iuiGe3H86Tb6qZL+3xNNAzXIu/UqpLz+FGc9TMJRK\nFZ/u0beD1U6Ij9/BZ6XO3UF7tN84UqhudZ2rnlG35QKBgQDeg4f6lNpTOKRgrVYx\nsLZN5HANWe9I5n8z+TZcv2/pPtQY1A9ZDPM7s0b+Zys089k4f5qXNew0u/JTpin8\nh2MYNvNxXt/fCMxw7PBTkXB1JW+Qofz9k04NRXvMXEtGA3VR+vQcUwdEa9t9dWjD\nrM1k5vp2tSIgqJujZmqtqQdpJwKBgQDJPr9qlVCbWGNXn70HPl5G2MVPvRT6aHVo\nHx9XUTU4spyCIfmsckh0S2BODJZAHlTZctOKPz7KfnPC6T8V9Vgwzwnv18X71+9w\n4Z8D4OznWL3FNP5RaXSkR7JkpyE79drjVS5MCWC1k7Rr5T9dMPLu6GyjjH6nLfrr\nMsKuNa7QhwKBgBoP1dFntdqhe79HDh1r0S52XxlxOzGSrbtsqQ1b7sOm9DikPdf0\nSFjpupr5gnoFRZ/0cirbyfqzOMLLZ4eIY/bmGMVik14QLcHcPpnLIxzVcafDEVqx\n8iZjyQg6lyZwKUGc3xKiNuuwplifc9HXX4c99oAI3yJsHS6aRExqy89pAoGACbTe\nFKz5A1UjDYHl4yiN8YrZEXyEO4O4TfpaT6LaF07+H4S1/yxP9FQCZCFVSehsnURd\nkah1Rd0NhlQrt8pqo4gI6amVog0LPn2TZuN9abctCAsDTTfx6U6P+yzYfITiNt7P\n6dj18iwaoq2e/cazoPRS8RyAq12bYabEHxT1xpcCgYAIEOqYHdawRk7nexDRiHcc\n8kDIofYXJRXzdjfWH+j1j5/Dk3Ssuiz+/mIZU3PeLwC/p8PS0MmuPe10fC7bHM43\nkI6rdzMEyM586eIEQGJoZmHanK6Ox27qTXoOtX0mpc7DfRVainH70Jseaz7WddNU\nwOWmTtGwe4WcO7Ky1RB/oQ==\n-----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIEwDCCAqigAwIBAgIUedqTn+lWoKa2Ns1KDFXAG15/uYYwDQYJKoZIhvcNAQEL\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTI1MDUwNDA4MDQwNFoXDTM1\nMDUwMjA4MDQwNFowgY4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh\nMRcwFQYDVQQHDA5TaWxpY29uIFZhbGxleTEPMA0GA1UECgwGUm9ja2V0MRswGQYD\nVQQDDBJSb2NrZXQgVExTIEV4YW1wbGUxIzAhBgkqhkiG9w0BCQEWFGV4YW1wbGVA\ncm9ja2V0LmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAruvP\n/3RCWU31G4OpSqNAJHI1nryjLWVaTumJwQkPuydHdVNKezgjfm4rAsdJ178wzulc\nQ4FhHJxuOCEdN6mFYoavgta//eiPunISiKitCyNloV7yf7F5889X3hcgWKM/6EjO\nkJ3XI1FfN0fJ86dfnnn7kw47oXAnXQJPH1OXyfTi3ewdrCorfGSx3R8KpWUllN9r\nEtdsRIz//042szcz9d+ylWvyilb0btsWJUVh0Zkdc2PLa0ste/eRiHb+9ffJxdov\ntKEuJND6xS8yFGIK9Xwma90GIyyu5hK0qZF1JORaBIQKZlqPYhizjlr9x1EgvMgo\nHXCHGrivDc06s9ojkQIDAQABo1wwWjAYBgNVHREEETAPgg1ETlM6bG9jYWxob3N0\nMB0GA1UdDgQWBBRfHH7YEW3/jj2tvNsdcEU7hB3SlDAfBgNVHSMEGDAWgBREAyUj\n0lTwopZ2B1VmnvMPfUtCkzANBgkqhkiG9w0BAQsFAAOCAgEAOTOF2u58WDp1kPKP\nmTcjeVBunpu1qWmditSlu9+YNPmKwv22Lcwg9dMPh1o8bH80wdtmrGH0Yi857M9D\neosieaKHNN7WUU9DRqENJutknFxZ2hd1L3GOqADJujL43BDgOWL8b3ffmfP0f7b1\n5OsFmQALNWMlI5ThpK6naor7aWjXshCVVfjrDFfAouEyr6gLgKVpYyi4cQX7MCH2\nRfDgbksKy5OmqhI2374DEQgxlqadnnc+HTx2zKmLErUSvuE1K1CmKgwrZDyueTPh\naDKBNZrWh7t7okrcbyWFMmqaZtpMWMSvldvihIXv10v9LuRuHMd+QoNvfigrJofd\nzEtk0+ZXx9DMSN5djhfyvxhapGGel68Kjt/XPamcx4pTzzxyKvoNLooEfV/WZnp7\n2n6MlNBcjmi0EBX8Xr7cbviBSXADAAGxnwFoLMUB/hK6oWdv5lkWPojzM7/E0cyW\ncjIkF54wM/mXsxoHRqNFKo5pdjZYvoonguYADTU9+EsfM7Amp06Xqm/YR79L5yCa\nGbRW0b4sUaYXGusTOuXpVqBfRxO7NG8J4r1OP9l3RP8tqwP+1JuDfyKyhD5yNmYl\nOJFfHxS8udBM3ZbrzrfaT4/1T66prRC4QeufkjP6Zhj+l88rxgdg3KEN3VOjJ1IB\nJ3ig0HbpD/ETWVT21vrqhHXJXWg=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIFbzCCA1egAwIBAgIURX345HUrWikAysSTFd8xoV5GSIYwDQYJKoZIhvcNAQEL\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx\nMDcwNzIzMzMzM1owRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQK\nDAlSb2NrZXQgQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEAybxw0cVrq8yn9W9xRDHdci8rnA5CxPcxAyM5\ny5LCFOV/tTY0IZgrmegRLo4blmz8QNiFta9Ydt7zsm7XUTm6BhJ7TkOUAcfP7eSv\n3jNEIEJQLU+k5SepV7pwFPRjUr6+a7yypS2xXAkDEVoyvzsuKYwzj+x6HvDuVhOF\n2zv4Kk0sLfS/3UelMdilKa5VBCL/WMEXaCpb7/BMUUwn868LVU8E9+1H6uDQMxKo\nZH1mH98yeFODjzM9Ko6n2ghXx8qbe+wab4mSHn/SPgFnDFU+ujyPXIQqrS4PSQW3\n5lkCn70hOw2K+8LHDBmgxOLk2Jb8o8PJWX6v346dlRcZr9VzMqCyKvEf1i5oT2hg\nNZrkDdUOgyMZeq6H7pQpSxSFSMtkaombSm816V0rg7/sXwS66KyaYJY7x8eYEpgd\nGuQKXkyIwp687TGLul97amoy/J3jIDnQOuf/YEcdyHCKojh20E5AERC4sCg6l+qs\n5Nbol7jZclzBFf+70JOsUFmCfVYd5e0LKWdYV9UhYABc3yQqJyzy/eyihWihUNZU\nLXStjd+XIkhKs+b7uKaBp1poFfgjpdboxmREyppWexua1t0eAReBgMU43bEGoy+B\niWoTFjyeQijd6M++npzsqwknYyv+7VjX3EfijyTFgIpZUL196PTJ5SGJMf7eJmaG\nBO0g2W0CAwEAAaNTMFEwHQYDVR0OBBYEFEQDJSPSVPCilnYHVWae8w99S0KTMB8G\nA1UdIwQYMBaAFEQDJSPSVPCilnYHVWae8w99S0KTMA8GA1UdEwEB/wQFMAMBAf8w\nDQYJKoZIhvcNAQELBQADggIBACCArR/ArOyoh97Pgie37miFJEJNtAe+ApzhDevh\n11P0Vn5hbu+dR7vftCJ7e+0u0irbPgfdxuW3IpEDgL+fttqCIRdAT6MTKLiUmrVS\nx0fQJqC4Hw4o+bIeRsaNAfB/SAEvOxBbyu5szOFak1r/sXVs4vzBINIF3NdtbNtj\nBhac0Fiy/+DlfTHJSRGvzYo+GljXHkrG02mF4aOWx9x97y/6UzbLqHJPINgyAIlN\nts29QIHVNtQQyUN292xC1F4TSrBNB+GziGt3XZ8YEASCkMEnIvs3Lpzsjjm9TrkE\nW/b9ee3C6RWg+RW3pokORMM7Q/lSOMWUmPrzI7CBCKaQUNN9g+iimLkPyp386sCS\nzXJDd0OKb0xkpxhrauEvzNfEJxGDQbxs8s598ZofhVo9ehdmmXcJAw/zUZjHSrI2\nPW+vHJ4kslBmKtH1oyAW3zYiFyYYPu4ohkeSrq8z8351upxwJUm4m/ndByXTrPwz\nYj6dEHaysjoRl0wOJgQ7G2ikw1QtWja2apJN9Q66i98vEDmtoEyOqOLMSjKjFL7c\nsSJ6vAittYtIziIeMK7E8lDc1rtzMT5MOAoTriVyIGBgHFs96YOoL0Vi5QmVtQtc\n8dkFUapFAUj8pREVxnJoLGose/FxBvF2FQZ5Sb25pyTPAeXk7y56noF78nusiVSF\nxRjI\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp256_sha256_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDYTCCAUmgAwIBAgIUWET3Ypdh7TK5UE24E9Smn1r03d0wDQYJKoZIhvcNAQEL\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx\nMDcwNzIzMzMzM1owPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK\nDAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49\nAwEHA0IABDtAvrDALV/ZGurSJdoRFDvB2q7PsdjWWvzFWvQortUzmWXuFO47QJ8v\nlqluDtQKK7gHmNm10MrDk2o0ipMkrzSjGDAWMBQGA1UdEQQNMAuCCWxvY2FsaG9z\ndDANBgkqhkiG9w0BAQsFAAOCAgEAGJ/mFUyJzomXpYqGHzBRUvBqGmY05F2YOu0a\nD620WyWUFYWOnbqSKqqrP2nI1eNQXbmTtcKokuC67I2laIYML/IwBuLj+JcenvaB\nTmtmHHFSb0fweXSK3r0m9KEQBvVeoMEFhTZ6NINmXjTZES2xOks47yVo704q3xhS\n7Rm7YGu3Wgjyn4YAb7UQhgnvN0x4UlDHQAU8PB4nLHgKkgaczaERcIa/nhGA1D85\nobNkh+QSNsShnrOrDJ4iRt5ZBLjmTX3qcbJTjjzaKwwMuBTOr7f5zh417ahPWq2v\nr0GgmMW+8k8D7CjBM5TkNzOTQRjLUUKF1YjX39E4J8E/rtg8/GlHVfKRG8bvGIK8\nEIiAaSjUTY00cQltlt9QMFOTGlakF8Id4Dxkke+oP+62EK1pOroQiRvNeopEy+dO\nGee7HN5eC6n548VrMMql1TMoraWMK4kiVy46xlBmwHXq/JPG0GV/I6i24jobYeGt\n8yoeB1DlCX9uiLOKlPctxMeVPkErvVGvVZZKMR2KYNznSj/L22VXSh0xg0L6zVRX\nDsW97MZsef1t2RZf7nSz4JkSecuUHNsk12Z/Pe3G7zofz2UtV1o3G9oBHSm91a/j\nL/sAlvawy8CwLll8DRk26mg7YLwgxnNfJzG9M0G8Fwi6XPUBx2ywsSTWSO0KQ+5C\np2mcGCY=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp256_sha256_key_pkcs8.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgz5+60CMzUC7X2U50\nS8KIDYQ6MHUtwMTsHcUrbDhLfLahRANCAAQ7QL6wwC1f2Rrq0iXaERQ7wdquz7HY\n1lr8xVr0KK7VM5ll7hTuO0CfL5apbg7UCiu4B5jZtdDKw5NqNIqTJK80\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp256_sha256_key_sec1.pem",
    "content": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIM+futAjM1Au19lOdEvCiA2EOjB1LcDE7B3FK2w4S3y2oAoGCCqGSM49\nAwEHoUQDQgAEO0C+sMAtX9ka6tIl2hEUO8Hars+x2NZa/MVa9Ciu1TOZZe4U7jtA\nny+WqW4O1AoruAeY2bXQysOTajSKkySvNA==\n-----END EC PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp384_sha384_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDfjCCAWagAwIBAgIUB+Ff5LDKhcdjusOuaCqjePqScwQwDQYJKoZIhvcNAQEM\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx\nMDcwNzIzMzMzM1owPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK\nDAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDB2MBAGByqGSM49AgEGBSuBBAAi\nA2IABNkp8NiqSoUc8bwJq0fIRFyvdDN0jUT4+9MdoJ/CJyKHjeVVBcMWXBJbKTmo\nrFbkJ6WcUbBU30K0+KTvqX9tFLXOmpwUZDyqmkeU78VV7DJrDKSy5Hgxz5hXJ309\nlz+Kr6MYMBYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBDAUAA4IC\nAQATXjqJmDfj0/C1KzSoFgvuiDK6NseMJijkKauaGdHUSGf2P06izvwke8xW3P/b\nVifOkpKX3K9RxY4R7xDenTXIEDnKYlp2a77djbef8mBL914ZQSXBFF8Lhz1QD/QC\nsIM8exCuelgHbfPh/UdLY1CmEcYOlHQYUpIMYkH7U0KbLvqafY3d7WkERuXwzAUd\nkYCAV2V23f2HiuOaX616QYW7Ow6jPrhU1RwEW25Y/Ubw+jQKDSRE6NF+inR7WPot\n2GN0ELY+6trxe0w0DL0syOsfF9SVkvgfKhwBKVCsJvCp4HmOIBDlZL40NhrnXK6L\nHmUsyckVVMSmPRrvNrIy7m6CoCbdb8wWPlhpygMrOFfhpGJ2fIMzf4JzQnsAKHO9\n1D5mtzaHNNcwBdWNTvVOojy0BRsRrNYcO/Lkf5+VwZ3+AQVPPwG04kk7fA/iONQx\nhraiVy6Majl4pFfbWcAOaSDDSMsZ8Joc6AmCiPQGVelrqzZ1wa+a12BBfibqYdm7\nab831J7KrkK2rfCC84ZdUcICcWkPCisMfPeoaQsp2R4Zw7Rcuyfce8UVZYZsmZ9X\nrmgp6O3oIWK31iHkgpb+bQM0YXykbK/fp7vxqnfk2kq+IadSlDwOJ/U8sdNMVHdK\nmct9ke+F1KFB+J8UU5w/JK/Tn7HtWY8lf9VTuK8pAkyQAg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp384_sha384_key_pkcs8.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDClF5pKlKs9J5iaOAJE\nHe7v7RfcSt14yMjrp6y1jntK9j9jzTXAGtHCyWwdW0GYTVmhZANiAATZKfDYqkqF\nHPG8CatHyERcr3QzdI1E+PvTHaCfwicih43lVQXDFlwSWyk5qKxW5CelnFGwVN9C\ntPik76l/bRS1zpqcFGQ8qppHlO/FVewyawyksuR4Mc+YVyd9PZc/iq8=\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp384_sha384_key_sec1.pem",
    "content": "-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDClF5pKlKs9J5iaOAJEHe7v7RfcSt14yMjrp6y1jntK9j9jzTXAGtHC\nyWwdW0GYTVmgBwYFK4EEACKhZANiAATZKfDYqkqFHPG8CatHyERcr3QzdI1E+PvT\nHaCfwicih43lVQXDFlwSWyk5qKxW5CelnFGwVN9CtPik76l/bRS1zpqcFGQ8qppH\nlO/FVewyawyksuR4Mc+YVyd9PZc/iq8=\n-----END EC PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp521_sha512_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIID5DCCAcygAwIBAgIUZ2n0Lhg+9cVPCOtK7Ov1D5n58GIwDQYJKoZIhvcNAQEN\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTI0MDMyNzExMDYzMFoXDTM0\nMDMyNTExMDYzMFowPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK\nDAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDCBmzAQBgcqhkjOPQIBBgUrgQQA\nIwOBhgAEAYXtydjaJR3BsC6NVEPD8wxIobzKO004WjyKFupkQcuQPg4DDzLTimho\nSyH3ohaYX398MBSSgxo5A1zTb0TB/Yl1AYLiP6SWmZfejRdyZuRQSNrNIH07MIId\ne+l8VD0DVSb9+Zej5eet4sRgcVgxIzfSCi1mVzSCttbwagpvZW/HBEEgo1gwVjAU\nBgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0OBBYEFMvhtxA9Tm+8JRx1MfLdJk3Z\nXW5DMB8GA1UdIwQYMBaAFEQDJSPSVPCilnYHVWae8w99S0KTMA0GCSqGSIb3DQEB\nDQUAA4ICAQCscu1VBrqQRLON5s86UQv+sCATmW9kWWLCnHn78iGfxMa9N4L9rsf4\naFTFpfklOHYBPLK0q2Jm681rzD09FN0DTxG5t9WIsQ2PEJc2akqbzx1Sm4sMZ/td\n79oS/BLgKEOL8RDtU4dQu5DsrOqOYtDbH4ETwGs3TL3eWH+3sC9S25Sq/DJ9TFHm\npZIzEB9rEwgXMsZ0KVYzEAByKZvJZJbp5nRFJPO4riuY+RkyeqQh+oWxRAplqk2s\nyZEgxgnJIPzVYJkZ8VxaWLF9mU2kHtJlHwlTf6Yp3LTuyr9mwVsNTY+xXco6d5p8\nbMVUBvVCxNmFHsv2maNOHF2AkxwncIkSNK00ohX5rSnZ1Tdipq3ckjpkbTccYWO2\naEPUphZUkGNReSnJ0LKDyCW4Y4Yna3SG152DfMaIjQjflyh8jUnsrGdISxuemE/z\n2RnTzoSJLGMZvw52BsPbq9aNiZy7kM495oANFSaHwDbkEAknYKyAj2uO2740qEOH\nxhmsa67lPeofZBoU86gydkszCOWN1GzGOmoF9OFfD5H9M6mtYJ6l1h6/80ofx2Fv\nSdaksbRdERx20hVPM6tsAbfeP2mmxelVmhxwziQe5ERybrBx23w+khsfsA8Ldv+7\nhbAqYufmcmsSxdEA+Fuo18vhHOT98UmKlXx1hyERm0hbJe9rW+rGKg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/tls/private/ecdsa_nistp521_sha512_key_pkcs8.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIA3a6vdhcCDC8p/8yG\neDASmWqQdkmgU9kaqqgmBh2gcLhTxxtjwAy8BxBy4UmRFo8VJtFUDLXt8ZR2vzTc\nzKybjrmhgYkDgYYABAGF7cnY2iUdwbAujVRDw/MMSKG8yjtNOFo8ihbqZEHLkD4O\nAw8y04poaEsh96IWmF9/fDAUkoMaOQNc029Ewf2JdQGC4j+klpmX3o0XcmbkUEja\nzSB9OzCCHXvpfFQ9A1Um/fmXo+XnreLEYHFYMSM30gotZlc0grbW8GoKb2VvxwRB\nIA==\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/private/ed25519_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDMjCCARqgAwIBAgIUdMGHQoLHGcks+Hnw7dC5dEl0/ogwDQYJKoZIhvcNAQEL\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx\nMDcwNzIzMzMzM1owPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK\nDAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDAqMAUGAytlcAMhAP7ORUynwg2q\nIbwJwpOThFhc/IhiWxIIACcaiNKPtdEzoxgwFjAUBgNVHREEDTALgglsb2NhbGhv\nc3QwDQYJKoZIhvcNAQELBQADggIBAKcrsLA9ijRjE/h8FUNbEz547a8wCy6NskRh\nvCLIsC3k3pfhmKatM3BSwrpePFv6iSPIlp6rY9rTYx+vnLGVnT5bjPDA3Q5VwyIF\nlAYnbZP7VSQKWr2hLqFd/3sUvg7kSL16nVi4GaRYTAH2W9IQWyx+GKqv6lRmDFwS\nTCoPu2YnoboWTYMFdsrxdkzvBkQX+IF45aVTnUbAcLAc7hgZdK6+ZAhIk4ymDDWj\nFeGi/hJ5zF9a/zdV+62CHuIwgCT3ETUXeVLKWf6+v2pOMYXmpdPJf5g06zsrpcYY\ni+ZdYPXFs4/yzwcUpgYdkpszMJcxgUSn/u2E9/9BFtJa/kwDbHCDItyR2rSeDoUI\n2mQY6Kjm8BucM8hBoNYh9HOHEn1450PHIyWzcSMFkhfqSAKzngVcuSmRkUYhIdHu\nbUu29CLJzvOCTFxAWd4uWO2EbH5QFOeD9sQjqzadw0KX5kZl3Oe0wJqLswpKXd7m\nuQzcIjGNhY3STk722z0sFuZOvZPoi2d46ZKRBIJ9OYQfUzLDWW1PjqIuX7gWOUfe\nPaSs8K2qQlfniPJzHFQ3XHB4KJoWP2BcTUh5mkmpq5st5Buox8JUeAH+SalltR+K\nSkvvyv6hIhKyUDrgqV3dhIdTiexRLsmosXdps7ifJdmDtJcuWVp5hCS05X5oHTk/\n6WWSkctl\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/tls/private/ed25519_key.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIKzhuOs4KVtmEBw86yumn8ID4tYm/aPmz8QtBIrlJkTE\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/private/gen_certs.sh",
    "content": "#! /bin/bash\n\n# Usage:\n#   ./gen_certs.sh [cert-kind]\n#\n# [cert-kind]:\n#   ed25519\n#   rsa_sha256\n#   ecdsa_nistp256_sha256\n#   ecdsa_nistp384_sha384\n#   ecdsa_nistp521_sha512\n#   client\n#\n# Generate a certificate of the [cert-kind] key type, or if no cert-kind is\n# specified, all of the certificates.\n#\n# Examples:\n#   ./gen_certs.sh ed25519\n#   ./gen_certs.sh rsa_sha256\n\n# TODO: `rustls` (really, `webpki`) doesn't currently use the CN in the subject\n# to check if a certificate is valid for a server name sent via SNI. It's not\n# clear if this is intended, since certificates _should_ have a `subjectAltName`\n# with a DNS name, or if it simply hasn't been implemented yet. See\n# https://bugzilla.mozilla.org/show_bug.cgi?id=552346 for a bit more info.\n\nCA_SUBJECT=\"/C=US/ST=CA/O=Rocket CA/CN=Rocket Root CA\"\nSUBJECT=\"/C=US/ST=CA/O=Rocket/CN=localhost\"\nALT=\"DNS:localhost\"\n\nfunction gen_ca() {\n  openssl genrsa -out ca_key.pem 4096\n  openssl req -new -x509 -days 3650 -key ca_key.pem \\\n    -subj \"${CA_SUBJECT}\" -out ca_cert.pem\n}\n\nfunction gen_ca_if_non_existent() {\n  if ! [ -f ./ca_cert.pem ]; then gen_ca; fi\n}\n\nfunction gen_rsa_sha256() {\n  gen_ca_if_non_existent\n\n  openssl req -newkey rsa:4096 -nodes -sha256 -keyout rsa_sha256_key.pem \\\n    -subj \"${SUBJECT}\" -out server.csr\n\n  openssl x509 -req -sha256 -extfile <(printf \"subjectAltName=${ALT}\") -days 3650 \\\n    -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \\\n    -in server.csr -out rsa_sha256_cert.pem\n\n  openssl pkcs12 -export -password pass:rocket \\\n    -in rsa_sha256_cert.pem -inkey rsa_sha256_key.pem -out rsa_sha256.p12\n\n  rm ca_cert.srl server.csr\n}\n\nfunction gen_ed25519() {\n  gen_ca_if_non_existent\n\n  openssl genpkey -algorithm ED25519 > ed25519_key.pem\n\n  openssl req -new -key ed25519_key.pem -subj \"${SUBJECT}\" -out server.csr\n\n  openssl x509 -req -extfile <(printf \"subjectAltName=${ALT}\") -days 3650 \\\n    -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \\\n    -in server.csr -out ed25519_cert.pem\n\n  openssl pkcs12 -export -password pass:rocket \\\n    -in ed25519_cert.pem -inkey ed25519_key.pem -out ed25519.p12\n\n  rm ca_cert.srl server.csr\n}\n\nfunction gen_ecdsa_nistp256_sha256() {\n  gen_ca_if_non_existent\n\n  openssl ecparam -out ecdsa_nistp256_sha256_key.pem -name prime256v1 -genkey\n\n  # Convert to pkcs8 format supported by rustls\n  openssl pkcs8 -topk8 -nocrypt -in ecdsa_nistp256_sha256_key.pem \\\n    -out ecdsa_nistp256_sha256_key_pkcs8.pem\n\n  openssl req -new -nodes -sha256 -key ecdsa_nistp256_sha256_key_pkcs8.pem \\\n    -subj \"${SUBJECT}\" -out server.csr\n\n  openssl x509 -req -sha256 -extfile <(printf \"subjectAltName=${ALT}\") -days 3650 \\\n    -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \\\n    -in server.csr -out ecdsa_nistp256_sha256_cert.pem\n\n  openssl pkcs12 -export -password pass:rocket -in ecdsa_nistp256_sha256_cert.pem \\\n    -inkey ecdsa_nistp256_sha256_key_pkcs8.pem -out ecdsa_nistp256_sha256.p12\n\n  rm ca_cert.srl server.csr ecdsa_nistp256_sha256_key.pem\n}\n\nfunction gen_ecdsa_nistp384_sha384() {\n  gen_ca_if_non_existent\n\n  openssl ecparam -out ecdsa_nistp384_sha384_key.pem -name secp384r1 -genkey\n\n  # Convert to pkcs8 format supported by rustls\n  openssl pkcs8 -topk8 -nocrypt -in ecdsa_nistp384_sha384_key.pem \\\n    -out ecdsa_nistp384_sha384_key_pkcs8.pem\n\n  openssl req -new -nodes -sha384 -key ecdsa_nistp384_sha384_key_pkcs8.pem \\\n    -subj \"${SUBJECT}\" -out server.csr\n\n  openssl x509 -req -sha384 -extfile <(printf \"subjectAltName=${ALT}\") -days 3650 \\\n    -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \\\n    -in server.csr -out ecdsa_nistp384_sha384_cert.pem\n\n  openssl pkcs12 -export -password pass:rocket -in ecdsa_nistp384_sha384_cert.pem \\\n    -inkey ecdsa_nistp384_sha384_key_pkcs8.pem -out ecdsa_nistp384_sha384.p12\n\n  rm ca_cert.srl server.csr ecdsa_nistp384_sha384_key.pem\n}\n\nfunction gen_ecdsa_nistp521_sha512() {\n  gen_ca_if_non_existent\n\n  openssl ecparam -out ecdsa_nistp521_sha512_key.pem -name secp521r1 -genkey\n\n  # Convert to pkcs8 format supported by rustls\n  openssl pkcs8 -topk8 -nocrypt -in ecdsa_nistp521_sha512_key.pem \\\n    -out ecdsa_nistp521_sha512_key_pkcs8.pem\n\n  openssl req -new -nodes -sha512 -key ecdsa_nistp521_sha512_key_pkcs8.pem \\\n    -subj \"${SUBJECT}\" -out server.csr\n\n  openssl x509 -req -sha512 -extfile <(printf \"subjectAltName=${ALT}\") -days 3650 \\\n    -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \\\n    -in server.csr -out ecdsa_nistp521_sha512_cert.pem\n\n  openssl pkcs12 -export -password pass:rocket -in ecdsa_nistp521_sha512_cert.pem \\\n    -inkey ecdsa_nistp521_sha512_key_pkcs8.pem -out ecdsa_nistp521_sha512.p12\n\n  rm ca_cert.srl server.csr ecdsa_nistp521_sha512_key.pem\n}\n\nfunction gen_client_cert() {\n  openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj \"/C=US/ST=California/L=Silicon Valley/O=Rocket/CN=Rocket TLS Example/emailAddress=example@rocket.local\"\n  openssl x509 -req -extfile <(printf \"subjectAltName=DNS:${ALT}\") -days 3650 \\\n    -in client.csr -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \\\n    -out client.crt\n\n  cat client.key client.crt ca_cert.pem > client.pem\n  rm client.key client.crt client.csr ca_cert.srl\n}\n\ncase $1 in\n  ed25519) gen_ed25519 ;;\n  rsa_sha256) gen_rsa_sha256 ;;\n  ecdsa_nistp256_sha256) gen_ecdsa_nistp256_sha256 ;;\n  ecdsa_nistp384_sha384) gen_ecdsa_nistp384_sha384 ;;\n  ecdsa_nistp521_sha512) gen_ecdsa_nistp521_sha512 ;;\n  client) gen_client_cert ;;\n  *)\n    gen_ed25519\n    gen_rsa_sha256\n    gen_ecdsa_nistp256_sha256\n    gen_ecdsa_nistp384_sha384\n    gen_ecdsa_nistp521_sha512\n    gen_client_cert\n    ;;\nesac\n"
  },
  {
    "path": "examples/tls/private/rsa_sha256_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIFLDCCAxSgAwIBAgIUNMz1ihOL/c1J1sgYy1c3ehB5z2cwDQYJKoZIhvcNAQEL\nBQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg\nQ0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx\nMDcwNzIzMzMzM1owPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK\nDAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQAD\nggIPADCCAgoCggIBAMdnhZbeSDVddiKDOf+ZXjlChpgsiIizflHLHu4sWob3ZrwW\nBiICo2fezTZojcvFaMJooojlShENuLLxnPgc5O6WZiElR8vwAV/1ZJBzSdtplj/F\nNeT2AwR9Maw/XfQ7/Mg7z+svCrXwWq95RHs2Dd4Mci6WrQuDEs2rTlodNoA1KHu/\nll+YTkAn9rhSjkMu3hM2MLYO0dGhAKm2FTEmeYvmbo5ZIoiMcC7I5jJpWlnA/niE\njCvku0CWXJSIrlFU36G0FzbkJOvnl/RlSr5jjEs8607Wf26wlCP6R880BzZKdNoi\nzzbc2Vj76kHuyOX2LAQ7v51p9n8PNuxnFJtJFnEPVXYlMenwgf63ElqQx8SoemlT\nZT/yJv49qYHPXOEs8aoxeT9QhZ+3DtB43LOkxbUSsIQs7RNWTbZQIqi7eHi1PkFg\nyoHUKnWGLo1narDdlr0yvBz4FrnBTcb6JHCYK1dVm2+y7XspKDX4/8ymG3VOaPf6\nAoafSHoL/eF2sfK7DL4pTv5sDDQiBafL3+KWOMRD/UoVEvriPdgnuwf9sNGdM/rY\n1vHjUgVnsD3UnkIoT7mhLKF+budS6KUaSh3ZA8+C8a82Zyeznxf9luR7hs7edt7G\nehcyTJ3WfNOKslmXnvrwhJ7zHpd//TU9hkBJLyve1zNtZPsJH7N94wfUYd1nAgMB\nAAGjGDAWMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAgEA\nr7yYMGxmRTtDyN49y+pMbyiIjpKj8VW2TEfPFQvvOIRlGj6GT6EQMdeTigp9t+Sl\nv0lyMv6DjNPANzFAPvMdtQBU3SC1Grd1CtvRXqy290B2WV01Kpj4Yfi7+HMQgy6G\nFEytkm+FEUQjF2fwxsiMrSVeaVX7a67fSxXqzzANQToE994IdW/qQmlCuQvh0J8D\nN6IGY5N7tVIWDKJpH/YmKbe20dFdSk2NTHTZpLLm4Eqe/gG8qIUf6RBJgiqxJV0y\nYPKM3qXdwmwVFe/+EkX6BO3xqDmjqCi4eQRAbTDEmHqO4zVdXBQMkeRTWwH68r4D\nzRvZOA+ZDpnIMiSKozn6ZKM1py5m8BT2rD1ZRoMxNpaVauZzIu4V90oOB7Bii7hC\nHZDsHeX9kiGdeslSsyWYBEpeEeuf0MEz11pfROG2/zwk6StGPvK0xaKkRFifiTFq\nI1RSV0vG78zS73eTm5EABfAsAQTjQjkfnJEiTueMqoD8NMCgyogeuVr6p7DzDHgh\n3VlzcImwOMSt1P1IRS5zty9AZR60Vrup33jYjCBj+GOQvU55etoHZV9PazEXbmN0\nv/zzIVvK3wF9NluX/ItSGTJkX+EDSCbFbp2U9C27XRHAIi+vRLYIZuWi3oLU8uLN\nbLlrSSTY/OmBxlmyayzPFElY5Qd8FHLQPF+his89eP4=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "examples/tls/private/rsa_sha256_key.pem",
    "content": "# COMMENTARY\n\n-----BEGIN PRIVATE KEY-----\nMIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDHZ4WW3kg1XXYi\ngzn/mV45QoaYLIiIs35Ryx7uLFqG92a8FgYiAqNn3s02aI3LxWjCaKKI5UoRDbiy\n8Zz4HOTulmYhJUfL8AFf9WSQc0nbaZY/xTXk9gMEfTGsP130O/zIO8/rLwq18Fqv\neUR7Ng3eDHIulq0LgxLNq05aHTaANSh7v5ZfmE5AJ/a4Uo5DLt4TNjC2DtHRoQCp\nthUxJnmL5m6OWSKIjHAuyOYyaVpZwP54hIwr5LtAllyUiK5RVN+htBc25CTr55f0\nZUq+Y4xLPOtO1n9usJQj+kfPNAc2SnTaIs823NlY++pB7sjl9iwEO7+dafZ/Dzbs\nZxSbSRZxD1V2JTHp8IH+txJakMfEqHppU2U/8ib+PamBz1zhLPGqMXk/UIWftw7Q\neNyzpMW1ErCELO0TVk22UCKou3h4tT5BYMqB1Cp1hi6NZ2qw3Za9Mrwc+Ba5wU3G\n+iRwmCtXVZtvsu17KSg1+P/Mpht1Tmj3+gKGn0h6C/3hdrHyuwy+KU7+bAw0IgWn\ny9/iljjEQ/1KFRL64j3YJ7sH/bDRnTP62Nbx41IFZ7A91J5CKE+5oSyhfm7nUuil\nGkod2QPPgvGvNmcns58X/Zbke4bO3nbexnoXMkyd1nzTirJZl5768ISe8x6Xf/01\nPYZASS8r3tczbWT7CR+zfeMH1GHdZwIDAQABAoICAQCEAEu2677xVMV3Y1dplKWD\nUj63TgO0Ot5MVyJKmKH05qHjsNCugwCZKiy+78euNSh8SbgO13qIf4TdMISw2q/S\nIU3Kc1tr7Z17YH8KAMfLr8H+xRZAU3r75cSUOf6AR5W3F6E0FxgICOx/bM+goM/d\nRm/v118GV+aCr/xWOzBw/r+l69YnwjNK1SnGKyBx6Pypyx3D51uOYf6GWjr9JnMf\n4ZMeOHNb4VwCHIwGoydkcxYBwfzosaojv2XaDgEXZhAEg6s6cxzd7Znx93vbPRsK\nU3GR5vzE0a+/gVc4G0EK948TOCfkMZ7QATO6IdBsKuJIiyT1l8fNpMy/Ah3qDiAD\n2+6PWUb7hnclFnIE0a4RYDNPUj5UEHT5emVwVU4/WOhDyUDMYP0hCXfBmRrsLu+C\n4KQpx23CG8D5oDy+gkplvi+oYZwLbMFhRculepfZHiC7ySaLsyXjJ3IxwUVoZ4W3\naffFufroXn6+yNIneETUi+IAXuEKDujVahniKi0VWwQuP19yTybiLhNaJwmd3/mJ\nb8xtKUMPf5qQgJXrzugCo4ZpAd12nbVgztIkH2wkss61xQ1cReuAKMzaDxd44ndi\nh7EaXEiLxpNZlpKli4AviIutyoe/Z1rJL0LweeJv/Eos01f0snjcqJt7LTn9Jiiv\nZbDltF1oR3HxLA7Ow8HGgQKCAQEA9Y6f60ngSlrgVGI/LTPLZUuEusu+hbNRoxgt\n9TAuU8IRLxVkGNa8mXUuqbvxcmhEeXKtJVcLUHl75l2muVYoTgjxbufLeJnLtFdg\nAYYFLCF1k/xTIZBG67JdnLmhLUsDj9U0ugUOhtQ6qWbAq2O9TIfsC542Bg20T4km\nLm6sNh717kwTTwiVgGG8koDmI8f8iFM9vITUWO6uwVc+VJS7jG9BL7TmRtUqCt5W\n77pScWPPTPkvwjxVKqCay5HT6JXcZCBtizabrlB0e+/LisAfDLzUHstwRcsJ+zOb\n59ZNpKVfUl36Wh6NJ7Y9r7Qgk0pPjl4xpoigjqtU0fEAkT+JKQKCAQEAz+Ju5HkG\n+SxKWUyTph824H6IaqJwAvybwTxvNzoH0yVTgzyADTBEjsvXbi/JREgXhPLQlp+/\nLKlhWer4GcdxEQZZtYefIJ+LhKEPPlmgR/z8mR4sKKelB82Vt+qurKVTWXzfniBZ\nmgZj+E7KHLphkX1GRedy0s3jmbdcnA75Pevi7adgGVMzofAn3sKD63soQxyizmGJ\nOqa6loywkMaiM0UlnrWcC0HnqJ2sodsVoJ66xRmdVZ6XIsahfHQrkvWXW1CDQPVN\nej4RfGNI6cF558DNTB3PwzwiRBthqyaTD6nqwBBolYVzXsp2KD/dVmiIlHK1Xaqq\nOnoUAMZ8yni0DwKCAQEAuj6Z5pCa0GqK2RXHSxaMv2B+5FriP3AZjDUrrlsD2D1K\nYUa9K+W7GD17zfshjx+sR90FnFuf1kK+CaSgbtP9L+qyi+a9OdSUX00iISWwSJ98\nGWj4+G0AjYY0YEmfCMZrhi00l558PSE8+P1ZRuUYT7KMAufVm9PLHcQtNGx2q3ni\nGAKVZo1hLwVyTD/9zcfCLvfLzG+Gy4kE/NmaCfbhJQvBClkPi0vkXmfy0lKkcyI7\nuesKIS03f2Re4+XQLwlzJnI+A6fAfn7BSrs+yxcatcOGs3Cj0BvGj0O+jSHKtAVF\n/igPWUjw0Nz1fo2FY5GqM5YX3HKmLG+gnrdHMeNZuQKCAQAkOkSzAjhp4gMO7t5o\nO9ZXZxWk56v3iUgnc7259R35+O5F15xFMB0yeWmQpTlA8gNPQvWA2lP5l4cEoYMd\nEvmsStwFW54qlEM/GMZMSlg5U2g90tlFOHn1Eym9RGOuaJ1O4gkiSGb1BZoUYr6s\nJPrt3NQLSJtlC0ZXunGkLKPY26vPWLTRlQNRfEWmd2V/+xV4JJxmtO6yTu4DYH9A\nq60GnE1DDEkmWRTi+J9mEYUCWccYpC8cBag3AkCQLLqPQMdgvXYyMs2OuRRZBgBl\n5Da3YY0lb6iOUIN0NQVfSzijqSvkzrc7H2eMpGHU/9Q1w7/Rhu/+Y8iIqk+kFvMW\nYdSXAoIBABYkzaflWSE2EnNDeMVLkQDHcC1zI08wfhAQH/oN832rqmCyL67GQU97\nmT3qOXG59RSODt2NcokEIuPo1CNlO9f9F/AXLel3eHErYrTIaYBVBTRI2O/1tkJi\nd0MY4CGw6qdqHguR3wx6b6iJwgRTrwwo6L+SOGmNmDlc84rt8f3SDVnsq+TLGeuL\nLwYN5uJn3fiiJXLNa6V5sbJHZ5xVgORpsM0LZDoLqZm2Dlw1JWKM44WBULu+G5LB\nhhqlyQOqwkGmAYmKWyZlOJtAWLbH6zrwcEo22EP0bQ2+NobkPPiNxv9o3PCWYE9p\nP8TQRNCBnG+P8u4TcF4+aFcjAlBHOUg=\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "examples/tls/src/main.rs",
    "content": "#[macro_use]\nextern crate rocket;\nextern crate self as tracing;\n\n#[cfg(test)]\nmod tests;\nmod redirector;\n\nuse rocket::tracing::*;\nuse rocket::mtls::Certificate;\nuse rocket::listener::Endpoint;\n\n#[get(\"/\")]\nfn mutual(cert: Certificate<'_>) -> String {\n    format!(\"Hello! Here's what we know: [{}] {}\", cert.serial(), cert.subject())\n}\n\n#[get(\"/\", rank = 2)]\nfn hello(endpoint: Option<&Endpoint>) -> String {\n    match endpoint {\n        Some(endpoint) => format!(\"Hello, {endpoint}!\"),\n        None => \"Hello, world!\".into(),\n    }\n}\n\n#[launch]\nfn rocket() -> _ {\n    // See `Rocket.toml` and `Cargo.toml` for TLS configuration.\n    // Run `./private/gen_certs.sh` to generate a CA and key pairs.\n    rocket::build()\n        .mount(\"/\", routes![hello, mutual])\n        .attach(redirector::Redirector::on(3000))\n}\n"
  },
  {
    "path": "examples/tls/src/redirector.rs",
    "content": "//! Redirect all HTTP requests to HTTPs.\n\nuse std::net::SocketAddr;\n\nuse rocket::{Rocket, Ignite, Orbit, State, Error};\nuse rocket::http::uri::{Origin, Host};\nuse rocket::tracing::Instrument;\nuse rocket::fairing::{Fairing, Info, Kind};\nuse rocket::response::Redirect;\nuse rocket::listener::tcp::TcpListener;\nuse rocket::trace::Trace;\n\n#[derive(Debug, Clone, Copy, Default)]\npub struct Redirector(u16);\n\n#[derive(Debug, Clone)]\npub struct Config {\n    server: rocket::Config,\n    tls_addr: SocketAddr,\n}\n\n#[route(\"/<_..>\")]\nfn redirect(config: &State<Config>, uri: &Origin<'_>, host: &Host<'_>) -> Redirect {\n    // FIXME: Check the host against a whitelist!\n    let domain = host.domain();\n    let https_uri = match config.tls_addr.port() {\n        443 => format!(\"https://{domain}{uri}\"),\n        port => format!(\"https://{domain}:{port}{uri}\"),\n    };\n\n    Redirect::permanent(https_uri)\n}\n\nimpl Redirector {\n    pub fn on(port: u16) -> Self {\n        Redirector(port)\n    }\n\n    // Launch an instance of Rocket than handles redirection on `self.port`.\n    pub async fn try_launch(self, config: Config) -> Result<Rocket<Ignite>, Error> {\n        rocket::span_info!(\"HTTP -> HTTPS Redirector\" => {\n            info!(from = self.0, to = config.tls_addr.port(),  \"redirecting\");\n        });\n\n        let addr = SocketAddr::new(config.tls_addr.ip(), self.0);\n        rocket::custom(&config.server)\n            .manage(config)\n            .mount(\"/\", routes![redirect])\n            .try_launch_on(TcpListener::bind(addr))\n            .await\n    }\n}\n\n#[rocket::async_trait]\nimpl Fairing for Redirector {\n    fn info(&self) -> Info {\n        Info {\n            name: \"HTTP -> HTTPS Redirector\",\n            kind: Kind::Liftoff | Kind::Singleton\n        }\n    }\n\n    #[tracing::instrument(name = \"HTTP -> HTTPS Redirector\", skip_all)]\n    async fn on_liftoff(&self, rocket: &Rocket<Orbit>) {\n        let Some(tls_addr) = rocket.endpoints().find_map(|e| e.tls()?.tcp()) else {\n            warn!(\"Main instance is not being served over TLS/TCP.\\n\\\n                Redirector refusing to start.\");\n\n            return;\n        };\n\n        let this = *self;\n        let shutdown = rocket.shutdown();\n        let span = tracing::info_span!(\"HTTP -> HTTPS Redirector\");\n        let config = Config { tls_addr, server: rocket.config().clone() };\n        rocket::tokio::spawn(async move {\n            if let Err(e) = this.try_launch(config).await {\n                e.trace_error();\n                info!(\"shutting down main instance\");\n                shutdown.notify();\n            }\n        }.instrument(span));\n    }\n}\n"
  },
  {
    "path": "examples/tls/src/tests.rs",
    "content": "use std::fs::{self, File};\n\nuse rocket::http::{CookieJar, Cookie};\nuse rocket::local::blocking::Client;\nuse rocket::fs::relative;\n\n#[get(\"/cookie\")]\nfn cookie(jar: &CookieJar<'_>) {\n    jar.add((\"k1\", \"v1\"));\n    jar.add_private((\"k2\", \"v2\"));\n\n    jar.add(Cookie::build((\"k1u\", \"v1u\")).secure(false));\n    jar.add_private(Cookie::build((\"k2u\", \"v2u\")).secure(false));\n}\n\n#[test]\nfn hello_mutual() {\n    let client = Client::tracked_secure(super::rocket()).unwrap();\n    let cert_paths = fs::read_dir(relative!(\"private\")).unwrap()\n        .map(|entry| entry.unwrap().path().to_string_lossy().into_owned())\n        .filter(|path| path.ends_with(\"_cert.pem\") && !path.ends_with(\"ca_cert.pem\"));\n\n    for path in cert_paths {\n        let response = client.get(\"/\")\n            .identity(File::open(&path).unwrap())\n            .dispatch();\n\n        let response = response.into_string().unwrap();\n        let subject = response.split(']').nth(1).unwrap().trim();\n        assert_eq!(subject, \"C=US, ST=CA, O=Rocket, CN=localhost\");\n    }\n}\n\n#[test]\nfn secure_cookies() {\n    let rocket = super::rocket().mount(\"/\", routes![cookie]);\n    let client = Client::tracked_secure(rocket).unwrap();\n\n    let response = client.get(\"/cookie\").dispatch();\n    let c1 = response.cookies().get(\"k1\").unwrap();\n    let c2 = response.cookies().get_private(\"k2\").unwrap();\n    let c3 = response.cookies().get(\"k1u\").unwrap();\n    let c4 = response.cookies().get_private(\"k2u\").unwrap();\n\n    assert_eq!(c1.secure(), Some(true));\n    assert_eq!(c2.secure(), Some(true));\n    assert_ne!(c3.secure(), Some(true));\n    assert_ne!(c4.secure(), Some(true));\n}\n\n#[test]\nfn insecure_cookies() {\n    let rocket = super::rocket().mount(\"/\", routes![cookie]);\n    let client = Client::tracked(rocket).unwrap();\n\n    let response = client.get(\"/cookie\").dispatch();\n    let c1 = response.cookies().get(\"k1\").unwrap();\n    let c2 = response.cookies().get_private(\"k2\").unwrap();\n    let c3 = response.cookies().get(\"k1u\").unwrap();\n    let c4 = response.cookies().get_private(\"k2u\").unwrap();\n\n    assert_eq!(c1.secure(), None);\n    assert_eq!(c2.secure(), None);\n    assert_eq!(c3.secure(), None);\n    assert_eq!(c4.secure(), None);\n}\n\nfn validate_profiles(profiles: &[&str]) {\n    use rocket::config::{Config, TlsConfig, SecretKey};\n\n    for profile in profiles {\n        let config = Config {\n            secret_key: SecretKey::generate().unwrap(),\n            ..Config::debug_default()\n        };\n\n        let figment = Config::figment().merge(config).select(profile);\n        let client = Client::tracked_secure(super::rocket().reconfigure(figment)).unwrap();\n        let response = client.get(\"/\").dispatch();\n        assert_eq!(response.into_string().unwrap(), \"Hello, world!\");\n\n        let figment = client.rocket().figment();\n        let config: TlsConfig = figment.extract_inner(\"tls\").unwrap();\n        config.validate().expect(\"valid TLS config\");\n    }\n}\n\n#[test]\nfn validate_tls_profiles() {\n    const DEFAULT_PROFILES: &[&str] = &[\n        \"rsa_sha256\",\n        \"ecdsa_nistp256_sha256_pkcs8\",\n        \"ecdsa_nistp384_sha384_pkcs8\",\n        \"ecdsa_nistp256_sha256_sec1\",\n        \"ecdsa_nistp384_sha384_sec1\",\n        \"ed25519\",\n    ];\n\n    validate_profiles(DEFAULT_PROFILES);\n\n    #[cfg(unix)] {\n        rustls::crypto::aws_lc_rs::default_provider().install_default().unwrap();\n        validate_profiles(DEFAULT_PROFILES);\n        validate_profiles(&[\"ecdsa_nistp521_sha512_pkcs8\"]);\n    }\n}\n"
  },
  {
    "path": "examples/todo/Cargo.toml",
    "content": "[package]\nname = \"todo\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\ndiesel = { version = \"2.0.0\", features = [\"sqlite\", \"r2d2\"] }\ndiesel_migrations = \"2.0.0\"\n\n[dev-dependencies]\nparking_lot = \"0.12\"\nrand = \"0.9\"\n\n[dependencies.rocket_sync_db_pools]\npath = \"../../contrib/sync_db_pools/lib/\"\nfeatures = [\"diesel_sqlite_pool\"]\n\n[dependencies.rocket_dyn_templates]\npath = \"../../contrib/dyn_templates\"\nfeatures = [\"tera\"]\n"
  },
  {
    "path": "examples/todo/README.md",
    "content": "# Rocket Todo Example\n\nThis example makes use of a SQLite database via `diesel` to store todo tasks. As\na result, you'll need to have `sqlite3` and its headers installed:\n\n  * **OS X:** `brew install sqlite`\n  * **Debian/Ubuntu:** `apt-get install libsqlite3-dev`\n  * **Arch:** `pacman -S sqlite`\n"
  },
  {
    "path": "examples/todo/Rocket.toml",
    "content": "[default]\ntemplate_dir = \"static\"\n\n[default.databases.sqlite_database]\nurl = \"db/db.sqlite\"\n"
  },
  {
    "path": "examples/todo/db/DB_LIVES_HERE",
    "content": ""
  },
  {
    "path": "examples/todo/migrations/.gitkeep",
    "content": ""
  },
  {
    "path": "examples/todo/migrations/20160720150332_create_tasks_table/down.sql",
    "content": "DROP TABLE tasks\n"
  },
  {
    "path": "examples/todo/migrations/20160720150332_create_tasks_table/up.sql",
    "content": "CREATE TABLE tasks (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    description VARCHAR NOT NULL,\n    completed BOOLEAN NOT NULL DEFAULT 0\n);\n\nINSERT INTO tasks (description) VALUES (\"demo task\");\nINSERT INTO tasks (description) VALUES (\"demo task2\");\n"
  },
  {
    "path": "examples/todo/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n#[macro_use] extern crate rocket_sync_db_pools;\n#[macro_use] extern crate diesel;\n\n#[cfg(test)]\nmod tests;\nmod task;\n\nuse rocket::{Rocket, Build};\nuse rocket::fairing::AdHoc;\nuse rocket::request::FlashMessage;\nuse rocket::response::{Flash, Redirect};\nuse rocket::serde::Serialize;\nuse rocket::form::Form;\nuse rocket::fs::{FileServer, relative};\n\nuse rocket_dyn_templates::Template;\n\nuse crate::task::{Task, Todo};\n\n#[database(\"sqlite_database\")]\npub struct DbConn(diesel::SqliteConnection);\n\n#[derive(Debug, Serialize)]\n#[serde(crate = \"rocket::serde\")]\nstruct Context {\n    flash: Option<(String, String)>,\n    tasks: Vec<Task>\n}\n\nimpl Context {\n    pub async fn err<M: std::fmt::Display>(conn: &DbConn, msg: M) -> Context {\n        Context {\n            flash: Some((\"error\".into(), msg.to_string())),\n            tasks: Task::all(conn).await.unwrap_or_default()\n        }\n    }\n\n    pub async fn raw(conn: &DbConn, flash: Option<(String, String)>) -> Context {\n        match Task::all(conn).await {\n            Ok(tasks) => Context { flash, tasks },\n            Err(e) => {\n                error!(\"DB Task::all() error: {e}\");\n                Context {\n                    flash: Some((\"error\".into(), \"Fail to access database.\".into())),\n                    tasks: vec![]\n                }\n            }\n        }\n    }\n}\n\n#[post(\"/\", data = \"<todo_form>\")]\nasync fn new(todo_form: Form<Todo>, conn: DbConn) -> Flash<Redirect> {\n    let todo = todo_form.into_inner();\n    if todo.description.is_empty() {\n        Flash::error(Redirect::to(\"/\"), \"Description cannot be empty.\")\n    } else if let Err(e) = Task::insert(todo, &conn).await {\n        error!(\"DB insertion error: {e}\");\n        Flash::error(Redirect::to(\"/\"), \"Todo could not be inserted due an internal error.\")\n    } else {\n        Flash::success(Redirect::to(\"/\"), \"Todo successfully added.\")\n    }\n}\n\n#[put(\"/<id>\")]\nasync fn toggle(id: i32, conn: DbConn) -> Result<Redirect, Template> {\n    match Task::toggle_with_id(id, &conn).await {\n        Ok(_) => Ok(Redirect::to(\"/\")),\n        Err(e) => {\n            error!(\"DB toggle({id}) error: {e}\");\n            Err(Template::render(\"index\", Context::err(&conn, \"Failed to toggle task.\").await))\n        }\n    }\n}\n\n#[delete(\"/<id>\")]\nasync fn delete(id: i32, conn: DbConn) -> Result<Flash<Redirect>, Template> {\n    match Task::delete_with_id(id, &conn).await {\n        Ok(_) => Ok(Flash::success(Redirect::to(\"/\"), \"Todo was deleted.\")),\n        Err(e) => {\n            error!(\"DB deletion({id}) error: {e}\");\n            Err(Template::render(\"index\", Context::err(&conn, \"Failed to delete task.\").await))\n        }\n    }\n}\n\n#[get(\"/\")]\nasync fn index(flash: Option<FlashMessage<'_>>, conn: DbConn) -> Template {\n    let flash = flash.map(FlashMessage::into_inner);\n    Template::render(\"index\", Context::raw(&conn, flash).await)\n}\n\nasync fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {\n    use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};\n\n    const MIGRATIONS: EmbeddedMigrations = embed_migrations!(\"migrations\");\n\n    DbConn::get_one(&rocket).await\n        .expect(\"database connection\")\n        .run(|conn| { conn.run_pending_migrations(MIGRATIONS).expect(\"diesel migrations\"); })\n        .await;\n\n    rocket\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .attach(DbConn::fairing())\n        .attach(Template::fairing())\n        .attach(AdHoc::on_ignite(\"Run Migrations\", run_migrations))\n        .mount(\"/\", FileServer::new(relative!(\"static\")))\n        .mount(\"/\", routes![index])\n        .mount(\"/todo\", routes![new, toggle, delete])\n}\n"
  },
  {
    "path": "examples/todo/src/task.rs",
    "content": "use rocket::serde::Serialize;\nuse diesel::{self, prelude::*};\n\nmod schema {\n    table! {\n        tasks {\n            id -> Nullable<Integer>,\n            description -> Text,\n            completed -> Bool,\n        }\n    }\n}\n\nuse self::schema::tasks;\n\nuse crate::DbConn;\n\n#[derive(Serialize, Queryable, Insertable, Debug, Clone)]\n#[serde(crate = \"rocket::serde\")]\n#[diesel(table_name = tasks)]\npub struct Task {\n    #[serde(skip_deserializing)]\n    pub id: Option<i32>,\n    pub description: String,\n    pub completed: bool\n}\n\n#[derive(Debug, FromForm)]\npub struct Todo {\n    pub description: String,\n}\n\nimpl Task {\n    pub async fn all(conn: &DbConn) -> QueryResult<Vec<Task>> {\n        conn.run(|c| {\n            tasks::table.order(tasks::id.desc()).load::<Task>(c)\n        }).await\n    }\n\n    /// Returns the number of affected rows: 1.\n    pub async fn insert(todo: Todo, conn: &DbConn) -> QueryResult<usize> {\n        conn.run(|c| {\n            let t = Task { id: None, description: todo.description, completed: false };\n            diesel::insert_into(tasks::table).values(&t).execute(c)\n        }).await\n    }\n\n    /// Returns the number of affected rows: 1.\n    pub async fn toggle_with_id(id: i32, conn: &DbConn) -> QueryResult<usize> {\n        conn.run(move |c| {\n            let task = tasks::table.filter(tasks::id.eq(id)).get_result::<Task>(c)?;\n            let new_status = !task.completed;\n            let updated_task = diesel::update(tasks::table.filter(tasks::id.eq(id)));\n            updated_task.set(tasks::completed.eq(new_status)).execute(c)\n        }).await\n    }\n\n    /// Returns the number of affected rows: 1.\n    pub async fn delete_with_id(id: i32, conn: &DbConn) -> QueryResult<usize> {\n        conn.run(move |c| diesel::delete(tasks::table)\n            .filter(tasks::id.eq(id))\n            .execute(c))\n            .await\n    }\n\n    /// Returns the number of affected rows.\n    #[cfg(test)]\n    pub async fn delete_all(conn: &DbConn) -> QueryResult<usize> {\n        conn.run(|c| diesel::delete(tasks::table).execute(c)).await\n    }\n}\n"
  },
  {
    "path": "examples/todo/src/tests.rs",
    "content": "use super::task::Task;\n\nuse rand::{self, Rng, distr::Alphanumeric};\n\nuse rocket::local::asynchronous::Client;\nuse rocket::http::{Status, ContentType};\n\n// We use a lock to synchronize between tests so DB operations don't collide.\n// For now. In the future, we'll have a nice way to run each test in a DB\n// transaction so we can regain concurrency.\nstatic DB_LOCK: parking_lot::Mutex<()> = parking_lot::const_mutex(());\n\nmacro_rules! run_test {\n    (|$client:ident, $conn:ident| $block:expr) => ({\n        let _lock = DB_LOCK.lock();\n\n        rocket::async_test(async move {\n            let $client = Client::tracked(super::rocket()).await.expect(\"Rocket client\");\n            let db = super::DbConn::get_one($client.rocket()).await;\n            let $conn = db.expect(\"failed to get database connection for testing\");\n            Task::delete_all(&$conn).await.expect(\"failed to delete all tasks for testing\");\n\n            $block\n        })\n    })\n}\n\n#[test]\nfn test_index() {\n    use rocket::local::blocking::Client;\n\n    let _lock = DB_LOCK.lock();\n    let client = Client::tracked(super::rocket()).unwrap();\n    let response = client.get(\"/\").dispatch();\n    assert_eq!(response.status(), Status::Ok);\n}\n\n#[test]\nfn test_insertion_deletion() {\n    run_test!(|client, conn| {\n        // Get the tasks before making changes.\n        let init_tasks = Task::all(&conn).await.unwrap();\n\n        // Issue a request to insert a new task.\n        client.post(\"/todo\")\n            .header(ContentType::Form)\n            .body(\"description=My+first+task\")\n            .dispatch()\n            .await;\n\n        // Ensure we have one more task in the database.\n        let new_tasks = Task::all(&conn).await.unwrap();\n        assert_eq!(new_tasks.len(), init_tasks.len() + 1);\n\n        // Ensure the task is what we expect.\n        assert_eq!(new_tasks[0].description, \"My first task\");\n        assert!(!new_tasks[0].completed);\n\n        // Issue a request to delete the task.\n        let id = new_tasks[0].id.unwrap();\n        client.delete(format!(\"/todo/{}\", id)).dispatch().await;\n\n        // Ensure it's gone.\n        let final_tasks = Task::all(&conn).await.unwrap();\n        assert_eq!(final_tasks.len(), init_tasks.len());\n        if !final_tasks.is_empty() {\n            assert_ne!(final_tasks[0].description, \"My first task\");\n        }\n    })\n}\n\n#[test]\nfn test_toggle() {\n    run_test!(|client, conn| {\n        // Issue a request to insert a new task; ensure it's not yet completed.\n        client.post(\"/todo\")\n            .header(ContentType::Form)\n            .body(\"description=test_for_completion\")\n            .dispatch()\n            .await;\n\n        let task = Task::all(&conn).await.unwrap()[0].clone();\n        assert!(!task.completed);\n\n        // Issue a request to toggle the task; ensure it is completed.\n        client.put(format!(\"/todo/{}\", task.id.unwrap())).dispatch().await;\n        assert!(Task::all(&conn).await.unwrap()[0].completed);\n\n        // Issue a request to toggle the task; ensure it's not completed again.\n        client.put(format!(\"/todo/{}\", task.id.unwrap())).dispatch().await;\n        assert!(!Task::all(&conn).await.unwrap()[0].completed);\n    })\n}\n\n#[test]\nfn test_many_insertions() {\n    const ITER: usize = 100;\n\n    run_test!(|client, conn| {\n        // Get the number of tasks initially.\n        let init_num = Task::all(&conn).await.unwrap().len();\n        let mut descs = Vec::new();\n\n        for i in 0..ITER {\n            // Issue a request to insert a new task with a random description.\n            let desc: String = rand::rng()\n                .sample_iter(&Alphanumeric)\n                .take(12)\n                .map(char::from)\n                .collect();\n\n            client.post(\"/todo\")\n                .header(ContentType::Form)\n                .body(format!(\"description={}\", desc))\n                .dispatch()\n                .await;\n\n            // Record the description we choose for this iteration.\n            descs.insert(0, desc);\n\n            // Ensure the task was inserted properly and all other tasks remain.\n            let tasks = Task::all(&conn).await.unwrap();\n            assert_eq!(tasks.len(), init_num + i + 1);\n\n            for j in 0..i {\n                assert_eq!(descs[j], tasks[j].description);\n            }\n        }\n    })\n}\n\n#[test]\nfn test_bad_form_submissions() {\n    run_test!(|client, _conn| {\n        // Submit an empty form. We should get a 422 but no flash error.\n        let res = client.post(\"/todo\")\n            .header(ContentType::Form)\n            .dispatch()\n            .await;\n\n        assert!(!res.cookies().iter().any(|c| c.value().contains(\"error\")));\n        assert_eq!(res.status(), Status::UnprocessableEntity);\n\n        // Submit a form with an empty description. We look for 'error' in the\n        // cookies which corresponds to flash message being set as an error.\n        let res = client.post(\"/todo\")\n            .header(ContentType::Form)\n            .body(\"description=\")\n            .dispatch()\n            .await;\n\n        // Check that the flash cookie set and that we're redirected to index.\n        assert!(res.cookies().iter().any(|c| c.value().contains(\"error\")));\n        assert_eq!(res.status(), Status::SeeOther);\n\n        // The flash cookie should still be present and the error message should\n        // be rendered the index.\n        let body = client.get(\"/\").dispatch().await.into_string().await.unwrap();\n        assert!(body.contains(\"Description cannot be empty.\"));\n\n        // Check that the flash is cleared upon another visit to the index.\n        let body = client.get(\"/\").dispatch().await.into_string().await.unwrap();\n        assert!(!body.contains(\"Description cannot be empty.\"));\n\n        // Submit a form without a description. Expect a 422 but no flash error.\n        let res = client.post(\"/todo\")\n            .header(ContentType::Form)\n            .body(\"evil=smile\")\n            .dispatch()\n            .await;\n\n        assert!(!res.cookies().iter().any(|c| c.value().contains(\"error\")));\n        assert_eq!(res.status(), Status::UnprocessableEntity);\n    })\n}\n"
  },
  {
    "path": "examples/todo/static/css/normalize.css",
    "content": "/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\n\n/**\n * 1. Set default font family to sans-serif.\n * 2. Prevent iOS text size adjust after orientation change, without disabling\n *    user zoom.\n */\n\nhtml {\n  font-family: sans-serif; /* 1 */\n  -ms-text-size-adjust: 100%; /* 2 */\n  -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/**\n * Remove default margin.\n */\n\nbody {\n  margin: 0;\n}\n\n/* HTML5 display definitions\n   ========================================================================== */\n\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11\n * and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\n\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block; /* 1 */\n  vertical-align: baseline; /* 2 */\n}\n\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n\n[hidden],\ntemplate {\n  display: none;\n}\n\n/* Links\n   ========================================================================== */\n\n/**\n * Remove the gray background color from active links in IE 10.\n */\n\na {\n  background-color: transparent;\n}\n\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\n\na:active,\na:hover {\n  outline: 0;\n}\n\n/* Text-level semantics\n   ========================================================================== */\n\n/**\n * Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n */\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n/**\n * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n */\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n/**\n * Address styling not present in Safari and Chrome.\n */\n\ndfn {\n  font-style: italic;\n}\n\n/**\n * Address variable `h1` font-size and margin within `section` and `article`\n * contexts in Firefox 4+, Safari, and Chrome.\n */\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n/**\n * Address styling not present in IE 8/9.\n */\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n/**\n * Address inconsistent and variable font size in all browsers.\n */\n\nsmall {\n  font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n/* Embedded content\n   ========================================================================== */\n\n/**\n * Remove border when inside `a` element in IE 8/9/10.\n */\n\nimg {\n  border: 0;\n}\n\n/**\n * Correct overflow not hidden in IE 9/10/11.\n */\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n/* Grouping content\n   ========================================================================== */\n\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\n\nfigure {\n  margin: 1em 40px;\n}\n\n/**\n * Address differences between Firefox and other browsers.\n */\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n/**\n * Contain overflow in all browsers.\n */\n\npre {\n  overflow: auto;\n}\n\n/**\n * Address odd `em`-unit font size rendering in all browsers.\n */\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n/* Forms\n   ========================================================================== */\n\n/**\n * Known limitation: by default, Chrome and Safari on OS X allow very limited\n * styling of `select`, unless a `border` property is set.\n */\n\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit; /* 1 */\n  font: inherit; /* 2 */\n  margin: 0; /* 3 */\n}\n\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\n\nbutton {\n  overflow: visible;\n}\n\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n */\n\nbutton,\nhtml input[type=\"button\"], /* 1 */\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; /* 2 */\n  cursor: pointer; /* 3 */\n}\n\n/**\n * Re-set default cursor for disabled elements.\n */\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n/**\n * Remove inner padding and border in Firefox 4+.\n */\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\n\ninput {\n  line-height: normal;\n}\n\n/**\n * It's recommended that you don't attempt to style these elements.\n * Firefox's implementation doesn't respect box-sizing, padding, or width.\n *\n * 1. Address box sizing set to `content-box` in IE 8/9/10.\n * 2. Remove excess padding in IE 8/9/10.\n */\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n *    (include `-moz` to future-proof).\n */\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; /* 1 */\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box; /* 2 */\n  box-sizing: content-box;\n}\n\n/**\n * Remove inner padding and search cancel button in Safari and Chrome on OS X.\n * Safari (but not Chrome) clips the cancel button when the search input has\n * padding (and `textfield` appearance).\n */\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n/**\n * Define consistent border, margin, and padding.\n */\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n/**\n * 1. Correct `color` not being inherited in IE 8/9/10/11.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\n\nlegend {\n  border: 0; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Remove default vertical scrollbar in IE 8/9/10/11.\n */\n\ntextarea {\n  overflow: auto;\n}\n\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\n\noptgroup {\n  font-weight: bold;\n}\n\n/* Tables\n   ========================================================================== */\n\n/**\n * Remove most spacing between table cells.\n */\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\ntd,\nth {\n  padding: 0;\n}\n"
  },
  {
    "path": "examples/todo/static/css/skeleton.css",
    "content": "/*\n* Skeleton V2.0.4\n* Copyright 2014, Dave Gamache\n* www.getskeleton.com\n* Free to use under the MIT license.\n* https://opensource.org/licenses/mit-license.php\n* 12/29/2014\n*/\n\n\n/* Table of contents\n––––––––––––––––––––––––––––––––––––––––––––––––––\n- Grid\n- Base Styles\n- Typography\n- Links\n- Buttons\n- Forms\n- Lists\n- Code\n- Tables\n- Spacing\n- Utilities\n- Clearing\n- Media Queries\n*/\n\n\n/* Grid\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\n.container {\n  position: relative;\n  width: 100%;\n  max-width: 960px;\n  margin: 0 auto;\n  padding: 0 20px;\n  box-sizing: border-box; }\n.column,\n.columns {\n  width: 100%;\n  float: left;\n  box-sizing: border-box; }\n\n/* For devices larger than 400px */\n@media (min-width: 400px) {\n  .container {\n    width: 85%;\n    padding: 0; }\n}\n\n/* For devices larger than 550px */\n@media (min-width: 550px) {\n  .container {\n    width: 80%; }\n  .column,\n  .columns {\n    margin-left: 4%; }\n  .column:first-child,\n  .columns:first-child {\n    margin-left: 0; }\n\n  .one.column,\n  .one.columns                    { width: 4.66666666667%; }\n  .two.columns                    { width: 13.3333333333%; }\n  .three.columns                  { width: 22%;            }\n  .four.columns                   { width: 30.6666666667%; }\n  .five.columns                   { width: 39.3333333333%; }\n  .six.columns                    { width: 48%;            }\n  .seven.columns                  { width: 56.6666666667%; }\n  .eight.columns                  { width: 65.3333333333%; }\n  .nine.columns                   { width: 74.0%;          }\n  .ten.columns                    { width: 82.6666666667%; }\n  .eleven.columns                 { width: 91.3333333333%; }\n  .twelve.columns                 { width: 100%; margin-left: 0; }\n\n  .one-third.column               { width: 30.6666666667%; }\n  .two-thirds.column              { width: 65.3333333333%; }\n\n  .one-half.column                { width: 48%; }\n\n  /* Offsets */\n  .offset-by-one.column,\n  .offset-by-one.columns          { margin-left: 8.66666666667%; }\n  .offset-by-two.column,\n  .offset-by-two.columns          { margin-left: 17.3333333333%; }\n  .offset-by-three.column,\n  .offset-by-three.columns        { margin-left: 26%;            }\n  .offset-by-four.column,\n  .offset-by-four.columns         { margin-left: 34.6666666667%; }\n  .offset-by-five.column,\n  .offset-by-five.columns         { margin-left: 43.3333333333%; }\n  .offset-by-six.column,\n  .offset-by-six.columns          { margin-left: 52%;            }\n  .offset-by-seven.column,\n  .offset-by-seven.columns        { margin-left: 60.6666666667%; }\n  .offset-by-eight.column,\n  .offset-by-eight.columns        { margin-left: 69.3333333333%; }\n  .offset-by-nine.column,\n  .offset-by-nine.columns         { margin-left: 78.0%;          }\n  .offset-by-ten.column,\n  .offset-by-ten.columns          { margin-left: 86.6666666667%; }\n  .offset-by-eleven.column,\n  .offset-by-eleven.columns       { margin-left: 95.3333333333%; }\n\n  .offset-by-one-third.column,\n  .offset-by-one-third.columns    { margin-left: 34.6666666667%; }\n  .offset-by-two-thirds.column,\n  .offset-by-two-thirds.columns   { margin-left: 69.3333333333%; }\n\n  .offset-by-one-half.column,\n  .offset-by-one-half.columns     { margin-left: 52%; }\n\n}\n\n\n/* Base Styles\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\n/* NOTE\nhtml is set to 62.5% so that all the REM measurements throughout Skeleton\nare based on 10px sizing. So basically 1.5rem = 15px :) */\nhtml {\n  font-size: 62.5%; }\nbody {\n  font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */\n  line-height: 1.6;\n  font-weight: 400;\n  font-family: \"Raleway\", \"HelveticaNeue\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  color: #222; }\n\n\n/* Typography\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\nh1, h2, h3, h4, h5, h6 {\n  margin-top: 0;\n  margin-bottom: 2rem;\n  font-weight: 300; }\nh1 { font-size: 4.0rem; line-height: 1.2;  letter-spacing: -.1rem;}\nh2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }\nh3 { font-size: 3.0rem; line-height: 1.3;  letter-spacing: -.1rem; }\nh4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }\nh5 { font-size: 1.8rem; line-height: 1.5;  letter-spacing: -.05rem; }\nh6 { font-size: 1.5rem; line-height: 1.6;  letter-spacing: 0; }\n\n/* Larger than phablet */\n@media (min-width: 550px) {\n  h1 { font-size: 5.0rem; }\n  h2 { font-size: 4.2rem; }\n  h3 { font-size: 3.6rem; }\n  h4 { font-size: 3.0rem; }\n  h5 { font-size: 2.4rem; }\n  h6 { font-size: 1.5rem; }\n}\n\np {\n  margin-top: 0; }\n\n\n/* Links\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\na {\n  color: #1EAEDB; }\na:hover {\n  color: #0FA0CE; }\n\n\n/* Buttons\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\n.button,\nbutton,\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n  display: inline-block;\n  height: 38px;\n  padding: 0 30px;\n  color: #555;\n  text-align: center;\n  font-size: 11px;\n  font-weight: 600;\n  line-height: 38px;\n  letter-spacing: .1rem;\n  text-transform: uppercase;\n  text-decoration: none;\n  white-space: nowrap;\n  background-color: transparent;\n  border-radius: 4px;\n  border: 1px solid #bbb;\n  cursor: pointer;\n  box-sizing: border-box; }\n.button:hover,\nbutton:hover,\ninput[type=\"submit\"]:hover,\ninput[type=\"reset\"]:hover,\ninput[type=\"button\"]:hover,\n.button:focus,\nbutton:focus,\ninput[type=\"submit\"]:focus,\ninput[type=\"reset\"]:focus,\ninput[type=\"button\"]:focus {\n  color: #333;\n  border-color: #888;\n  outline: 0; }\n.button.button-primary,\nbutton.button-primary,\nbutton.primary,\ninput[type=\"submit\"].button-primary,\ninput[type=\"reset\"].button-primary,\ninput[type=\"button\"].button-primary {\n  color: #FFF;\n  background-color: #33C3F0;\n  border-color: #33C3F0; }\n.button.button-primary:hover,\nbutton.button-primary:hover,\nbutton.primary:hover,\ninput[type=\"submit\"].button-primary:hover,\ninput[type=\"reset\"].button-primary:hover,\ninput[type=\"button\"].button-primary:hover,\n.button.button-primary:focus,\nbutton.button-primary:focus,\nbutton.primary:focus,\ninput[type=\"submit\"].button-primary:focus,\ninput[type=\"reset\"].button-primary:focus,\ninput[type=\"button\"].button-primary:focus {\n  color: #FFF;\n  background-color: #1EAEDB;\n  border-color: #1EAEDB; }\n\n\n/* Forms\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\ninput[type=\"email\"],\ninput[type=\"number\"],\ninput[type=\"search\"],\ninput[type=\"text\"],\ninput[type=\"tel\"],\ninput[type=\"url\"],\ninput[type=\"password\"],\ntextarea,\nselect {\n  height: 38px;\n  padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */\n  background-color: #fff;\n  border: 1px solid #D1D1D1;\n  border-radius: 4px;\n  box-shadow: none;\n  box-sizing: border-box; }\n/* Removes awkward default styles on some inputs for iOS */\ninput[type=\"email\"],\ninput[type=\"number\"],\ninput[type=\"search\"],\ninput[type=\"text\"],\ninput[type=\"tel\"],\ninput[type=\"url\"],\ninput[type=\"password\"],\ntextarea {\n  -webkit-appearance: none;\n     -moz-appearance: none;\n          appearance: none; }\ntextarea {\n  min-height: 65px;\n  padding-top: 6px;\n  padding-bottom: 6px; }\ninput[type=\"email\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"password\"]:focus,\ntextarea:focus,\nselect:focus {\n  border: 1px solid #33C3F0;\n  outline: 0; }\nlabel,\nlegend {\n  display: block;\n  margin-bottom: .5rem;\n  font-weight: 600; }\nfieldset {\n  padding: 0;\n  border-width: 0; }\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  display: inline; }\nlabel > .label-body {\n  display: inline-block;\n  margin-left: .5rem;\n  font-weight: normal; }\n\n\n/* Lists\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\nul {\n  list-style: circle inside; }\nol {\n  list-style: decimal inside; }\nol, ul {\n  padding-left: 0;\n  margin-top: 0; }\nul ul,\nul ol,\nol ol,\nol ul {\n  margin: 1.5rem 0 1.5rem 3rem;\n  font-size: 90%; }\nli {\n  margin-bottom: 1rem; }\n\n\n/* Code\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\ncode {\n  padding: .2rem .5rem;\n  margin: 0 .2rem;\n  font-size: 90%;\n  white-space: nowrap;\n  background: #F1F1F1;\n  border: 1px solid #E1E1E1;\n  border-radius: 4px; }\npre > code {\n  display: block;\n  padding: 1rem 1.5rem;\n  white-space: pre; }\n\n\n/* Tables\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\nth,\ntd {\n  padding: 12px 15px;\n  text-align: left;\n  border-bottom: 1px solid #E1E1E1; }\nth:first-child,\ntd:first-child {\n  padding-left: 0; }\nth:last-child,\ntd:last-child {\n  padding-right: 0; }\n\n\n/* Spacing\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\nbutton,\n.button {\n  margin-bottom: 1rem; }\ninput,\ntextarea,\nselect,\nfieldset {\n  margin-bottom: 1.5rem; }\npre,\nblockquote,\ndl,\nfigure,\ntable,\np,\nul,\nol,\nform {\n  margin-bottom: 2.5rem; }\n\n\n/* Utilities\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\n.u-full-width {\n  width: 100%;\n  box-sizing: border-box; }\n.u-max-full-width {\n  max-width: 100%;\n  box-sizing: border-box; }\n.u-pull-right {\n  float: right; }\n.u-pull-left {\n  float: left; }\n\n\n/* Misc\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\nhr {\n  margin-top: 3rem;\n  margin-bottom: 3.5rem;\n  border-width: 0;\n  border-top: 1px solid #E1E1E1; }\n\n\n/* Clearing\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\n\n/* Self Clearing Goodness */\n.container:after,\n.row:after,\n.u-cf {\n  content: \"\";\n  display: table;\n  clear: both; }\n\n\n/* Media Queries\n–––––––––––––––––––––––––––––––––––––––––––––––––– */\n/*\nNote: The best way to structure the use of media queries is to create the queries\nnear the relevant code. For example, if you wanted to change the styles for buttons\non small devices, paste the mobile query code up in the buttons section and style it\nthere.\n*/\n\n\n/* Larger than mobile */\n@media (min-width: 400px) {}\n\n/* Larger than phablet (also point when grid becomes active) */\n@media (min-width: 550px) {}\n\n/* Larger than tablet */\n@media (min-width: 750px) {}\n\n/* Larger than desktop */\n@media (min-width: 1000px) {}\n\n/* Larger than Desktop HD */\n@media (min-width: 1200px) {}\n"
  },
  {
    "path": "examples/todo/static/css/style.css",
    "content": ".field-error {\n  border: 1px solid #ff0000 !important;\n}\n\n.field-error-msg {\n  color: #ff0000;\n  display: block;\n  margin: -10px 0 10px 0;\n}\n\n.field-success {\n  border: 1px solid #5AB953 !important;\n}\n\n.field-success-msg {\n  color: #5AB953;\n  display: block;\n  margin: -10px 0 10px 0;\n}\n\nspan.completed {\n    text-decoration: line-through;\n}\n\nform.inline {\n  display: inline;\n}\n\nform.link,\nbutton.link {\n  display: inline;\n  color: #1EAEDB;\n  border: none;\n  outline: none;\n  background: none;\n  cursor: pointer;\n  padding: 0;\n  margin: 0 0 0 0;\n  height: inherit;\n  text-decoration: underline;\n  font-size: inherit;\n  text-transform: none;\n  font-weight: normal;\n  line-height: inherit;\n  letter-spacing: inherit;\n}\n\nform.link:hover, button.link:hover {\n  color: #0FA0CE;\n}\n\nbutton.small {\n  height: 20px;\n  padding: 0 10px;\n  font-size: 10px;\n  line-height: 20px;\n  margin: 0 2.5px;\n}\n"
  },
  {
    "path": "examples/todo/static/index.html.tera",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>Rocket Todo Example</title>\n  <meta name=\"description\" content=\"A todo application written in Rocket.\">\n  <meta name=\"author\" content=\"Sergio Benitez\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n  <link href=\"//fonts.googleapis.com/css?family=Raleway:400,300,600\" rel=\"stylesheet\" type=\"text/css\">\n  <link rel=\"stylesheet\" href=\"/css/normalize.css\">\n  <link rel=\"stylesheet\" href=\"/css/skeleton.css\">\n  <link rel=\"stylesheet\" href=\"/css/style.css\">\n  <link rel=\"icon\" type=\"image/png\" href=\"/images/favicon.png\">\n</head>\n<body>\n  <div class=\"container\">\n    <p><!--Nothing to see here --></p>\n\n    <div class=\"row\">\n      <h4>Rocket Todo</h4>\n      <form action=\"/todo\" method=\"post\">\n        <div class=\"ten columns\">\n          <input type=\"text\" placeholder=\"enter a task description...\"\n            name=\"description\" id=\"description\" value=\"\" autofocus\n            class=\"u-full-width {% if flash %}field-{{flash.0}}{% endif %}\" />\n          {% if flash %}\n            <small class=\"field-{{flash.0}}-msg\">\n               {{ flash.1 }}\n            </small>\n          {% endif %}\n        </div>\n        <div class=\"two columns\">\n          <input type=\"submit\" value=\"add task\">\n        </div>\n      </form>\n    </div>\n\n    <div class=\"row\">\n      <div class=\"twelve columns\">\n        <ul>\n        {% for task in tasks %}\n          {% if task.completed %}\n            <li>\n              <span class=\"completed\">{{ task.description }}</span>\n              <form class=\"inline\" action=\"/todo/{{task.id}}\" method=\"post\">\n                <input type=\"hidden\" name=\"_method\" value=\"put\" />\n                <button class=\"small\" type=\"submit\">undo</button>\n              </form>\n              <form class=\"inline\" action=\"/todo/{{task.id}}\" method=\"post\">\n                <input type=\"hidden\" name=\"_method\" value=\"delete\" />\n                <button class=\"primary small\" type=\"submit\">delete</button>\n              </form>\n            </li>\n          {% else %}\n            <li>\n              <form class=\"link\" action=\"/todo/{{task.id}}\" method=\"post\">\n                <input type=\"hidden\" name=\"_method\" value=\"put\" />\n                <button class=\"link\" type=\"submit\">{{ task.description }}</button>\n              </form>\n            </li>\n          {% endif %}\n        {% endfor %}\n        </ul>\n      </div>\n    </div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "examples/upgrade/Cargo.toml",
    "content": "[package]\nname = \"upgrade\"\nversion = \"0.0.0\"\nworkspace = \"../\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nrocket = { path = \"../../core/lib\" }\nws = { package = \"rocket_ws\", path = \"../../contrib/ws\" }\n"
  },
  {
    "path": "examples/upgrade/src/main.rs",
    "content": "#[macro_use] extern crate rocket;\n\nuse rocket::fs::{self, FileServer};\nuse rocket::futures::{SinkExt, StreamExt};\n\n#[get(\"/echo?stream\", rank = 1)]\nfn echo_stream(ws: ws::WebSocket) -> ws::Stream!['static] {\n    ws::Stream! { ws =>\n        for await message in ws {\n            yield message?;\n        }\n    }\n}\n\n#[get(\"/echo?channel\", rank = 2)]\nfn echo_channel(ws: ws::WebSocket) -> ws::Channel<'static> {\n    // This is entirely optional. Change default configuration.\n    let ws = ws.config(ws::Config {\n        // set max message size to 3MiB\n        max_message_size: Some(3 << 20),\n        ..Default::default()\n    });\n\n    ws.channel(move |mut stream| Box::pin(async move {\n        while let Some(message) = stream.next().await {\n            let _ = stream.send(message?).await;\n        }\n\n        Ok(())\n    }))\n}\n\n#[get(\"/echo?raw\", rank = 3)]\nfn echo_raw(ws: ws::WebSocket) -> ws::Stream!['static] {\n    ws.stream(|stream| stream)\n}\n\n#[launch]\nfn rocket() -> _ {\n    rocket::build()\n        .mount(\"/\", routes![echo_channel, echo_stream, echo_raw])\n        .mount(\"/\", FileServer::new(fs::relative!(\"static\")))\n}\n"
  },
  {
    "path": "examples/upgrade/static/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <title>WebSocket Client Test</title>\n        <meta charset=\"UTF-8\">\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    </head>\n    <body>\n        <h1>WebSocket Client Test</h1>\n        <form action=\"#\">\n            <input type=\"text\" id=\"message\" name=\"message\" value=\"\" placeholder=\"Send a message...\">\n            <input type=\"submit\" value=\"Submit\">\n        </form>\n        <div id=\"log\"></div>\n    </body>\n    <script language=\"javascript\" type=\"text/javascript\">\n    var wsUri = \"ws://127.0.0.1:8000/echo?raw\";\n    var log;\n\n    function init() {\n        log = document.getElementById(\"log\");\n        form = document.getElementsByTagName(\"form\")[0];\n        message = document.getElementById(\"message\");\n\n        testWebSocket();\n\n        form.addEventListener(\"submit\", (e) => {\n            e.preventDefault();\n            if (message.value !== \"\") {\n                sendMessage(message.value);\n                message.value = \"\";\n            }\n        });\n    }\n\n    function testWebSocket() {\n        websocket = new WebSocket(wsUri);\n        websocket.onopen = onOpen;\n        websocket.onclose = onClose;\n        websocket.onmessage = onMessage;\n        websocket.onerror = onError;\n    }\n\n    function onOpen(evt) {\n        writeLog(\"CONNECTED\");\n        sendMessage(\"Hello, Rocket!\");\n    }\n\n    function onClose(evt) {\n        writeLog(\"Websocket DISCONNECTED\");\n    }\n\n    function onMessage(evt) {\n        writeLog('<span style=\"color: blue;\">RESPONSE: ' + evt.data+'</span>');\n    }\n\n    function onError(evt) {\n        writeLog('<span style=\"color: red;\">ERROR:</span> ' + evt.data);\n    }\n\n    function sendMessage(message) {\n        writeLog(\"SENT: \" + message);\n        websocket.send(message);\n    }\n\n    function writeLog(message) {\n        var pre = document.createElement(\"p\");\n        pre.innerHTML = message;\n        log.prepend(pre);\n    }\n\n    window.addEventListener(\"load\", init, false);\n    </script>\n</html>\n"
  },
  {
    "path": "scripts/config.sh",
    "content": "# Simply sets up a few useful variables.\n\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\nfunction relative() {\n  local full_path=\"${SCRIPT_DIR}/../${1}\"\n\n  if [ -d \"${full_path}\" ]; then\n    # Try to use readlink as a fallback to readpath for cross-platform compat.\n    if command -v realpath >/dev/null 2>&1; then\n      realpath \"${full_path}\"\n    elif ! (readlink -f 2>&1 | grep illegal > /dev/null); then\n      readlink -f \"${full_path}\"\n    else\n      echo \"Rocket's scripts require 'realpath' or 'readlink -f' support.\" >&2\n      echo \"Install realpath or GNU readlink via your package manager.\" >&2\n      echo \"Aborting.\" >&2\n      exit 1\n    fi\n  else\n    # when the directory doesn't exist, fallback to this.\n    echo \"${full_path}\"\n  fi\n}\n\nfunction future_date() {\n  local days_in_future=`[[ -z \"$1\" ]] && echo \"0\" || echo \"$1\"`\n  if date -v+1d +%Y-%m-%d > /dev/null 2>&1; then\n    echo $(date -v+${days_in_future}d +%Y-%m-%d)\n  elif date -d \"+1 day\" > /dev/null 2>&1; then\n    echo $(date '+%Y-%m-%d' -d \"+${days_in_future} days\")\n  else\n    echo \"Error: need a 'date' cmd that accepts -v (BSD) or -d (GNU)\"\n    exit 1\n  fi\n}\n\n# Root of workspace-like directories.\nPROJECT_ROOT=$(relative \"\") || exit $?\nCONTRIB_ROOT=$(relative \"contrib\") || exit $?\nBENCHMARKS_ROOT=$(relative \"benchmarks\") || exit $?\nTESTBENCH_ROOT=$(relative \"testbench\") || exit $?\nFUZZ_ROOT=$(relative \"core/lib/fuzz\") || exit $?\n\n# Root of project-like directories.\nCORE_LIB_ROOT=$(relative \"core/lib\") || exit $?\nCORE_CODEGEN_ROOT=$(relative \"core/codegen\") || exit $?\nCORE_HTTP_ROOT=$(relative \"core/http\") || exit $?\n\nCORE_CRATE_ROOTS=(\n    \"${CORE_LIB_ROOT}\"\n    \"${CORE_CODEGEN_ROOT}\"\n    \"${CORE_HTTP_ROOT}\"\n)\n\nCONTRIB_SYNC_DB_POOLS_CRATE_ROOTS=(\n    \"${CONTRIB_ROOT}/sync_db_pools/lib\"\n    \"${CONTRIB_ROOT}/sync_db_pools/codegen\"\n)\n\nCONTRIB_DB_POOLS_CRATE_ROOTS=(\n    \"${CONTRIB_ROOT}/db_pools/lib\"\n    \"${CONTRIB_ROOT}/db_pools/codegen\"\n)\n\n# Root of infrastructure directories.\nEXAMPLES_DIR=$(relative \"examples\") || exit $?\nDOC_DIR=$(relative \"target/doc\") || exit $?\n\n# Versioning information.\nVERSION=$(git grep -h \"^version\" \"${CORE_LIB_ROOT}\" | head -n 1 | cut -d '\"' -f2)\nGIT_BRANCH=\"$(git branch --show-current)\"\nGIT_BRANCH=${GIT_BRANCH:-$BRANCH}\nIS_DEV_BRANCH=$( [[ $GIT_BRANCH == \"v\"* ]]; echo $? )\n\ncase $IS_DEV_BRANCH in\n  1) DOC_VERSION=\"${GIT_BRANCH}-$(future_date)\" ;;\n  *) DOC_VERSION=\"${VERSION}\" ;;\nesac\n\nfunction print_environment() {\n  echo \"  VERSION: ${VERSION}\"\n  echo \"  GIT_BRANCH: ${GIT_BRANCH}\"\n  echo \"  IS_DEV_BRANCH: ${IS_DEV_BRANCH}\"\n  echo \"  DOC_VERSION: ${DOC_VERSION}\"\n  echo \"  SCRIPT_DIR: ${SCRIPT_DIR}\"\n  echo \"  PROJECT_ROOT: ${PROJECT_ROOT}\"\n  echo \"  CONTRIB_ROOT: ${CONTRIB_ROOT}\"\n  echo \"  FUZZ_ROOT: ${FUZZ_ROOT}\"\n  echo \"  BENCHMARKS_ROOT: ${BENCHMARKS_ROOT}\"\n  echo \"  TESTBENCH_ROOT: ${TESTBENCH_ROOT}\"\n  echo \"  CORE_LIB_ROOT: ${CORE_LIB_ROOT}\"\n  echo \"  CORE_CODEGEN_ROOT: ${CORE_CODEGEN_ROOT}\"\n  echo \"  CORE_HTTP_ROOT: ${CORE_HTTP_ROOT}\"\n  echo \"  CONTRIB_SYNC_DB_POOLS_CRATE_ROOTS: ${CONTRIB_SYNC_DB_POOLS_CRATE_ROOTS[*]}\"\n  echo \"  CONTRIB_DB_POOLS_CRATE_ROOTS: ${CONTRIB_DB_POOLS_CRATE_ROOTS[*]}\"\n  echo \"  EXAMPLES_DIR: ${EXAMPLES_DIR}\"\n  echo \"  DOC_DIR: ${DOC_DIR}\"\n  echo \"  date(): $(future_date)\"\n}\n\nif [ \"${1}\" = \"-p\" ]; then\n  print_environment\nfi\n"
  },
  {
    "path": "scripts/mk-docs.sh",
    "content": "#!/bin/bash\nset -e\n\n#\n# Builds the rustdocs for all of the libraries.\n#\n\n# Brings in: PROJECT_ROOT, EXAMPLES_DIR, LIB_DIR, CODEGEN_DIR, CONTRIB_DIR, DOC_DIR\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\nsource \"${SCRIPT_DIR}/config.sh\"\n\nif [ \"${1}\" != \"-d\" ]; then\n  # We need to clean-up beforehand so we don't get all of the dependencies.\n  echo \":::: Cleaning up before documenting...\"\n  cargo clean\n  cargo update\nfi\n\n# Generate the rustdocs for all of the crates.\necho \":::: Generating docs (${DOC_VERSION})...\"\npushd \"${PROJECT_ROOT}\" > /dev/null 2>&1\n  # Set the crate version and fill in missing doc URLs with docs.rs links.\n  RUSTDOCFLAGS=\"-Z unstable-options \\\n      --extern-html-root-url rocket=https://api.rocket.rs/${GIT_BRANCH}/rocket/ \\\n      --crate-version ${DOC_VERSION} \\\n      --enable-index-page \\\n      --generate-link-to-definition\" \\\n      cargo doc -Zrustdoc-map --no-deps --all-features \\\n        -p rocket \\\n        -p rocket_db_pools \\\n        -p rocket_sync_db_pools \\\n        -p rocket_dyn_templates \\\n        -p rocket_ws\npopd > /dev/null 2>&1\n"
  },
  {
    "path": "scripts/publish.sh",
    "content": "#! /usr/bin/env bash\nset -e\n\n#\n# Publishes the current versions of all Rocket crates to crates.io.\n#\n\n# Brings in _ROOT, _DIR, _DIRS globals.\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\nsource \"${SCRIPT_DIR}/config.sh\"\n\nif ! [ -z \"$(git status --porcelain)\" ]; then\n  echo \"There are uncommitted changes! Aborting.\"\n  exit 1\nfi\n\n# Ensure everything passes before trying to publish.\necho \":::: Running complete test suite...\"\ncargo clean\nbash \"${SCRIPT_DIR}/test.sh\" +stable --all\nbash \"${SCRIPT_DIR}/test.sh\" +stable --all --release\n\n# Publish all the things.\nfor dir in \"${ALL_CRATE_ROOTS[@]}\"; do\n  pushd \"${dir}\"\n  echo \":::: Publishing '${dir}'...\"\n  # We already checked things ourselves. Don't spend time reverifying.\n  cargo publish --no-verify --allow-dirty ${@:1}\n  # Give the index some time to update so the deps are there if we need them.\n  sleep 5\n  popd\ndone\n"
  },
  {
    "path": "scripts/test.sh",
    "content": "#!/usr/bin/env bash\nset -e\n\n# Brings in _ROOT, _DIR, _DIRS globals.\nSCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\nsource \"${SCRIPT_DIR}/config.sh\"\n\n# Add Cargo to PATH.\nexport PATH=${HOME}/.cargo/bin:${PATH}\nexport CARGO_INCREMENTAL=0\nexport RUSTC_BOOTSTRAP=1\nCARGO=\"cargo\"\n\n# Checks that the versions for Cargo projects $@ all match\nfunction check_versions_match() {\n  local last_version=\"\"\n  for dir in \"${@}\"; do\n    local cargo_toml=\"${dir}/Cargo.toml\"\n    if ! [ -f \"${cargo_toml}\" ]; then\n      echo \"Cargo configuration file '${cargo_toml}' does not exist.\"\n      exit 1\n    fi\n\n    local version=$(grep version \"${cargo_toml}\" | head -n 1 | cut -d' ' -f3)\n    if [ -z \"${last_version}\" ]; then\n      last_version=\"${version}\"\n    elif ! [ \"${version}\" = \"${last_version}\" ]; then\n      echo \"Versions differ in '${cargo_toml}'. ${version} != ${last_version}\"\n      exit 1\n    fi\n  done\n}\n\nfunction check_style() {\n  # Ensure there are no tabs in any file.\n  local tab=$(printf '\\t')\n  local matches=$(git grep -PIn \"${tab}\" \"${PROJECT_ROOT}\" | grep -v 'LICENSE')\n  if ! [ -z \"${matches}\" ]; then\n    echo \"Tab characters were found in the following:\"\n    echo \"${matches}\"\n    exit 1\n  fi\n\n  # Ensure non-comment lines are under 100 characters.\n  local n=100\n  local matches=$(git grep -PIn \"(?=^..{$n,}$)(?!^\\s*\\/\\/[\\/!].*$).*\" '*.rs')\n  if ! [ -z \"${matches}\" ]; then\n    echo \"Lines longer than $n characters were found in the following:\"\n    echo \"${matches}\"\n    exit 1\n  fi\n\n  # Ensure there's no trailing whitespace.\n  local matches=$(git grep -PIn \"\\s+$\" \"${PROJECT_ROOT}\" | grep -v -F '.stderr:')\n  if ! [ -z \"${matches}\" ]; then\n    echo \"Trailing whitespace was found in the following:\"\n    echo \"${matches}\"\n    exit 1\n  fi\n\n  local pattern='tail -n 1 % | grep -q \"^$\" && echo %'\n  local matches=$(git grep -z -Il '' | xargs -0 -P 16 -I % sh -c \"${pattern}\")\n  if ! [ -z \"${matches}\" ]; then\n    echo \"Trailing new line(s) found in the following:\"\n    echo \"${matches}\"\n    exit 1\n  fi\n}\n\nfunction indir() {\n  local dir=\"${1}\"\n  shift\n  pushd \"${dir}\" > /dev/null 2>&1 ; $@ ; popd > /dev/null 2>&1\n}\n\nfunction test_contrib() {\n  DB_POOLS_FEATURES=(\n    deadpool_postgres\n    deadpool_redis\n    sqlx_mysql\n    sqlx_postgres\n    sqlx_sqlite\n    mongodb\n    diesel_mysql\n    diesel_postgres\n  )\n\n  SYNC_DB_POOLS_FEATURES=(\n    diesel_postgres_pool\n    diesel_sqlite_pool\n    diesel_mysql_pool\n    postgres_pool\n    sqlite_pool\n    memcache_pool\n  )\n\n  DYN_TEMPLATES_FEATURES=(\n    tera\n    handlebars\n    minijinja\n  )\n\n  WS_FEATURES=(\n    tungstenite\n  )\n\n  for feature in \"${DB_POOLS_FEATURES[@]}\"; do\n    echo \":: Building and testing db_pools [$feature]...\"\n    $CARGO test -p rocket_db_pools --no-default-features --features $feature $@\n  done\n\n  for feature in \"${SYNC_DB_POOLS_FEATURES[@]}\"; do\n    echo \":: Building and testing sync_db_pools [$feature]...\"\n    $CARGO test -p rocket_sync_db_pools --no-default-features --features $feature $@\n  done\n\n  for feature in \"${DYN_TEMPLATES_FEATURES[@]}\"; do\n    echo \":: Building and testing dyn_templates [$feature]...\"\n    $CARGO test -p rocket_dyn_templates --no-default-features --features $feature $@\n  done\n\n  for feature in \"${WS_FEATURES[@]}\"; do\n    echo \":: Building and testing ws [$feature]...\"\n    $CARGO test -p rocket_ws --no-default-features --features $feature $@\n  done\n}\n\nfunction test_core() {\n  FEATURES=(\n    tokio-macros\n    http2\n    http3-preview\n    secrets\n    tls\n    mtls\n    json\n    msgpack\n    uuid\n    trace\n  )\n\n  echo \":: Building and checking core [no features]...\"\n  RUSTDOCFLAGS=\"-Zunstable-options --no-run\" \\\n    indir \"${CORE_LIB_ROOT}\" $CARGO test --no-default-features $@\n\n  for feature in \"${FEATURES[@]}\"; do\n    echo \":: Building and checking core [${feature}]...\"\n    RUSTDOCFLAGS=\"-Zunstable-options --no-run\" \\\n      indir \"${CORE_LIB_ROOT}\" $CARGO test --no-default-features --features \"${feature}\" $@\n  done\n}\n\nfunction test_examples() {\n  # Cargo compiles Rocket once with the `secrets` feature enabled, so when run\n  # in production, we need a secret key or tests will fail needlessly. We test\n  # in core that secret key failing/not failing works as expected, but here we\n  # provide a valid secret_key so tests don't fail.\n  echo \":: Building and testing examples...\"\n  indir \"${EXAMPLES_DIR}\" $CARGO update\n  ROCKET_SECRET_KEY=\"itlYmFR2vYKrOmFhupMIn/hyB6lYCCTXz4yaQX89XVg=\" \\\n    indir \"${EXAMPLES_DIR}\" $CARGO test --all $@\n}\n\nfunction test_default() {\n  echo \":: Building and testing core libraries...\"\n  indir \"${PROJECT_ROOT}\" $CARGO test --all --all-features $@\n\n  echo \":: Checking benchmarks...\"\n  indir \"${BENCHMARKS_ROOT}\" $CARGO update\n  indir \"${BENCHMARKS_ROOT}\" $CARGO check --benches --all-features $@\n\n  case \"$OSTYPE\" in\n      darwin* | linux*)\n          echo \":: Checking testbench...\"\n          indir \"${TESTBENCH_ROOT}\" $CARGO update\n          indir \"${TESTBENCH_ROOT}\" $CARGO check $@\n\n          echo \":: Checking fuzzers...\"\n          indir \"${FUZZ_ROOT}\" $CARGO update\n          indir \"${FUZZ_ROOT}\" $CARGO check --all --all-features $@\n          ;;\n      *) echo \":: Skipping testbench, fuzzers [$OSTYPE]\" ;;\n  esac\n}\n\nfunction test_ui() {\n  echo \":: Testing compile-time UI output...\"\n  indir \"${PROJECT_ROOT}\" $CARGO test --test ui-fail --all --all-features -- --ignored $@\n}\n\nfunction run_benchmarks() {\n  echo \":: Running benchmarks...\"\n  indir \"${BENCHMARKS_ROOT}\" $CARGO update\n  indir \"${BENCHMARKS_ROOT}\" $CARGO bench $@\n}\n\nfunction run_testbench() {\n  echo \":: Running testbench...\"\n  indir \"${TESTBENCH_ROOT}\" $CARGO update\n  indir \"${TESTBENCH_ROOT}\" $CARGO run $@\n}\n\n# The kind of test we'll be running.\nTEST_KIND=\"default\"\nKINDS=(\"default\" \"all\" \"core\" \"contrib\" \"examples\" \"benchmarks\" \"testbench\" \"ui\")\n\nfunction print_help() {\n  echo \"USAGE:\"\n  echo \"  $0 [+<TOOLCHAIN>] [--help|-h] [--<TEST>]\"\n  echo \"\"\n  echo \"OPTIONS:\"\n  echo \"  +<TOOLCHAIN>   Forwarded to Cargo to select toolchain.\"\n  echo \"  --help, -h     Print this help message and exit.\"\n  echo \"  --<TEST>       Run the specified test suite.\"\n  echo \"                 (Run without --<TEST> to run default tests.)\"\n\n  echo \"\"\n  echo \"AVAILABLE <TEST> OPTIONS:\"\n  for kind in \"${KINDS[@]}\"; do\n    echo \"  ${kind}\"\n  done\n\n  echo \"\"\n  echo \"EXAMPLES:\"\n  echo \"  $0                     # Run default tests on current toolchain.\"\n  echo \"  $0 +stable --all       # Run all tests on stable toolchain.\"\n  echo \"  $0 --ui                # Run UI tests on current toolchain.\"\n}\n\nif [[ $1 == +* ]]; then\n  CARGO=\"$CARGO $1\"\n  shift\nfi\n\nif [[ $1 == \"--help\" ]] || [[ $1 == \"-h\" ]]; then\n  print_help\n  exit 0\nfi\n\nif [[ \" ${KINDS[@]} \" =~ \" ${1#\"--\"} \" ]]; then\n  TEST_KIND=${1#\"--\"}\n  shift\nfi\n\necho \":: Preparing. Environment is...\"\nprint_environment\necho \"  CARGO: $CARGO\"\necho \"  EXTRA FLAGS: $@\"\n\necho \":: Ensuring core crate versions match...\"\ncheck_versions_match \"${CORE_CRATE_ROOTS[@]}\"\n\necho \":: Ensuring contrib sync_db_pools versions match...\"\ncheck_versions_match \"${CONTRIB_SYNC_DB_POOLS_CRATE_ROOTS[@]}\"\n\necho \":: Ensuring contrib db_pools versions match...\"\ncheck_versions_match \"${CONTRIB_DB_POOLS_CRATE_ROOTS[@]}\"\n\necho \":: Ensuring minimum style requirements are met...\"\ncheck_style\n\necho \":: Updating dependencies...\"\nif ! $CARGO update ; then\n  echo \"   WARNING: Update failed! Proceeding with possibly outdated deps...\"\nfi\n\ncase $TEST_KIND in\n  core) test_core $@ ;;\n  contrib) test_contrib $@ ;;\n  examples) test_examples $@ ;;\n  default) test_default $@ ;;\n  benchmarks) run_benchmarks $@ ;;\n  testbench) run_testbench $@ ;;\n  ui) test_ui $@ ;;\n  all)\n    test_default $@ & default=$!\n    test_examples $@ & examples=$!\n    test_core $@ & core=$!\n    test_contrib $@ & contrib=$!\n    run_testbench $@ & testbench=$!\n    test_ui $@ & ui=$!\n\n    failures=()\n    if ! wait $default ; then failures+=(\"DEFAULT\"); fi\n    if ! wait $examples ; then failures+=(\"EXAMPLES\"); fi\n    if ! wait $core ; then failures+=(\"CORE\"); fi\n    if ! wait $contrib ; then failures+=(\"CONTRIB\"); fi\n    if ! wait $testbench ; then failures+=(\"TESTBENCH\"); fi\n    if ! wait $ui ; then failures+=(\"UI\"); fi\n\n    if [ ${#failures[@]} -ne 0 ]; then\n      tput setaf 1;\n      echo -e \"\\n!!! ${#failures[@]} TEST SUITE FAILURE(S) !!!\"\n      for failure in \"${failures[@]}\"; do\n        echo \"    :: ${failure}\"\n      done\n\n      tput sgr0\n      exit ${#failures[@]}\n    fi\n\n    ;;\nesac\n"
  },
  {
    "path": "testbench/Cargo.toml",
    "content": "[package]\nname = \"testbench\"\ndescription = \"End-to-end HTTP Rocket testbench.\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n[workspace]\n\n[dependencies]\nthiserror = \"1.0\"\nprocspawn = \"1\"\npretty_assertions = \"1.4.0\"\nipc-channel = \"0.18\"\nrustls-pemfile = \"2.1\"\ninventory = \"0.3.15\"\n\n[dependencies.nix]\nversion = \"0.28\"\nfeatures = [\"signal\"]\n\n[dependencies.rocket]\npath = \"../core/lib/\"\nfeatures = [\"secrets\", \"tls\", \"mtls\"]\n\n[dependencies.reqwest]\nversion = \"0.12.3\"\ndefault-features = false\nfeatures = [\"rustls-tls-manual-roots\", \"charset\", \"cookies\", \"blocking\", \"http2\"]\n"
  },
  {
    "path": "testbench/src/client.rs",
    "content": "use std::{str::FromStr, time::Duration};\n\nuse reqwest::blocking::{ClientBuilder, RequestBuilder};\nuse rocket::http::{ext::IntoOwned, uri::{Absolute, Uri}, Method};\n\nuse crate::{Result, Error, Server};\n\n#[derive(Debug)]\npub struct Client {\n    client: reqwest::blocking::Client,\n}\n\nimpl Client {\n    pub fn default() -> Client {\n        Client::build()\n            .try_into()\n            .expect(\"default builder ok\")\n    }\n\n    pub fn build() -> ClientBuilder {\n        reqwest::blocking::Client::builder()\n            .danger_accept_invalid_certs(true)\n            .cookie_store(true)\n            .tls_info(true)\n            .timeout(Duration::from_secs(5))\n            .connect_timeout(Duration::from_secs(5))\n    }\n\n    pub fn request<M>(&self, server: &Server, method: M, url: &str) -> Result<RequestBuilder>\n        where M: AsRef<str>\n    {\n        let uri = match Uri::parse_any(url).map_err(|e| e.into_owned())? {\n            Uri::Origin(uri) => {\n                let proto = if server.tls { \"https\" } else { \"http\" };\n                let uri = format!(\"{proto}://127.0.0.1:{}{uri}\", server.port);\n                Absolute::parse_owned(uri)?\n            }\n            Uri::Absolute(mut uri) => {\n                if let Some(auth) = uri.authority() {\n                    let mut auth = auth.clone();\n                    auth.set_port(server.port);\n                    uri.set_authority(auth);\n                }\n\n                uri\n            }\n            uri => return Err(Error::InvalidUri(uri.into_owned())),\n        };\n\n        let method = reqwest::Method::from_str(method.as_ref()).unwrap();\n        Ok(self.client.request(method, uri.to_string()))\n    }\n\n    pub fn get(&self, server: &Server, url: &str) -> Result<RequestBuilder> {\n        self.request(server, Method::Get, url)\n    }\n\n    pub fn post(&self, server: &Server, url: &str) -> Result<RequestBuilder> {\n        self.request(server, Method::Post, url)\n    }\n}\n\nimpl From<reqwest::blocking::Client> for Client {\n    fn from(client: reqwest::blocking::Client) -> Self {\n        Client { client }\n    }\n}\n\nimpl TryFrom<ClientBuilder> for Client {\n    type Error = Error;\n\n    fn try_from(builder: ClientBuilder) -> Result<Self, Self::Error> {\n        Ok(Client { client: builder.build()? })\n    }\n}\n"
  },
  {
    "path": "testbench/src/config.rs",
    "content": "use rocket::{Build, Rocket};\n\nuse testbench::{Result, Error};\n\npub static DEFAULT_CONFIG: &str = r#\"\n    [default]\n    address = \"tcp:127.0.0.1\"\n    workers = 2\n    port = 0\n    cli_colors = false\n    log_level = \"debug\"\n    secret_key = \"itlYmFR2vYKrOmFhupMIn/hyB6lYCCTXz4yaQX89XVg=\"\n\n    [default.shutdown]\n    grace = 1\n    mercy = 1\n\"#;\n\npub static TLS_CONFIG: &str = r#\"\n    [default.tls]\n    certs = \"{ROCKET}/examples/tls/private/rsa_sha256_cert.pem\"\n    key = \"{ROCKET}/examples/tls/private/rsa_sha256_key.pem\"\n\"#;\n\npub trait RocketExt {\n    fn default() -> Self;\n    fn tls_default() -> Self;\n    fn reconfigure_with_toml(self, toml: &str) -> Self;\n}\n\nimpl RocketExt for Rocket<Build> {\n    fn default() -> Self {\n        rocket::build().reconfigure_with_toml(DEFAULT_CONFIG)\n    }\n\n    fn tls_default() -> Self {\n        rocket::build()\n            .reconfigure_with_toml(DEFAULT_CONFIG)\n            .reconfigure_with_toml(TLS_CONFIG)\n    }\n\n    fn reconfigure_with_toml(self, toml: &str) -> Self {\n        use rocket::figment::{Figment, providers::{Format, Toml}};\n\n        let toml = toml.replace(\"{ROCKET}\", rocket::fs::relative!(\"../\"));\n        let config = Figment::from(self.figment())\n            .merge(Toml::string(&toml).nested());\n\n        self.reconfigure(config)\n    }\n}\n\npub fn read(path: &str) -> Result<Vec<u8>> {\n    let path = path.replace(\"{ROCKET}\", rocket::fs::relative!(\"../\"));\n    Ok(std::fs::read(path)?)\n}\n\npub fn cert(path: &str) -> Result<Vec<u8>> {\n    let mut data = std::io::Cursor::new(read(path)?);\n    let cert = rustls_pemfile::certs(&mut data).last();\n    Ok(cert.ok_or(Error::MissingCertificate)??.to_vec())\n}\n"
  },
  {
    "path": "testbench/src/lib.rs",
    "content": "// pub mod session;\nmod client;\nmod server;\n\npub use server::*;\npub use client::*;\n\nuse std::io;\nuse thiserror::Error;\nuse procspawn::SpawnError;\nuse rocket::http::uri;\n\npub type Result<T, E = Error> = std::result::Result<T, E>;\n\n#[derive(Error, Debug)]\npub enum Error {\n    #[error(\"join/kill failed: {0}\")]\n    JoinError(#[from] SpawnError),\n    #[error(\"kill failed: {0}\")]\n    TermFailure(#[from] nix::errno::Errno),\n    #[error(\"i/o error: {0}\")]\n    Io(#[from] io::Error),\n    #[error(\"invalid URI: {0}\")]\n    Uri(#[from] uri::Error<'static>),\n    #[error(\"invalid uri: {0}\")]\n    InvalidUri(uri::Uri<'static>),\n    #[error(\"expected certificates are not present\")]\n    MissingCertificate,\n    #[error(\"bad request: {0}\")]\n    Request(#[from] reqwest::Error),\n    #[error(\"IPC failure: {0}\")]\n    Ipc(#[from] ipc_channel::ipc::IpcError),\n    #[error(\"liftoff failed\")]\n    Liftoff(String, String),\n}\n"
  },
  {
    "path": "testbench/src/main.rs",
    "content": "mod runner;\nmod servers;\nmod config;\n\npub mod prelude {\n    pub use rocket::*;\n    pub use rocket::fairing::*;\n    pub use rocket::response::stream::*;\n\n    pub use testbench::{Error, Result, *};\n    pub use crate::register;\n    pub use crate::config::*;\n}\n\npub use runner::Test;\n\nfn main() -> std::process::ExitCode {\n    runner::run()\n}\n"
  },
  {
    "path": "testbench/src/runner.rs",
    "content": "use std::time::Duration;\n\nuse rocket::yansi::Paint;\n\n#[derive(Copy, Clone)]\npub struct Test {\n    pub name: &'static str,\n    pub run: fn(()) -> Result<(), String>,\n}\n\n#[macro_export]\nmacro_rules! register {\n    ($f:ident $( ( $($v:ident: $a:expr),* ) )?) => {\n        ::inventory::submit!($crate::Test {\n            name: stringify!($f $(($($v = $a),*))?),\n            run: |_: ()| $f($($($a),*)?).map_err(|e| e.to_string()),\n        });\n    };\n}\n\ninventory::collect!(Test);\n\npub fn run() -> std::process::ExitCode {\n    procspawn::init();\n\n    let filter = std::env::args().nth(1).unwrap_or_default();\n    let filtered = inventory::iter::<Test>\n        .into_iter()\n        .filter(|t| t.name.contains(&filter));\n\n    let total_tests = inventory::iter::<Test>.into_iter().count();\n    println!(\"running {}/{total_tests} tests\", filtered.clone().count());\n    let handles = filtered.map(|test| (test, std::thread::spawn(|| {\n        let name = test.name;\n        let start = std::time::SystemTime::now();\n        let mut proc = procspawn::spawn((), test.run);\n        let result = loop {\n            match proc.join_timeout(Duration::from_secs(10)) {\n                Err(e) if e.is_timeout() => {\n                    let elapsed = start.elapsed().unwrap().as_secs();\n                    println!(\"{name} has been running for {elapsed} seconds...\");\n\n                    if elapsed >= 30 {\n                        println!(\"{name} timeout\");\n                        break Err(e);\n                    }\n                },\n                result => break result,\n            }\n        };\n\n        match result.as_ref().map_err(|e| e.panic_info()) {\n            Ok(Ok(_)) => println!(\"test {name} ... {}\", \"ok\".green()),\n            Ok(Err(e)) => println!(\"test {name} ... {}\\n  {e}\", \"fail\".red()),\n            Err(Some(_)) => println!(\"test {name} ... {}\", \"panic\".red().underline()),\n            Err(None) => println!(\"test {name} ... {}\", \"error\".magenta()),\n        }\n\n        matches!(result, Ok(Ok(())))\n    })));\n\n    let mut success = true;\n    for (_, handle) in handles {\n        success &= handle.join().unwrap_or(false);\n    }\n\n    match success {\n        true => std::process::ExitCode::SUCCESS,\n        false => {\n            println!(\"note: use `NOCAPTURE=1` to see test output\");\n            std::process::ExitCode::FAILURE\n        }\n    }\n}\n"
  },
  {
    "path": "testbench/src/server.rs",
    "content": "use std::future::Future;\nuse std::net::{Ipv4Addr, SocketAddr};\nuse std::time::Duration;\nuse std::sync::Once;\nuse std::process::Stdio;\nuse std::io::Read;\n\nuse rocket::fairing::AdHoc;\nuse rocket::listener::{Bind, DefaultListener};\nuse rocket::serde::{Deserialize, DeserializeOwned, Serialize};\nuse rocket::{Build, Ignite, Rocket};\nuse rocket::trace::Trace;\n\nuse ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};\n\nuse crate::{Result, Error};\n\n#[derive(Debug)]\npub struct Server {\n    proc: procspawn::JoinHandle<Launched>,\n    pub tls: bool,\n    pub port: u16,\n    _rx: IpcReceiver<Message>,\n}\n\n#[derive(Debug, Serialize, Deserialize)]\n#[serde(crate = \"rocket::serde\")]\npub enum Message {\n    Liftoff(bool, u16),\n    Failure,\n}\n\n#[derive(Serialize, Deserialize)]\n#[serde(crate = \"rocket::serde\")]\npub struct Token(String);\n\n#[derive(Serialize, Deserialize)]\n#[serde(crate = \"rocket::serde\")]\npub struct Launched(());\n\nfn stdio() -> Stdio {\n    std::env::var_os(\"NOCAPTURE\")\n        .map(|_| Stdio::inherit())\n        .unwrap_or_else(Stdio::piped)\n}\n\nfn read<T: Read>(io: Option<T>) -> Result<String> {\n    if let Some(mut io) = io {\n        let mut string = String::new();\n        io.read_to_string(&mut string)?;\n        return Ok(string);\n    }\n\n    Ok(String::new())\n}\n\nimpl Server {\n    pub fn spawn<T>(ctxt: T, f: fn((Token, T)) -> Launched) -> Result<Server>\n        where T: Serialize + DeserializeOwned\n    {\n        static INIT: Once = Once::new();\n        INIT.call_once(procspawn::init);\n\n        let (ipc, server) = IpcOneShotServer::new()?;\n        let mut proc = procspawn::Builder::new()\n            .stdin(Stdio::null())\n            .stdout(stdio())\n            .stderr(stdio())\n            .spawn((Token(server), ctxt), f);\n\n        let (rx, _) = ipc.accept().unwrap();\n        match rx.recv()? {\n            Message::Liftoff(tls, port) => {\n                Ok(Server { proc, tls, port, _rx: rx })\n            },\n            Message::Failure => {\n                Err(Error::Liftoff(read(proc.stdout())?, read(proc.stderr())?))\n            }\n        }\n    }\n\n    pub fn socket_addr(&self) -> SocketAddr {\n        let ip = Ipv4Addr::LOCALHOST;\n        SocketAddr::new(ip.into(), self.port)\n    }\n\n    pub fn read_stdout(&mut self) -> Result<String> {\n        read(self.proc.stdout())\n    }\n\n    pub fn read_stderr(&mut self) -> Result<String> {\n        read(self.proc.stderr())\n    }\n\n    pub fn kill(&mut self) -> Result<()> {\n        Ok(self.proc.kill()?)\n    }\n\n    pub fn terminate(&mut self) -> Result<()> {\n        use nix::{sys::signal, unistd::Pid};\n\n        let pid = Pid::from_raw(self.proc.pid().unwrap() as i32);\n        Ok(signal::kill(pid, signal::SIGTERM)?)\n    }\n\n    pub fn join(&mut self, duration: Duration) -> Result<()> {\n        match self.proc.join_timeout(duration) {\n            Ok(_) => Ok(()),\n            Err(e) if e.is_remote_close() => Ok(()),\n            Err(e) => Err(e.into()),\n        }\n    }\n}\n\nimpl Token {\n    pub fn with_launch<F, Fut>(self, rocket: Rocket<Build>, launch: F) -> Launched\n        where F: FnOnce(Rocket<Ignite>) -> Fut + Send + Sync + 'static,\n              Fut: Future<Output = Result<Rocket<Ignite>, rocket::Error>> + Send\n    {\n        let server = self.0.clone();\n        let rocket = rocket.attach(AdHoc::on_liftoff(\"Liftoff\", move |rocket| Box::pin(async move {\n            let tcp = rocket.endpoints().find_map(|e| e.tcp()).unwrap();\n            let tls = rocket.endpoints().any(|e| e.is_tls());\n            let sender = IpcSender::<Message>::connect(server).unwrap();\n            let _ = sender.send(Message::Liftoff(tls, tcp.port()));\n            let _ = sender.send(Message::Liftoff(tls, tcp.port()));\n        })));\n\n        let server = self.0.clone();\n        let launch = async move {\n            let rocket = rocket.ignite().await?;\n            launch(rocket).await\n        };\n\n        if let Err(e) = rocket::execute(launch) {\n            let sender = IpcSender::<Message>::connect(server).unwrap();\n            let _ = sender.send(Message::Failure);\n            let _ = sender.send(Message::Failure);\n            e.trace_error();\n            std::process::exit(1);\n        }\n\n        Launched(())\n    }\n\n    pub fn launch_with<B: Bind>(self, rocket: Rocket<Build>) -> Launched\n        where B: Send + Sync + 'static\n    {\n        self.with_launch(rocket, |rocket| rocket.launch_with::<B>())\n    }\n\n    pub fn launch(self, rocket: Rocket<Build>) -> Launched {\n        self.launch_with::<DefaultListener>(rocket)\n    }\n}\n\nimpl Drop for Server {\n    fn drop(&mut self) {\n        let _ = self.terminate();\n        if self.join(Duration::from_secs(3)).is_err() {\n            let _ = self.kill();\n        }\n    }\n}\n\n#[macro_export]\nmacro_rules! spawn {\n    ($($arg:ident : $t:ty),* => $rocket:block) => {{\n        #[allow(unused_parens)]\n        fn _server((token, $($arg),*): ($crate::Token, $($t),*)) -> $crate::Launched {\n            let rocket: rocket::Rocket<rocket::Build> = $rocket;\n            token.launch(rocket)\n        }\n\n        Server::spawn(($($arg),*), _server)\n    }};\n\n    ($($token:tt)*) => {{\n        let _unit = ();\n        spawn!(_unit: () => { $($token)* } )\n    }};\n}\n"
  },
  {
    "path": "testbench/src/servers/bind.rs",
    "content": "use rocket::{tokio::net::TcpListener};\n\nuse crate::prelude::*;\n\n#[cfg(unix)]\nfn tcp_unix_listener_fail() -> Result<()> {\n    use rocket::listener::unix::UnixListener;\n\n    let server = spawn! {\n        Rocket::default().reconfigure_with_toml(\"[default]\\naddress = 123\")\n    };\n\n    if let Err(Error::Liftoff(stdout, _)) = server {\n        assert!(stdout.contains(\"expected: valid TCP (ip) or unix (path)\"));\n        assert!(stdout.contains(\"default.address\"));\n    } else {\n        panic!(\"unexpected result: {server:#?}\");\n    }\n\n    let server = Server::spawn((), |(token, _)| {\n        let rocket = Rocket::default().reconfigure_with_toml(\"[default]\\naddress = \\\"unix:foo\\\"\");\n        token.launch_with::<TcpListener>(rocket)\n    });\n\n    if let Err(Error::Liftoff(stdout, _)) = server {\n        assert!(stdout.contains(\"invalid tcp endpoint: unix:foo\"));\n    } else {\n        panic!(\"unexpected result: {server:#?}\");\n    }\n\n    let server = Server::spawn((), |(token, _)| {\n        token.launch_with::<UnixListener>(Rocket::default())\n    });\n\n    if let Err(Error::Liftoff(stdout, _)) = server {\n        assert!(stdout.contains(\"invalid unix endpoint: tcp:127.0.0.1:8000\"));\n    } else {\n        panic!(\"unexpected result: {server:#?}\");\n    }\n\n    Ok(())\n}\n\n#[cfg(unix)]\nregister!(tcp_unix_listener_fail);\n"
  },
  {
    "path": "testbench/src/servers/http_extensions.rs",
    "content": "//! Test that HTTP method extensions unlike POST or GET work.\n\nuse crate::prelude::*;\n\nuse rocket::http::Method;\n\n#[route(\"/\", method = PROPFIND)]\nfn route() -> &'static str {\n    \"Hello, World!\"\n}\n\npub fn test_http_extensions() -> Result<()> {\n    let server = spawn! {\n        Rocket::default().mount(\"/\", routes![route])\n    }?;\n\n    let client = Client::default();\n    let response = client.request(&server, Method::PropFind, \"/\")?.send()?;\n    assert_eq!(response.status(), 200);\n    assert_eq!(response.text()?, \"Hello, World!\");\n\n    // Make sure that verbs outside of extensions are marked as errors\n    let res = client.request(&server, \"BAKEMEACOOKIE\", \"/\")?.send()?;\n    assert_eq!(res.status(), 400);\n\n    Ok(())\n}\n\nregister!(test_http_extensions);\n"
  },
  {
    "path": "testbench/src/servers/ignite_failure.rs",
    "content": "use crate::prelude::*;\n\nfn test_ignite_failure() -> Result<()> {\n    let server = spawn! {\n        let fail = AdHoc::try_on_ignite(\"FailNow\", |rocket| async { Err(rocket) });\n        Rocket::default().attach(fail)\n    };\n\n    if let Err(Error::Liftoff(stdout, _)) = server {\n        assert!(stdout.contains(\"failed ignite\"));\n        assert!(stdout.contains(\"FailNow\"));\n    } else {\n        panic!(\"unexpected result: {server:#?}\");\n    }\n\n    Ok(())\n}\n\nregister!(test_ignite_failure);\n"
  },
  {
    "path": "testbench/src/servers/infinite_stream.rs",
    "content": "use crate::prelude::*;\n\n#[get(\"/\")]\nfn infinite() -> TextStream![&'static str] {\n    TextStream! {\n        loop {\n            yield rocket::futures::future::pending::<&str>().await;\n        }\n    }\n}\n\npub fn test_inifinite_streams_end() -> Result<()> {\n    let mut server = spawn! {\n        Rocket::default().mount(\"/\", routes![infinite])\n    }?;\n\n    let client = Client::default();\n    client.get(&server, \"/\")?.send()?;\n    server.terminate()?;\n\n    let stdout = server.read_stdout()?;\n    assert!(stdout.contains(\"Rocket has launched on http\"));\n    assert!(stdout.contains(\"GET /\"));\n    assert!(stdout.contains(\"Graceful shutdown completed\"));\n\n    Ok(())\n}\n\nregister!(test_inifinite_streams_end);\n"
  },
  {
    "path": "testbench/src/servers/mod.rs",
    "content": "pub mod ignite_failure;\npub mod bind;\npub mod http_extensions;\npub mod infinite_stream;\npub mod tls_resolver;\npub mod mtls;\npub mod sni_resolver;\npub mod tracing;\npub mod tls;\npub mod no_content;\n"
  },
  {
    "path": "testbench/src/servers/mtls.rs",
    "content": "use crate::prelude::*;\n\nfn test_mtls(mandatory: bool) -> Result<()> {\n    let server = spawn!(mandatory: bool => {\n        let mtls_config = format!(r#\"\n            [default.tls.mutual]\n            ca_certs = \"{{ROCKET}}/examples/tls/private/ca_cert.pem\"\n            mandatory = {mandatory}\n        \"#);\n\n        #[get(\"/\")]\n        fn hello(cert: rocket::mtls::Certificate<'_>) -> String {\n            format!(\"{}:{}[{}] {}\", cert.serial(), cert.version(), cert.issuer(), cert.subject())\n        }\n\n        #[get(\"/\", rank = 2)]\n        fn hi() -> &'static str {\n            \"Hello!\"\n        }\n\n        Rocket::tls_default()\n            .reconfigure_with_toml(&mtls_config)\n            .mount(\"/\", routes![hello, hi])\n    })?;\n\n    let pem = read(\"{ROCKET}/examples/tls/private/client.pem\")?;\n    let client: Client = Client::build()\n        .identity(reqwest::Identity::from_pem(&pem)?)\n        .try_into()?;\n\n    let response = client.get(&server, \"/\")?.send()?.text()?;\n    let (_key_hash, subject) = response.split_once(\":2\").unwrap();\n    assert_eq!(subject,\n        \"[C=US, ST=CA, O=Rocket CA, CN=Rocket Root CA] \\\n            C=US, ST=California, L=Silicon Valley, O=Rocket, \\\n            CN=Rocket TLS Example, Email=example@rocket.local\");\n\n    let client = Client::default();\n    let response = client.get(&server, \"/\")?.send();\n    if mandatory {\n        assert!(response.unwrap_err().is_request());\n    } else {\n        assert_eq!(response?.text()?, \"Hello!\");\n    }\n\n    Ok(())\n}\n\nregister!(test_mtls(mandatory: true));\nregister!(test_mtls(mandatory: false));\n"
  },
  {
    "path": "testbench/src/servers/no_content.rs",
    "content": "//! Ensure that responses with a status of 204 or 304 do not have a body, and\n//! for the former, do not have a Content-Length header.\n\nuse crate::prelude::*;\n\nuse rocket::http::Status;\n\n#[get(\"/<code>\")]\nfn status(code: u16) -> (Status, &'static [u8]) {\n    (Status::new(code), &[1, 2, 3, 4])\n}\n\npub fn test_no_content() -> Result<()> {\n    let server = spawn!(Rocket::default().mount(\"/\", routes![status]))?;\n\n    let client = Client::default();\n    let response = client.get(&server, \"/204\")?.send()?;\n    assert_eq!(response.status(), 204);\n    assert!(response.headers().get(\"Content-Length\").is_none());\n    assert!(response.bytes()?.is_empty());\n\n    let response = client.get(&server, \"/304\")?.send()?;\n    assert_eq!(response.status(), 304);\n    assert_eq!(response.headers().get(\"Content-Length\").unwrap(), \"4\");\n    assert!(response.bytes()?.is_empty());\n\n    Ok(())\n}\n\nregister!(test_no_content);\n"
  },
  {
    "path": "testbench/src/servers/sni_resolver.rs",
    "content": "use std::sync::Arc;\nuse std::collections::HashMap;\nuse std::sync::atomic::{Ordering, AtomicUsize};\n\nuse rocket::http::uri::Host;\nuse rocket::tls::{Resolver, TlsConfig, ClientHello, ServerConfig};\nuse reqwest::tls::TlsInfo;\n\nuse crate::prelude::*;\n\nstatic SNI_TLS_CONFIG: &str = r#\"\n    [default.tls]\n    certs = \"{ROCKET}/examples/tls/private/rsa_sha256_cert.pem\"\n    key = \"{ROCKET}/examples/tls/private/rsa_sha256_key.pem\"\n\n    [default.tls.sni.\"sni1.dev\"]\n    certs = \"{ROCKET}/examples/tls/private/ecdsa_nistp256_sha256_cert.pem\"\n    key = \"{ROCKET}/examples/tls/private/ecdsa_nistp256_sha256_key_pkcs8.pem\"\n\n    [default.tls.sni.\"sni2.dev\"]\n    certs = \"{ROCKET}/examples/tls/private/ed25519_cert.pem\"\n    key = \"{ROCKET}/examples/tls/private/ed25519_key.pem\"\n\"#;\n\nstruct SniResolver {\n    default: Arc<ServerConfig>,\n    map: HashMap<Host<'static>, Arc<ServerConfig>>\n}\n\n#[rocket::async_trait]\nimpl Resolver for SniResolver {\n    async fn init(rocket: &Rocket<Build>) -> rocket::tls::Result<Self> {\n        let default: TlsConfig = rocket.figment().extract_inner(\"tls\")?;\n        let sni: HashMap<Host<'_>, TlsConfig> = rocket.figment().extract_inner(\"tls.sni\")?;\n\n        let default = Arc::new(default.server_config().await?);\n        let mut map = HashMap::new();\n        for (host, config) in sni {\n            let config = config.server_config().await?;\n            map.insert(host, Arc::new(config));\n        }\n\n        Ok(SniResolver { default, map })\n    }\n\n    async fn resolve(&self, hello: ClientHello<'_>) -> Option<Arc<ServerConfig>> {\n        if let Some(Ok(host)) = hello.server_name().map(Host::parse) {\n            if let Some(config) = self.map.get(&host) {\n                return Some(config.clone());\n            }\n        }\n\n        Some(self.default.clone())\n    }\n}\n\nfn sni_resolver() -> Result<()> {\n    let server = spawn! {\n        #[get(\"/\")] fn index() { }\n\n        Rocket::default()\n            .reconfigure_with_toml(SNI_TLS_CONFIG)\n            .mount(\"/\", routes![index])\n            .attach(SniResolver::fairing())\n    }?;\n\n    let client: Client = Client::build()\n        .resolve(\"unknown.dev\", server.socket_addr())\n        .resolve(\"sni1.dev\", server.socket_addr())\n        .resolve(\"sni2.dev\", server.socket_addr())\n        .try_into()?;\n\n    let response = client.get(&server, \"https://unknown.dev\")?.send()?;\n    let tls = response.extensions().get::<TlsInfo>().unwrap();\n    let expected = cert(\"{ROCKET}/examples/tls/private/rsa_sha256_cert.pem\")?;\n    assert_eq!(tls.peer_certificate().unwrap(), expected);\n\n    let response = client.get(&server, \"https://sni1.dev\")?.send()?;\n    let tls = response.extensions().get::<TlsInfo>().unwrap();\n    let expected = cert(\"{ROCKET}/examples/tls/private/ecdsa_nistp256_sha256_cert.pem\")?;\n    assert_eq!(tls.peer_certificate().unwrap(), expected);\n\n    let response = client.get(&server, \"https://sni2.dev\")?.send()?;\n    let tls = response.extensions().get::<TlsInfo>().unwrap();\n    let expected = cert(\"{ROCKET}/examples/tls/private/ed25519_cert.pem\")?;\n    assert_eq!(tls.peer_certificate().unwrap(), expected);\n    Ok(())\n}\n\nstruct CountingResolver {\n    config: Arc<ServerConfig>,\n    counter: Arc<AtomicUsize>,\n}\n\n#[rocket::async_trait]\nimpl Resolver for CountingResolver {\n    async fn init(rocket: &Rocket<Build>) -> rocket::tls::Result<Self> {\n        let config: TlsConfig = rocket.figment().extract_inner(\"tls\")?;\n        let config = Arc::new(config.server_config().await?);\n        let counter = rocket.state::<Arc<AtomicUsize>>().unwrap().clone();\n        Ok(Self { config, counter })\n    }\n\n    async fn resolve(&self, _: ClientHello<'_>) -> Option<Arc<ServerConfig>> {\n        self.counter.fetch_add(1, Ordering::Release);\n        Some(self.config.clone())\n    }\n}\n\n#[get(\"/count\")]\nfn count(counter: &State<Arc<AtomicUsize>>) -> String {\n    counter.load(Ordering::Acquire).to_string()\n}\n\nfn counting_resolver() -> Result<()> {\n    let server = spawn! {\n        let counter = Arc::new(AtomicUsize::new(0));\n        Rocket::tls_default()\n            .manage(counter)\n            .mount(\"/\", routes![count])\n            .attach(CountingResolver::fairing())\n    }?;\n\n    let client = Client::default();\n    let response = client.get(&server, \"/count\")?.send()?;\n    assert_eq!(response.text()?, \"1\");\n\n    // Use a new client so we get a new TLS session.\n    let client = Client::default();\n    let response = client.get(&server, \"/count\")?.send()?;\n    assert_eq!(response.text()?, \"2\");\n    Ok(())\n}\n\nregister!(counting_resolver);\nregister!(sni_resolver);\n"
  },
  {
    "path": "testbench/src/servers/tls.rs",
    "content": "use crate::prelude::*;\n\nuse std::net::{Ipv4Addr, SocketAddr};\n\nuse rocket::tokio::net::TcpListener;\nuse rocket::{get, routes, Rocket};\nuse rocket::listener::Endpoint;\nuse rocket::tls::TlsListener;\n\nuse reqwest::tls::TlsInfo;\n\n#[get(\"/\")]\nfn hello_world(endpoint: &Endpoint) -> String {\n    format!(\"Hello, {endpoint}!\")\n}\n\nfn test_tls_works() -> Result<()> {\n    let mut server = spawn! {\n        Rocket::tls_default().mount(\"/\", routes![hello_world])\n    }?;\n\n    let client = Client::default();\n    let response = client.get(&server, \"/\")?.send()?;\n    let tls = response.extensions().get::<TlsInfo>().unwrap();\n    assert!(!tls.peer_certificate().unwrap().is_empty());\n    assert!(response.text()?.starts_with(\"Hello, https://127.0.0.1\"));\n\n    server.terminate()?;\n    let stdout = server.read_stdout()?;\n    assert!(stdout.contains(\"Rocket has launched on https\"));\n    assert!(stdout.contains(\"Graceful shutdown completed\"));\n    assert!(stdout.contains(\"GET /\"));\n\n    let server = Server::spawn((), |(token, _)| {\n        let rocket = rocket::build()\n            .reconfigure_with_toml(TLS_CONFIG)\n            .mount(\"/\", routes![hello_world]);\n\n        token.with_launch(rocket, |rocket| {\n            let config = rocket.figment().extract_inner(\"tls\");\n            rocket.try_launch_on(async move {\n                let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0);\n                let listener = TcpListener::bind(addr).await?;\n                TlsListener::from(listener, config?).await\n            })\n        })\n    }).unwrap();\n\n    let client = Client::default();\n    let response = client.get(&server, \"/\")?.send()?;\n    let tls = response.extensions().get::<TlsInfo>().unwrap();\n    assert!(!tls.peer_certificate().unwrap().is_empty());\n    assert!(response.text()?.starts_with(\"Hello, https://127.0.0.1\"));\n\n    Ok(())\n}\n\nregister!(test_tls_works);\n"
  },
  {
    "path": "testbench/src/servers/tls_resolver.rs",
    "content": "use crate::prelude::*;\n\nuse std::sync::Arc;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse rocket::tls::{ClientHello, Resolver, ServerConfig, TlsConfig};\n\nstruct CountingResolver {\n    config: Arc<ServerConfig>,\n    counter: Arc<AtomicUsize>,\n}\n\n#[rocket::async_trait]\nimpl Resolver for CountingResolver {\n    async fn init(rocket: &Rocket<Build>) -> rocket::tls::Result<Self> {\n        let config: TlsConfig = rocket.figment().extract_inner(\"tls\")?;\n        let config = Arc::new(config.server_config().await?);\n        let counter = rocket.state::<Arc<AtomicUsize>>().unwrap().clone();\n        Ok(Self { config, counter })\n    }\n\n    async fn resolve(&self, _: ClientHello<'_>) -> Option<Arc<ServerConfig>> {\n        self.counter.fetch_add(1, Ordering::Release);\n        Some(self.config.clone())\n    }\n}\n\n#[get(\"/count\")]\nfn count(counter: &State<Arc<AtomicUsize>>) -> String {\n    counter.load(Ordering::Acquire).to_string()\n}\n\nfn test_tls_resolver() -> Result<()> {\n    let server = spawn! {\n        let counter = Arc::new(AtomicUsize::new(0));\n        Rocket::tls_default()\n            .manage(counter)\n            .mount(\"/\", routes![count])\n            .attach(CountingResolver::fairing())\n    }?;\n\n    let client = Client::default();\n    let response = client.get(&server, \"/count\")?.send()?;\n    assert_eq!(response.text()?, \"1\");\n\n    // Use a new client so we get a new TLS session.\n    let client = Client::default();\n    let response = client.get(&server, \"/count\")?.send()?;\n    assert_eq!(response.text()?, \"2\");\n    Ok(())\n}\n\nregister!(test_tls_resolver);\n\n// TODO: Implement an `UpdatingResolver`. Expose `SniResolver` and\n// `UpdatingResolver` in a `contrib` library or as part of `rocket`.\n//\n// struct UpdatingResolver {\n//     timestamp: AtomicU64,\n//     config: ArcSwap<ServerConfig>\n// }\n//\n// #[crate::async_trait]\n// impl Resolver for UpdatingResolver {\n//     async fn resolve(&self, _: ClientHello<'_>) -> Option<Arc<ServerConfig>> {\n//         if let Either::Left(path) = self.tls_config.certs() {\n//             let metadata = tokio::fs::metadata(&path).await.ok()?;\n//             let modtime = metadata.modified().ok()?;\n//             let timestamp = modtime.duration_since(UNIX_EPOCH).ok()?.as_secs();\n//             let old_timestamp = self.timestamp.load(Ordering::Acquire);\n//             if timestamp > old_timestamp {\n//                 let new_config = self.tls_config.to_server_config().await.ok()?;\n//                 self.server_config.store(Arc::new(new_config));\n//                 self.timestamp.store(timestamp, Ordering::Release);\n//             }\n//         }\n//\n//         Some(self.server_config.load_full())\n//     }\n// }\n"
  },
  {
    "path": "testbench/src/servers/tracing.rs",
    "content": "//! Check that guard failures result in trace with `Display` message for guard\n//! types that implement `Display` and otherwise uses `Debug`.\n\nuse std::fmt;\n\nuse rocket::http::Status;\nuse rocket::data::{self, FromData};\nuse rocket::http::uri::{Segments, fmt::Path};\nuse rocket::request::{self, FromParam, FromRequest, FromSegments};\n\nuse crate::prelude::*;\n\n#[derive(Debug)]\nstruct UseDisplay(&'static str);\n\n#[derive(Debug)]\nstruct UseDebug;\n\nimpl fmt::Display for UseDisplay {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"this is the display impl: {}\", self.0)\n    }\n}\n\nimpl FromParam<'_> for UseDisplay {\n    type Error = Self;\n    fn from_param(_: &str) -> Result<Self, Self::Error> { Err(Self(\"param\")) }\n}\n\nimpl FromParam<'_> for UseDebug {\n    type Error = Self;\n    fn from_param(_: &str) -> Result<Self, Self::Error> { Err(Self) }\n}\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for UseDisplay {\n    type Error = Self;\n    async fn from_request(_: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n        request::Outcome::Error((Status::InternalServerError, Self(\"req\")))\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r> FromRequest<'r> for UseDebug {\n    type Error = Self;\n    async fn from_request(_: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {\n        request::Outcome::Error((Status::InternalServerError, Self))\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r> FromData<'r> for UseDisplay {\n    type Error = Self;\n    async fn from_data(_: &'r Request<'_>, _: Data<'r>) -> data::Outcome<'r, Self> {\n        data::Outcome::Error((Status::InternalServerError, Self(\"data\")))\n    }\n}\n\n#[rocket::async_trait]\nimpl<'r> FromData<'r> for UseDebug {\n    type Error = Self;\n    async fn from_data(_: &'r Request<'_>, _: Data<'r>) -> data::Outcome<'r, Self> {\n        data::Outcome::Error((Status::InternalServerError, Self))\n    }\n}\n\nimpl<'r> FromSegments<'r> for UseDisplay {\n    type Error = Self;\n    fn from_segments(_: Segments<'r, Path>) -> Result<Self, Self::Error> { Err(Self(\"segment\")) }\n}\n\nimpl<'r> FromSegments<'r> for UseDebug {\n    type Error = Self;\n    fn from_segments(_: Segments<'r, Path>) -> Result<Self, Self::Error> { Err(Self) }\n}\n\npub fn test_display_guard_err() -> Result<()> {\n    #[get(\"/<_v>\", rank = 1)] fn a(_v: UseDisplay) {}\n    #[get(\"/<_v..>\", rank = 2)] fn b(_v: UseDisplay) {}\n    #[get(\"/<_..>\", rank = 3)] fn d(_v: UseDisplay) {}\n    #[post(\"/<_..>\", data = \"<_v>\")] fn c(_v: UseDisplay) {}\n\n    let mut server = spawn! {\n        Rocket::default().mount(\"/\", routes![a, b, c, d])\n    }?;\n\n    let client = Client::default();\n    client.get(&server, \"/foo\")?.send()?;\n    client.post(&server, \"/foo\")?.send()?;\n    server.terminate()?;\n\n    let stdout = server.read_stdout()?;\n    assert!(stdout.contains(\"this is the display impl: param\"));\n    assert!(stdout.contains(\"this is the display impl: req\"));\n    assert!(stdout.contains(\"this is the display impl: segment\"));\n    assert!(stdout.contains(\"this is the display impl: data\"));\n\n    Ok(())\n}\n\npub fn test_debug_guard_err() -> Result<()> {\n    #[get(\"/<_v>\", rank = 1)] fn a(_v: UseDebug) {}\n    #[get(\"/<_v..>\", rank = 2)] fn b(_v: UseDebug) {}\n    #[get(\"/<_..>\", rank = 3)] fn d(_v: UseDebug) {}\n    #[post(\"/<_..>\", data = \"<_v>\")] fn c(_v: UseDebug) {}\n\n    let mut server = spawn! {\n        Rocket::default().mount(\"/\", routes![a, b, c, d])\n    }?;\n\n    let client = Client::default();\n    client.get(&server, \"/foo\")?.send()?;\n    client.post(&server, \"/foo\")?.send()?;\n    server.terminate()?;\n\n    let stdout = server.read_stdout()?;\n    assert!(!stdout.contains(\"this is the display impl\"));\n    assert!(stdout.contains(\"UseDebug\"));\n    Ok(())\n}\n\nregister!(test_display_guard_err);\nregister!(test_debug_guard_err);\n"
  }
]