Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/prettyplease/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/prettyplease/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"822b13df00b7ab882ea9a83cdfba7dfc9b07407ac276920c9c6684b21376e1ab","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"dde54d4d5c759fbaea82b4039ab9cea7ee91918431dae011ffe01472e2e9eb44","build.rs":"fdf8aa9b5441b298c72ae23645e227adc52ac69d2decc1bda04e1a91f70ff87d","examples/input.rs":"53350088f12a346a99034af41ef432dedcc9e5d581c5592d9aae3807c42656c1","examples/output.prettyplease.rs":"fa63c118daadb64c456ec5b8d5e46e5d7fabbbeb6a6e61a08eabc23360a18fbd","examples/output.rustc.rs":"0c66f8929fa40a2822d4ea1aec3d8b83db598aba043b17f3c1a6133f0d657135","examples/output.rustfmt.rs":"914a9aea1c51e097bfd80c9af4011811e6126c9df5fb0eac3d40b1203fba7c58","src/algorithm.rs":"7a4a7b62f5300aabf7fcff3cd8c8aaa3ae1e3d1dc717eea1e4797988ce0e18c7","src/attr.rs":"54e829ae468f22c8e2853d669515575f1444bfee026cfd9b19538f77caf10ab7","src/convenience.rs":"dd392b009b691d3587c7d8e3caeaacf450303c4223792b5f89c336358e371c39","src/data.rs":"9db6623d3ccc79b541a28bdc88875ad0036576689e085007eb362819f8e9a2d3","src/expr.rs":"504979b496098b26690d2c0172923d0a5ca4858cccea92b142d3de15b155ba3a","src/file.rs":"5689efa3c5959a6a0d8cfc2c13bf8a37ab0669e2b81dbded3f3c28884a88fca0","src/generics.rs":"bf85de6211ad048cf81fcc4e7a1c8cb2da1eff97acf088055df090876b70c748","src/item.rs":"93ee2d34969966d3628f657a00f7a5ee5caff9319202597ad8915b1bc400f293","src/iter.rs":"38b2cd3b38719c6024fb6b3aa739f6f8736c83193fd21e2365d4f6c27bc41666","src/lib.rs":"ff6a89df2252a2f303d0a1ba6fe7542e2b56bcc9143ac961adda72db6fb3a0cb","src/lifetime.rs":"6d420430168185b2da3409bc38a45f63cced9443915f04e6aec71367fc070dcf","src/lit.rs":"43ad4c7e1ff52b6649e79136186caefc1f3b064c04a01d12a5db511fa6f142d4","src/mac.rs":"62911747c308187afc750b4bd4f8bd24ee825081043d78da68a001ea55ab5853","src/pat.rs":"1edd39e24cb46633290285dcf1819de27ab458c4438934402a51ed43ec2883b7","src/path.rs":"f2689a5d401a7c9943f626cbd13cf65b97b988b8d4e015f3dbe8c7d9c7a415de","src/ring.rs":"e23d133209b977e457b07b0cd93b3711d01f4172d7cfa4cf6a7247637390e606","src/stmt.rs":"709fc67780455873b0fac233df4c19c76cc2d04386e37b70e1b4882c8397d870","src/token.rs":"c288b1d81f2a35673d4ca1dd10d3386670b067460121df3038303e1ed73b41a7","src/ty.rs":"09aae378a9a866d87bf25053942de6adbdd8a8466e1999c2bbaee4b2c944d31a","tests/test.rs":"04994ad0a37c43457390f11ade6ab74fc26c5e879b0a374f0b64acb530a0a496"},"package":"a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"}
|
||||
65
third-party/vendor/prettyplease/Cargo.toml
vendored
Normal file
65
third-party/vendor/prettyplease/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
name = "prettyplease"
|
||||
version = "0.2.16"
|
||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||
links = "prettyplease02"
|
||||
exclude = ["cargo-expand"]
|
||||
autoexamples = false
|
||||
description = "A minimal `syn` syntax tree pretty-printer"
|
||||
documentation = "https://docs.rs/prettyplease"
|
||||
readme = "README.md"
|
||||
keywords = ["rustfmt"]
|
||||
categories = ["development-tools"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/dtolnay/prettyplease"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[package.metadata.playground]
|
||||
features = ["verbatim"]
|
||||
|
||||
[lib]
|
||||
doc-scrape-examples = false
|
||||
|
||||
[dependencies.proc-macro2]
|
||||
version = "1.0.74"
|
||||
default-features = false
|
||||
|
||||
[dependencies.syn]
|
||||
version = "2.0.46"
|
||||
features = ["full"]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.indoc]
|
||||
version = "2"
|
||||
|
||||
[dev-dependencies.proc-macro2]
|
||||
version = "1.0.74"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.quote]
|
||||
version = "1.0.35"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.syn]
|
||||
version = "2.0.46"
|
||||
features = ["parsing"]
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
verbatim = ["syn/parsing"]
|
||||
176
third-party/vendor/prettyplease/LICENSE-APACHE
vendored
Normal file
176
third-party/vendor/prettyplease/LICENSE-APACHE
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
23
third-party/vendor/prettyplease/LICENSE-MIT
vendored
Normal file
23
third-party/vendor/prettyplease/LICENSE-MIT
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
312
third-party/vendor/prettyplease/README.md
vendored
Normal file
312
third-party/vendor/prettyplease/README.md
vendored
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
prettyplease::unparse
|
||||
=====================
|
||||
|
||||
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/prettyplease-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/prettyplease)
|
||||
[<img alt="crates.io" src="https://img.shields.io/crates/v/prettyplease.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/prettyplease)
|
||||
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-prettyplease-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/prettyplease)
|
||||
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/prettyplease/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/prettyplease/actions?query=branch%3Amaster)
|
||||
|
||||
A minimal `syn` syntax tree pretty-printer.
|
||||
|
||||
<br>
|
||||
|
||||
## Overview
|
||||
|
||||
This is a pretty-printer to turn a `syn` syntax tree into a `String` of
|
||||
well-formatted source code. In contrast to rustfmt, this library is intended to
|
||||
be suitable for arbitrary generated code.
|
||||
|
||||
Rustfmt prioritizes high-quality output that is impeccable enough that you'd be
|
||||
comfortable spending your career staring at its output — but that means
|
||||
some heavyweight algorithms, and it has a tendency to bail out on code that is
|
||||
hard to format (for example [rustfmt#3697], and there are dozens more issues
|
||||
like it). That's not necessarily a big deal for human-generated code because
|
||||
when code gets highly nested, the human will naturally be inclined to refactor
|
||||
into more easily formattable code. But for generated code, having the formatter
|
||||
just give up leaves it totally unreadable.
|
||||
|
||||
[rustfmt#3697]: https://github.com/rust-lang/rustfmt/issues/3697
|
||||
|
||||
This library is designed using the simplest possible algorithm and data
|
||||
structures that can deliver about 95% of the quality of rustfmt-formatted
|
||||
output. In my experience testing real-world code, approximately 97-98% of output
|
||||
lines come out identical between rustfmt's formatting and this crate's. The rest
|
||||
have slightly different linebreak decisions, but still clearly follow the
|
||||
dominant modern Rust style.
|
||||
|
||||
The tradeoffs made by this crate are a good fit for generated code that you will
|
||||
*not* spend your career staring at. For example, the output of `bindgen`, or the
|
||||
output of `cargo-expand`. In those cases it's more important that the whole
|
||||
thing be formattable without the formatter giving up, than that it be flawless.
|
||||
|
||||
<br>
|
||||
|
||||
## Feature matrix
|
||||
|
||||
Here are a few superficial comparisons of this crate against the AST
|
||||
pretty-printer built into rustc, and rustfmt. The sections below go into more
|
||||
detail comparing the output of each of these libraries.
|
||||
|
||||
| | prettyplease | rustc | rustfmt |
|
||||
|:---|:---:|:---:|:---:|
|
||||
| non-pathological behavior on big or generated code | 💚 | ❌ | ❌ |
|
||||
| idiomatic modern formatting ("locally indistinguishable from rustfmt") | 💚 | ❌ | 💚 |
|
||||
| throughput | 60 MB/s | 39 MB/s | 2.8 MB/s |
|
||||
| number of dependencies | 3 | 72 | 66 |
|
||||
| compile time including dependencies | 2.4 sec | 23.1 sec | 29.8 sec |
|
||||
| buildable using a stable Rust compiler | 💚 | ❌ | ❌ |
|
||||
| published to crates.io | 💚 | ❌ | ❌ |
|
||||
| extensively configurable output | ❌ | ❌ | 💚 |
|
||||
| intended to accommodate hand-maintained source code | ❌ | ❌ | 💚 |
|
||||
|
||||
<br>
|
||||
|
||||
## Comparison to rustfmt
|
||||
|
||||
- [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
|
||||
- [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
|
||||
- [output.rustfmt.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustfmt.rs)
|
||||
|
||||
If you weren't told which output file is which, it would be practically
|
||||
impossible to tell — **except** for line 435 in the rustfmt output, which
|
||||
is more than 1000 characters long because rustfmt just gave up formatting that
|
||||
part of the file:
|
||||
|
||||
```rust
|
||||
match segments[5] {
|
||||
0 => write!(f, "::{}", ipv4),
|
||||
0xffff => write!(f, "::ffff:{}", ipv4),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } }
|
||||
} else {
|
||||
const IPV6_BUF_LEN: usize = (4 * 8) + 7;
|
||||
let mut buf = [0u8; IPV6_BUF_LEN];
|
||||
let mut buf_slice = &mut buf[..];
|
||||
```
|
||||
|
||||
This is a pretty typical manifestation of rustfmt bailing out in generated code
|
||||
— a chunk of the input ends up on one line. The other manifestation is
|
||||
that you're working on some code, running rustfmt on save like a conscientious
|
||||
developer, but after a while notice it isn't doing anything. You introduce an
|
||||
intentional formatting issue, like a stray indent or semicolon, and run rustfmt
|
||||
to check your suspicion. Nope, it doesn't get cleaned up — rustfmt is just
|
||||
not formatting the part of the file you are working on.
|
||||
|
||||
The prettyplease library is designed to have no pathological cases that force a
|
||||
bail out; the entire input you give it will get formatted in some "good enough"
|
||||
form.
|
||||
|
||||
Separately, rustfmt can be problematic to integrate into projects. It's written
|
||||
using rustc's internal syntax tree, so it can't be built by a stable compiler.
|
||||
Its releases are not regularly published to crates.io, so in Cargo builds you'd
|
||||
need to depend on it as a git dependency, which precludes publishing your crate
|
||||
to crates.io also. You can shell out to a `rustfmt` binary, but that'll be
|
||||
whatever rustfmt version is installed on each developer's system (if any), which
|
||||
can lead to spurious diffs in checked-in generated code formatted by different
|
||||
versions. In contrast prettyplease is designed to be easy to pull in as a
|
||||
library, and compiles fast.
|
||||
|
||||
<br>
|
||||
|
||||
## Comparison to rustc_ast_pretty
|
||||
|
||||
- [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
|
||||
- [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
|
||||
- [output.rustc.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustc.rs)
|
||||
|
||||
This is the pretty-printer that gets used when rustc prints source code, such as
|
||||
`rustc -Zunpretty=expanded`. It's used also by the standard library's
|
||||
`stringify!` when stringifying an interpolated macro_rules AST fragment, like an
|
||||
$:expr, and transitively by `dbg!` and many macros in the ecosystem.
|
||||
|
||||
Rustc's formatting is mostly okay, but does not hew closely to the dominant
|
||||
contemporary style of Rust formatting. Some things wouldn't ever be written on
|
||||
one line, like this `match` expression, and certainly not with a comma in front
|
||||
of the closing brace:
|
||||
|
||||
```rust
|
||||
fn eq(&self, other: &IpAddr) -> bool {
|
||||
match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, }
|
||||
}
|
||||
```
|
||||
|
||||
Some places use non-multiple-of-4 indentation, which is definitely not the norm:
|
||||
|
||||
```rust
|
||||
pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
|
||||
let [a, b, c, d] = self.octets();
|
||||
Ipv6Addr{inner:
|
||||
c::in6_addr{s6_addr:
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF,
|
||||
0xFF, a, b, c, d],},}
|
||||
}
|
||||
```
|
||||
|
||||
And although there isn't an egregious example of it in the link because the
|
||||
input code is pretty tame, in general rustc_ast_pretty has pathological behavior
|
||||
on generated code. It has a tendency to use excessive horizontal indentation and
|
||||
rapidly run out of width:
|
||||
|
||||
```rust
|
||||
::std::io::_print(::core::fmt::Arguments::new_v1(&[""],
|
||||
&match (&msg,) {
|
||||
_args =>
|
||||
[::core::fmt::ArgumentV1::new(_args.0,
|
||||
::core::fmt::Display::fmt)],
|
||||
}));
|
||||
```
|
||||
|
||||
The snippets above are clearly different from modern rustfmt style. In contrast,
|
||||
prettyplease is designed to have output that is practically indistinguishable
|
||||
from rustfmt-formatted code.
|
||||
|
||||
<br>
|
||||
|
||||
## Example
|
||||
|
||||
```rust
|
||||
// [dependencies]
|
||||
// prettyplease = "0.2"
|
||||
// syn = { version = "2", default-features = false, features = ["full", "parsing"] }
|
||||
|
||||
const INPUT: &str = stringify! {
|
||||
use crate::{
|
||||
lazy::{Lazy, SyncLazy, SyncOnceCell}, panic,
|
||||
sync::{ atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
mpsc::channel, Mutex, },
|
||||
thread,
|
||||
};
|
||||
impl<T, U> Into<U> for T where U: From<T> {
|
||||
fn into(self) -> U { U::from(self) }
|
||||
}
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let syntax_tree = syn::parse_file(INPUT).unwrap();
|
||||
let formatted = prettyplease::unparse(&syntax_tree);
|
||||
print!("{}", formatted);
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Algorithm notes
|
||||
|
||||
The approach and terminology used in the implementation are derived from [*Derek
|
||||
C. Oppen, "Pretty Printing" (1979)*][paper], on which rustc_ast_pretty is also
|
||||
based, and from rustc_ast_pretty's implementation written by Graydon Hoare in
|
||||
2011 (and modernized over the years by dozens of volunteer maintainers).
|
||||
|
||||
[paper]: http://i.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf
|
||||
|
||||
The paper describes two language-agnostic interacting procedures `Scan()` and
|
||||
`Print()`. Language-specific code decomposes an input data structure into a
|
||||
stream of `string` and `break` tokens, and `begin` and `end` tokens for
|
||||
grouping. Each `begin`–`end` range may be identified as either "consistent
|
||||
breaking" or "inconsistent breaking". If a group is consistently breaking, then
|
||||
if the whole contents do not fit on the line, *every* `break` token in the group
|
||||
will receive a linebreak. This is appropriate, for example, for Rust struct
|
||||
literals, or arguments of a function call. If a group is inconsistently
|
||||
breaking, then the `string` tokens in the group are greedily placed on the line
|
||||
until out of space, and linebroken only at those `break` tokens for which the
|
||||
next string would not fit. For example, this is appropriate for the contents of
|
||||
a braced `use` statement in Rust.
|
||||
|
||||
Scan's job is to efficiently accumulate sizing information about groups and
|
||||
breaks. For every `begin` token we compute the distance to the matched `end`
|
||||
token, and for every `break` we compute the distance to the next `break`. The
|
||||
algorithm uses a ringbuffer to hold tokens whose size is not yet ascertained.
|
||||
The maximum size of the ringbuffer is bounded by the target line length and does
|
||||
not grow indefinitely, regardless of deep nesting in the input stream. That's
|
||||
because once a group is sufficiently big, the precise size can no longer make a
|
||||
difference to linebreak decisions and we can effectively treat it as "infinity".
|
||||
|
||||
Print's job is to use the sizing information to efficiently assign a "broken" or
|
||||
"not broken" status to every `begin` token. At that point the output is easily
|
||||
constructed by concatenating `string` tokens and breaking at `break` tokens
|
||||
contained within a broken group.
|
||||
|
||||
Leveraging these primitives (i.e. cleverly placing the all-or-nothing consistent
|
||||
breaks and greedy inconsistent breaks) to yield rustfmt-compatible formatting
|
||||
for all of Rust's syntax tree nodes is a fun challenge.
|
||||
|
||||
Here is a visualization of some Rust tokens fed into the pretty printing
|
||||
algorithm. Consistently breaking `begin`—`end` pairs are represented by
|
||||
`«`⁠`»`, inconsistently breaking by `‹`⁠`›`, `break` by `·`, and the
|
||||
rest of the non-whitespace are `string`.
|
||||
|
||||
```text
|
||||
use crate::«{·
|
||||
‹ lazy::«{·‹Lazy,· SyncLazy,· SyncOnceCell›·}»,·
|
||||
panic,·
|
||||
sync::«{·
|
||||
‹ atomic::«{·‹AtomicUsize,· Ordering::SeqCst›·}»,·
|
||||
mpsc::channel,· Mutex›,·
|
||||
}»,·
|
||||
thread›,·
|
||||
}»;·
|
||||
«‹«impl<«·T‹›,· U‹›·»>» Into<«·U·»>· for T›·
|
||||
where·
|
||||
U:‹ From<«·T·»>›,·
|
||||
{·
|
||||
« fn into(·«·self·») -> U {·
|
||||
‹ U::from(«·self·»)›·
|
||||
» }·
|
||||
»}·
|
||||
```
|
||||
|
||||
The algorithm described in the paper is not quite sufficient for producing
|
||||
well-formatted Rust code that is locally indistinguishable from rustfmt's style.
|
||||
The reason is that in the paper, the complete non-whitespace contents are
|
||||
assumed to be independent of linebreak decisions, with Scan and Print being only
|
||||
in control of the whitespace (spaces and line breaks). In Rust as idiomatically
|
||||
formattted by rustfmt, that is not the case. Trailing commas are one example;
|
||||
the punctuation is only known *after* the broken vs non-broken status of the
|
||||
surrounding group is known:
|
||||
|
||||
```rust
|
||||
let _ = Struct { x: 0, y: true };
|
||||
|
||||
let _ = Struct {
|
||||
x: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
||||
y: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, //<- trailing comma if the expression wrapped
|
||||
};
|
||||
```
|
||||
|
||||
The formatting of `match` expressions is another case; we want small arms on the
|
||||
same line as the pattern, and big arms wrapped in a brace. The presence of the
|
||||
brace punctuation, comma, and semicolon are all dependent on whether the arm
|
||||
fits on the line:
|
||||
|
||||
```rust
|
||||
match total_nanos.checked_add(entry.nanos as u64) {
|
||||
Some(n) => tmp = n, //<- small arm, inline with comma
|
||||
None => {
|
||||
total_secs = total_secs
|
||||
.checked_add(total_nanos / NANOS_PER_SEC as u64)
|
||||
.expect("overflow in iter::sum over durations");
|
||||
} //<- big arm, needs brace added, and also semicolon^
|
||||
}
|
||||
```
|
||||
|
||||
The printing algorithm implementation in this crate accommodates all of these
|
||||
situations with conditional punctuation tokens whose selection can be deferred
|
||||
and populated after it's known that the group is or is not broken.
|
||||
|
||||
<br>
|
||||
|
||||
#### License
|
||||
|
||||
<sup>
|
||||
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
|
||||
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
|
||||
</sup>
|
||||
|
||||
<br>
|
||||
|
||||
<sub>
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
|
||||
be dual licensed as above, without any additional terms or conditions.
|
||||
</sub>
|
||||
5
third-party/vendor/prettyplease/build.rs
vendored
Normal file
5
third-party/vendor/prettyplease/build.rs
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
println!(concat!("cargo:VERSION=", env!("CARGO_PKG_VERSION")));
|
||||
}
|
||||
1
third-party/vendor/prettyplease/examples/input.rs
vendored
Normal file
1
third-party/vendor/prettyplease/examples/input.rs
vendored
Normal file
File diff suppressed because one or more lines are too long
593
third-party/vendor/prettyplease/examples/output.prettyplease.rs
vendored
Normal file
593
third-party/vendor/prettyplease/examples/output.prettyplease.rs
vendored
Normal file
|
|
@ -0,0 +1,593 @@
|
|||
use crate::cmp::Ordering;
|
||||
use crate::fmt::{self, Write as FmtWrite};
|
||||
use crate::hash;
|
||||
use crate::io::Write as IoWrite;
|
||||
use crate::mem::transmute;
|
||||
use crate::sys::net::netc as c;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
|
||||
pub enum IpAddr {
|
||||
V4(Ipv4Addr),
|
||||
V6(Ipv6Addr),
|
||||
}
|
||||
#[derive(Copy)]
|
||||
pub struct Ipv4Addr {
|
||||
inner: c::in_addr,
|
||||
}
|
||||
#[derive(Copy)]
|
||||
pub struct Ipv6Addr {
|
||||
inner: c::in6_addr,
|
||||
}
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Ipv6MulticastScope {
|
||||
InterfaceLocal,
|
||||
LinkLocal,
|
||||
RealmLocal,
|
||||
AdminLocal,
|
||||
SiteLocal,
|
||||
OrganizationLocal,
|
||||
Global,
|
||||
}
|
||||
impl IpAddr {
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_unspecified(),
|
||||
IpAddr::V6(ip) => ip.is_unspecified(),
|
||||
}
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_loopback(),
|
||||
IpAddr::V6(ip) => ip.is_loopback(),
|
||||
}
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_global(),
|
||||
IpAddr::V6(ip) => ip.is_global(),
|
||||
}
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_multicast(),
|
||||
IpAddr::V6(ip) => ip.is_multicast(),
|
||||
}
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_documentation(),
|
||||
IpAddr::V6(ip) => ip.is_documentation(),
|
||||
}
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_benchmarking(),
|
||||
IpAddr::V6(ip) => ip.is_benchmarking(),
|
||||
}
|
||||
}
|
||||
pub const fn is_ipv4(&self) -> bool {
|
||||
matches!(self, IpAddr::V4(_))
|
||||
}
|
||||
pub const fn is_ipv6(&self) -> bool {
|
||||
matches!(self, IpAddr::V6(_))
|
||||
}
|
||||
pub const fn to_canonical(&self) -> IpAddr {
|
||||
match self {
|
||||
&v4 @ IpAddr::V4(_) => v4,
|
||||
IpAddr::V6(v6) => v6.to_canonical(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ipv4Addr {
|
||||
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
|
||||
Ipv4Addr {
|
||||
inner: c::in_addr {
|
||||
s_addr: u32::from_ne_bytes([a, b, c, d]),
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
|
||||
#[doc(alias = "INADDR_ANY")]
|
||||
pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
|
||||
pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
|
||||
pub const fn octets(&self) -> [u8; 4] {
|
||||
self.inner.s_addr.to_ne_bytes()
|
||||
}
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
self.inner.s_addr == 0
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
self.octets()[0] == 127
|
||||
}
|
||||
pub const fn is_private(&self) -> bool {
|
||||
match self.octets() {
|
||||
[10, ..] => true,
|
||||
[172, b, ..] if b >= 16 && b <= 31 => true,
|
||||
[192, 168, ..] => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub const fn is_link_local(&self) -> bool {
|
||||
matches!(self.octets(), [169, 254, ..])
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
if u32::from_be_bytes(self.octets()) == 0xc0000009
|
||||
|| u32::from_be_bytes(self.octets()) == 0xc000000a
|
||||
{
|
||||
return true;
|
||||
}
|
||||
!self.is_private() && !self.is_loopback() && !self.is_link_local()
|
||||
&& !self.is_broadcast() && !self.is_documentation() && !self.is_shared()
|
||||
&& !(self.octets()[0] == 192 && self.octets()[1] == 0
|
||||
&& self.octets()[2] == 0) && !self.is_reserved()
|
||||
&& !self.is_benchmarking() && self.octets()[0] != 0
|
||||
}
|
||||
pub const fn is_shared(&self) -> bool {
|
||||
self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
|
||||
}
|
||||
pub const fn is_reserved(&self) -> bool {
|
||||
self.octets()[0] & 240 == 240 && !self.is_broadcast()
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
self.octets()[0] >= 224 && self.octets()[0] <= 239
|
||||
}
|
||||
pub const fn is_broadcast(&self) -> bool {
|
||||
u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
|
||||
}
|
||||
pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
|
||||
let [a, b, c, d] = self.octets();
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d],
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
|
||||
let [a, b, c, d] = self.octets();
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Display for IpAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.fmt(fmt),
|
||||
IpAddr::V6(ip) => ip.fmt(fmt),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for IpAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl From<Ipv4Addr> for IpAddr {
|
||||
fn from(ipv4: Ipv4Addr) -> IpAddr {
|
||||
IpAddr::V4(ipv4)
|
||||
}
|
||||
}
|
||||
impl From<Ipv6Addr> for IpAddr {
|
||||
fn from(ipv6: Ipv6Addr) -> IpAddr {
|
||||
IpAddr::V6(ipv6)
|
||||
}
|
||||
}
|
||||
impl fmt::Display for Ipv4Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let octets = self.octets();
|
||||
if fmt.precision().is_none() && fmt.width().is_none() {
|
||||
write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
|
||||
} else {
|
||||
const IPV4_BUF_LEN: usize = 15;
|
||||
let mut buf = [0u8; IPV4_BUF_LEN];
|
||||
let mut buf_slice = &mut buf[..];
|
||||
write!(buf_slice, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
|
||||
.unwrap();
|
||||
let len = IPV4_BUF_LEN - buf_slice.len();
|
||||
let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
|
||||
fmt.pad(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for Ipv4Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl Clone for Ipv4Addr {
|
||||
fn clone(&self) -> Ipv4Addr {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl PartialEq for Ipv4Addr {
|
||||
fn eq(&self, other: &Ipv4Addr) -> bool {
|
||||
self.inner.s_addr == other.inner.s_addr
|
||||
}
|
||||
}
|
||||
impl PartialEq<Ipv4Addr> for IpAddr {
|
||||
fn eq(&self, other: &Ipv4Addr) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(v4) => v4 == other,
|
||||
IpAddr::V6(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq<IpAddr> for Ipv4Addr {
|
||||
fn eq(&self, other: &IpAddr) -> bool {
|
||||
match other {
|
||||
IpAddr::V4(v4) => self == v4,
|
||||
IpAddr::V6(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Eq for Ipv4Addr {}
|
||||
impl hash::Hash for Ipv4Addr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
{ self.inner.s_addr }.hash(s)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Ipv4Addr {
|
||||
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Ipv4Addr> for IpAddr {
|
||||
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
|
||||
match self {
|
||||
IpAddr::V4(v4) => v4.partial_cmp(other),
|
||||
IpAddr::V6(_) => Some(Ordering::Greater),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialOrd<IpAddr> for Ipv4Addr {
|
||||
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
|
||||
match other {
|
||||
IpAddr::V4(v4) => self.partial_cmp(v4),
|
||||
IpAddr::V6(_) => Some(Ordering::Less),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ord for Ipv4Addr {
|
||||
fn cmp(&self, other: &Ipv4Addr) -> Ordering {
|
||||
u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
|
||||
}
|
||||
}
|
||||
impl IntoInner<c::in_addr> for Ipv4Addr {
|
||||
fn into_inner(self) -> c::in_addr {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
impl From<Ipv4Addr> for u32 {
|
||||
fn from(ip: Ipv4Addr) -> u32 {
|
||||
let ip = ip.octets();
|
||||
u32::from_be_bytes(ip)
|
||||
}
|
||||
}
|
||||
impl From<u32> for Ipv4Addr {
|
||||
fn from(ip: u32) -> Ipv4Addr {
|
||||
Ipv4Addr::from(ip.to_be_bytes())
|
||||
}
|
||||
}
|
||||
impl From<[u8; 4]> for Ipv4Addr {
|
||||
fn from(octets: [u8; 4]) -> Ipv4Addr {
|
||||
Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
|
||||
}
|
||||
}
|
||||
impl From<[u8; 4]> for IpAddr {
|
||||
fn from(octets: [u8; 4]) -> IpAddr {
|
||||
IpAddr::V4(Ipv4Addr::from(octets))
|
||||
}
|
||||
}
|
||||
impl Ipv6Addr {
|
||||
pub const fn new(
|
||||
a: u16,
|
||||
b: u16,
|
||||
c: u16,
|
||||
d: u16,
|
||||
e: u16,
|
||||
f: u16,
|
||||
g: u16,
|
||||
h: u16,
|
||||
) -> Ipv6Addr {
|
||||
let addr16 = [
|
||||
a.to_be(),
|
||||
b.to_be(),
|
||||
c.to_be(),
|
||||
d.to_be(),
|
||||
e.to_be(),
|
||||
f.to_be(),
|
||||
g.to_be(),
|
||||
h.to_be(),
|
||||
];
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
pub const fn segments(&self) -> [u16; 8] {
|
||||
let [a, b, c, d, e, f, g, h] = unsafe {
|
||||
transmute::<_, [u16; 8]>(self.inner.s6_addr)
|
||||
};
|
||||
[
|
||||
u16::from_be(a),
|
||||
u16::from_be(b),
|
||||
u16::from_be(c),
|
||||
u16::from_be(d),
|
||||
u16::from_be(e),
|
||||
u16::from_be(f),
|
||||
u16::from_be(g),
|
||||
u16::from_be(h),
|
||||
]
|
||||
}
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets())
|
||||
== u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets())
|
||||
== u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self.multicast_scope() {
|
||||
Some(Ipv6MulticastScope::Global) => true,
|
||||
None => self.is_unicast_global(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub const fn is_unique_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xfe00) == 0xfc00
|
||||
}
|
||||
pub const fn is_unicast(&self) -> bool {
|
||||
!self.is_multicast()
|
||||
}
|
||||
pub const fn is_unicast_link_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xffc0) == 0xfe80
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2)
|
||||
&& (self.segments()[2] == 0)
|
||||
}
|
||||
pub const fn is_unicast_global(&self) -> bool {
|
||||
self.is_unicast() && !self.is_loopback() && !self.is_unicast_link_local()
|
||||
&& !self.is_unique_local() && !self.is_unspecified()
|
||||
&& !self.is_documentation()
|
||||
}
|
||||
pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
|
||||
if self.is_multicast() {
|
||||
match self.segments()[0] & 0x000f {
|
||||
1 => Some(Ipv6MulticastScope::InterfaceLocal),
|
||||
2 => Some(Ipv6MulticastScope::LinkLocal),
|
||||
3 => Some(Ipv6MulticastScope::RealmLocal),
|
||||
4 => Some(Ipv6MulticastScope::AdminLocal),
|
||||
5 => Some(Ipv6MulticastScope::SiteLocal),
|
||||
8 => Some(Ipv6MulticastScope::OrganizationLocal),
|
||||
14 => Some(Ipv6MulticastScope::Global),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
(self.segments()[0] & 0xff00) == 0xff00
|
||||
}
|
||||
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
|
||||
match self.octets() {
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
|
||||
Some(Ipv4Addr::new(a, b, c, d))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
|
||||
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
|
||||
let [a, b] = ab.to_be_bytes();
|
||||
let [c, d] = cd.to_be_bytes();
|
||||
Some(Ipv4Addr::new(a, b, c, d))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub const fn to_canonical(&self) -> IpAddr {
|
||||
if let Some(mapped) = self.to_ipv4_mapped() {
|
||||
return IpAddr::V4(mapped);
|
||||
}
|
||||
IpAddr::V6(*self)
|
||||
}
|
||||
pub const fn octets(&self) -> [u8; 16] {
|
||||
self.inner.s6_addr
|
||||
}
|
||||
}
|
||||
impl fmt::Display for Ipv6Addr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if f.precision().is_none() && f.width().is_none() {
|
||||
let segments = self.segments();
|
||||
if self.is_unspecified() {
|
||||
f.write_str("::")
|
||||
} else if self.is_loopback() {
|
||||
f.write_str("::1")
|
||||
} else if let Some(ipv4) = self.to_ipv4() {
|
||||
match segments[5] {
|
||||
0 => write!(f, "::{}", ipv4),
|
||||
0xffff => write!(f, "::ffff:{}", ipv4),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
#[derive(Copy, Clone, Default)]
|
||||
struct Span {
|
||||
start: usize,
|
||||
len: usize,
|
||||
}
|
||||
let zeroes = {
|
||||
let mut longest = Span::default();
|
||||
let mut current = Span::default();
|
||||
for (i, &segment) in segments.iter().enumerate() {
|
||||
if segment == 0 {
|
||||
if current.len == 0 {
|
||||
current.start = i;
|
||||
}
|
||||
current.len += 1;
|
||||
if current.len > longest.len {
|
||||
longest = current;
|
||||
}
|
||||
} else {
|
||||
current = Span::default();
|
||||
}
|
||||
}
|
||||
longest
|
||||
};
|
||||
/// Write a colon-separated part of the address
|
||||
#[inline]
|
||||
fn fmt_subslice(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
chunk: &[u16],
|
||||
) -> fmt::Result {
|
||||
if let Some((first, tail)) = chunk.split_first() {
|
||||
write!(f, "{:x}", first)?;
|
||||
for segment in tail {
|
||||
f.write_char(':')?;
|
||||
write!(f, "{:x}", segment)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
if zeroes.len > 1 {
|
||||
fmt_subslice(f, &segments[..zeroes.start])?;
|
||||
f.write_str("::")?;
|
||||
fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
|
||||
} else {
|
||||
fmt_subslice(f, &segments)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const IPV6_BUF_LEN: usize = (4 * 8) + 7;
|
||||
let mut buf = [0u8; IPV6_BUF_LEN];
|
||||
let mut buf_slice = &mut buf[..];
|
||||
write!(buf_slice, "{}", self).unwrap();
|
||||
let len = IPV6_BUF_LEN - buf_slice.len();
|
||||
let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
|
||||
f.pad(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for Ipv6Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl Clone for Ipv6Addr {
|
||||
fn clone(&self) -> Ipv6Addr {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl PartialEq for Ipv6Addr {
|
||||
fn eq(&self, other: &Ipv6Addr) -> bool {
|
||||
self.inner.s6_addr == other.inner.s6_addr
|
||||
}
|
||||
}
|
||||
impl PartialEq<IpAddr> for Ipv6Addr {
|
||||
fn eq(&self, other: &IpAddr) -> bool {
|
||||
match other {
|
||||
IpAddr::V4(_) => false,
|
||||
IpAddr::V6(v6) => self == v6,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq<Ipv6Addr> for IpAddr {
|
||||
fn eq(&self, other: &Ipv6Addr) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(_) => false,
|
||||
IpAddr::V6(v6) => v6 == other,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Eq for Ipv6Addr {}
|
||||
impl hash::Hash for Ipv6Addr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
self.inner.s6_addr.hash(s)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Ipv6Addr {
|
||||
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Ipv6Addr> for IpAddr {
|
||||
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
|
||||
match self {
|
||||
IpAddr::V4(_) => Some(Ordering::Less),
|
||||
IpAddr::V6(v6) => v6.partial_cmp(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialOrd<IpAddr> for Ipv6Addr {
|
||||
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
|
||||
match other {
|
||||
IpAddr::V4(_) => Some(Ordering::Greater),
|
||||
IpAddr::V6(v6) => self.partial_cmp(v6),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ord for Ipv6Addr {
|
||||
fn cmp(&self, other: &Ipv6Addr) -> Ordering {
|
||||
self.segments().cmp(&other.segments())
|
||||
}
|
||||
}
|
||||
impl AsInner<c::in6_addr> for Ipv6Addr {
|
||||
fn as_inner(&self) -> &c::in6_addr {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
impl FromInner<c::in6_addr> for Ipv6Addr {
|
||||
fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
|
||||
Ipv6Addr { inner: addr }
|
||||
}
|
||||
}
|
||||
impl From<Ipv6Addr> for u128 {
|
||||
fn from(ip: Ipv6Addr) -> u128 {
|
||||
let ip = ip.octets();
|
||||
u128::from_be_bytes(ip)
|
||||
}
|
||||
}
|
||||
impl From<u128> for Ipv6Addr {
|
||||
fn from(ip: u128) -> Ipv6Addr {
|
||||
Ipv6Addr::from(ip.to_be_bytes())
|
||||
}
|
||||
}
|
||||
impl From<[u8; 16]> for Ipv6Addr {
|
||||
fn from(octets: [u8; 16]) -> Ipv6Addr {
|
||||
let inner = c::in6_addr { s6_addr: octets };
|
||||
Ipv6Addr::from_inner(inner)
|
||||
}
|
||||
}
|
||||
impl From<[u16; 8]> for Ipv6Addr {
|
||||
fn from(segments: [u16; 8]) -> Ipv6Addr {
|
||||
let [a, b, c, d, e, f, g, h] = segments;
|
||||
Ipv6Addr::new(a, b, c, d, e, f, g, h)
|
||||
}
|
||||
}
|
||||
impl From<[u8; 16]> for IpAddr {
|
||||
fn from(octets: [u8; 16]) -> IpAddr {
|
||||
IpAddr::V6(Ipv6Addr::from(octets))
|
||||
}
|
||||
}
|
||||
impl From<[u16; 8]> for IpAddr {
|
||||
fn from(segments: [u16; 8]) -> IpAddr {
|
||||
IpAddr::V6(Ipv6Addr::from(segments))
|
||||
}
|
||||
}
|
||||
508
third-party/vendor/prettyplease/examples/output.rustc.rs
vendored
Normal file
508
third-party/vendor/prettyplease/examples/output.rustc.rs
vendored
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
use crate::cmp::Ordering;use crate::fmt::{self, Write as FmtWrite};
|
||||
use crate::hash;
|
||||
use crate::io::Write as IoWrite;
|
||||
use crate::mem::transmute;
|
||||
use crate::sys::net::netc as c;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
|
||||
pub enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), }
|
||||
#[derive(Copy)]
|
||||
pub struct Ipv4Addr {
|
||||
inner: c::in_addr,
|
||||
}
|
||||
#[derive(Copy)]
|
||||
pub struct Ipv6Addr {
|
||||
inner: c::in6_addr,
|
||||
}
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Ipv6MulticastScope {
|
||||
InterfaceLocal,
|
||||
LinkLocal,
|
||||
RealmLocal,
|
||||
AdminLocal,
|
||||
SiteLocal,
|
||||
OrganizationLocal,
|
||||
Global,
|
||||
}
|
||||
impl IpAddr {
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_unspecified(),
|
||||
IpAddr::V6(ip) => ip.is_unspecified(),
|
||||
}
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_loopback(),
|
||||
IpAddr::V6(ip) => ip.is_loopback(),
|
||||
}
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_global(),
|
||||
IpAddr::V6(ip) => ip.is_global(),
|
||||
}
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_multicast(),
|
||||
IpAddr::V6(ip) => ip.is_multicast(),
|
||||
}
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_documentation(),
|
||||
IpAddr::V6(ip) => ip.is_documentation(),
|
||||
}
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_benchmarking(),
|
||||
IpAddr::V6(ip) => ip.is_benchmarking(),
|
||||
}
|
||||
}
|
||||
pub const fn is_ipv4(&self) -> bool { matches!(self, IpAddr :: V4(_)) }
|
||||
pub const fn is_ipv6(&self) -> bool { matches!(self, IpAddr :: V6(_)) }
|
||||
pub const fn to_canonical(&self) -> IpAddr {
|
||||
match self {
|
||||
&v4 @ IpAddr::V4(_) => v4,
|
||||
IpAddr::V6(v6) => v6.to_canonical(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ipv4Addr {
|
||||
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
|
||||
Ipv4Addr {
|
||||
inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) },
|
||||
}
|
||||
}
|
||||
pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
|
||||
#[doc(alias = "INADDR_ANY")]
|
||||
pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
|
||||
pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
|
||||
pub const fn octets(&self) -> [u8; 4] { self.inner.s_addr.to_ne_bytes() }
|
||||
pub const fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 }
|
||||
pub const fn is_loopback(&self) -> bool { self.octets()[0] == 127 }
|
||||
pub const fn is_private(&self) -> bool {
|
||||
match self.octets() {
|
||||
[10, ..] => true,
|
||||
[172, b, ..] if b >= 16 && b <= 31 => true,
|
||||
[192, 168, ..] => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub const fn is_link_local(&self) -> bool {
|
||||
matches!(self.octets(), [169, 254, ..])
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
if u32::from_be_bytes(self.octets()) == 0xc0000009 ||
|
||||
u32::from_be_bytes(self.octets()) == 0xc000000a {
|
||||
return true;
|
||||
}
|
||||
!self.is_private() && !self.is_loopback() && !self.is_link_local() &&
|
||||
!self.is_broadcast() && !self.is_documentation() &&
|
||||
!self.is_shared() &&
|
||||
!(self.octets()[0] == 192 && self.octets()[1] == 0 &&
|
||||
self.octets()[2] == 0) && !self.is_reserved() &&
|
||||
!self.is_benchmarking() && self.octets()[0] != 0
|
||||
}
|
||||
pub const fn is_shared(&self) -> bool {
|
||||
self.octets()[0] == 100 &&
|
||||
(self.octets()[1] & 0b1100_0000 == 0b0100_0000)
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
|
||||
}
|
||||
pub const fn is_reserved(&self) -> bool {
|
||||
self.octets()[0] & 240 == 240 && !self.is_broadcast()
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
self.octets()[0] >= 224 && self.octets()[0] <= 239
|
||||
}
|
||||
pub const fn is_broadcast(&self) -> bool {
|
||||
u32::from_be_bytes(self.octets()) ==
|
||||
u32::from_be_bytes(Self::BROADCAST.octets())
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] |
|
||||
[203, 0, 113, _])
|
||||
}
|
||||
pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
|
||||
let [a, b, c, d] = self.octets();
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d],
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
|
||||
let [a, b, c, d] = self.octets();
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c,
|
||||
d],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Display for IpAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.fmt(fmt),
|
||||
IpAddr::V6(ip) => ip.fmt(fmt),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for IpAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl From<Ipv4Addr> for IpAddr {
|
||||
fn from(ipv4: Ipv4Addr) -> IpAddr { IpAddr::V4(ipv4) }
|
||||
}
|
||||
impl From<Ipv6Addr> for IpAddr {
|
||||
fn from(ipv6: Ipv6Addr) -> IpAddr { IpAddr::V6(ipv6) }
|
||||
}
|
||||
impl fmt::Display for Ipv4Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let octets = self.octets();
|
||||
if fmt.precision().is_none() && fmt.width().is_none() {
|
||||
write!(fmt, "{}.{}.{}.{}", octets [0], octets [1], octets [2],
|
||||
octets [3])
|
||||
} else {
|
||||
const IPV4_BUF_LEN: usize = 15;
|
||||
let mut buf = [0u8; IPV4_BUF_LEN];
|
||||
let mut buf_slice = &mut buf[..];
|
||||
write!(buf_slice, "{}.{}.{}.{}", octets [0], octets [1], octets
|
||||
[2], octets [3]).unwrap();
|
||||
let len = IPV4_BUF_LEN - buf_slice.len();
|
||||
let buf =
|
||||
unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
|
||||
fmt.pad(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for Ipv4Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl Clone for Ipv4Addr {
|
||||
fn clone(&self) -> Ipv4Addr { *self }
|
||||
}
|
||||
impl PartialEq for Ipv4Addr {
|
||||
fn eq(&self, other: &Ipv4Addr) -> bool {
|
||||
self.inner.s_addr == other.inner.s_addr
|
||||
}
|
||||
}
|
||||
impl PartialEq<Ipv4Addr> for IpAddr {
|
||||
fn eq(&self, other: &Ipv4Addr) -> bool {
|
||||
match self { IpAddr::V4(v4) => v4 == other, IpAddr::V6(_) => false, }
|
||||
}
|
||||
}
|
||||
impl PartialEq<IpAddr> for Ipv4Addr {
|
||||
fn eq(&self, other: &IpAddr) -> bool {
|
||||
match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, }
|
||||
}
|
||||
}
|
||||
impl Eq for Ipv4Addr {}
|
||||
impl hash::Hash for Ipv4Addr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
{ self.inner.s_addr }.hash(s)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Ipv4Addr {
|
||||
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Ipv4Addr> for IpAddr {
|
||||
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
|
||||
match self {
|
||||
IpAddr::V4(v4) => v4.partial_cmp(other),
|
||||
IpAddr::V6(_) => Some(Ordering::Greater),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialOrd<IpAddr> for Ipv4Addr {
|
||||
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
|
||||
match other {
|
||||
IpAddr::V4(v4) => self.partial_cmp(v4),
|
||||
IpAddr::V6(_) => Some(Ordering::Less),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ord for Ipv4Addr {
|
||||
fn cmp(&self, other: &Ipv4Addr) -> Ordering {
|
||||
u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
|
||||
}
|
||||
}
|
||||
impl IntoInner<c::in_addr> for Ipv4Addr {
|
||||
fn into_inner(self) -> c::in_addr { self.inner }
|
||||
}
|
||||
impl From<Ipv4Addr> for u32 {
|
||||
fn from(ip: Ipv4Addr) -> u32 {
|
||||
let ip = ip.octets();
|
||||
u32::from_be_bytes(ip)
|
||||
}
|
||||
}
|
||||
impl From<u32> for Ipv4Addr {
|
||||
fn from(ip: u32) -> Ipv4Addr { Ipv4Addr::from(ip.to_be_bytes()) }
|
||||
}
|
||||
impl From<[u8; 4]> for Ipv4Addr {
|
||||
fn from(octets: [u8; 4]) -> Ipv4Addr {
|
||||
Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
|
||||
}
|
||||
}
|
||||
impl From<[u8; 4]> for IpAddr {
|
||||
fn from(octets: [u8; 4]) -> IpAddr { IpAddr::V4(Ipv4Addr::from(octets)) }
|
||||
}
|
||||
impl Ipv6Addr {
|
||||
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
|
||||
h: u16) -> Ipv6Addr {
|
||||
let addr16 =
|
||||
[a.to_be(), b.to_be(), c.to_be(), d.to_be(), e.to_be(), f.to_be(),
|
||||
g.to_be(), h.to_be()];
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
pub const fn segments(&self) -> [u16; 8] {
|
||||
let [a, b, c, d, e, f, g, h] =
|
||||
unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
|
||||
[u16::from_be(a), u16::from_be(b), u16::from_be(c), u16::from_be(d),
|
||||
u16::from_be(e), u16::from_be(f), u16::from_be(g),
|
||||
u16::from_be(h)]
|
||||
}
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets()) ==
|
||||
u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets()) ==
|
||||
u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self.multicast_scope() {
|
||||
Some(Ipv6MulticastScope::Global) => true,
|
||||
None => self.is_unicast_global(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub const fn is_unique_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xfe00) == 0xfc00
|
||||
}
|
||||
pub const fn is_unicast(&self) -> bool { !self.is_multicast() }
|
||||
pub const fn is_unicast_link_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xffc0) == 0xfe80
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) &&
|
||||
(self.segments()[2] == 0)
|
||||
}
|
||||
pub const fn is_unicast_global(&self) -> bool {
|
||||
self.is_unicast() && !self.is_loopback() &&
|
||||
!self.is_unicast_link_local() && !self.is_unique_local() &&
|
||||
!self.is_unspecified() && !self.is_documentation()
|
||||
}
|
||||
pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
|
||||
if self.is_multicast() {
|
||||
match self.segments()[0] & 0x000f {
|
||||
1 => Some(Ipv6MulticastScope::InterfaceLocal),
|
||||
2 => Some(Ipv6MulticastScope::LinkLocal),
|
||||
3 => Some(Ipv6MulticastScope::RealmLocal),
|
||||
4 => Some(Ipv6MulticastScope::AdminLocal),
|
||||
5 => Some(Ipv6MulticastScope::SiteLocal),
|
||||
8 => Some(Ipv6MulticastScope::OrganizationLocal),
|
||||
14 => Some(Ipv6MulticastScope::Global),
|
||||
_ => None,
|
||||
}
|
||||
} else { None }
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
(self.segments()[0] & 0xff00) == 0xff00
|
||||
}
|
||||
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
|
||||
match self.octets() {
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
|
||||
Some(Ipv4Addr::new(a, b, c, d))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
|
||||
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
|
||||
let [a, b] = ab.to_be_bytes();
|
||||
let [c, d] = cd.to_be_bytes();
|
||||
Some(Ipv4Addr::new(a, b, c, d))
|
||||
} else { None }
|
||||
}
|
||||
pub const fn to_canonical(&self) -> IpAddr {
|
||||
if let Some(mapped) = self.to_ipv4_mapped() {
|
||||
return IpAddr::V4(mapped);
|
||||
}
|
||||
IpAddr::V6(*self)
|
||||
}
|
||||
pub const fn octets(&self) -> [u8; 16] { self.inner.s6_addr }
|
||||
}
|
||||
impl fmt::Display for Ipv6Addr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if f.precision().is_none() && f.width().is_none() {
|
||||
let segments = self.segments();
|
||||
if self.is_unspecified() {
|
||||
f.write_str("::")
|
||||
} else if self.is_loopback() {
|
||||
f.write_str("::1")
|
||||
} else if let Some(ipv4) = self.to_ipv4() {
|
||||
match segments[5] {
|
||||
0 => write!(f, "::{}", ipv4),
|
||||
0xffff => write!(f, "::ffff:{}", ipv4),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
#[derive(Copy, Clone, Default)]
|
||||
struct Span {
|
||||
start: usize,
|
||||
len: usize,
|
||||
}
|
||||
let zeroes =
|
||||
{
|
||||
let mut longest = Span::default();
|
||||
let mut current = Span::default();
|
||||
for (i, &segment) in segments.iter().enumerate() {
|
||||
if segment == 0 {
|
||||
if current.len == 0 { current.start = i; }
|
||||
current.len += 1;
|
||||
if current.len > longest.len { longest = current; }
|
||||
} else { current = Span::default(); }
|
||||
}
|
||||
longest
|
||||
};
|
||||
#[doc = " Write a colon-separated part of the address"]
|
||||
#[inline]
|
||||
fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16])
|
||||
-> fmt::Result {
|
||||
if let Some((first, tail)) = chunk.split_first() {
|
||||
write!(f, "{:x}", first)?;
|
||||
for segment in tail {
|
||||
f.write_char(':')?;
|
||||
write!(f, "{:x}", segment)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
if zeroes.len > 1 {
|
||||
fmt_subslice(f, &segments[..zeroes.start])?;
|
||||
f.write_str("::")?;
|
||||
fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
|
||||
} else { fmt_subslice(f, &segments) }
|
||||
}
|
||||
} else {
|
||||
const IPV6_BUF_LEN: usize = (4 * 8) + 7;
|
||||
let mut buf = [0u8; IPV6_BUF_LEN];
|
||||
let mut buf_slice = &mut buf[..];
|
||||
write!(buf_slice, "{}", self).unwrap();
|
||||
let len = IPV6_BUF_LEN - buf_slice.len();
|
||||
let buf =
|
||||
unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
|
||||
f.pad(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for Ipv6Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl Clone for Ipv6Addr {
|
||||
fn clone(&self) -> Ipv6Addr { *self }
|
||||
}
|
||||
impl PartialEq for Ipv6Addr {
|
||||
fn eq(&self, other: &Ipv6Addr) -> bool {
|
||||
self.inner.s6_addr == other.inner.s6_addr
|
||||
}
|
||||
}
|
||||
impl PartialEq<IpAddr> for Ipv6Addr {
|
||||
fn eq(&self, other: &IpAddr) -> bool {
|
||||
match other { IpAddr::V4(_) => false, IpAddr::V6(v6) => self == v6, }
|
||||
}
|
||||
}
|
||||
impl PartialEq<Ipv6Addr> for IpAddr {
|
||||
fn eq(&self, other: &Ipv6Addr) -> bool {
|
||||
match self { IpAddr::V4(_) => false, IpAddr::V6(v6) => v6 == other, }
|
||||
}
|
||||
}
|
||||
impl Eq for Ipv6Addr {}
|
||||
impl hash::Hash for Ipv6Addr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) { self.inner.s6_addr.hash(s) }
|
||||
}
|
||||
impl PartialOrd for Ipv6Addr {
|
||||
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Ipv6Addr> for IpAddr {
|
||||
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
|
||||
match self {
|
||||
IpAddr::V4(_) => Some(Ordering::Less),
|
||||
IpAddr::V6(v6) => v6.partial_cmp(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialOrd<IpAddr> for Ipv6Addr {
|
||||
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
|
||||
match other {
|
||||
IpAddr::V4(_) => Some(Ordering::Greater),
|
||||
IpAddr::V6(v6) => self.partial_cmp(v6),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ord for Ipv6Addr {
|
||||
fn cmp(&self, other: &Ipv6Addr) -> Ordering {
|
||||
self.segments().cmp(&other.segments())
|
||||
}
|
||||
}
|
||||
impl AsInner<c::in6_addr> for Ipv6Addr {
|
||||
fn as_inner(&self) -> &c::in6_addr { &self.inner }
|
||||
}
|
||||
impl FromInner<c::in6_addr> for Ipv6Addr {
|
||||
fn from_inner(addr: c::in6_addr) -> Ipv6Addr { Ipv6Addr { inner: addr } }
|
||||
}
|
||||
impl From<Ipv6Addr> for u128 {
|
||||
fn from(ip: Ipv6Addr) -> u128 {
|
||||
let ip = ip.octets();
|
||||
u128::from_be_bytes(ip)
|
||||
}
|
||||
}
|
||||
impl From<u128> for Ipv6Addr {
|
||||
fn from(ip: u128) -> Ipv6Addr { Ipv6Addr::from(ip.to_be_bytes()) }
|
||||
}
|
||||
impl From<[u8; 16]> for Ipv6Addr {
|
||||
fn from(octets: [u8; 16]) -> Ipv6Addr {
|
||||
let inner = c::in6_addr { s6_addr: octets };
|
||||
Ipv6Addr::from_inner(inner)
|
||||
}
|
||||
}
|
||||
impl From<[u16; 8]> for Ipv6Addr {
|
||||
fn from(segments: [u16; 8]) -> Ipv6Addr {
|
||||
let [a, b, c, d, e, f, g, h] = segments;
|
||||
Ipv6Addr::new(a, b, c, d, e, f, g, h)
|
||||
}
|
||||
}
|
||||
impl From<[u8; 16]> for IpAddr {
|
||||
fn from(octets: [u8; 16]) -> IpAddr { IpAddr::V6(Ipv6Addr::from(octets)) }
|
||||
}
|
||||
impl From<[u16; 8]> for IpAddr {
|
||||
fn from(segments: [u16; 8]) -> IpAddr {
|
||||
IpAddr::V6(Ipv6Addr::from(segments))
|
||||
}
|
||||
}
|
||||
552
third-party/vendor/prettyplease/examples/output.rustfmt.rs
vendored
Normal file
552
third-party/vendor/prettyplease/examples/output.rustfmt.rs
vendored
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
use crate::cmp::Ordering;
|
||||
use crate::fmt::{self, Write as FmtWrite};
|
||||
use crate::hash;
|
||||
use crate::io::Write as IoWrite;
|
||||
use crate::mem::transmute;
|
||||
use crate::sys::net::netc as c;
|
||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
|
||||
pub enum IpAddr {
|
||||
V4(Ipv4Addr),
|
||||
V6(Ipv6Addr),
|
||||
}
|
||||
#[derive(Copy)]
|
||||
pub struct Ipv4Addr {
|
||||
inner: c::in_addr,
|
||||
}
|
||||
#[derive(Copy)]
|
||||
pub struct Ipv6Addr {
|
||||
inner: c::in6_addr,
|
||||
}
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Ipv6MulticastScope {
|
||||
InterfaceLocal,
|
||||
LinkLocal,
|
||||
RealmLocal,
|
||||
AdminLocal,
|
||||
SiteLocal,
|
||||
OrganizationLocal,
|
||||
Global,
|
||||
}
|
||||
impl IpAddr {
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_unspecified(),
|
||||
IpAddr::V6(ip) => ip.is_unspecified(),
|
||||
}
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_loopback(),
|
||||
IpAddr::V6(ip) => ip.is_loopback(),
|
||||
}
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_global(),
|
||||
IpAddr::V6(ip) => ip.is_global(),
|
||||
}
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_multicast(),
|
||||
IpAddr::V6(ip) => ip.is_multicast(),
|
||||
}
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_documentation(),
|
||||
IpAddr::V6(ip) => ip.is_documentation(),
|
||||
}
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.is_benchmarking(),
|
||||
IpAddr::V6(ip) => ip.is_benchmarking(),
|
||||
}
|
||||
}
|
||||
pub const fn is_ipv4(&self) -> bool {
|
||||
matches!(self, IpAddr::V4(_))
|
||||
}
|
||||
pub const fn is_ipv6(&self) -> bool {
|
||||
matches!(self, IpAddr::V6(_))
|
||||
}
|
||||
pub const fn to_canonical(&self) -> IpAddr {
|
||||
match self {
|
||||
&v4 @ IpAddr::V4(_) => v4,
|
||||
IpAddr::V6(v6) => v6.to_canonical(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ipv4Addr {
|
||||
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
|
||||
Ipv4Addr {
|
||||
inner: c::in_addr {
|
||||
s_addr: u32::from_ne_bytes([a, b, c, d]),
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
|
||||
#[doc(alias = "INADDR_ANY")]
|
||||
pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
|
||||
pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
|
||||
pub const fn octets(&self) -> [u8; 4] {
|
||||
self.inner.s_addr.to_ne_bytes()
|
||||
}
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
self.inner.s_addr == 0
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
self.octets()[0] == 127
|
||||
}
|
||||
pub const fn is_private(&self) -> bool {
|
||||
match self.octets() {
|
||||
[10, ..] => true,
|
||||
[172, b, ..] if b >= 16 && b <= 31 => true,
|
||||
[192, 168, ..] => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub const fn is_link_local(&self) -> bool {
|
||||
matches!(self.octets(), [169, 254, ..])
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
if u32::from_be_bytes(self.octets()) == 0xc0000009
|
||||
|| u32::from_be_bytes(self.octets()) == 0xc000000a
|
||||
{
|
||||
return true;
|
||||
}
|
||||
!self.is_private()
|
||||
&& !self.is_loopback()
|
||||
&& !self.is_link_local()
|
||||
&& !self.is_broadcast()
|
||||
&& !self.is_documentation()
|
||||
&& !self.is_shared()
|
||||
&& !(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
|
||||
&& !self.is_reserved()
|
||||
&& !self.is_benchmarking()
|
||||
&& self.octets()[0] != 0
|
||||
}
|
||||
pub const fn is_shared(&self) -> bool {
|
||||
self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
|
||||
}
|
||||
pub const fn is_reserved(&self) -> bool {
|
||||
self.octets()[0] & 240 == 240 && !self.is_broadcast()
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
self.octets()[0] >= 224 && self.octets()[0] <= 239
|
||||
}
|
||||
pub const fn is_broadcast(&self) -> bool {
|
||||
u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
matches!(
|
||||
self.octets(),
|
||||
[192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _]
|
||||
)
|
||||
}
|
||||
pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
|
||||
let [a, b, c, d] = self.octets();
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d],
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
|
||||
let [a, b, c, d] = self.octets();
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Display for IpAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
IpAddr::V4(ip) => ip.fmt(fmt),
|
||||
IpAddr::V6(ip) => ip.fmt(fmt),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for IpAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl From<Ipv4Addr> for IpAddr {
|
||||
fn from(ipv4: Ipv4Addr) -> IpAddr {
|
||||
IpAddr::V4(ipv4)
|
||||
}
|
||||
}
|
||||
impl From<Ipv6Addr> for IpAddr {
|
||||
fn from(ipv6: Ipv6Addr) -> IpAddr {
|
||||
IpAddr::V6(ipv6)
|
||||
}
|
||||
}
|
||||
impl fmt::Display for Ipv4Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let octets = self.octets();
|
||||
if fmt.precision().is_none() && fmt.width().is_none() {
|
||||
write!(
|
||||
fmt,
|
||||
"{}.{}.{}.{}",
|
||||
octets[0], octets[1], octets[2], octets[3]
|
||||
)
|
||||
} else {
|
||||
const IPV4_BUF_LEN: usize = 15;
|
||||
let mut buf = [0u8; IPV4_BUF_LEN];
|
||||
let mut buf_slice = &mut buf[..];
|
||||
write!(
|
||||
buf_slice,
|
||||
"{}.{}.{}.{}",
|
||||
octets[0], octets[1], octets[2], octets[3]
|
||||
)
|
||||
.unwrap();
|
||||
let len = IPV4_BUF_LEN - buf_slice.len();
|
||||
let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
|
||||
fmt.pad(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for Ipv4Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl Clone for Ipv4Addr {
|
||||
fn clone(&self) -> Ipv4Addr {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl PartialEq for Ipv4Addr {
|
||||
fn eq(&self, other: &Ipv4Addr) -> bool {
|
||||
self.inner.s_addr == other.inner.s_addr
|
||||
}
|
||||
}
|
||||
impl PartialEq<Ipv4Addr> for IpAddr {
|
||||
fn eq(&self, other: &Ipv4Addr) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(v4) => v4 == other,
|
||||
IpAddr::V6(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq<IpAddr> for Ipv4Addr {
|
||||
fn eq(&self, other: &IpAddr) -> bool {
|
||||
match other {
|
||||
IpAddr::V4(v4) => self == v4,
|
||||
IpAddr::V6(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Eq for Ipv4Addr {}
|
||||
impl hash::Hash for Ipv4Addr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
{ self.inner.s_addr }.hash(s)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Ipv4Addr {
|
||||
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Ipv4Addr> for IpAddr {
|
||||
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
|
||||
match self {
|
||||
IpAddr::V4(v4) => v4.partial_cmp(other),
|
||||
IpAddr::V6(_) => Some(Ordering::Greater),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialOrd<IpAddr> for Ipv4Addr {
|
||||
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
|
||||
match other {
|
||||
IpAddr::V4(v4) => self.partial_cmp(v4),
|
||||
IpAddr::V6(_) => Some(Ordering::Less),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ord for Ipv4Addr {
|
||||
fn cmp(&self, other: &Ipv4Addr) -> Ordering {
|
||||
u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
|
||||
}
|
||||
}
|
||||
impl IntoInner<c::in_addr> for Ipv4Addr {
|
||||
fn into_inner(self) -> c::in_addr {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
impl From<Ipv4Addr> for u32 {
|
||||
fn from(ip: Ipv4Addr) -> u32 {
|
||||
let ip = ip.octets();
|
||||
u32::from_be_bytes(ip)
|
||||
}
|
||||
}
|
||||
impl From<u32> for Ipv4Addr {
|
||||
fn from(ip: u32) -> Ipv4Addr {
|
||||
Ipv4Addr::from(ip.to_be_bytes())
|
||||
}
|
||||
}
|
||||
impl From<[u8; 4]> for Ipv4Addr {
|
||||
fn from(octets: [u8; 4]) -> Ipv4Addr {
|
||||
Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
|
||||
}
|
||||
}
|
||||
impl From<[u8; 4]> for IpAddr {
|
||||
fn from(octets: [u8; 4]) -> IpAddr {
|
||||
IpAddr::V4(Ipv4Addr::from(octets))
|
||||
}
|
||||
}
|
||||
impl Ipv6Addr {
|
||||
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
|
||||
let addr16 = [
|
||||
a.to_be(),
|
||||
b.to_be(),
|
||||
c.to_be(),
|
||||
d.to_be(),
|
||||
e.to_be(),
|
||||
f.to_be(),
|
||||
g.to_be(),
|
||||
h.to_be(),
|
||||
];
|
||||
Ipv6Addr {
|
||||
inner: c::in6_addr {
|
||||
s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
|
||||
},
|
||||
}
|
||||
}
|
||||
pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
pub const fn segments(&self) -> [u16; 8] {
|
||||
let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
|
||||
[
|
||||
u16::from_be(a),
|
||||
u16::from_be(b),
|
||||
u16::from_be(c),
|
||||
u16::from_be(d),
|
||||
u16::from_be(e),
|
||||
u16::from_be(f),
|
||||
u16::from_be(g),
|
||||
u16::from_be(h),
|
||||
]
|
||||
}
|
||||
pub const fn is_unspecified(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
|
||||
}
|
||||
pub const fn is_loopback(&self) -> bool {
|
||||
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
|
||||
}
|
||||
pub const fn is_global(&self) -> bool {
|
||||
match self.multicast_scope() {
|
||||
Some(Ipv6MulticastScope::Global) => true,
|
||||
None => self.is_unicast_global(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub const fn is_unique_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xfe00) == 0xfc00
|
||||
}
|
||||
pub const fn is_unicast(&self) -> bool {
|
||||
!self.is_multicast()
|
||||
}
|
||||
pub const fn is_unicast_link_local(&self) -> bool {
|
||||
(self.segments()[0] & 0xffc0) == 0xfe80
|
||||
}
|
||||
pub const fn is_documentation(&self) -> bool {
|
||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
|
||||
}
|
||||
pub const fn is_benchmarking(&self) -> bool {
|
||||
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
|
||||
}
|
||||
pub const fn is_unicast_global(&self) -> bool {
|
||||
self.is_unicast()
|
||||
&& !self.is_loopback()
|
||||
&& !self.is_unicast_link_local()
|
||||
&& !self.is_unique_local()
|
||||
&& !self.is_unspecified()
|
||||
&& !self.is_documentation()
|
||||
}
|
||||
pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
|
||||
if self.is_multicast() {
|
||||
match self.segments()[0] & 0x000f {
|
||||
1 => Some(Ipv6MulticastScope::InterfaceLocal),
|
||||
2 => Some(Ipv6MulticastScope::LinkLocal),
|
||||
3 => Some(Ipv6MulticastScope::RealmLocal),
|
||||
4 => Some(Ipv6MulticastScope::AdminLocal),
|
||||
5 => Some(Ipv6MulticastScope::SiteLocal),
|
||||
8 => Some(Ipv6MulticastScope::OrganizationLocal),
|
||||
14 => Some(Ipv6MulticastScope::Global),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub const fn is_multicast(&self) -> bool {
|
||||
(self.segments()[0] & 0xff00) == 0xff00
|
||||
}
|
||||
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
|
||||
match self.octets() {
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
|
||||
Some(Ipv4Addr::new(a, b, c, d))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
|
||||
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
|
||||
let [a, b] = ab.to_be_bytes();
|
||||
let [c, d] = cd.to_be_bytes();
|
||||
Some(Ipv4Addr::new(a, b, c, d))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub const fn to_canonical(&self) -> IpAddr {
|
||||
if let Some(mapped) = self.to_ipv4_mapped() {
|
||||
return IpAddr::V4(mapped);
|
||||
}
|
||||
IpAddr::V6(*self)
|
||||
}
|
||||
pub const fn octets(&self) -> [u8; 16] {
|
||||
self.inner.s6_addr
|
||||
}
|
||||
}
|
||||
impl fmt::Display for Ipv6Addr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if f.precision().is_none() && f.width().is_none() {
|
||||
let segments = self.segments();
|
||||
if self.is_unspecified() {
|
||||
f.write_str("::")
|
||||
} else if self.is_loopback() {
|
||||
f.write_str("::1")
|
||||
} else if let Some(ipv4) = self.to_ipv4() {
|
||||
match segments[5] {
|
||||
0 => write!(f, "::{}", ipv4),
|
||||
0xffff => write!(f, "::ffff:{}", ipv4),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } }
|
||||
} else {
|
||||
const IPV6_BUF_LEN: usize = (4 * 8) + 7;
|
||||
let mut buf = [0u8; IPV6_BUF_LEN];
|
||||
let mut buf_slice = &mut buf[..];
|
||||
write!(buf_slice, "{}", self).unwrap();
|
||||
let len = IPV6_BUF_LEN - buf_slice.len();
|
||||
let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
|
||||
f.pad(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Debug for Ipv6Addr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
impl Clone for Ipv6Addr {
|
||||
fn clone(&self) -> Ipv6Addr {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl PartialEq for Ipv6Addr {
|
||||
fn eq(&self, other: &Ipv6Addr) -> bool {
|
||||
self.inner.s6_addr == other.inner.s6_addr
|
||||
}
|
||||
}
|
||||
impl PartialEq<IpAddr> for Ipv6Addr {
|
||||
fn eq(&self, other: &IpAddr) -> bool {
|
||||
match other {
|
||||
IpAddr::V4(_) => false,
|
||||
IpAddr::V6(v6) => self == v6,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq<Ipv6Addr> for IpAddr {
|
||||
fn eq(&self, other: &Ipv6Addr) -> bool {
|
||||
match self {
|
||||
IpAddr::V4(_) => false,
|
||||
IpAddr::V6(v6) => v6 == other,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Eq for Ipv6Addr {}
|
||||
impl hash::Hash for Ipv6Addr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
self.inner.s6_addr.hash(s)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Ipv6Addr {
|
||||
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Ipv6Addr> for IpAddr {
|
||||
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
|
||||
match self {
|
||||
IpAddr::V4(_) => Some(Ordering::Less),
|
||||
IpAddr::V6(v6) => v6.partial_cmp(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialOrd<IpAddr> for Ipv6Addr {
|
||||
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
|
||||
match other {
|
||||
IpAddr::V4(_) => Some(Ordering::Greater),
|
||||
IpAddr::V6(v6) => self.partial_cmp(v6),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Ord for Ipv6Addr {
|
||||
fn cmp(&self, other: &Ipv6Addr) -> Ordering {
|
||||
self.segments().cmp(&other.segments())
|
||||
}
|
||||
}
|
||||
impl AsInner<c::in6_addr> for Ipv6Addr {
|
||||
fn as_inner(&self) -> &c::in6_addr {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
impl FromInner<c::in6_addr> for Ipv6Addr {
|
||||
fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
|
||||
Ipv6Addr { inner: addr }
|
||||
}
|
||||
}
|
||||
impl From<Ipv6Addr> for u128 {
|
||||
fn from(ip: Ipv6Addr) -> u128 {
|
||||
let ip = ip.octets();
|
||||
u128::from_be_bytes(ip)
|
||||
}
|
||||
}
|
||||
impl From<u128> for Ipv6Addr {
|
||||
fn from(ip: u128) -> Ipv6Addr {
|
||||
Ipv6Addr::from(ip.to_be_bytes())
|
||||
}
|
||||
}
|
||||
impl From<[u8; 16]> for Ipv6Addr {
|
||||
fn from(octets: [u8; 16]) -> Ipv6Addr {
|
||||
let inner = c::in6_addr { s6_addr: octets };
|
||||
Ipv6Addr::from_inner(inner)
|
||||
}
|
||||
}
|
||||
impl From<[u16; 8]> for Ipv6Addr {
|
||||
fn from(segments: [u16; 8]) -> Ipv6Addr {
|
||||
let [a, b, c, d, e, f, g, h] = segments;
|
||||
Ipv6Addr::new(a, b, c, d, e, f, g, h)
|
||||
}
|
||||
}
|
||||
impl From<[u8; 16]> for IpAddr {
|
||||
fn from(octets: [u8; 16]) -> IpAddr {
|
||||
IpAddr::V6(Ipv6Addr::from(octets))
|
||||
}
|
||||
}
|
||||
impl From<[u16; 8]> for IpAddr {
|
||||
fn from(segments: [u16; 8]) -> IpAddr {
|
||||
IpAddr::V6(Ipv6Addr::from(segments))
|
||||
}
|
||||
}
|
||||
376
third-party/vendor/prettyplease/src/algorithm.rs
vendored
Normal file
376
third-party/vendor/prettyplease/src/algorithm.rs
vendored
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
// Adapted from https://github.com/rust-lang/rust/blob/1.57.0/compiler/rustc_ast_pretty/src/pp.rs.
|
||||
// See "Algorithm notes" in the crate-level rustdoc.
|
||||
|
||||
use crate::ring::RingBuffer;
|
||||
use crate::{MARGIN, MIN_SPACE};
|
||||
use std::borrow::Cow;
|
||||
use std::cmp;
|
||||
use std::collections::VecDeque;
|
||||
use std::iter;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum Breaks {
|
||||
Consistent,
|
||||
Inconsistent,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct BreakToken {
|
||||
pub offset: isize,
|
||||
pub blank_space: usize,
|
||||
pub pre_break: Option<char>,
|
||||
pub post_break: Option<char>,
|
||||
pub no_break: Option<char>,
|
||||
pub if_nonempty: bool,
|
||||
pub never_break: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct BeginToken {
|
||||
pub offset: isize,
|
||||
pub breaks: Breaks,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Token {
|
||||
String(Cow<'static, str>),
|
||||
Break(BreakToken),
|
||||
Begin(BeginToken),
|
||||
End,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum PrintFrame {
|
||||
Fits(Breaks),
|
||||
Broken(usize, Breaks),
|
||||
}
|
||||
|
||||
pub const SIZE_INFINITY: isize = 0xffff;
|
||||
|
||||
pub struct Printer {
|
||||
out: String,
|
||||
// Number of spaces left on line
|
||||
space: isize,
|
||||
// Ring-buffer of tokens and calculated sizes
|
||||
buf: RingBuffer<BufEntry>,
|
||||
// Total size of tokens already printed
|
||||
left_total: isize,
|
||||
// Total size of tokens enqueued, including printed and not yet printed
|
||||
right_total: isize,
|
||||
// Holds the ring-buffer index of the Begin that started the current block,
|
||||
// possibly with the most recent Break after that Begin (if there is any) on
|
||||
// top of it. Values are pushed and popped on the back of the queue using it
|
||||
// like stack, and elsewhere old values are popped from the front of the
|
||||
// queue as they become irrelevant due to the primary ring-buffer advancing.
|
||||
scan_stack: VecDeque<usize>,
|
||||
// Stack of blocks-in-progress being flushed by print
|
||||
print_stack: Vec<PrintFrame>,
|
||||
// Level of indentation of current line
|
||||
indent: usize,
|
||||
// Buffered indentation to avoid writing trailing whitespace
|
||||
pending_indentation: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct BufEntry {
|
||||
token: Token,
|
||||
size: isize,
|
||||
}
|
||||
|
||||
impl Printer {
|
||||
pub fn new() -> Self {
|
||||
Printer {
|
||||
out: String::new(),
|
||||
space: MARGIN,
|
||||
buf: RingBuffer::new(),
|
||||
left_total: 0,
|
||||
right_total: 0,
|
||||
scan_stack: VecDeque::new(),
|
||||
print_stack: Vec::new(),
|
||||
indent: 0,
|
||||
pending_indentation: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eof(mut self) -> String {
|
||||
if !self.scan_stack.is_empty() {
|
||||
self.check_stack(0);
|
||||
self.advance_left();
|
||||
}
|
||||
self.out
|
||||
}
|
||||
|
||||
pub fn scan_begin(&mut self, token: BeginToken) {
|
||||
if self.scan_stack.is_empty() {
|
||||
self.left_total = 1;
|
||||
self.right_total = 1;
|
||||
self.buf.clear();
|
||||
}
|
||||
let right = self.buf.push(BufEntry {
|
||||
token: Token::Begin(token),
|
||||
size: -self.right_total,
|
||||
});
|
||||
self.scan_stack.push_back(right);
|
||||
}
|
||||
|
||||
pub fn scan_end(&mut self) {
|
||||
if self.scan_stack.is_empty() {
|
||||
self.print_end();
|
||||
} else {
|
||||
if !self.buf.is_empty() {
|
||||
if let Token::Break(break_token) = self.buf.last().token {
|
||||
if self.buf.len() >= 2 {
|
||||
if let Token::Begin(_) = self.buf.second_last().token {
|
||||
self.buf.pop_last();
|
||||
self.buf.pop_last();
|
||||
self.scan_stack.pop_back();
|
||||
self.scan_stack.pop_back();
|
||||
self.right_total -= break_token.blank_space as isize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if break_token.if_nonempty {
|
||||
self.buf.pop_last();
|
||||
self.scan_stack.pop_back();
|
||||
self.right_total -= break_token.blank_space as isize;
|
||||
}
|
||||
}
|
||||
}
|
||||
let right = self.buf.push(BufEntry {
|
||||
token: Token::End,
|
||||
size: -1,
|
||||
});
|
||||
self.scan_stack.push_back(right);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scan_break(&mut self, token: BreakToken) {
|
||||
if self.scan_stack.is_empty() {
|
||||
self.left_total = 1;
|
||||
self.right_total = 1;
|
||||
self.buf.clear();
|
||||
} else {
|
||||
self.check_stack(0);
|
||||
}
|
||||
let right = self.buf.push(BufEntry {
|
||||
token: Token::Break(token),
|
||||
size: -self.right_total,
|
||||
});
|
||||
self.scan_stack.push_back(right);
|
||||
self.right_total += token.blank_space as isize;
|
||||
}
|
||||
|
||||
pub fn scan_string(&mut self, string: Cow<'static, str>) {
|
||||
if self.scan_stack.is_empty() {
|
||||
self.print_string(string);
|
||||
} else {
|
||||
let len = string.len() as isize;
|
||||
self.buf.push(BufEntry {
|
||||
token: Token::String(string),
|
||||
size: len,
|
||||
});
|
||||
self.right_total += len;
|
||||
self.check_stream();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&mut self, offset: isize) {
|
||||
match &mut self.buf.last_mut().token {
|
||||
Token::Break(token) => token.offset += offset,
|
||||
Token::Begin(_) => {}
|
||||
Token::String(_) | Token::End => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_with_max_width(&mut self, max: isize) {
|
||||
let mut depth = 1;
|
||||
for &index in self.scan_stack.iter().rev() {
|
||||
let entry = &self.buf[index];
|
||||
match entry.token {
|
||||
Token::Begin(_) => {
|
||||
depth -= 1;
|
||||
if depth == 0 {
|
||||
if entry.size < 0 {
|
||||
let actual_width = entry.size + self.right_total;
|
||||
if actual_width > max {
|
||||
self.buf.push(BufEntry {
|
||||
token: Token::String(Cow::Borrowed("")),
|
||||
size: SIZE_INFINITY,
|
||||
});
|
||||
self.right_total += SIZE_INFINITY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Token::End => depth += 1,
|
||||
Token::Break(_) => {}
|
||||
Token::String(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
self.scan_end();
|
||||
}
|
||||
|
||||
fn check_stream(&mut self) {
|
||||
while self.right_total - self.left_total > self.space {
|
||||
if *self.scan_stack.front().unwrap() == self.buf.index_of_first() {
|
||||
self.scan_stack.pop_front().unwrap();
|
||||
self.buf.first_mut().size = SIZE_INFINITY;
|
||||
}
|
||||
|
||||
self.advance_left();
|
||||
|
||||
if self.buf.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn advance_left(&mut self) {
|
||||
while self.buf.first().size >= 0 {
|
||||
let left = self.buf.pop_first();
|
||||
|
||||
match left.token {
|
||||
Token::String(string) => {
|
||||
self.left_total += left.size;
|
||||
self.print_string(string);
|
||||
}
|
||||
Token::Break(token) => {
|
||||
self.left_total += token.blank_space as isize;
|
||||
self.print_break(token, left.size);
|
||||
}
|
||||
Token::Begin(token) => self.print_begin(token, left.size),
|
||||
Token::End => self.print_end(),
|
||||
}
|
||||
|
||||
if self.buf.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_stack(&mut self, mut depth: usize) {
|
||||
while let Some(&index) = self.scan_stack.back() {
|
||||
let entry = &mut self.buf[index];
|
||||
match entry.token {
|
||||
Token::Begin(_) => {
|
||||
if depth == 0 {
|
||||
break;
|
||||
}
|
||||
self.scan_stack.pop_back().unwrap();
|
||||
entry.size += self.right_total;
|
||||
depth -= 1;
|
||||
}
|
||||
Token::End => {
|
||||
self.scan_stack.pop_back().unwrap();
|
||||
entry.size = 1;
|
||||
depth += 1;
|
||||
}
|
||||
Token::Break(_) => {
|
||||
self.scan_stack.pop_back().unwrap();
|
||||
entry.size += self.right_total;
|
||||
if depth == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Token::String(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_top(&self) -> PrintFrame {
|
||||
const OUTER: PrintFrame = PrintFrame::Broken(0, Breaks::Inconsistent);
|
||||
self.print_stack.last().map_or(OUTER, PrintFrame::clone)
|
||||
}
|
||||
|
||||
fn print_begin(&mut self, token: BeginToken, size: isize) {
|
||||
if cfg!(prettyplease_debug) {
|
||||
self.out.push(match token.breaks {
|
||||
Breaks::Consistent => '«',
|
||||
Breaks::Inconsistent => '‹',
|
||||
});
|
||||
if cfg!(prettyplease_debug_indent) {
|
||||
self.out
|
||||
.extend(token.offset.to_string().chars().map(|ch| match ch {
|
||||
'0'..='9' => ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉']
|
||||
[(ch as u8 - b'0') as usize],
|
||||
'-' => '₋',
|
||||
_ => unreachable!(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
if size > self.space {
|
||||
self.print_stack
|
||||
.push(PrintFrame::Broken(self.indent, token.breaks));
|
||||
self.indent = usize::try_from(self.indent as isize + token.offset).unwrap();
|
||||
} else {
|
||||
self.print_stack.push(PrintFrame::Fits(token.breaks));
|
||||
}
|
||||
}
|
||||
|
||||
fn print_end(&mut self) {
|
||||
let breaks = match self.print_stack.pop().unwrap() {
|
||||
PrintFrame::Broken(indent, breaks) => {
|
||||
self.indent = indent;
|
||||
breaks
|
||||
}
|
||||
PrintFrame::Fits(breaks) => breaks,
|
||||
};
|
||||
if cfg!(prettyplease_debug) {
|
||||
self.out.push(match breaks {
|
||||
Breaks::Consistent => '»',
|
||||
Breaks::Inconsistent => '›',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn print_break(&mut self, token: BreakToken, size: isize) {
|
||||
let fits = token.never_break
|
||||
|| match self.get_top() {
|
||||
PrintFrame::Fits(..) => true,
|
||||
PrintFrame::Broken(.., Breaks::Consistent) => false,
|
||||
PrintFrame::Broken(.., Breaks::Inconsistent) => size <= self.space,
|
||||
};
|
||||
if fits {
|
||||
self.pending_indentation += token.blank_space;
|
||||
self.space -= token.blank_space as isize;
|
||||
if let Some(no_break) = token.no_break {
|
||||
self.out.push(no_break);
|
||||
self.space -= no_break.len_utf8() as isize;
|
||||
}
|
||||
if cfg!(prettyplease_debug) {
|
||||
self.out.push('·');
|
||||
}
|
||||
} else {
|
||||
if let Some(pre_break) = token.pre_break {
|
||||
self.print_indent();
|
||||
self.out.push(pre_break);
|
||||
}
|
||||
if cfg!(prettyplease_debug) {
|
||||
self.out.push('·');
|
||||
}
|
||||
self.out.push('\n');
|
||||
let indent = self.indent as isize + token.offset;
|
||||
self.pending_indentation = usize::try_from(indent).unwrap();
|
||||
self.space = cmp::max(MARGIN - indent, MIN_SPACE);
|
||||
if let Some(post_break) = token.post_break {
|
||||
self.print_indent();
|
||||
self.out.push(post_break);
|
||||
self.space -= post_break.len_utf8() as isize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_string(&mut self, string: Cow<'static, str>) {
|
||||
self.print_indent();
|
||||
self.out.push_str(&string);
|
||||
self.space -= string.len() as isize;
|
||||
}
|
||||
|
||||
fn print_indent(&mut self) {
|
||||
self.out.reserve(self.pending_indentation);
|
||||
self.out
|
||||
.extend(iter::repeat(' ').take(self.pending_indentation));
|
||||
self.pending_indentation = 0;
|
||||
}
|
||||
}
|
||||
287
third-party/vendor/prettyplease/src/attr.rs
vendored
Normal file
287
third-party/vendor/prettyplease/src/attr.rs
vendored
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::path::PathKind;
|
||||
use crate::INDENT;
|
||||
use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
|
||||
use syn::{AttrStyle, Attribute, Expr, Lit, MacroDelimiter, Meta, MetaList, MetaNameValue};
|
||||
|
||||
impl Printer {
|
||||
pub fn outer_attrs(&mut self, attrs: &[Attribute]) {
|
||||
for attr in attrs {
|
||||
if let AttrStyle::Outer = attr.style {
|
||||
self.attr(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inner_attrs(&mut self, attrs: &[Attribute]) {
|
||||
for attr in attrs {
|
||||
if let AttrStyle::Inner(_) = attr.style {
|
||||
self.attr(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn attr(&mut self, attr: &Attribute) {
|
||||
if let Some(mut doc) = value_of_attribute("doc", attr) {
|
||||
if !doc.contains('\n')
|
||||
&& match attr.style {
|
||||
AttrStyle::Outer => !doc.starts_with('/'),
|
||||
AttrStyle::Inner(_) => true,
|
||||
}
|
||||
{
|
||||
trim_trailing_spaces(&mut doc);
|
||||
self.word(match attr.style {
|
||||
AttrStyle::Outer => "///",
|
||||
AttrStyle::Inner(_) => "//!",
|
||||
});
|
||||
self.word(doc);
|
||||
self.hardbreak();
|
||||
return;
|
||||
} else if can_be_block_comment(&doc)
|
||||
&& match attr.style {
|
||||
AttrStyle::Outer => !doc.starts_with(&['*', '/'][..]),
|
||||
AttrStyle::Inner(_) => true,
|
||||
}
|
||||
{
|
||||
trim_interior_trailing_spaces(&mut doc);
|
||||
self.word(match attr.style {
|
||||
AttrStyle::Outer => "/**",
|
||||
AttrStyle::Inner(_) => "/*!",
|
||||
});
|
||||
self.word(doc);
|
||||
self.word("*/");
|
||||
self.hardbreak();
|
||||
return;
|
||||
}
|
||||
} else if let Some(mut comment) = value_of_attribute("comment", attr) {
|
||||
if !comment.contains('\n') {
|
||||
trim_trailing_spaces(&mut comment);
|
||||
self.word("//");
|
||||
self.word(comment);
|
||||
self.hardbreak();
|
||||
return;
|
||||
} else if can_be_block_comment(&comment) && !comment.starts_with(&['*', '!'][..]) {
|
||||
trim_interior_trailing_spaces(&mut comment);
|
||||
self.word("/*");
|
||||
self.word(comment);
|
||||
self.word("*/");
|
||||
self.hardbreak();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.word(match attr.style {
|
||||
AttrStyle::Outer => "#",
|
||||
AttrStyle::Inner(_) => "#!",
|
||||
});
|
||||
self.word("[");
|
||||
self.meta(&attr.meta);
|
||||
self.word("]");
|
||||
self.space();
|
||||
}
|
||||
|
||||
fn meta(&mut self, meta: &Meta) {
|
||||
match meta {
|
||||
Meta::Path(path) => self.path(path, PathKind::Simple),
|
||||
Meta::List(meta) => self.meta_list(meta),
|
||||
Meta::NameValue(meta) => self.meta_name_value(meta),
|
||||
}
|
||||
}
|
||||
|
||||
fn meta_list(&mut self, meta: &MetaList) {
|
||||
self.path(&meta.path, PathKind::Simple);
|
||||
let delimiter = match meta.delimiter {
|
||||
MacroDelimiter::Paren(_) => Delimiter::Parenthesis,
|
||||
MacroDelimiter::Brace(_) => Delimiter::Brace,
|
||||
MacroDelimiter::Bracket(_) => Delimiter::Bracket,
|
||||
};
|
||||
let group = Group::new(delimiter, meta.tokens.clone());
|
||||
self.attr_tokens(TokenStream::from(TokenTree::Group(group)));
|
||||
}
|
||||
|
||||
fn meta_name_value(&mut self, meta: &MetaNameValue) {
|
||||
self.path(&meta.path, PathKind::Simple);
|
||||
self.word(" = ");
|
||||
self.expr(&meta.value);
|
||||
}
|
||||
|
||||
fn attr_tokens(&mut self, tokens: TokenStream) {
|
||||
let mut stack = Vec::new();
|
||||
stack.push((tokens.into_iter().peekable(), Delimiter::None));
|
||||
let mut space = Self::nbsp as fn(&mut Self);
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum State {
|
||||
Word,
|
||||
Punct,
|
||||
TrailingComma,
|
||||
}
|
||||
|
||||
use State::*;
|
||||
let mut state = Word;
|
||||
|
||||
while let Some((tokens, delimiter)) = stack.last_mut() {
|
||||
match tokens.next() {
|
||||
Some(TokenTree::Ident(ident)) => {
|
||||
if let Word = state {
|
||||
space(self);
|
||||
}
|
||||
self.ident(&ident);
|
||||
state = Word;
|
||||
}
|
||||
Some(TokenTree::Punct(punct)) => {
|
||||
let ch = punct.as_char();
|
||||
if let (Word, '=') = (state, ch) {
|
||||
self.nbsp();
|
||||
}
|
||||
if ch == ',' && tokens.peek().is_none() {
|
||||
self.trailing_comma(true);
|
||||
state = TrailingComma;
|
||||
} else {
|
||||
self.token_punct(ch);
|
||||
if ch == '=' {
|
||||
self.nbsp();
|
||||
} else if ch == ',' {
|
||||
space(self);
|
||||
}
|
||||
state = Punct;
|
||||
}
|
||||
}
|
||||
Some(TokenTree::Literal(literal)) => {
|
||||
if let Word = state {
|
||||
space(self);
|
||||
}
|
||||
self.token_literal(&literal);
|
||||
state = Word;
|
||||
}
|
||||
Some(TokenTree::Group(group)) => {
|
||||
let delimiter = group.delimiter();
|
||||
let stream = group.stream();
|
||||
match delimiter {
|
||||
Delimiter::Parenthesis => {
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
state = Punct;
|
||||
}
|
||||
Delimiter::Brace => {
|
||||
self.word("{");
|
||||
state = Punct;
|
||||
}
|
||||
Delimiter::Bracket => {
|
||||
self.word("[");
|
||||
state = Punct;
|
||||
}
|
||||
Delimiter::None => {}
|
||||
}
|
||||
stack.push((stream.into_iter().peekable(), delimiter));
|
||||
space = Self::space;
|
||||
}
|
||||
None => {
|
||||
match delimiter {
|
||||
Delimiter::Parenthesis => {
|
||||
if state != TrailingComma {
|
||||
self.zerobreak();
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
state = Punct;
|
||||
}
|
||||
Delimiter::Brace => {
|
||||
self.word("}");
|
||||
state = Punct;
|
||||
}
|
||||
Delimiter::Bracket => {
|
||||
self.word("]");
|
||||
state = Punct;
|
||||
}
|
||||
Delimiter::None => {}
|
||||
}
|
||||
stack.pop();
|
||||
if stack.is_empty() {
|
||||
space = Self::nbsp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn value_of_attribute(requested: &str, attr: &Attribute) -> Option<String> {
|
||||
let value = match &attr.meta {
|
||||
Meta::NameValue(meta) if meta.path.is_ident(requested) => &meta.value,
|
||||
_ => return None,
|
||||
};
|
||||
let lit = match value {
|
||||
Expr::Lit(expr) if expr.attrs.is_empty() => &expr.lit,
|
||||
_ => return None,
|
||||
};
|
||||
match lit {
|
||||
Lit::Str(string) => Some(string.value()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_outer(attrs: &[Attribute]) -> bool {
|
||||
for attr in attrs {
|
||||
if let AttrStyle::Outer = attr.style {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn has_inner(attrs: &[Attribute]) -> bool {
|
||||
for attr in attrs {
|
||||
if let AttrStyle::Inner(_) = attr.style {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn trim_trailing_spaces(doc: &mut String) {
|
||||
doc.truncate(doc.trim_end_matches(' ').len());
|
||||
}
|
||||
|
||||
fn trim_interior_trailing_spaces(doc: &mut String) {
|
||||
if !doc.contains(" \n") {
|
||||
return;
|
||||
}
|
||||
let mut trimmed = String::with_capacity(doc.len());
|
||||
let mut lines = doc.split('\n').peekable();
|
||||
while let Some(line) = lines.next() {
|
||||
if lines.peek().is_some() {
|
||||
trimmed.push_str(line.trim_end_matches(' '));
|
||||
trimmed.push('\n');
|
||||
} else {
|
||||
trimmed.push_str(line);
|
||||
}
|
||||
}
|
||||
*doc = trimmed;
|
||||
}
|
||||
|
||||
fn can_be_block_comment(value: &str) -> bool {
|
||||
let mut depth = 0usize;
|
||||
let bytes = value.as_bytes();
|
||||
let mut i = 0usize;
|
||||
let upper = bytes.len() - 1;
|
||||
|
||||
while i < upper {
|
||||
if bytes[i] == b'/' && bytes[i + 1] == b'*' {
|
||||
depth += 1;
|
||||
i += 2;
|
||||
} else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
|
||||
if depth == 0 {
|
||||
return false;
|
||||
}
|
||||
depth -= 1;
|
||||
i += 2;
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
depth == 0
|
||||
}
|
||||
98
third-party/vendor/prettyplease/src/convenience.rs
vendored
Normal file
98
third-party/vendor/prettyplease/src/convenience.rs
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
use crate::algorithm::{self, BeginToken, BreakToken, Breaks, Printer};
|
||||
use std::borrow::Cow;
|
||||
|
||||
impl Printer {
|
||||
pub fn ibox(&mut self, indent: isize) {
|
||||
self.scan_begin(BeginToken {
|
||||
offset: indent,
|
||||
breaks: Breaks::Inconsistent,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn cbox(&mut self, indent: isize) {
|
||||
self.scan_begin(BeginToken {
|
||||
offset: indent,
|
||||
breaks: Breaks::Consistent,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn end(&mut self) {
|
||||
self.scan_end();
|
||||
}
|
||||
|
||||
pub fn word<S: Into<Cow<'static, str>>>(&mut self, wrd: S) {
|
||||
let s = wrd.into();
|
||||
self.scan_string(s);
|
||||
}
|
||||
|
||||
fn spaces(&mut self, n: usize) {
|
||||
self.scan_break(BreakToken {
|
||||
blank_space: n,
|
||||
..BreakToken::default()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn zerobreak(&mut self) {
|
||||
self.spaces(0);
|
||||
}
|
||||
|
||||
pub fn space(&mut self) {
|
||||
self.spaces(1);
|
||||
}
|
||||
|
||||
pub fn nbsp(&mut self) {
|
||||
self.word(" ");
|
||||
}
|
||||
|
||||
pub fn hardbreak(&mut self) {
|
||||
self.spaces(algorithm::SIZE_INFINITY as usize);
|
||||
}
|
||||
|
||||
pub fn space_if_nonempty(&mut self) {
|
||||
self.scan_break(BreakToken {
|
||||
blank_space: 1,
|
||||
if_nonempty: true,
|
||||
..BreakToken::default()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn hardbreak_if_nonempty(&mut self) {
|
||||
self.scan_break(BreakToken {
|
||||
blank_space: algorithm::SIZE_INFINITY as usize,
|
||||
if_nonempty: true,
|
||||
..BreakToken::default()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn trailing_comma(&mut self, is_last: bool) {
|
||||
if is_last {
|
||||
self.scan_break(BreakToken {
|
||||
pre_break: Some(','),
|
||||
..BreakToken::default()
|
||||
});
|
||||
} else {
|
||||
self.word(",");
|
||||
self.space();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trailing_comma_or_space(&mut self, is_last: bool) {
|
||||
if is_last {
|
||||
self.scan_break(BreakToken {
|
||||
blank_space: 1,
|
||||
pre_break: Some(','),
|
||||
..BreakToken::default()
|
||||
});
|
||||
} else {
|
||||
self.word(",");
|
||||
self.space();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn neverbreak(&mut self) {
|
||||
self.scan_break(BreakToken {
|
||||
never_break: true,
|
||||
..BreakToken::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
78
third-party/vendor/prettyplease/src/data.rs
vendored
Normal file
78
third-party/vendor/prettyplease/src/data.rs
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::iter::IterDelimited;
|
||||
use crate::path::PathKind;
|
||||
use crate::INDENT;
|
||||
use syn::{Field, Fields, FieldsUnnamed, Variant, VisRestricted, Visibility};
|
||||
|
||||
impl Printer {
|
||||
pub fn variant(&mut self, variant: &Variant) {
|
||||
self.outer_attrs(&variant.attrs);
|
||||
self.ident(&variant.ident);
|
||||
match &variant.fields {
|
||||
Fields::Named(fields) => {
|
||||
self.nbsp();
|
||||
self.word("{");
|
||||
self.cbox(INDENT);
|
||||
self.space();
|
||||
for field in fields.named.iter().delimited() {
|
||||
self.field(&field);
|
||||
self.trailing_comma_or_space(field.is_last);
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("}");
|
||||
}
|
||||
Fields::Unnamed(fields) => {
|
||||
self.cbox(INDENT);
|
||||
self.fields_unnamed(fields);
|
||||
self.end();
|
||||
}
|
||||
Fields::Unit => {}
|
||||
}
|
||||
if let Some((_eq_token, discriminant)) = &variant.discriminant {
|
||||
self.word(" = ");
|
||||
self.expr(discriminant);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fields_unnamed(&mut self, fields: &FieldsUnnamed) {
|
||||
self.word("(");
|
||||
self.zerobreak();
|
||||
for field in fields.unnamed.iter().delimited() {
|
||||
self.field(&field);
|
||||
self.trailing_comma(field.is_last);
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.word(")");
|
||||
}
|
||||
|
||||
pub fn field(&mut self, field: &Field) {
|
||||
self.outer_attrs(&field.attrs);
|
||||
self.visibility(&field.vis);
|
||||
if let Some(ident) = &field.ident {
|
||||
self.ident(ident);
|
||||
self.word(": ");
|
||||
}
|
||||
self.ty(&field.ty);
|
||||
}
|
||||
|
||||
pub fn visibility(&mut self, vis: &Visibility) {
|
||||
match vis {
|
||||
Visibility::Public(_) => self.word("pub "),
|
||||
Visibility::Restricted(vis) => self.vis_restricted(vis),
|
||||
Visibility::Inherited => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn vis_restricted(&mut self, vis: &VisRestricted) {
|
||||
self.word("pub(");
|
||||
let omit_in = vis.path.get_ident().map_or(false, |ident| {
|
||||
matches!(ident.to_string().as_str(), "self" | "super" | "crate")
|
||||
});
|
||||
if !omit_in {
|
||||
self.word("in ");
|
||||
}
|
||||
self.path(&vis.path, PathKind::Simple);
|
||||
self.word(") ");
|
||||
}
|
||||
}
|
||||
1276
third-party/vendor/prettyplease/src/expr.rs
vendored
Normal file
1276
third-party/vendor/prettyplease/src/expr.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
17
third-party/vendor/prettyplease/src/file.rs
vendored
Normal file
17
third-party/vendor/prettyplease/src/file.rs
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use crate::algorithm::Printer;
|
||||
use syn::File;
|
||||
|
||||
impl Printer {
|
||||
pub fn file(&mut self, file: &File) {
|
||||
self.cbox(0);
|
||||
if let Some(shebang) = &file.shebang {
|
||||
self.word(shebang.clone());
|
||||
self.hardbreak();
|
||||
}
|
||||
self.inner_attrs(&file.attrs);
|
||||
for item in &file.items {
|
||||
self.item(item);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
}
|
||||
337
third-party/vendor/prettyplease/src/generics.rs
vendored
Normal file
337
third-party/vendor/prettyplease/src/generics.rs
vendored
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::iter::IterDelimited;
|
||||
use crate::path::PathKind;
|
||||
use crate::INDENT;
|
||||
use proc_macro2::TokenStream;
|
||||
use std::ptr;
|
||||
use syn::{
|
||||
BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
|
||||
PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
|
||||
WherePredicate,
|
||||
};
|
||||
|
||||
impl Printer {
|
||||
pub fn generics(&mut self, generics: &Generics) {
|
||||
if generics.params.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.word("<");
|
||||
self.cbox(0);
|
||||
self.zerobreak();
|
||||
|
||||
// Print lifetimes before types and consts, regardless of their
|
||||
// order in self.params.
|
||||
#[derive(Ord, PartialOrd, Eq, PartialEq)]
|
||||
enum Group {
|
||||
First,
|
||||
Second,
|
||||
}
|
||||
fn group(param: &GenericParam) -> Group {
|
||||
match param {
|
||||
GenericParam::Lifetime(_) => Group::First,
|
||||
GenericParam::Type(_) | GenericParam::Const(_) => Group::Second,
|
||||
}
|
||||
}
|
||||
let last = generics.params.iter().max_by_key(|param| group(param));
|
||||
for current_group in [Group::First, Group::Second] {
|
||||
for param in &generics.params {
|
||||
if group(param) == current_group {
|
||||
self.generic_param(param);
|
||||
self.trailing_comma(ptr::eq(param, last.unwrap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(">");
|
||||
}
|
||||
|
||||
fn generic_param(&mut self, generic_param: &GenericParam) {
|
||||
match generic_param {
|
||||
GenericParam::Type(type_param) => self.type_param(type_param),
|
||||
GenericParam::Lifetime(lifetime_param) => self.lifetime_param(lifetime_param),
|
||||
GenericParam::Const(const_param) => self.const_param(const_param),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bound_lifetimes(&mut self, bound_lifetimes: &BoundLifetimes) {
|
||||
self.word("for<");
|
||||
for param in bound_lifetimes.lifetimes.iter().delimited() {
|
||||
self.generic_param(¶m);
|
||||
if !param.is_last {
|
||||
self.word(", ");
|
||||
}
|
||||
}
|
||||
self.word("> ");
|
||||
}
|
||||
|
||||
fn lifetime_param(&mut self, lifetime_param: &LifetimeParam) {
|
||||
self.outer_attrs(&lifetime_param.attrs);
|
||||
self.lifetime(&lifetime_param.lifetime);
|
||||
for lifetime in lifetime_param.bounds.iter().delimited() {
|
||||
if lifetime.is_first {
|
||||
self.word(": ");
|
||||
} else {
|
||||
self.word(" + ");
|
||||
}
|
||||
self.lifetime(&lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
fn type_param(&mut self, type_param: &TypeParam) {
|
||||
self.outer_attrs(&type_param.attrs);
|
||||
self.ident(&type_param.ident);
|
||||
self.ibox(INDENT);
|
||||
for type_param_bound in type_param.bounds.iter().delimited() {
|
||||
if type_param_bound.is_first {
|
||||
self.word(": ");
|
||||
} else {
|
||||
self.space();
|
||||
self.word("+ ");
|
||||
}
|
||||
self.type_param_bound(&type_param_bound);
|
||||
}
|
||||
if let Some(default) = &type_param.default {
|
||||
self.space();
|
||||
self.word("= ");
|
||||
self.ty(default);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
pub fn type_param_bound(&mut self, type_param_bound: &TypeParamBound) {
|
||||
match type_param_bound {
|
||||
TypeParamBound::Trait(trait_bound) => {
|
||||
let tilde_const = false;
|
||||
self.trait_bound(trait_bound, tilde_const);
|
||||
}
|
||||
TypeParamBound::Lifetime(lifetime) => self.lifetime(lifetime),
|
||||
TypeParamBound::Verbatim(bound) => self.type_param_bound_verbatim(bound),
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => unimplemented!("unknown TypeParamBound"),
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_bound(&mut self, trait_bound: &TraitBound, tilde_const: bool) {
|
||||
if trait_bound.paren_token.is_some() {
|
||||
self.word("(");
|
||||
}
|
||||
if tilde_const {
|
||||
self.word("~const ");
|
||||
}
|
||||
self.trait_bound_modifier(&trait_bound.modifier);
|
||||
if let Some(bound_lifetimes) = &trait_bound.lifetimes {
|
||||
self.bound_lifetimes(bound_lifetimes);
|
||||
}
|
||||
for segment in trait_bound.path.segments.iter().delimited() {
|
||||
if !segment.is_first || trait_bound.path.leading_colon.is_some() {
|
||||
self.word("::");
|
||||
}
|
||||
self.path_segment(&segment, PathKind::Type);
|
||||
}
|
||||
if trait_bound.paren_token.is_some() {
|
||||
self.word(")");
|
||||
}
|
||||
}
|
||||
|
||||
fn trait_bound_modifier(&mut self, trait_bound_modifier: &TraitBoundModifier) {
|
||||
match trait_bound_modifier {
|
||||
TraitBoundModifier::None => {}
|
||||
TraitBoundModifier::Maybe(_question_mark) => self.word("?"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "verbatim"))]
|
||||
fn type_param_bound_verbatim(&mut self, bound: &TokenStream) {
|
||||
unimplemented!("TypeParamBound::Verbatim `{}`", bound);
|
||||
}
|
||||
|
||||
#[cfg(feature = "verbatim")]
|
||||
fn type_param_bound_verbatim(&mut self, tokens: &TokenStream) {
|
||||
use syn::parse::{Parse, ParseStream, Result};
|
||||
use syn::{parenthesized, token, Token};
|
||||
|
||||
enum TypeParamBoundVerbatim {
|
||||
Ellipsis,
|
||||
TildeConst(TraitBound),
|
||||
}
|
||||
|
||||
impl Parse for TypeParamBoundVerbatim {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let content;
|
||||
let (paren_token, content) = if input.peek(token::Paren) {
|
||||
(Some(parenthesized!(content in input)), &content)
|
||||
} else {
|
||||
(None, input)
|
||||
};
|
||||
let lookahead = content.lookahead1();
|
||||
if lookahead.peek(Token![~]) {
|
||||
content.parse::<Token![~]>()?;
|
||||
content.parse::<Token![const]>()?;
|
||||
let mut bound: TraitBound = content.parse()?;
|
||||
bound.paren_token = paren_token;
|
||||
Ok(TypeParamBoundVerbatim::TildeConst(bound))
|
||||
} else if lookahead.peek(Token![...]) {
|
||||
content.parse::<Token![...]>()?;
|
||||
Ok(TypeParamBoundVerbatim::Ellipsis)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let bound: TypeParamBoundVerbatim = match syn::parse2(tokens.clone()) {
|
||||
Ok(bound) => bound,
|
||||
Err(_) => unimplemented!("TypeParamBound::Verbatim `{}`", tokens),
|
||||
};
|
||||
|
||||
match bound {
|
||||
TypeParamBoundVerbatim::Ellipsis => {
|
||||
self.word("...");
|
||||
}
|
||||
TypeParamBoundVerbatim::TildeConst(trait_bound) => {
|
||||
let tilde_const = true;
|
||||
self.trait_bound(&trait_bound, tilde_const);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn const_param(&mut self, const_param: &ConstParam) {
|
||||
self.outer_attrs(&const_param.attrs);
|
||||
self.word("const ");
|
||||
self.ident(&const_param.ident);
|
||||
self.word(": ");
|
||||
self.ty(&const_param.ty);
|
||||
if let Some(default) = &const_param.default {
|
||||
self.word(" = ");
|
||||
self.expr(default);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn where_clause_for_body(&mut self, where_clause: &Option<WhereClause>) {
|
||||
let hardbreaks = true;
|
||||
let semi = false;
|
||||
self.where_clause_impl(where_clause, hardbreaks, semi);
|
||||
}
|
||||
|
||||
pub fn where_clause_semi(&mut self, where_clause: &Option<WhereClause>) {
|
||||
let hardbreaks = true;
|
||||
let semi = true;
|
||||
self.where_clause_impl(where_clause, hardbreaks, semi);
|
||||
}
|
||||
|
||||
pub fn where_clause_oneline(&mut self, where_clause: &Option<WhereClause>) {
|
||||
let hardbreaks = false;
|
||||
let semi = false;
|
||||
self.where_clause_impl(where_clause, hardbreaks, semi);
|
||||
}
|
||||
|
||||
pub fn where_clause_oneline_semi(&mut self, where_clause: &Option<WhereClause>) {
|
||||
let hardbreaks = false;
|
||||
let semi = true;
|
||||
self.where_clause_impl(where_clause, hardbreaks, semi);
|
||||
}
|
||||
|
||||
fn where_clause_impl(
|
||||
&mut self,
|
||||
where_clause: &Option<WhereClause>,
|
||||
hardbreaks: bool,
|
||||
semi: bool,
|
||||
) {
|
||||
let where_clause = match where_clause {
|
||||
Some(where_clause) if !where_clause.predicates.is_empty() => where_clause,
|
||||
_ => {
|
||||
if semi {
|
||||
self.word(";");
|
||||
} else {
|
||||
self.nbsp();
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
if hardbreaks {
|
||||
self.hardbreak();
|
||||
self.offset(-INDENT);
|
||||
self.word("where");
|
||||
self.hardbreak();
|
||||
for predicate in where_clause.predicates.iter().delimited() {
|
||||
self.where_predicate(&predicate);
|
||||
if predicate.is_last && semi {
|
||||
self.word(";");
|
||||
} else {
|
||||
self.word(",");
|
||||
self.hardbreak();
|
||||
}
|
||||
}
|
||||
if !semi {
|
||||
self.offset(-INDENT);
|
||||
}
|
||||
} else {
|
||||
self.space();
|
||||
self.offset(-INDENT);
|
||||
self.word("where");
|
||||
self.space();
|
||||
for predicate in where_clause.predicates.iter().delimited() {
|
||||
self.where_predicate(&predicate);
|
||||
if predicate.is_last && semi {
|
||||
self.word(";");
|
||||
} else {
|
||||
self.trailing_comma_or_space(predicate.is_last);
|
||||
}
|
||||
}
|
||||
if !semi {
|
||||
self.offset(-INDENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn where_predicate(&mut self, predicate: &WherePredicate) {
|
||||
match predicate {
|
||||
WherePredicate::Type(predicate) => self.predicate_type(predicate),
|
||||
WherePredicate::Lifetime(predicate) => self.predicate_lifetime(predicate),
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => unimplemented!("unknown WherePredicate"),
|
||||
}
|
||||
}
|
||||
|
||||
fn predicate_type(&mut self, predicate: &PredicateType) {
|
||||
if let Some(bound_lifetimes) = &predicate.lifetimes {
|
||||
self.bound_lifetimes(bound_lifetimes);
|
||||
}
|
||||
self.ty(&predicate.bounded_ty);
|
||||
self.word(":");
|
||||
if predicate.bounds.len() == 1 {
|
||||
self.ibox(0);
|
||||
} else {
|
||||
self.ibox(INDENT);
|
||||
}
|
||||
for type_param_bound in predicate.bounds.iter().delimited() {
|
||||
if type_param_bound.is_first {
|
||||
self.nbsp();
|
||||
} else {
|
||||
self.space();
|
||||
self.word("+ ");
|
||||
}
|
||||
self.type_param_bound(&type_param_bound);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
fn predicate_lifetime(&mut self, predicate: &PredicateLifetime) {
|
||||
self.lifetime(&predicate.lifetime);
|
||||
self.word(":");
|
||||
self.ibox(INDENT);
|
||||
for lifetime in predicate.bounds.iter().delimited() {
|
||||
if lifetime.is_first {
|
||||
self.nbsp();
|
||||
} else {
|
||||
self.space();
|
||||
self.word("+ ");
|
||||
}
|
||||
self.lifetime(&lifetime);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
}
|
||||
1707
third-party/vendor/prettyplease/src/item.rs
vendored
Normal file
1707
third-party/vendor/prettyplease/src/item.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
46
third-party/vendor/prettyplease/src/iter.rs
vendored
Normal file
46
third-party/vendor/prettyplease/src/iter.rs
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
use std::iter::Peekable;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub struct Delimited<I: Iterator> {
|
||||
is_first: bool,
|
||||
iter: Peekable<I>,
|
||||
}
|
||||
|
||||
pub trait IterDelimited: Iterator + Sized {
|
||||
fn delimited(self) -> Delimited<Self> {
|
||||
Delimited {
|
||||
is_first: true,
|
||||
iter: self.peekable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Iterator> IterDelimited for I {}
|
||||
|
||||
pub struct IteratorItem<T> {
|
||||
value: T,
|
||||
pub is_first: bool,
|
||||
pub is_last: bool,
|
||||
}
|
||||
|
||||
impl<I: Iterator> Iterator for Delimited<I> {
|
||||
type Item = IteratorItem<I::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let item = IteratorItem {
|
||||
value: self.iter.next()?,
|
||||
is_first: self.is_first,
|
||||
is_last: self.iter.peek().is_none(),
|
||||
};
|
||||
self.is_first = false;
|
||||
Some(item)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for IteratorItem<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
379
third-party/vendor/prettyplease/src/lib.rs
vendored
Normal file
379
third-party/vendor/prettyplease/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
//! [![github]](https://github.com/dtolnay/prettyplease) [![crates-io]](https://crates.io/crates/prettyplease) [![docs-rs]](https://docs.rs/prettyplease)
|
||||
//!
|
||||
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
|
||||
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
|
||||
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! **prettyplease::unparse** — a minimal `syn` syntax tree pretty-printer
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Overview
|
||||
//!
|
||||
//! This is a pretty-printer to turn a `syn` syntax tree into a `String` of
|
||||
//! well-formatted source code. In contrast to rustfmt, this library is intended
|
||||
//! to be suitable for arbitrary generated code.
|
||||
//!
|
||||
//! Rustfmt prioritizes high-quality output that is impeccable enough that you'd
|
||||
//! be comfortable spending your career staring at its output — but that
|
||||
//! means some heavyweight algorithms, and it has a tendency to bail out on code
|
||||
//! that is hard to format (for example [rustfmt#3697], and there are dozens
|
||||
//! more issues like it). That's not necessarily a big deal for human-generated
|
||||
//! code because when code gets highly nested, the human will naturally be
|
||||
//! inclined to refactor into more easily formattable code. But for generated
|
||||
//! code, having the formatter just give up leaves it totally unreadable.
|
||||
//!
|
||||
//! [rustfmt#3697]: https://github.com/rust-lang/rustfmt/issues/3697
|
||||
//!
|
||||
//! This library is designed using the simplest possible algorithm and data
|
||||
//! structures that can deliver about 95% of the quality of rustfmt-formatted
|
||||
//! output. In my experience testing real-world code, approximately 97-98% of
|
||||
//! output lines come out identical between rustfmt's formatting and this
|
||||
//! crate's. The rest have slightly different linebreak decisions, but still
|
||||
//! clearly follow the dominant modern Rust style.
|
||||
//!
|
||||
//! The tradeoffs made by this crate are a good fit for generated code that you
|
||||
//! will *not* spend your career staring at. For example, the output of
|
||||
//! `bindgen`, or the output of `cargo-expand`. In those cases it's more
|
||||
//! important that the whole thing be formattable without the formatter giving
|
||||
//! up, than that it be flawless.
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Feature matrix
|
||||
//!
|
||||
//! Here are a few superficial comparisons of this crate against the AST
|
||||
//! pretty-printer built into rustc, and rustfmt. The sections below go into
|
||||
//! more detail comparing the output of each of these libraries.
|
||||
//!
|
||||
//! | | prettyplease | rustc | rustfmt |
|
||||
//! |:---|:---:|:---:|:---:|
|
||||
//! | non-pathological behavior on big or generated code | 💚 | ❌ | ❌ |
|
||||
//! | idiomatic modern formatting ("locally indistinguishable from rustfmt") | 💚 | ❌ | 💚 |
|
||||
//! | throughput | 60 MB/s | 39 MB/s | 2.8 MB/s |
|
||||
//! | number of dependencies | 3 | 72 | 66 |
|
||||
//! | compile time including dependencies | 2.4 sec | 23.1 sec | 29.8 sec |
|
||||
//! | buildable using a stable Rust compiler | 💚 | ❌ | ❌ |
|
||||
//! | published to crates.io | 💚 | ❌ | ❌ |
|
||||
//! | extensively configurable output | ❌ | ❌ | 💚 |
|
||||
//! | intended to accommodate hand-maintained source code | ❌ | ❌ | 💚 |
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Comparison to rustfmt
|
||||
//!
|
||||
//! - [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
|
||||
//! - [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
|
||||
//! - [output.rustfmt.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustfmt.rs)
|
||||
//!
|
||||
//! If you weren't told which output file is which, it would be practically
|
||||
//! impossible to tell — **except** for line 435 in the rustfmt output,
|
||||
//! which is more than 1000 characters long because rustfmt just gave up
|
||||
//! formatting that part of the file:
|
||||
//!
|
||||
//! ```
|
||||
//! # const _: &str = stringify! {{{
|
||||
//! match segments[5] {
|
||||
//! 0 => write!(f, "::{}", ipv4),
|
||||
//! 0xffff => write!(f, "::ffff:{}", ipv4),
|
||||
//! _ => unreachable!(),
|
||||
//! }
|
||||
//! } else { # [derive (Copy , Clone , Default)] struct Span { start : usize , len : usize , } let zeroes = { let mut longest = Span :: default () ; let mut current = Span :: default () ; for (i , & segment) in segments . iter () . enumerate () { if segment == 0 { if current . len == 0 { current . start = i ; } current . len += 1 ; if current . len > longest . len { longest = current ; } } else { current = Span :: default () ; } } longest } ; # [doc = " Write a colon-separated part of the address"] # [inline] fn fmt_subslice (f : & mut fmt :: Formatter < '_ > , chunk : & [u16]) -> fmt :: Result { if let Some ((first , tail)) = chunk . split_first () { write ! (f , "{:x}" , first) ? ; for segment in tail { f . write_char (':') ? ; write ! (f , "{:x}" , segment) ? ; } } Ok (()) } if zeroes . len > 1 { fmt_subslice (f , & segments [.. zeroes . start]) ? ; f . write_str ("::") ? ; fmt_subslice (f , & segments [zeroes . start + zeroes . len ..]) } else { fmt_subslice (f , & segments) } }
|
||||
//! } else {
|
||||
//! const IPV6_BUF_LEN: usize = (4 * 8) + 7;
|
||||
//! let mut buf = [0u8; IPV6_BUF_LEN];
|
||||
//! let mut buf_slice = &mut buf[..];
|
||||
//! # }};
|
||||
//! ```
|
||||
//!
|
||||
//! This is a pretty typical manifestation of rustfmt bailing out in generated
|
||||
//! code — a chunk of the input ends up on one line. The other
|
||||
//! manifestation is that you're working on some code, running rustfmt on save
|
||||
//! like a conscientious developer, but after a while notice it isn't doing
|
||||
//! anything. You introduce an intentional formatting issue, like a stray indent
|
||||
//! or semicolon, and run rustfmt to check your suspicion. Nope, it doesn't get
|
||||
//! cleaned up — rustfmt is just not formatting the part of the file you
|
||||
//! are working on.
|
||||
//!
|
||||
//! The prettyplease library is designed to have no pathological cases that
|
||||
//! force a bail out; the entire input you give it will get formatted in some
|
||||
//! "good enough" form.
|
||||
//!
|
||||
//! Separately, rustfmt can be problematic to integrate into projects. It's
|
||||
//! written using rustc's internal syntax tree, so it can't be built by a stable
|
||||
//! compiler. Its releases are not regularly published to crates.io, so in Cargo
|
||||
//! builds you'd need to depend on it as a git dependency, which precludes
|
||||
//! publishing your crate to crates.io also. You can shell out to a `rustfmt`
|
||||
//! binary, but that'll be whatever rustfmt version is installed on each
|
||||
//! developer's system (if any), which can lead to spurious diffs in checked-in
|
||||
//! generated code formatted by different versions. In contrast prettyplease is
|
||||
//! designed to be easy to pull in as a library, and compiles fast.
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Comparison to rustc_ast_pretty
|
||||
//!
|
||||
//! - [input.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/input.rs)
|
||||
//! - [output.prettyplease.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.prettyplease.rs)
|
||||
//! - [output.rustc.rs](https://github.com/dtolnay/prettyplease/blob/0.1.0/examples/output.rustc.rs)
|
||||
//!
|
||||
//! This is the pretty-printer that gets used when rustc prints source code,
|
||||
//! such as `rustc -Zunpretty=expanded`. It's used also by the standard
|
||||
//! library's `stringify!` when stringifying an interpolated macro_rules AST
|
||||
//! fragment, like an $:expr, and transitively by `dbg!` and many macros in the
|
||||
//! ecosystem.
|
||||
//!
|
||||
//! Rustc's formatting is mostly okay, but does not hew closely to the dominant
|
||||
//! contemporary style of Rust formatting. Some things wouldn't ever be written
|
||||
//! on one line, like this `match` expression, and certainly not with a comma in
|
||||
//! front of the closing brace:
|
||||
//!
|
||||
//! ```
|
||||
//! # const _: &str = stringify! {
|
||||
//! fn eq(&self, other: &IpAddr) -> bool {
|
||||
//! match other { IpAddr::V4(v4) => self == v4, IpAddr::V6(_) => false, }
|
||||
//! }
|
||||
//! # };
|
||||
//! ```
|
||||
//!
|
||||
//! Some places use non-multiple-of-4 indentation, which is definitely not the
|
||||
//! norm:
|
||||
//!
|
||||
//! ```
|
||||
//! # const _: &str = stringify! {
|
||||
//! pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
|
||||
//! let [a, b, c, d] = self.octets();
|
||||
//! Ipv6Addr{inner:
|
||||
//! c::in6_addr{s6_addr:
|
||||
//! [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF,
|
||||
//! 0xFF, a, b, c, d],},}
|
||||
//! }
|
||||
//! # };
|
||||
//! ```
|
||||
//!
|
||||
//! And although there isn't an egregious example of it in the link because the
|
||||
//! input code is pretty tame, in general rustc_ast_pretty has pathological
|
||||
//! behavior on generated code. It has a tendency to use excessive horizontal
|
||||
//! indentation and rapidly run out of width:
|
||||
//!
|
||||
//! ```
|
||||
//! # const _: &str = stringify! {
|
||||
//! ::std::io::_print(::core::fmt::Arguments::new_v1(&[""],
|
||||
//! &match (&msg,) {
|
||||
//! _args =>
|
||||
//! [::core::fmt::ArgumentV1::new(_args.0,
|
||||
//! ::core::fmt::Display::fmt)],
|
||||
//! }));
|
||||
//! # };
|
||||
//! ```
|
||||
//!
|
||||
//! The snippets above are clearly different from modern rustfmt style. In
|
||||
//! contrast, prettyplease is designed to have output that is practically
|
||||
//! indistinguishable from rustfmt-formatted code.
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
//! // [dependencies]
|
||||
//! // prettyplease = "0.2"
|
||||
//! // syn = { version = "2", default-features = false, features = ["full", "parsing"] }
|
||||
//!
|
||||
//! const INPUT: &str = stringify! {
|
||||
//! use crate::{
|
||||
//! lazy::{Lazy, SyncLazy, SyncOnceCell}, panic,
|
||||
//! sync::{ atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
//! mpsc::channel, Mutex, },
|
||||
//! thread,
|
||||
//! };
|
||||
//! impl<T, U> Into<U> for T where U: From<T> {
|
||||
//! fn into(self) -> U { U::from(self) }
|
||||
//! }
|
||||
//! };
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let syntax_tree = syn::parse_file(INPUT).unwrap();
|
||||
//! let formatted = prettyplease::unparse(&syntax_tree);
|
||||
//! print!("{}", formatted);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! <br>
|
||||
//!
|
||||
//! # Algorithm notes
|
||||
//!
|
||||
//! The approach and terminology used in the implementation are derived from
|
||||
//! [*Derek C. Oppen, "Pretty Printing" (1979)*][paper], on which
|
||||
//! rustc_ast_pretty is also based, and from rustc_ast_pretty's implementation
|
||||
//! written by Graydon Hoare in 2011 (and modernized over the years by dozens of
|
||||
//! volunteer maintainers).
|
||||
//!
|
||||
//! [paper]: http://i.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf
|
||||
//!
|
||||
//! The paper describes two language-agnostic interacting procedures `Scan()`
|
||||
//! and `Print()`. Language-specific code decomposes an input data structure
|
||||
//! into a stream of `string` and `break` tokens, and `begin` and `end` tokens
|
||||
//! for grouping. Each `begin`–`end` range may be identified as either
|
||||
//! "consistent breaking" or "inconsistent breaking". If a group is consistently
|
||||
//! breaking, then if the whole contents do not fit on the line, *every* `break`
|
||||
//! token in the group will receive a linebreak. This is appropriate, for
|
||||
//! example, for Rust struct literals, or arguments of a function call. If a
|
||||
//! group is inconsistently breaking, then the `string` tokens in the group are
|
||||
//! greedily placed on the line until out of space, and linebroken only at those
|
||||
//! `break` tokens for which the next string would not fit. For example, this is
|
||||
//! appropriate for the contents of a braced `use` statement in Rust.
|
||||
//!
|
||||
//! Scan's job is to efficiently accumulate sizing information about groups and
|
||||
//! breaks. For every `begin` token we compute the distance to the matched `end`
|
||||
//! token, and for every `break` we compute the distance to the next `break`.
|
||||
//! The algorithm uses a ringbuffer to hold tokens whose size is not yet
|
||||
//! ascertained. The maximum size of the ringbuffer is bounded by the target
|
||||
//! line length and does not grow indefinitely, regardless of deep nesting in
|
||||
//! the input stream. That's because once a group is sufficiently big, the
|
||||
//! precise size can no longer make a difference to linebreak decisions and we
|
||||
//! can effectively treat it as "infinity".
|
||||
//!
|
||||
//! Print's job is to use the sizing information to efficiently assign a
|
||||
//! "broken" or "not broken" status to every `begin` token. At that point the
|
||||
//! output is easily constructed by concatenating `string` tokens and breaking
|
||||
//! at `break` tokens contained within a broken group.
|
||||
//!
|
||||
//! Leveraging these primitives (i.e. cleverly placing the all-or-nothing
|
||||
//! consistent breaks and greedy inconsistent breaks) to yield
|
||||
//! rustfmt-compatible formatting for all of Rust's syntax tree nodes is a fun
|
||||
//! challenge.
|
||||
//!
|
||||
//! Here is a visualization of some Rust tokens fed into the pretty printing
|
||||
//! algorithm. Consistently breaking `begin`—`end` pairs are represented
|
||||
//! by `«`⁠`»`, inconsistently breaking by `‹`⁠`›`, `break` by `·`,
|
||||
//! and the rest of the non-whitespace are `string`.
|
||||
//!
|
||||
//! ```text
|
||||
//! use crate::«{·
|
||||
//! ‹ lazy::«{·‹Lazy,· SyncLazy,· SyncOnceCell›·}»,·
|
||||
//! panic,·
|
||||
//! sync::«{·
|
||||
//! ‹ atomic::«{·‹AtomicUsize,· Ordering::SeqCst›·}»,·
|
||||
//! mpsc::channel,· Mutex›,·
|
||||
//! }»,·
|
||||
//! thread›,·
|
||||
//! }»;·
|
||||
//! «‹«impl<«·T‹›,· U‹›·»>» Into<«·U·»>· for T›·
|
||||
//! where·
|
||||
//! U:‹ From<«·T·»>›,·
|
||||
//! {·
|
||||
//! « fn into(·«·self·») -> U {·
|
||||
//! ‹ U::from(«·self·»)›·
|
||||
//! » }·
|
||||
//! »}·
|
||||
//! ```
|
||||
//!
|
||||
//! The algorithm described in the paper is not quite sufficient for producing
|
||||
//! well-formatted Rust code that is locally indistinguishable from rustfmt's
|
||||
//! style. The reason is that in the paper, the complete non-whitespace contents
|
||||
//! are assumed to be independent of linebreak decisions, with Scan and Print
|
||||
//! being only in control of the whitespace (spaces and line breaks). In Rust as
|
||||
//! idiomatically formattted by rustfmt, that is not the case. Trailing commas
|
||||
//! are one example; the punctuation is only known *after* the broken vs
|
||||
//! non-broken status of the surrounding group is known:
|
||||
//!
|
||||
//! ```
|
||||
//! # struct Struct { x: u64, y: bool }
|
||||
//! # let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = 0;
|
||||
//! # let yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy = true;
|
||||
//! #
|
||||
//! let _ = Struct { x: 0, y: true };
|
||||
//!
|
||||
//! let _ = Struct {
|
||||
//! x: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
|
||||
//! y: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, //<- trailing comma if the expression wrapped
|
||||
//! };
|
||||
//! ```
|
||||
//!
|
||||
//! The formatting of `match` expressions is another case; we want small arms on
|
||||
//! the same line as the pattern, and big arms wrapped in a brace. The presence
|
||||
//! of the brace punctuation, comma, and semicolon are all dependent on whether
|
||||
//! the arm fits on the line:
|
||||
//!
|
||||
//! ```
|
||||
//! # struct Entry { nanos: u32 }
|
||||
//! # let total_nanos = 0u64;
|
||||
//! # let mut total_secs = 0u64;
|
||||
//! # let tmp;
|
||||
//! # let entry = Entry { nanos: 0 };
|
||||
//! # const NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||
//! #
|
||||
//! match total_nanos.checked_add(entry.nanos as u64) {
|
||||
//! Some(n) => tmp = n, //<- small arm, inline with comma
|
||||
//! None => {
|
||||
//! total_secs = total_secs
|
||||
//! .checked_add(total_nanos / NANOS_PER_SEC as u64)
|
||||
//! .expect("overflow in iter::sum over durations");
|
||||
//! } //<- big arm, needs brace added, and also semicolon^
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The printing algorithm implementation in this crate accommodates all of
|
||||
//! these situations with conditional punctuation tokens whose selection can be
|
||||
//! deferred and populated after it's known that the group is or is not broken.
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/prettyplease/0.2.16")]
|
||||
#![allow(
|
||||
clippy::cast_possible_wrap,
|
||||
clippy::cast_sign_loss,
|
||||
clippy::derive_partial_eq_without_eq,
|
||||
clippy::doc_markdown,
|
||||
clippy::enum_glob_use,
|
||||
clippy::items_after_statements,
|
||||
clippy::let_underscore_untyped,
|
||||
clippy::match_like_matches_macro,
|
||||
clippy::match_same_arms,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::similar_names,
|
||||
clippy::too_many_lines,
|
||||
clippy::unused_self,
|
||||
clippy::vec_init_then_push
|
||||
)]
|
||||
#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
|
||||
|
||||
mod algorithm;
|
||||
mod attr;
|
||||
mod convenience;
|
||||
mod data;
|
||||
mod expr;
|
||||
mod file;
|
||||
mod generics;
|
||||
mod item;
|
||||
mod iter;
|
||||
mod lifetime;
|
||||
mod lit;
|
||||
mod mac;
|
||||
mod pat;
|
||||
mod path;
|
||||
mod ring;
|
||||
mod stmt;
|
||||
mod token;
|
||||
mod ty;
|
||||
|
||||
use crate::algorithm::Printer;
|
||||
use syn::File;
|
||||
|
||||
// Target line width.
|
||||
const MARGIN: isize = 89;
|
||||
|
||||
// Number of spaces increment at each level of block indentation.
|
||||
const INDENT: isize = 4;
|
||||
|
||||
// Every line is allowed at least this much space, even if highly indented.
|
||||
const MIN_SPACE: isize = 60;
|
||||
|
||||
pub fn unparse(file: &File) -> String {
|
||||
let mut p = Printer::new();
|
||||
p.file(file);
|
||||
p.eof()
|
||||
}
|
||||
9
third-party/vendor/prettyplease/src/lifetime.rs
vendored
Normal file
9
third-party/vendor/prettyplease/src/lifetime.rs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
use crate::algorithm::Printer;
|
||||
use syn::Lifetime;
|
||||
|
||||
impl Printer {
|
||||
pub fn lifetime(&mut self, lifetime: &Lifetime) {
|
||||
self.word("'");
|
||||
self.ident(&lifetime.ident);
|
||||
}
|
||||
}
|
||||
52
third-party/vendor/prettyplease/src/lit.rs
vendored
Normal file
52
third-party/vendor/prettyplease/src/lit.rs
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use crate::algorithm::Printer;
|
||||
use proc_macro2::Literal;
|
||||
use syn::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
|
||||
|
||||
impl Printer {
|
||||
pub fn lit(&mut self, lit: &Lit) {
|
||||
match lit {
|
||||
Lit::Str(lit) => self.lit_str(lit),
|
||||
Lit::ByteStr(lit) => self.lit_byte_str(lit),
|
||||
Lit::Byte(lit) => self.lit_byte(lit),
|
||||
Lit::Char(lit) => self.lit_char(lit),
|
||||
Lit::Int(lit) => self.lit_int(lit),
|
||||
Lit::Float(lit) => self.lit_float(lit),
|
||||
Lit::Bool(lit) => self.lit_bool(lit),
|
||||
Lit::Verbatim(lit) => self.lit_verbatim(lit),
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => unimplemented!("unknown Lit"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lit_str(&mut self, lit: &LitStr) {
|
||||
self.word(lit.token().to_string());
|
||||
}
|
||||
|
||||
fn lit_byte_str(&mut self, lit: &LitByteStr) {
|
||||
self.word(lit.token().to_string());
|
||||
}
|
||||
|
||||
fn lit_byte(&mut self, lit: &LitByte) {
|
||||
self.word(lit.token().to_string());
|
||||
}
|
||||
|
||||
fn lit_char(&mut self, lit: &LitChar) {
|
||||
self.word(lit.token().to_string());
|
||||
}
|
||||
|
||||
fn lit_int(&mut self, lit: &LitInt) {
|
||||
self.word(lit.token().to_string());
|
||||
}
|
||||
|
||||
fn lit_float(&mut self, lit: &LitFloat) {
|
||||
self.word(lit.token().to_string());
|
||||
}
|
||||
|
||||
fn lit_bool(&mut self, lit: &LitBool) {
|
||||
self.word(if lit.value { "true" } else { "false" });
|
||||
}
|
||||
|
||||
fn lit_verbatim(&mut self, token: &Literal) {
|
||||
self.word(token.to_string());
|
||||
}
|
||||
}
|
||||
670
third-party/vendor/prettyplease/src/mac.rs
vendored
Normal file
670
third-party/vendor/prettyplease/src/mac.rs
vendored
Normal file
|
|
@ -0,0 +1,670 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::path::PathKind;
|
||||
use crate::token::Token;
|
||||
use crate::INDENT;
|
||||
use proc_macro2::{Delimiter, Spacing, TokenStream};
|
||||
use syn::{Ident, Macro, MacroDelimiter};
|
||||
|
||||
impl Printer {
|
||||
pub fn mac(&mut self, mac: &Macro, ident: Option<&Ident>, semicolon: bool) {
|
||||
if mac.path.is_ident("macro_rules") {
|
||||
if let Some(ident) = ident {
|
||||
self.macro_rules(ident, &mac.tokens);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "verbatim")]
|
||||
if ident.is_none() && self.standard_library_macro(mac, semicolon) {
|
||||
return;
|
||||
}
|
||||
self.path(&mac.path, PathKind::Simple);
|
||||
self.word("!");
|
||||
if let Some(ident) = ident {
|
||||
self.nbsp();
|
||||
self.ident(ident);
|
||||
}
|
||||
let (open, close, delimiter_break) = match mac.delimiter {
|
||||
MacroDelimiter::Paren(_) => ("(", ")", Self::zerobreak as fn(&mut Self)),
|
||||
MacroDelimiter::Brace(_) => (" {", "}", Self::hardbreak as fn(&mut Self)),
|
||||
MacroDelimiter::Bracket(_) => ("[", "]", Self::zerobreak as fn(&mut Self)),
|
||||
};
|
||||
self.word(open);
|
||||
if !mac.tokens.is_empty() {
|
||||
self.cbox(INDENT);
|
||||
delimiter_break(self);
|
||||
self.ibox(0);
|
||||
self.macro_rules_tokens(mac.tokens.clone(), false);
|
||||
self.end();
|
||||
delimiter_break(self);
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
}
|
||||
self.word(close);
|
||||
if semicolon {
|
||||
match mac.delimiter {
|
||||
MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => self.word(";"),
|
||||
MacroDelimiter::Brace(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn macro_rules(&mut self, name: &Ident, rules: &TokenStream) {
|
||||
enum State {
|
||||
Start,
|
||||
Matcher,
|
||||
Equal,
|
||||
Greater,
|
||||
Expander,
|
||||
}
|
||||
|
||||
use State::*;
|
||||
|
||||
self.word("macro_rules! ");
|
||||
self.ident(name);
|
||||
self.word(" {");
|
||||
self.cbox(INDENT);
|
||||
self.hardbreak_if_nonempty();
|
||||
let mut state = State::Start;
|
||||
for tt in rules.clone() {
|
||||
let token = Token::from(tt);
|
||||
match (state, token) {
|
||||
(Start, Token::Group(delimiter, stream)) => {
|
||||
self.delimiter_open(delimiter);
|
||||
if !stream.is_empty() {
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
self.ibox(0);
|
||||
self.macro_rules_tokens(stream, true);
|
||||
self.end();
|
||||
self.zerobreak();
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
}
|
||||
self.delimiter_close(delimiter);
|
||||
state = Matcher;
|
||||
}
|
||||
(Matcher, Token::Punct('=', Spacing::Joint)) => {
|
||||
self.word(" =");
|
||||
state = Equal;
|
||||
}
|
||||
(Equal, Token::Punct('>', Spacing::Alone)) => {
|
||||
self.word(">");
|
||||
state = Greater;
|
||||
}
|
||||
(Greater, Token::Group(_delimiter, stream)) => {
|
||||
self.word(" {");
|
||||
self.neverbreak();
|
||||
if !stream.is_empty() {
|
||||
self.cbox(INDENT);
|
||||
self.hardbreak();
|
||||
self.ibox(0);
|
||||
self.macro_rules_tokens(stream, false);
|
||||
self.end();
|
||||
self.hardbreak();
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
}
|
||||
self.word("}");
|
||||
state = Expander;
|
||||
}
|
||||
(Expander, Token::Punct(';', Spacing::Alone)) => {
|
||||
self.word(";");
|
||||
self.hardbreak();
|
||||
state = Start;
|
||||
}
|
||||
_ => unimplemented!("bad macro_rules syntax"),
|
||||
}
|
||||
}
|
||||
match state {
|
||||
Start => {}
|
||||
Expander => {
|
||||
self.word(";");
|
||||
self.hardbreak();
|
||||
}
|
||||
_ => self.hardbreak(),
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("}");
|
||||
}
|
||||
|
||||
pub fn macro_rules_tokens(&mut self, stream: TokenStream, matcher: bool) {
|
||||
#[derive(PartialEq)]
|
||||
enum State {
|
||||
Start,
|
||||
Dollar,
|
||||
DollarIdent,
|
||||
DollarIdentColon,
|
||||
DollarParen,
|
||||
DollarParenSep,
|
||||
Pound,
|
||||
PoundBang,
|
||||
Dot,
|
||||
Colon,
|
||||
Colon2,
|
||||
Ident,
|
||||
IdentBang,
|
||||
Delim,
|
||||
Other,
|
||||
}
|
||||
|
||||
use State::*;
|
||||
|
||||
let mut state = Start;
|
||||
let mut previous_is_joint = true;
|
||||
for tt in stream {
|
||||
let token = Token::from(tt);
|
||||
let (needs_space, next_state) = match (&state, &token) {
|
||||
(Dollar, Token::Ident(_)) => (false, if matcher { DollarIdent } else { Other }),
|
||||
(DollarIdent, Token::Punct(':', Spacing::Alone)) => (false, DollarIdentColon),
|
||||
(DollarIdentColon, Token::Ident(_)) => (false, Other),
|
||||
(DollarParen, Token::Punct('+' | '*' | '?', Spacing::Alone)) => (false, Other),
|
||||
(DollarParen, Token::Ident(_) | Token::Literal(_)) => (false, DollarParenSep),
|
||||
(DollarParen, Token::Punct(_, Spacing::Joint)) => (false, DollarParen),
|
||||
(DollarParen, Token::Punct(_, Spacing::Alone)) => (false, DollarParenSep),
|
||||
(DollarParenSep, Token::Punct('+' | '*', _)) => (false, Other),
|
||||
(Pound, Token::Punct('!', _)) => (false, PoundBang),
|
||||
(Dollar, Token::Group(Delimiter::Parenthesis, _)) => (false, DollarParen),
|
||||
(Pound | PoundBang, Token::Group(Delimiter::Bracket, _)) => (false, Other),
|
||||
(Ident, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => {
|
||||
(false, Delim)
|
||||
}
|
||||
(Ident, Token::Punct('!', Spacing::Alone)) => (false, IdentBang),
|
||||
(IdentBang, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => {
|
||||
(false, Other)
|
||||
}
|
||||
(Colon, Token::Punct(':', _)) => (false, Colon2),
|
||||
(_, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => (true, Delim),
|
||||
(_, Token::Group(Delimiter::Brace | Delimiter::None, _)) => (true, Other),
|
||||
(_, Token::Ident(ident)) if !is_keyword(ident) => {
|
||||
(state != Dot && state != Colon2, Ident)
|
||||
}
|
||||
(_, Token::Literal(_)) => (state != Dot, Ident),
|
||||
(_, Token::Punct(',' | ';', _)) => (false, Other),
|
||||
(_, Token::Punct('.', _)) if !matcher => (state != Ident && state != Delim, Dot),
|
||||
(_, Token::Punct(':', Spacing::Joint)) => (state != Ident, Colon),
|
||||
(_, Token::Punct('$', _)) => (true, Dollar),
|
||||
(_, Token::Punct('#', _)) => (true, Pound),
|
||||
(_, _) => (true, Other),
|
||||
};
|
||||
if !previous_is_joint {
|
||||
if needs_space {
|
||||
self.space();
|
||||
} else if let Token::Punct('.', _) = token {
|
||||
self.zerobreak();
|
||||
}
|
||||
}
|
||||
previous_is_joint = match token {
|
||||
Token::Punct(_, Spacing::Joint) | Token::Punct('$', _) => true,
|
||||
_ => false,
|
||||
};
|
||||
self.single_token(
|
||||
token,
|
||||
if matcher {
|
||||
|printer, stream| printer.macro_rules_tokens(stream, true)
|
||||
} else {
|
||||
|printer, stream| printer.macro_rules_tokens(stream, false)
|
||||
},
|
||||
);
|
||||
state = next_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_keyword(ident: &Ident) -> bool {
|
||||
match ident.to_string().as_str() {
|
||||
"as" | "async" | "await" | "box" | "break" | "const" | "continue" | "crate" | "dyn"
|
||||
| "else" | "enum" | "extern" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop"
|
||||
| "macro" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "static"
|
||||
| "struct" | "trait" | "type" | "unsafe" | "use" | "where" | "while" | "yield" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "verbatim")]
|
||||
mod standard_library {
|
||||
use crate::algorithm::Printer;
|
||||
use crate::iter::IterDelimited;
|
||||
use crate::path::PathKind;
|
||||
use crate::INDENT;
|
||||
use syn::ext::IdentExt;
|
||||
use syn::parse::{Parse, ParseStream, Parser, Result};
|
||||
use syn::{
|
||||
parenthesized, token, Attribute, Expr, ExprAssign, ExprPath, Ident, Lit, Macro, Pat, Path,
|
||||
Token, Type, Visibility,
|
||||
};
|
||||
|
||||
enum KnownMacro {
|
||||
Expr(Expr),
|
||||
Exprs(Vec<Expr>),
|
||||
Cfg(Cfg),
|
||||
Matches(Matches),
|
||||
ThreadLocal(Vec<ThreadLocal>),
|
||||
VecArray(Vec<Expr>),
|
||||
VecRepeat { elem: Expr, n: Expr },
|
||||
}
|
||||
|
||||
enum Cfg {
|
||||
Eq(Ident, Option<Lit>),
|
||||
Call(Ident, Vec<Cfg>),
|
||||
}
|
||||
|
||||
struct Matches {
|
||||
expression: Expr,
|
||||
pattern: Pat,
|
||||
guard: Option<Expr>,
|
||||
}
|
||||
|
||||
struct ThreadLocal {
|
||||
attrs: Vec<Attribute>,
|
||||
vis: Visibility,
|
||||
name: Ident,
|
||||
ty: Type,
|
||||
init: Expr,
|
||||
}
|
||||
|
||||
struct FormatArgs {
|
||||
format_string: Expr,
|
||||
args: Vec<Expr>,
|
||||
}
|
||||
|
||||
impl Parse for FormatArgs {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let format_string: Expr = input.parse()?;
|
||||
|
||||
let mut args = Vec::new();
|
||||
while !input.is_empty() {
|
||||
input.parse::<Token![,]>()?;
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
let arg = if input.peek(Ident::peek_any)
|
||||
&& input.peek2(Token![=])
|
||||
&& !input.peek2(Token![==])
|
||||
{
|
||||
let key = input.call(Ident::parse_any)?;
|
||||
let eq_token: Token![=] = input.parse()?;
|
||||
let value: Expr = input.parse()?;
|
||||
Expr::Assign(ExprAssign {
|
||||
attrs: Vec::new(),
|
||||
left: Box::new(Expr::Path(ExprPath {
|
||||
attrs: Vec::new(),
|
||||
qself: None,
|
||||
path: Path::from(key),
|
||||
})),
|
||||
eq_token,
|
||||
right: Box::new(value),
|
||||
})
|
||||
} else {
|
||||
input.parse()?
|
||||
};
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
Ok(FormatArgs {
|
||||
format_string,
|
||||
args,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl KnownMacro {
|
||||
fn parse_expr(input: ParseStream) -> Result<Self> {
|
||||
let expr: Expr = input.parse()?;
|
||||
Ok(KnownMacro::Expr(expr))
|
||||
}
|
||||
|
||||
fn parse_expr_comma(input: ParseStream) -> Result<Self> {
|
||||
let expr: Expr = input.parse()?;
|
||||
input.parse::<Option<Token![,]>>()?;
|
||||
Ok(KnownMacro::Exprs(vec![expr]))
|
||||
}
|
||||
|
||||
fn parse_exprs(input: ParseStream) -> Result<Self> {
|
||||
let exprs = input.parse_terminated(Expr::parse, Token![,])?;
|
||||
Ok(KnownMacro::Exprs(Vec::from_iter(exprs)))
|
||||
}
|
||||
|
||||
fn parse_assert(input: ParseStream) -> Result<Self> {
|
||||
let mut exprs = Vec::new();
|
||||
let cond: Expr = input.parse()?;
|
||||
exprs.push(cond);
|
||||
if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
|
||||
let format_args: FormatArgs = input.parse()?;
|
||||
exprs.push(format_args.format_string);
|
||||
exprs.extend(format_args.args);
|
||||
}
|
||||
Ok(KnownMacro::Exprs(exprs))
|
||||
}
|
||||
|
||||
fn parse_assert_cmp(input: ParseStream) -> Result<Self> {
|
||||
let mut exprs = Vec::new();
|
||||
let left: Expr = input.parse()?;
|
||||
exprs.push(left);
|
||||
input.parse::<Token![,]>()?;
|
||||
let right: Expr = input.parse()?;
|
||||
exprs.push(right);
|
||||
if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
|
||||
let format_args: FormatArgs = input.parse()?;
|
||||
exprs.push(format_args.format_string);
|
||||
exprs.extend(format_args.args);
|
||||
}
|
||||
Ok(KnownMacro::Exprs(exprs))
|
||||
}
|
||||
|
||||
fn parse_cfg(input: ParseStream) -> Result<Self> {
|
||||
fn parse_single(input: ParseStream) -> Result<Cfg> {
|
||||
let ident: Ident = input.parse()?;
|
||||
if input.peek(token::Paren) && (ident == "all" || ident == "any") {
|
||||
let content;
|
||||
parenthesized!(content in input);
|
||||
let list = content.call(parse_multiple)?;
|
||||
Ok(Cfg::Call(ident, list))
|
||||
} else if input.peek(token::Paren) && ident == "not" {
|
||||
let content;
|
||||
parenthesized!(content in input);
|
||||
let cfg = content.call(parse_single)?;
|
||||
content.parse::<Option<Token![,]>>()?;
|
||||
Ok(Cfg::Call(ident, vec![cfg]))
|
||||
} else if input.peek(Token![=]) {
|
||||
input.parse::<Token![=]>()?;
|
||||
let string: Lit = input.parse()?;
|
||||
Ok(Cfg::Eq(ident, Some(string)))
|
||||
} else {
|
||||
Ok(Cfg::Eq(ident, None))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_multiple(input: ParseStream) -> Result<Vec<Cfg>> {
|
||||
let mut vec = Vec::new();
|
||||
while !input.is_empty() {
|
||||
let cfg = input.call(parse_single)?;
|
||||
vec.push(cfg);
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
let cfg = input.call(parse_single)?;
|
||||
input.parse::<Option<Token![,]>>()?;
|
||||
Ok(KnownMacro::Cfg(cfg))
|
||||
}
|
||||
|
||||
fn parse_env(input: ParseStream) -> Result<Self> {
|
||||
let mut exprs = Vec::new();
|
||||
let name: Expr = input.parse()?;
|
||||
exprs.push(name);
|
||||
if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
|
||||
let error_msg: Expr = input.parse()?;
|
||||
exprs.push(error_msg);
|
||||
input.parse::<Option<Token![,]>>()?;
|
||||
}
|
||||
Ok(KnownMacro::Exprs(exprs))
|
||||
}
|
||||
|
||||
fn parse_format_args(input: ParseStream) -> Result<Self> {
|
||||
let format_args: FormatArgs = input.parse()?;
|
||||
let mut exprs = format_args.args;
|
||||
exprs.insert(0, format_args.format_string);
|
||||
Ok(KnownMacro::Exprs(exprs))
|
||||
}
|
||||
|
||||
fn parse_matches(input: ParseStream) -> Result<Self> {
|
||||
let expression: Expr = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
let pattern = input.call(Pat::parse_multi_with_leading_vert)?;
|
||||
let guard = if input.parse::<Option<Token![if]>>()?.is_some() {
|
||||
Some(input.parse()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
input.parse::<Option<Token![,]>>()?;
|
||||
Ok(KnownMacro::Matches(Matches {
|
||||
expression,
|
||||
pattern,
|
||||
guard,
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_thread_local(input: ParseStream) -> Result<Self> {
|
||||
let mut items = Vec::new();
|
||||
while !input.is_empty() {
|
||||
let attrs = input.call(Attribute::parse_outer)?;
|
||||
let vis: Visibility = input.parse()?;
|
||||
input.parse::<Token![static]>()?;
|
||||
let name: Ident = input.parse()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
let ty: Type = input.parse()?;
|
||||
input.parse::<Token![=]>()?;
|
||||
let init: Expr = input.parse()?;
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
input.parse::<Token![;]>()?;
|
||||
items.push(ThreadLocal {
|
||||
attrs,
|
||||
vis,
|
||||
name,
|
||||
ty,
|
||||
init,
|
||||
});
|
||||
}
|
||||
Ok(KnownMacro::ThreadLocal(items))
|
||||
}
|
||||
|
||||
fn parse_vec(input: ParseStream) -> Result<Self> {
|
||||
if input.is_empty() {
|
||||
return Ok(KnownMacro::VecArray(Vec::new()));
|
||||
}
|
||||
let first: Expr = input.parse()?;
|
||||
if input.parse::<Option<Token![;]>>()?.is_some() {
|
||||
let len: Expr = input.parse()?;
|
||||
Ok(KnownMacro::VecRepeat {
|
||||
elem: first,
|
||||
n: len,
|
||||
})
|
||||
} else {
|
||||
let mut vec = vec![first];
|
||||
while !input.is_empty() {
|
||||
input.parse::<Token![,]>()?;
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
let next: Expr = input.parse()?;
|
||||
vec.push(next);
|
||||
}
|
||||
Ok(KnownMacro::VecArray(vec))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_write(input: ParseStream) -> Result<Self> {
|
||||
let mut exprs = Vec::new();
|
||||
let dst: Expr = input.parse()?;
|
||||
exprs.push(dst);
|
||||
input.parse::<Token![,]>()?;
|
||||
let format_args: FormatArgs = input.parse()?;
|
||||
exprs.push(format_args.format_string);
|
||||
exprs.extend(format_args.args);
|
||||
Ok(KnownMacro::Exprs(exprs))
|
||||
}
|
||||
|
||||
fn parse_writeln(input: ParseStream) -> Result<Self> {
|
||||
let mut exprs = Vec::new();
|
||||
let dst: Expr = input.parse()?;
|
||||
exprs.push(dst);
|
||||
if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
|
||||
let format_args: FormatArgs = input.parse()?;
|
||||
exprs.push(format_args.format_string);
|
||||
exprs.extend(format_args.args);
|
||||
}
|
||||
Ok(KnownMacro::Exprs(exprs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Printer {
|
||||
pub fn standard_library_macro(&mut self, mac: &Macro, mut semicolon: bool) -> bool {
|
||||
let name = mac.path.segments.last().unwrap().ident.to_string();
|
||||
let parser = match name.as_str() {
|
||||
"addr_of" | "addr_of_mut" => KnownMacro::parse_expr,
|
||||
"assert" | "debug_assert" => KnownMacro::parse_assert,
|
||||
"assert_eq" | "assert_ne" | "debug_assert_eq" | "debug_assert_ne" => {
|
||||
KnownMacro::parse_assert_cmp
|
||||
}
|
||||
"cfg" => KnownMacro::parse_cfg,
|
||||
"compile_error" | "include" | "include_bytes" | "include_str" | "option_env" => {
|
||||
KnownMacro::parse_expr_comma
|
||||
}
|
||||
"concat" | "concat_bytes" | "dbg" => KnownMacro::parse_exprs,
|
||||
"const_format_args" | "eprint" | "eprintln" | "format" | "format_args"
|
||||
| "format_args_nl" | "panic" | "print" | "println" | "todo" | "unimplemented"
|
||||
| "unreachable" => KnownMacro::parse_format_args,
|
||||
"env" => KnownMacro::parse_env,
|
||||
"matches" => KnownMacro::parse_matches,
|
||||
"thread_local" => KnownMacro::parse_thread_local,
|
||||
"vec" => KnownMacro::parse_vec,
|
||||
"write" => KnownMacro::parse_write,
|
||||
"writeln" => KnownMacro::parse_writeln,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
let known_macro = match parser.parse2(mac.tokens.clone()) {
|
||||
Ok(known_macro) => known_macro,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
self.path(&mac.path, PathKind::Simple);
|
||||
self.word("!");
|
||||
|
||||
match &known_macro {
|
||||
KnownMacro::Expr(expr) => {
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
self.expr(expr);
|
||||
self.zerobreak();
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
}
|
||||
KnownMacro::Exprs(exprs) => {
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
for elem in exprs.iter().delimited() {
|
||||
self.expr(&elem);
|
||||
self.trailing_comma(elem.is_last);
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
}
|
||||
KnownMacro::Cfg(cfg) => {
|
||||
self.word("(");
|
||||
self.cfg(cfg);
|
||||
self.word(")");
|
||||
}
|
||||
KnownMacro::Matches(matches) => {
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
self.expr(&matches.expression);
|
||||
self.word(",");
|
||||
self.space();
|
||||
self.pat(&matches.pattern);
|
||||
if let Some(guard) = &matches.guard {
|
||||
self.space();
|
||||
self.word("if ");
|
||||
self.expr(guard);
|
||||
}
|
||||
self.zerobreak();
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
}
|
||||
KnownMacro::ThreadLocal(items) => {
|
||||
self.word(" {");
|
||||
self.cbox(INDENT);
|
||||
self.hardbreak_if_nonempty();
|
||||
for item in items {
|
||||
self.outer_attrs(&item.attrs);
|
||||
self.cbox(0);
|
||||
self.visibility(&item.vis);
|
||||
self.word("static ");
|
||||
self.ident(&item.name);
|
||||
self.word(": ");
|
||||
self.ty(&item.ty);
|
||||
self.word(" = ");
|
||||
self.neverbreak();
|
||||
self.expr(&item.init);
|
||||
self.word(";");
|
||||
self.end();
|
||||
self.hardbreak();
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("}");
|
||||
semicolon = false;
|
||||
}
|
||||
KnownMacro::VecArray(vec) => {
|
||||
self.word("[");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
for elem in vec.iter().delimited() {
|
||||
self.expr(&elem);
|
||||
self.trailing_comma(elem.is_last);
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("]");
|
||||
}
|
||||
KnownMacro::VecRepeat { elem, n } => {
|
||||
self.word("[");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
self.expr(elem);
|
||||
self.word(";");
|
||||
self.space();
|
||||
self.expr(n);
|
||||
self.zerobreak();
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("]");
|
||||
}
|
||||
}
|
||||
|
||||
if semicolon {
|
||||
self.word(";");
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn cfg(&mut self, cfg: &Cfg) {
|
||||
match cfg {
|
||||
Cfg::Eq(ident, value) => {
|
||||
self.ident(ident);
|
||||
if let Some(value) = value {
|
||||
self.word(" = ");
|
||||
self.lit(value);
|
||||
}
|
||||
}
|
||||
Cfg::Call(ident, args) => {
|
||||
self.ident(ident);
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
for arg in args.iter().delimited() {
|
||||
self.cfg(&arg);
|
||||
self.trailing_comma(arg.is_last);
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
253
third-party/vendor/prettyplease/src/pat.rs
vendored
Normal file
253
third-party/vendor/prettyplease/src/pat.rs
vendored
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::iter::IterDelimited;
|
||||
use crate::path::PathKind;
|
||||
use crate::INDENT;
|
||||
use proc_macro2::TokenStream;
|
||||
use syn::{
|
||||
FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple,
|
||||
PatTupleStruct, PatType, PatWild,
|
||||
};
|
||||
|
||||
impl Printer {
|
||||
pub fn pat(&mut self, pat: &Pat) {
|
||||
match pat {
|
||||
Pat::Const(pat) => self.expr_const(pat),
|
||||
Pat::Ident(pat) => self.pat_ident(pat),
|
||||
Pat::Lit(pat) => self.expr_lit(pat),
|
||||
Pat::Macro(pat) => self.expr_macro(pat),
|
||||
Pat::Or(pat) => self.pat_or(pat),
|
||||
Pat::Paren(pat) => self.pat_paren(pat),
|
||||
Pat::Path(pat) => self.expr_path(pat),
|
||||
Pat::Range(pat) => self.expr_range(pat),
|
||||
Pat::Reference(pat) => self.pat_reference(pat),
|
||||
Pat::Rest(pat) => self.pat_rest(pat),
|
||||
Pat::Slice(pat) => self.pat_slice(pat),
|
||||
Pat::Struct(pat) => self.pat_struct(pat),
|
||||
Pat::Tuple(pat) => self.pat_tuple(pat),
|
||||
Pat::TupleStruct(pat) => self.pat_tuple_struct(pat),
|
||||
Pat::Type(pat) => self.pat_type(pat),
|
||||
Pat::Verbatim(pat) => self.pat_verbatim(pat),
|
||||
Pat::Wild(pat) => self.pat_wild(pat),
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => unimplemented!("unknown Pat"),
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_ident(&mut self, pat: &PatIdent) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
if pat.by_ref.is_some() {
|
||||
self.word("ref ");
|
||||
}
|
||||
if pat.mutability.is_some() {
|
||||
self.word("mut ");
|
||||
}
|
||||
self.ident(&pat.ident);
|
||||
if let Some((_at_token, subpat)) = &pat.subpat {
|
||||
self.word(" @ ");
|
||||
self.pat(subpat);
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_or(&mut self, pat: &PatOr) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
let mut consistent_break = false;
|
||||
for case in &pat.cases {
|
||||
match case {
|
||||
Pat::Lit(_) | Pat::Wild(_) => {}
|
||||
_ => {
|
||||
consistent_break = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if consistent_break {
|
||||
self.cbox(0);
|
||||
} else {
|
||||
self.ibox(0);
|
||||
}
|
||||
for case in pat.cases.iter().delimited() {
|
||||
if !case.is_first {
|
||||
self.space();
|
||||
self.word("| ");
|
||||
}
|
||||
self.pat(&case);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
fn pat_paren(&mut self, pat: &PatParen) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.word("(");
|
||||
self.pat(&pat.pat);
|
||||
self.word(")");
|
||||
}
|
||||
|
||||
fn pat_reference(&mut self, pat: &PatReference) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.word("&");
|
||||
if pat.mutability.is_some() {
|
||||
self.word("mut ");
|
||||
}
|
||||
self.pat(&pat.pat);
|
||||
}
|
||||
|
||||
fn pat_rest(&mut self, pat: &PatRest) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.word("..");
|
||||
}
|
||||
|
||||
fn pat_slice(&mut self, pat: &PatSlice) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.word("[");
|
||||
for elem in pat.elems.iter().delimited() {
|
||||
self.pat(&elem);
|
||||
self.trailing_comma(elem.is_last);
|
||||
}
|
||||
self.word("]");
|
||||
}
|
||||
|
||||
fn pat_struct(&mut self, pat: &PatStruct) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.cbox(INDENT);
|
||||
self.path(&pat.path, PathKind::Expr);
|
||||
self.word(" {");
|
||||
self.space_if_nonempty();
|
||||
for field in pat.fields.iter().delimited() {
|
||||
self.field_pat(&field);
|
||||
self.trailing_comma_or_space(field.is_last && pat.rest.is_none());
|
||||
}
|
||||
if let Some(rest) = &pat.rest {
|
||||
self.pat_rest(rest);
|
||||
self.space();
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("}");
|
||||
}
|
||||
|
||||
fn pat_tuple(&mut self, pat: &PatTuple) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
for elem in pat.elems.iter().delimited() {
|
||||
self.pat(&elem);
|
||||
if pat.elems.len() == 1 {
|
||||
if pat.elems.trailing_punct() {
|
||||
self.word(",");
|
||||
}
|
||||
self.zerobreak();
|
||||
} else {
|
||||
self.trailing_comma(elem.is_last);
|
||||
}
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
}
|
||||
|
||||
fn pat_tuple_struct(&mut self, pat: &PatTupleStruct) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.path(&pat.path, PathKind::Expr);
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
for elem in pat.elems.iter().delimited() {
|
||||
self.pat(&elem);
|
||||
self.trailing_comma(elem.is_last);
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
}
|
||||
|
||||
pub fn pat_type(&mut self, pat: &PatType) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.pat(&pat.pat);
|
||||
self.word(": ");
|
||||
self.ty(&pat.ty);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "verbatim"))]
|
||||
fn pat_verbatim(&mut self, pat: &TokenStream) {
|
||||
unimplemented!("Pat::Verbatim `{}`", pat);
|
||||
}
|
||||
|
||||
#[cfg(feature = "verbatim")]
|
||||
fn pat_verbatim(&mut self, tokens: &TokenStream) {
|
||||
use syn::parse::{Parse, ParseStream, Result};
|
||||
use syn::{braced, Attribute, Block, Token};
|
||||
|
||||
enum PatVerbatim {
|
||||
Ellipsis,
|
||||
Box(Pat),
|
||||
Const(PatConst),
|
||||
}
|
||||
|
||||
struct PatConst {
|
||||
attrs: Vec<Attribute>,
|
||||
block: Block,
|
||||
}
|
||||
|
||||
impl Parse for PatVerbatim {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(Token![box]) {
|
||||
input.parse::<Token![box]>()?;
|
||||
let inner = Pat::parse_single(input)?;
|
||||
Ok(PatVerbatim::Box(inner))
|
||||
} else if lookahead.peek(Token![const]) {
|
||||
input.parse::<Token![const]>()?;
|
||||
let content;
|
||||
let brace_token = braced!(content in input);
|
||||
let attrs = content.call(Attribute::parse_inner)?;
|
||||
let stmts = content.call(Block::parse_within)?;
|
||||
Ok(PatVerbatim::Const(PatConst {
|
||||
attrs,
|
||||
block: Block { brace_token, stmts },
|
||||
}))
|
||||
} else if lookahead.peek(Token![...]) {
|
||||
input.parse::<Token![...]>()?;
|
||||
Ok(PatVerbatim::Ellipsis)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let pat: PatVerbatim = match syn::parse2(tokens.clone()) {
|
||||
Ok(pat) => pat,
|
||||
Err(_) => unimplemented!("Pat::Verbatim `{}`", tokens),
|
||||
};
|
||||
|
||||
match pat {
|
||||
PatVerbatim::Ellipsis => {
|
||||
self.word("...");
|
||||
}
|
||||
PatVerbatim::Box(pat) => {
|
||||
self.word("box ");
|
||||
self.pat(&pat);
|
||||
}
|
||||
PatVerbatim::Const(pat) => {
|
||||
self.word("const ");
|
||||
self.cbox(INDENT);
|
||||
self.small_block(&pat.block, &pat.attrs);
|
||||
self.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pat_wild(&mut self, pat: &PatWild) {
|
||||
self.outer_attrs(&pat.attrs);
|
||||
self.word("_");
|
||||
}
|
||||
|
||||
fn field_pat(&mut self, field_pat: &FieldPat) {
|
||||
self.outer_attrs(&field_pat.attrs);
|
||||
if field_pat.colon_token.is_some() {
|
||||
self.member(&field_pat.member);
|
||||
self.word(": ");
|
||||
}
|
||||
self.pat(&field_pat.pat);
|
||||
}
|
||||
}
|
||||
207
third-party/vendor/prettyplease/src/path.rs
vendored
Normal file
207
third-party/vendor/prettyplease/src/path.rs
vendored
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::iter::IterDelimited;
|
||||
use crate::INDENT;
|
||||
use std::ptr;
|
||||
use syn::{
|
||||
AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, Expr, GenericArgument,
|
||||
ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum PathKind {
|
||||
// a::B
|
||||
Simple,
|
||||
// a::B<T>
|
||||
Type,
|
||||
// a::B::<T>
|
||||
Expr,
|
||||
}
|
||||
|
||||
impl Printer {
|
||||
pub fn path(&mut self, path: &Path, kind: PathKind) {
|
||||
assert!(!path.segments.is_empty());
|
||||
for segment in path.segments.iter().delimited() {
|
||||
if !segment.is_first || path.leading_colon.is_some() {
|
||||
self.word("::");
|
||||
}
|
||||
self.path_segment(&segment, kind);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_segment(&mut self, segment: &PathSegment, kind: PathKind) {
|
||||
self.ident(&segment.ident);
|
||||
self.path_arguments(&segment.arguments, kind);
|
||||
}
|
||||
|
||||
fn path_arguments(&mut self, arguments: &PathArguments, kind: PathKind) {
|
||||
match arguments {
|
||||
PathArguments::None => {}
|
||||
PathArguments::AngleBracketed(arguments) => {
|
||||
self.angle_bracketed_generic_arguments(arguments, kind);
|
||||
}
|
||||
PathArguments::Parenthesized(arguments) => {
|
||||
self.parenthesized_generic_arguments(arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generic_argument(&mut self, arg: &GenericArgument) {
|
||||
match arg {
|
||||
GenericArgument::Lifetime(lifetime) => self.lifetime(lifetime),
|
||||
GenericArgument::Type(ty) => self.ty(ty),
|
||||
GenericArgument::Const(expr) => {
|
||||
match expr {
|
||||
Expr::Lit(expr) => self.expr_lit(expr),
|
||||
Expr::Block(expr) => self.expr_block(expr),
|
||||
// ERROR CORRECTION: Add braces to make sure that the
|
||||
// generated code is valid.
|
||||
_ => {
|
||||
self.word("{");
|
||||
self.expr(expr);
|
||||
self.word("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
GenericArgument::AssocType(assoc) => self.assoc_type(assoc),
|
||||
GenericArgument::AssocConst(assoc) => self.assoc_const(assoc),
|
||||
GenericArgument::Constraint(constraint) => self.constraint(constraint),
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => unimplemented!("unknown GenericArgument"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn angle_bracketed_generic_arguments(
|
||||
&mut self,
|
||||
generic: &AngleBracketedGenericArguments,
|
||||
path_kind: PathKind,
|
||||
) {
|
||||
if generic.args.is_empty() || path_kind == PathKind::Simple {
|
||||
return;
|
||||
}
|
||||
|
||||
if path_kind == PathKind::Expr {
|
||||
self.word("::");
|
||||
}
|
||||
self.word("<");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
|
||||
// Print lifetimes before types/consts/bindings, regardless of their
|
||||
// order in self.args.
|
||||
#[derive(Ord, PartialOrd, Eq, PartialEq)]
|
||||
enum Group {
|
||||
First,
|
||||
Second,
|
||||
}
|
||||
fn group(arg: &GenericArgument) -> Group {
|
||||
match arg {
|
||||
GenericArgument::Lifetime(_) => Group::First,
|
||||
GenericArgument::Type(_)
|
||||
| GenericArgument::Const(_)
|
||||
| GenericArgument::AssocType(_)
|
||||
| GenericArgument::AssocConst(_)
|
||||
| GenericArgument::Constraint(_) => Group::Second,
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => Group::Second,
|
||||
}
|
||||
}
|
||||
let last = generic.args.iter().max_by_key(|param| group(param));
|
||||
for current_group in [Group::First, Group::Second] {
|
||||
for arg in &generic.args {
|
||||
if group(arg) == current_group {
|
||||
self.generic_argument(arg);
|
||||
self.trailing_comma(ptr::eq(arg, last.unwrap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(">");
|
||||
}
|
||||
|
||||
fn assoc_type(&mut self, assoc: &AssocType) {
|
||||
self.ident(&assoc.ident);
|
||||
if let Some(generics) = &assoc.generics {
|
||||
self.angle_bracketed_generic_arguments(generics, PathKind::Type);
|
||||
}
|
||||
self.word(" = ");
|
||||
self.ty(&assoc.ty);
|
||||
}
|
||||
|
||||
fn assoc_const(&mut self, assoc: &AssocConst) {
|
||||
self.ident(&assoc.ident);
|
||||
if let Some(generics) = &assoc.generics {
|
||||
self.angle_bracketed_generic_arguments(generics, PathKind::Type);
|
||||
}
|
||||
self.word(" = ");
|
||||
self.expr(&assoc.value);
|
||||
}
|
||||
|
||||
fn constraint(&mut self, constraint: &Constraint) {
|
||||
self.ident(&constraint.ident);
|
||||
if let Some(generics) = &constraint.generics {
|
||||
self.angle_bracketed_generic_arguments(generics, PathKind::Type);
|
||||
}
|
||||
self.ibox(INDENT);
|
||||
for bound in constraint.bounds.iter().delimited() {
|
||||
if bound.is_first {
|
||||
self.word(": ");
|
||||
} else {
|
||||
self.space();
|
||||
self.word("+ ");
|
||||
}
|
||||
self.type_param_bound(&bound);
|
||||
}
|
||||
self.end();
|
||||
}
|
||||
|
||||
fn parenthesized_generic_arguments(&mut self, arguments: &ParenthesizedGenericArguments) {
|
||||
self.cbox(INDENT);
|
||||
self.word("(");
|
||||
self.zerobreak();
|
||||
for ty in arguments.inputs.iter().delimited() {
|
||||
self.ty(&ty);
|
||||
self.trailing_comma(ty.is_last);
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.word(")");
|
||||
self.return_type(&arguments.output);
|
||||
self.end();
|
||||
}
|
||||
|
||||
pub fn qpath(&mut self, qself: &Option<QSelf>, path: &Path, kind: PathKind) {
|
||||
let qself = match qself {
|
||||
Some(qself) => qself,
|
||||
None => {
|
||||
self.path(path, kind);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
assert!(qself.position < path.segments.len());
|
||||
|
||||
self.word("<");
|
||||
self.ty(&qself.ty);
|
||||
|
||||
let mut segments = path.segments.iter();
|
||||
if qself.position > 0 {
|
||||
self.word(" as ");
|
||||
for segment in segments.by_ref().take(qself.position).delimited() {
|
||||
if !segment.is_first || path.leading_colon.is_some() {
|
||||
self.word("::");
|
||||
}
|
||||
self.path_segment(&segment, PathKind::Type);
|
||||
if segment.is_last {
|
||||
self.word(">");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.word(">");
|
||||
}
|
||||
for segment in segments {
|
||||
self.word("::");
|
||||
self.path_segment(segment, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
third-party/vendor/prettyplease/src/ring.rs
vendored
Normal file
81
third-party/vendor/prettyplease/src/ring.rs
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
pub struct RingBuffer<T> {
|
||||
data: VecDeque<T>,
|
||||
// Abstract index of data[0] in infinitely sized queue
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl<T> RingBuffer<T> {
|
||||
pub fn new() -> Self {
|
||||
RingBuffer {
|
||||
data: VecDeque::new(),
|
||||
offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.data.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.data.len()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, value: T) -> usize {
|
||||
let index = self.offset + self.data.len();
|
||||
self.data.push_back(value);
|
||||
index
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.data.clear();
|
||||
}
|
||||
|
||||
pub fn index_of_first(&self) -> usize {
|
||||
self.offset
|
||||
}
|
||||
|
||||
pub fn first(&self) -> &T {
|
||||
&self.data[0]
|
||||
}
|
||||
|
||||
pub fn first_mut(&mut self) -> &mut T {
|
||||
&mut self.data[0]
|
||||
}
|
||||
|
||||
pub fn pop_first(&mut self) -> T {
|
||||
self.offset += 1;
|
||||
self.data.pop_front().unwrap()
|
||||
}
|
||||
|
||||
pub fn last(&self) -> &T {
|
||||
self.data.back().unwrap()
|
||||
}
|
||||
|
||||
pub fn last_mut(&mut self) -> &mut T {
|
||||
self.data.back_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn second_last(&self) -> &T {
|
||||
&self.data[self.data.len() - 2]
|
||||
}
|
||||
|
||||
pub fn pop_last(&mut self) {
|
||||
self.data.pop_back().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<usize> for RingBuffer<T> {
|
||||
type Output = T;
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.data[index.checked_sub(self.offset).unwrap()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IndexMut<usize> for RingBuffer<T> {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
&mut self.data[index.checked_sub(self.offset).unwrap()]
|
||||
}
|
||||
}
|
||||
217
third-party/vendor/prettyplease/src/stmt.rs
vendored
Normal file
217
third-party/vendor/prettyplease/src/stmt.rs
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::INDENT;
|
||||
use syn::{BinOp, Expr, Stmt};
|
||||
|
||||
impl Printer {
|
||||
pub fn stmt(&mut self, stmt: &Stmt) {
|
||||
match stmt {
|
||||
Stmt::Local(local) => {
|
||||
self.outer_attrs(&local.attrs);
|
||||
self.ibox(0);
|
||||
self.word("let ");
|
||||
self.pat(&local.pat);
|
||||
if let Some(local_init) = &local.init {
|
||||
self.word(" = ");
|
||||
self.neverbreak();
|
||||
self.expr(&local_init.expr);
|
||||
if let Some((_else, diverge)) = &local_init.diverge {
|
||||
self.space();
|
||||
self.word("else ");
|
||||
self.end();
|
||||
self.neverbreak();
|
||||
if let Expr::Block(expr) = diverge.as_ref() {
|
||||
self.cbox(INDENT);
|
||||
self.small_block(&expr.block, &[]);
|
||||
self.end();
|
||||
} else {
|
||||
self.word("{");
|
||||
self.space();
|
||||
self.ibox(INDENT);
|
||||
self.expr(diverge);
|
||||
self.end();
|
||||
self.space();
|
||||
self.offset(-INDENT);
|
||||
self.word("}");
|
||||
}
|
||||
} else {
|
||||
self.end();
|
||||
}
|
||||
} else {
|
||||
self.end();
|
||||
}
|
||||
self.word(";");
|
||||
self.hardbreak();
|
||||
}
|
||||
Stmt::Item(item) => self.item(item),
|
||||
Stmt::Expr(expr, None) => {
|
||||
if break_after(expr) {
|
||||
self.ibox(0);
|
||||
self.expr_beginning_of_line(expr, true);
|
||||
if add_semi(expr) {
|
||||
self.word(";");
|
||||
}
|
||||
self.end();
|
||||
self.hardbreak();
|
||||
} else {
|
||||
self.expr_beginning_of_line(expr, true);
|
||||
}
|
||||
}
|
||||
Stmt::Expr(expr, Some(_semi)) => {
|
||||
if let Expr::Verbatim(tokens) = expr {
|
||||
if tokens.is_empty() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.ibox(0);
|
||||
self.expr_beginning_of_line(expr, true);
|
||||
if !remove_semi(expr) {
|
||||
self.word(";");
|
||||
}
|
||||
self.end();
|
||||
self.hardbreak();
|
||||
}
|
||||
Stmt::Macro(stmt) => {
|
||||
self.outer_attrs(&stmt.attrs);
|
||||
let semicolon = true;
|
||||
self.mac(&stmt.mac, None, semicolon);
|
||||
self.hardbreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_semi(expr: &Expr) -> bool {
|
||||
match expr {
|
||||
Expr::Assign(_) | Expr::Break(_) | Expr::Continue(_) | Expr::Return(_) | Expr::Yield(_) => {
|
||||
true
|
||||
}
|
||||
Expr::Binary(expr) => match expr.op {
|
||||
BinOp::AddAssign(_)
|
||||
| BinOp::SubAssign(_)
|
||||
| BinOp::MulAssign(_)
|
||||
| BinOp::DivAssign(_)
|
||||
| BinOp::RemAssign(_)
|
||||
| BinOp::BitXorAssign(_)
|
||||
| BinOp::BitAndAssign(_)
|
||||
| BinOp::BitOrAssign(_)
|
||||
| BinOp::ShlAssign(_)
|
||||
| BinOp::ShrAssign(_) => true,
|
||||
BinOp::Add(_)
|
||||
| BinOp::Sub(_)
|
||||
| BinOp::Mul(_)
|
||||
| BinOp::Div(_)
|
||||
| BinOp::Rem(_)
|
||||
| BinOp::And(_)
|
||||
| BinOp::Or(_)
|
||||
| BinOp::BitXor(_)
|
||||
| BinOp::BitAnd(_)
|
||||
| BinOp::BitOr(_)
|
||||
| BinOp::Shl(_)
|
||||
| BinOp::Shr(_)
|
||||
| BinOp::Eq(_)
|
||||
| BinOp::Lt(_)
|
||||
| BinOp::Le(_)
|
||||
| BinOp::Ne(_)
|
||||
| BinOp::Ge(_)
|
||||
| BinOp::Gt(_) => false,
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => unimplemented!("unknown BinOp"),
|
||||
},
|
||||
Expr::Group(group) => add_semi(&group.expr),
|
||||
|
||||
Expr::Array(_)
|
||||
| Expr::Async(_)
|
||||
| Expr::Await(_)
|
||||
| Expr::Block(_)
|
||||
| Expr::Call(_)
|
||||
| Expr::Cast(_)
|
||||
| Expr::Closure(_)
|
||||
| Expr::Const(_)
|
||||
| Expr::Field(_)
|
||||
| Expr::ForLoop(_)
|
||||
| Expr::If(_)
|
||||
| Expr::Index(_)
|
||||
| Expr::Infer(_)
|
||||
| Expr::Let(_)
|
||||
| Expr::Lit(_)
|
||||
| Expr::Loop(_)
|
||||
| Expr::Macro(_)
|
||||
| Expr::Match(_)
|
||||
| Expr::MethodCall(_)
|
||||
| Expr::Paren(_)
|
||||
| Expr::Path(_)
|
||||
| Expr::Range(_)
|
||||
| Expr::Reference(_)
|
||||
| Expr::Repeat(_)
|
||||
| Expr::Struct(_)
|
||||
| Expr::Try(_)
|
||||
| Expr::TryBlock(_)
|
||||
| Expr::Tuple(_)
|
||||
| Expr::Unary(_)
|
||||
| Expr::Unsafe(_)
|
||||
| Expr::Verbatim(_)
|
||||
| Expr::While(_) => false,
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn break_after(expr: &Expr) -> bool {
|
||||
if let Expr::Group(group) = expr {
|
||||
if let Expr::Verbatim(verbatim) = group.expr.as_ref() {
|
||||
return !verbatim.is_empty();
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn remove_semi(expr: &Expr) -> bool {
|
||||
match expr {
|
||||
Expr::ForLoop(_) | Expr::While(_) => true,
|
||||
Expr::Group(group) => remove_semi(&group.expr),
|
||||
Expr::If(expr) => match &expr.else_branch {
|
||||
Some((_else_token, else_branch)) => remove_semi(else_branch),
|
||||
None => true,
|
||||
},
|
||||
|
||||
Expr::Array(_)
|
||||
| Expr::Assign(_)
|
||||
| Expr::Async(_)
|
||||
| Expr::Await(_)
|
||||
| Expr::Binary(_)
|
||||
| Expr::Block(_)
|
||||
| Expr::Break(_)
|
||||
| Expr::Call(_)
|
||||
| Expr::Cast(_)
|
||||
| Expr::Closure(_)
|
||||
| Expr::Continue(_)
|
||||
| Expr::Const(_)
|
||||
| Expr::Field(_)
|
||||
| Expr::Index(_)
|
||||
| Expr::Infer(_)
|
||||
| Expr::Let(_)
|
||||
| Expr::Lit(_)
|
||||
| Expr::Loop(_)
|
||||
| Expr::Macro(_)
|
||||
| Expr::Match(_)
|
||||
| Expr::MethodCall(_)
|
||||
| Expr::Paren(_)
|
||||
| Expr::Path(_)
|
||||
| Expr::Range(_)
|
||||
| Expr::Reference(_)
|
||||
| Expr::Repeat(_)
|
||||
| Expr::Return(_)
|
||||
| Expr::Struct(_)
|
||||
| Expr::Try(_)
|
||||
| Expr::TryBlock(_)
|
||||
| Expr::Tuple(_)
|
||||
| Expr::Unary(_)
|
||||
| Expr::Unsafe(_)
|
||||
| Expr::Verbatim(_)
|
||||
| Expr::Yield(_) => false,
|
||||
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
80
third-party/vendor/prettyplease/src/token.rs
vendored
Normal file
80
third-party/vendor/prettyplease/src/token.rs
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use crate::algorithm::Printer;
|
||||
use proc_macro2::{Delimiter, Ident, Literal, Spacing, TokenStream, TokenTree};
|
||||
|
||||
impl Printer {
|
||||
pub fn single_token(&mut self, token: Token, group_contents: fn(&mut Self, TokenStream)) {
|
||||
match token {
|
||||
Token::Group(delimiter, stream) => self.token_group(delimiter, stream, group_contents),
|
||||
Token::Ident(ident) => self.ident(&ident),
|
||||
Token::Punct(ch, _spacing) => self.token_punct(ch),
|
||||
Token::Literal(literal) => self.token_literal(&literal),
|
||||
}
|
||||
}
|
||||
|
||||
fn token_group(
|
||||
&mut self,
|
||||
delimiter: Delimiter,
|
||||
stream: TokenStream,
|
||||
group_contents: fn(&mut Self, TokenStream),
|
||||
) {
|
||||
self.delimiter_open(delimiter);
|
||||
if !stream.is_empty() {
|
||||
if delimiter == Delimiter::Brace {
|
||||
self.space();
|
||||
}
|
||||
group_contents(self, stream);
|
||||
if delimiter == Delimiter::Brace {
|
||||
self.space();
|
||||
}
|
||||
}
|
||||
self.delimiter_close(delimiter);
|
||||
}
|
||||
|
||||
pub fn ident(&mut self, ident: &Ident) {
|
||||
self.word(ident.to_string());
|
||||
}
|
||||
|
||||
pub fn token_punct(&mut self, ch: char) {
|
||||
self.word(ch.to_string());
|
||||
}
|
||||
|
||||
pub fn token_literal(&mut self, literal: &Literal) {
|
||||
self.word(literal.to_string());
|
||||
}
|
||||
|
||||
pub fn delimiter_open(&mut self, delimiter: Delimiter) {
|
||||
self.word(match delimiter {
|
||||
Delimiter::Parenthesis => "(",
|
||||
Delimiter::Brace => "{",
|
||||
Delimiter::Bracket => "[",
|
||||
Delimiter::None => return,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn delimiter_close(&mut self, delimiter: Delimiter) {
|
||||
self.word(match delimiter {
|
||||
Delimiter::Parenthesis => ")",
|
||||
Delimiter::Brace => "}",
|
||||
Delimiter::Bracket => "]",
|
||||
Delimiter::None => return,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Token {
|
||||
Group(Delimiter, TokenStream),
|
||||
Ident(Ident),
|
||||
Punct(char, Spacing),
|
||||
Literal(Literal),
|
||||
}
|
||||
|
||||
impl From<TokenTree> for Token {
|
||||
fn from(tt: TokenTree) -> Self {
|
||||
match tt {
|
||||
TokenTree::Group(group) => Token::Group(group.delimiter(), group.stream()),
|
||||
TokenTree::Ident(ident) => Token::Ident(ident),
|
||||
TokenTree::Punct(punct) => Token::Punct(punct.as_char(), punct.spacing()),
|
||||
TokenTree::Literal(literal) => Token::Literal(literal),
|
||||
}
|
||||
}
|
||||
}
|
||||
338
third-party/vendor/prettyplease/src/ty.rs
vendored
Normal file
338
third-party/vendor/prettyplease/src/ty.rs
vendored
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
use crate::algorithm::Printer;
|
||||
use crate::iter::IterDelimited;
|
||||
use crate::path::PathKind;
|
||||
use crate::INDENT;
|
||||
use proc_macro2::TokenStream;
|
||||
use syn::{
|
||||
Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
|
||||
TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
|
||||
TypeSlice, TypeTraitObject, TypeTuple,
|
||||
};
|
||||
|
||||
impl Printer {
|
||||
pub fn ty(&mut self, ty: &Type) {
|
||||
match ty {
|
||||
Type::Array(ty) => self.type_array(ty),
|
||||
Type::BareFn(ty) => self.type_bare_fn(ty),
|
||||
Type::Group(ty) => self.type_group(ty),
|
||||
Type::ImplTrait(ty) => self.type_impl_trait(ty),
|
||||
Type::Infer(ty) => self.type_infer(ty),
|
||||
Type::Macro(ty) => self.type_macro(ty),
|
||||
Type::Never(ty) => self.type_never(ty),
|
||||
Type::Paren(ty) => self.type_paren(ty),
|
||||
Type::Path(ty) => self.type_path(ty),
|
||||
Type::Ptr(ty) => self.type_ptr(ty),
|
||||
Type::Reference(ty) => self.type_reference(ty),
|
||||
Type::Slice(ty) => self.type_slice(ty),
|
||||
Type::TraitObject(ty) => self.type_trait_object(ty),
|
||||
Type::Tuple(ty) => self.type_tuple(ty),
|
||||
Type::Verbatim(ty) => self.type_verbatim(ty),
|
||||
#[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
|
||||
_ => unimplemented!("unknown Type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn type_array(&mut self, ty: &TypeArray) {
|
||||
self.word("[");
|
||||
self.ty(&ty.elem);
|
||||
self.word("; ");
|
||||
self.expr(&ty.len);
|
||||
self.word("]");
|
||||
}
|
||||
|
||||
fn type_bare_fn(&mut self, ty: &TypeBareFn) {
|
||||
if let Some(bound_lifetimes) = &ty.lifetimes {
|
||||
self.bound_lifetimes(bound_lifetimes);
|
||||
}
|
||||
if ty.unsafety.is_some() {
|
||||
self.word("unsafe ");
|
||||
}
|
||||
if let Some(abi) = &ty.abi {
|
||||
self.abi(abi);
|
||||
}
|
||||
self.word("fn(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
for bare_fn_arg in ty.inputs.iter().delimited() {
|
||||
self.bare_fn_arg(&bare_fn_arg);
|
||||
self.trailing_comma(bare_fn_arg.is_last && ty.variadic.is_none());
|
||||
}
|
||||
if let Some(variadic) = &ty.variadic {
|
||||
self.bare_variadic(variadic);
|
||||
self.zerobreak();
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
self.return_type(&ty.output);
|
||||
}
|
||||
|
||||
fn type_group(&mut self, ty: &TypeGroup) {
|
||||
self.ty(&ty.elem);
|
||||
}
|
||||
|
||||
fn type_impl_trait(&mut self, ty: &TypeImplTrait) {
|
||||
self.word("impl ");
|
||||
for type_param_bound in ty.bounds.iter().delimited() {
|
||||
if !type_param_bound.is_first {
|
||||
self.word(" + ");
|
||||
}
|
||||
self.type_param_bound(&type_param_bound);
|
||||
}
|
||||
}
|
||||
|
||||
fn type_infer(&mut self, ty: &TypeInfer) {
|
||||
let _ = ty;
|
||||
self.word("_");
|
||||
}
|
||||
|
||||
fn type_macro(&mut self, ty: &TypeMacro) {
|
||||
let semicolon = false;
|
||||
self.mac(&ty.mac, None, semicolon);
|
||||
}
|
||||
|
||||
fn type_never(&mut self, ty: &TypeNever) {
|
||||
let _ = ty;
|
||||
self.word("!");
|
||||
}
|
||||
|
||||
fn type_paren(&mut self, ty: &TypeParen) {
|
||||
self.word("(");
|
||||
self.ty(&ty.elem);
|
||||
self.word(")");
|
||||
}
|
||||
|
||||
fn type_path(&mut self, ty: &TypePath) {
|
||||
self.qpath(&ty.qself, &ty.path, PathKind::Type);
|
||||
}
|
||||
|
||||
fn type_ptr(&mut self, ty: &TypePtr) {
|
||||
self.word("*");
|
||||
if ty.mutability.is_some() {
|
||||
self.word("mut ");
|
||||
} else {
|
||||
self.word("const ");
|
||||
}
|
||||
self.ty(&ty.elem);
|
||||
}
|
||||
|
||||
fn type_reference(&mut self, ty: &TypeReference) {
|
||||
self.word("&");
|
||||
if let Some(lifetime) = &ty.lifetime {
|
||||
self.lifetime(lifetime);
|
||||
self.nbsp();
|
||||
}
|
||||
if ty.mutability.is_some() {
|
||||
self.word("mut ");
|
||||
}
|
||||
self.ty(&ty.elem);
|
||||
}
|
||||
|
||||
fn type_slice(&mut self, ty: &TypeSlice) {
|
||||
self.word("[");
|
||||
self.ty(&ty.elem);
|
||||
self.word("]");
|
||||
}
|
||||
|
||||
fn type_trait_object(&mut self, ty: &TypeTraitObject) {
|
||||
self.word("dyn ");
|
||||
for type_param_bound in ty.bounds.iter().delimited() {
|
||||
if !type_param_bound.is_first {
|
||||
self.word(" + ");
|
||||
}
|
||||
self.type_param_bound(&type_param_bound);
|
||||
}
|
||||
}
|
||||
|
||||
fn type_tuple(&mut self, ty: &TypeTuple) {
|
||||
self.word("(");
|
||||
self.cbox(INDENT);
|
||||
self.zerobreak();
|
||||
for elem in ty.elems.iter().delimited() {
|
||||
self.ty(&elem);
|
||||
if ty.elems.len() == 1 {
|
||||
self.word(",");
|
||||
self.zerobreak();
|
||||
} else {
|
||||
self.trailing_comma(elem.is_last);
|
||||
}
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word(")");
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "verbatim"))]
|
||||
fn type_verbatim(&mut self, ty: &TokenStream) {
|
||||
unimplemented!("Type::Verbatim `{}`", ty);
|
||||
}
|
||||
|
||||
#[cfg(feature = "verbatim")]
|
||||
fn type_verbatim(&mut self, tokens: &TokenStream) {
|
||||
use syn::parse::{Parse, ParseStream, Result};
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::{token, FieldsNamed, Token, TypeParamBound};
|
||||
|
||||
enum TypeVerbatim {
|
||||
Ellipsis,
|
||||
AnonStruct(AnonStruct),
|
||||
AnonUnion(AnonUnion),
|
||||
DynStar(DynStar),
|
||||
MutSelf(MutSelf),
|
||||
NotType(NotType),
|
||||
}
|
||||
|
||||
struct AnonStruct {
|
||||
fields: FieldsNamed,
|
||||
}
|
||||
|
||||
struct AnonUnion {
|
||||
fields: FieldsNamed,
|
||||
}
|
||||
|
||||
struct DynStar {
|
||||
bounds: Punctuated<TypeParamBound, Token![+]>,
|
||||
}
|
||||
|
||||
struct MutSelf {
|
||||
ty: Option<Type>,
|
||||
}
|
||||
|
||||
struct NotType {
|
||||
inner: Type,
|
||||
}
|
||||
|
||||
impl Parse for TypeVerbatim {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
if lookahead.peek(Token![struct]) {
|
||||
input.parse::<Token![struct]>()?;
|
||||
let fields: FieldsNamed = input.parse()?;
|
||||
Ok(TypeVerbatim::AnonStruct(AnonStruct { fields }))
|
||||
} else if lookahead.peek(Token![union]) && input.peek2(token::Brace) {
|
||||
input.parse::<Token![union]>()?;
|
||||
let fields: FieldsNamed = input.parse()?;
|
||||
Ok(TypeVerbatim::AnonUnion(AnonUnion { fields }))
|
||||
} else if lookahead.peek(Token![dyn]) {
|
||||
input.parse::<Token![dyn]>()?;
|
||||
input.parse::<Token![*]>()?;
|
||||
let bounds = input.parse_terminated(TypeParamBound::parse, Token![+])?;
|
||||
Ok(TypeVerbatim::DynStar(DynStar { bounds }))
|
||||
} else if lookahead.peek(Token![mut]) {
|
||||
input.parse::<Token![mut]>()?;
|
||||
input.parse::<Token![self]>()?;
|
||||
let ty = if input.is_empty() {
|
||||
None
|
||||
} else {
|
||||
input.parse::<Token![:]>()?;
|
||||
let ty: Type = input.parse()?;
|
||||
Some(ty)
|
||||
};
|
||||
Ok(TypeVerbatim::MutSelf(MutSelf { ty }))
|
||||
} else if lookahead.peek(Token![!]) {
|
||||
input.parse::<Token![!]>()?;
|
||||
let inner: Type = input.parse()?;
|
||||
Ok(TypeVerbatim::NotType(NotType { inner }))
|
||||
} else if lookahead.peek(Token![...]) {
|
||||
input.parse::<Token![...]>()?;
|
||||
Ok(TypeVerbatim::Ellipsis)
|
||||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let ty: TypeVerbatim = match syn::parse2(tokens.clone()) {
|
||||
Ok(ty) => ty,
|
||||
Err(_) => unimplemented!("Type::Verbatim `{}`", tokens),
|
||||
};
|
||||
|
||||
match ty {
|
||||
TypeVerbatim::Ellipsis => {
|
||||
self.word("...");
|
||||
}
|
||||
TypeVerbatim::AnonStruct(ty) => {
|
||||
self.cbox(INDENT);
|
||||
self.word("struct {");
|
||||
self.hardbreak_if_nonempty();
|
||||
for field in &ty.fields.named {
|
||||
self.field(field);
|
||||
self.word(",");
|
||||
self.hardbreak();
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("}");
|
||||
}
|
||||
TypeVerbatim::AnonUnion(ty) => {
|
||||
self.cbox(INDENT);
|
||||
self.word("union {");
|
||||
self.hardbreak_if_nonempty();
|
||||
for field in &ty.fields.named {
|
||||
self.field(field);
|
||||
self.word(",");
|
||||
self.hardbreak();
|
||||
}
|
||||
self.offset(-INDENT);
|
||||
self.end();
|
||||
self.word("}");
|
||||
}
|
||||
TypeVerbatim::DynStar(ty) => {
|
||||
self.word("dyn* ");
|
||||
for type_param_bound in ty.bounds.iter().delimited() {
|
||||
if !type_param_bound.is_first {
|
||||
self.word(" + ");
|
||||
}
|
||||
self.type_param_bound(&type_param_bound);
|
||||
}
|
||||
}
|
||||
TypeVerbatim::MutSelf(bare_fn_arg) => {
|
||||
self.word("mut self");
|
||||
if let Some(ty) = &bare_fn_arg.ty {
|
||||
self.word(": ");
|
||||
self.ty(ty);
|
||||
}
|
||||
}
|
||||
TypeVerbatim::NotType(ty) => {
|
||||
self.word("!");
|
||||
self.ty(&ty.inner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn return_type(&mut self, ty: &ReturnType) {
|
||||
match ty {
|
||||
ReturnType::Default => {}
|
||||
ReturnType::Type(_arrow, ty) => {
|
||||
self.word(" -> ");
|
||||
self.ty(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bare_fn_arg(&mut self, bare_fn_arg: &BareFnArg) {
|
||||
self.outer_attrs(&bare_fn_arg.attrs);
|
||||
if let Some((name, _colon)) = &bare_fn_arg.name {
|
||||
self.ident(name);
|
||||
self.word(": ");
|
||||
}
|
||||
self.ty(&bare_fn_arg.ty);
|
||||
}
|
||||
|
||||
fn bare_variadic(&mut self, variadic: &BareVariadic) {
|
||||
self.outer_attrs(&variadic.attrs);
|
||||
if let Some((name, _colon)) = &variadic.name {
|
||||
self.ident(name);
|
||||
self.word(": ");
|
||||
}
|
||||
self.word("...");
|
||||
}
|
||||
|
||||
pub fn abi(&mut self, abi: &Abi) {
|
||||
self.word("extern ");
|
||||
if let Some(name) = &abi.name {
|
||||
self.lit_str(name);
|
||||
self.nbsp();
|
||||
}
|
||||
}
|
||||
}
|
||||
57
third-party/vendor/prettyplease/tests/test.rs
vendored
Normal file
57
third-party/vendor/prettyplease/tests/test.rs
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
use indoc::indoc;
|
||||
use proc_macro2::{Delimiter, Group, TokenStream};
|
||||
use quote::quote;
|
||||
|
||||
#[track_caller]
|
||||
fn test(tokens: TokenStream, expected: &str) {
|
||||
let syntax_tree: syn::File = syn::parse2(tokens).unwrap();
|
||||
let pretty = prettyplease::unparse(&syntax_tree);
|
||||
assert_eq!(pretty, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parenthesize_cond() {
|
||||
let s = Group::new(Delimiter::None, quote!(Struct {}));
|
||||
test(
|
||||
quote! {
|
||||
fn main() {
|
||||
if #s == #s {}
|
||||
}
|
||||
},
|
||||
indoc! {"
|
||||
fn main() {
|
||||
if (Struct {} == Struct {}) {}
|
||||
}
|
||||
"},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parenthesize_match_guard() {
|
||||
let expr_struct = Group::new(Delimiter::None, quote!(Struct {}));
|
||||
let expr_binary = Group::new(Delimiter::None, quote!(true && false));
|
||||
test(
|
||||
quote! {
|
||||
fn main() {
|
||||
match () {
|
||||
() if let _ = #expr_struct => {}
|
||||
() if let _ = #expr_binary => {}
|
||||
}
|
||||
}
|
||||
},
|
||||
// FIXME: no parens around `Struct {}` because anything until the `=>`
|
||||
// is considered part of the match guard expression. Parsing of the
|
||||
// expression is not terminated by `{` in that position.
|
||||
//
|
||||
// FIXME: the `true && false` needs parens. Otherwise the precedence is
|
||||
// `(let _ = true) && false` which means something different.
|
||||
indoc! {"
|
||||
fn main() {
|
||||
match () {
|
||||
() if let _ = (Struct {}) => {}
|
||||
() if let _ = true && false => {}
|
||||
}
|
||||
}
|
||||
"},
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue