mirror of
https://github.com/fatedier/frp.git
synced 2025-02-02 07:54:23 +00:00
remove vendor
This commit is contained in:
parent
859a330e6c
commit
f65ffe2812
2
vendor/github.com/coreos/go-oidc/.gitignore
generated
vendored
2
vendor/github.com/coreos/go-oidc/.gitignore
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
/bin
|
|
||||||
/gopath
|
|
16
vendor/github.com/coreos/go-oidc/.travis.yml
generated
vendored
16
vendor/github.com/coreos/go-oidc/.travis.yml
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.12"
|
|
||||||
- "1.13"
|
|
||||||
|
|
||||||
install:
|
|
||||||
- go get -v -t github.com/coreos/go-oidc/...
|
|
||||||
- go get golang.org/x/tools/cmd/cover
|
|
||||||
- go get golang.org/x/lint/golint
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./test
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
71
vendor/github.com/coreos/go-oidc/CONTRIBUTING.md
generated
vendored
71
vendor/github.com/coreos/go-oidc/CONTRIBUTING.md
generated
vendored
@ -1,71 +0,0 @@
|
|||||||
# How to Contribute
|
|
||||||
|
|
||||||
CoreOS projects are [Apache 2.0 licensed](LICENSE) and accept contributions via
|
|
||||||
GitHub pull requests. This document outlines some of the conventions on
|
|
||||||
development workflow, commit message formatting, contact points and other
|
|
||||||
resources to make it easier to get your contribution accepted.
|
|
||||||
|
|
||||||
# Certificate of Origin
|
|
||||||
|
|
||||||
By contributing to this project you agree to the Developer Certificate of
|
|
||||||
Origin (DCO). This document was created by the Linux Kernel community and is a
|
|
||||||
simple statement that you, as a contributor, have the legal right to make the
|
|
||||||
contribution. See the [DCO](DCO) file for details.
|
|
||||||
|
|
||||||
# Email and Chat
|
|
||||||
|
|
||||||
The project currently uses the general CoreOS email list and IRC channel:
|
|
||||||
- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev)
|
|
||||||
- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org
|
|
||||||
|
|
||||||
Please avoid emailing maintainers found in the MAINTAINERS file directly. They
|
|
||||||
are very busy and read the mailing lists.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
- Fork the repository on GitHub
|
|
||||||
- Read the [README](README.md) for build and test instructions
|
|
||||||
- Play with the project, submit bugs, submit patches!
|
|
||||||
|
|
||||||
## Contribution Flow
|
|
||||||
|
|
||||||
This is a rough outline of what a contributor's workflow looks like:
|
|
||||||
|
|
||||||
- Create a topic branch from where you want to base your work (usually master).
|
|
||||||
- Make commits of logical units.
|
|
||||||
- Make sure your commit messages are in the proper format (see below).
|
|
||||||
- Push your changes to a topic branch in your fork of the repository.
|
|
||||||
- Make sure the tests pass, and add any new tests as appropriate.
|
|
||||||
- Submit a pull request to the original repository.
|
|
||||||
|
|
||||||
Thanks for your contributions!
|
|
||||||
|
|
||||||
### Format of the Commit Message
|
|
||||||
|
|
||||||
We follow a rough convention for commit messages that is designed to answer two
|
|
||||||
questions: what changed and why. The subject line should feature the what and
|
|
||||||
the body of the commit should describe the why.
|
|
||||||
|
|
||||||
```
|
|
||||||
scripts: add the test-cluster command
|
|
||||||
|
|
||||||
this uses tmux to setup a test cluster that you can easily kill and
|
|
||||||
start for debugging.
|
|
||||||
|
|
||||||
Fixes #38
|
|
||||||
```
|
|
||||||
|
|
||||||
The format can be described more formally as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
<subsystem>: <what changed>
|
|
||||||
<BLANK LINE>
|
|
||||||
<why this change was made>
|
|
||||||
<BLANK LINE>
|
|
||||||
<footer>
|
|
||||||
```
|
|
||||||
|
|
||||||
The first line is the subject and should be no longer than 70 characters, the
|
|
||||||
second line is always blank, and other lines should be wrapped at 80 characters.
|
|
||||||
This allows the message to be easier to read on GitHub as well as in various
|
|
||||||
git tools.
|
|
36
vendor/github.com/coreos/go-oidc/DCO
generated
vendored
36
vendor/github.com/coreos/go-oidc/DCO
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
Developer Certificate of Origin
|
|
||||||
Version 1.1
|
|
||||||
|
|
||||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
|
||||||
660 York Street, Suite 102,
|
|
||||||
San Francisco, CA 94110 USA
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies of this
|
|
||||||
license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
|
|
||||||
Developer's Certificate of Origin 1.1
|
|
||||||
|
|
||||||
By making a contribution to this project, I certify that:
|
|
||||||
|
|
||||||
(a) The contribution was created in whole or in part by me and I
|
|
||||||
have the right to submit it under the open source license
|
|
||||||
indicated in the file; or
|
|
||||||
|
|
||||||
(b) The contribution is based upon previous work that, to the best
|
|
||||||
of my knowledge, is covered under an appropriate open source
|
|
||||||
license and I have the right under that license to submit that
|
|
||||||
work with modifications, whether created in whole or in part
|
|
||||||
by me, under the same open source license (unless I am
|
|
||||||
permitted to submit under a different license), as indicated
|
|
||||||
in the file; or
|
|
||||||
|
|
||||||
(c) The contribution was provided directly to me by some other
|
|
||||||
person who certified (a), (b) or (c) and I have not modified
|
|
||||||
it.
|
|
||||||
|
|
||||||
(d) I understand and agree that this project and the contribution
|
|
||||||
are public and that a record of the contribution (including all
|
|
||||||
personal information I submit with it, including my sign-off) is
|
|
||||||
maintained indefinitely and may be redistributed consistent with
|
|
||||||
this project or the open source license(s) involved.
|
|
202
vendor/github.com/coreos/go-oidc/LICENSE
generated
vendored
202
vendor/github.com/coreos/go-oidc/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
3
vendor/github.com/coreos/go-oidc/MAINTAINERS
generated
vendored
3
vendor/github.com/coreos/go-oidc/MAINTAINERS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
Eric Chiang <ericchiang@google.com> (@ericchiang)
|
|
||||||
Mike Danese <mikedanese@google.com> (@mikedanese)
|
|
||||||
Rithu Leena John <rjohn@redhat.com> (@rithujohn191)
|
|
5
vendor/github.com/coreos/go-oidc/NOTICE
generated
vendored
5
vendor/github.com/coreos/go-oidc/NOTICE
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
CoreOS Project
|
|
||||||
Copyright 2014 CoreOS, Inc
|
|
||||||
|
|
||||||
This product includes software developed at CoreOS, Inc.
|
|
||||||
(http://www.coreos.com/).
|
|
72
vendor/github.com/coreos/go-oidc/README.md
generated
vendored
72
vendor/github.com/coreos/go-oidc/README.md
generated
vendored
@ -1,72 +0,0 @@
|
|||||||
# go-oidc
|
|
||||||
|
|
||||||
[![GoDoc](https://godoc.org/github.com/coreos/go-oidc?status.svg)](https://godoc.org/github.com/coreos/go-oidc)
|
|
||||||
[![Build Status](https://travis-ci.org/coreos/go-oidc.png?branch=master)](https://travis-ci.org/coreos/go-oidc)
|
|
||||||
|
|
||||||
## OpenID Connect support for Go
|
|
||||||
|
|
||||||
This package enables OpenID Connect support for the [golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2) package.
|
|
||||||
|
|
||||||
```go
|
|
||||||
provider, err := oidc.NewProvider(ctx, "https://accounts.google.com")
|
|
||||||
if err != nil {
|
|
||||||
// handle error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure an OpenID Connect aware OAuth2 client.
|
|
||||||
oauth2Config := oauth2.Config{
|
|
||||||
ClientID: clientID,
|
|
||||||
ClientSecret: clientSecret,
|
|
||||||
RedirectURL: redirectURL,
|
|
||||||
|
|
||||||
// Discovery returns the OAuth2 endpoints.
|
|
||||||
Endpoint: provider.Endpoint(),
|
|
||||||
|
|
||||||
// "openid" is a required scope for OpenID Connect flows.
|
|
||||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
OAuth2 redirects are unchanged.
|
|
||||||
|
|
||||||
```go
|
|
||||||
func handleRedirect(w http.ResponseWriter, r *http.Request) {
|
|
||||||
http.Redirect(w, r, oauth2Config.AuthCodeURL(state), http.StatusFound)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The on responses, the provider can be used to verify ID Tokens.
|
|
||||||
|
|
||||||
```go
|
|
||||||
var verifier = provider.Verifier(&oidc.Config{ClientID: clientID})
|
|
||||||
|
|
||||||
func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// Verify state and errors.
|
|
||||||
|
|
||||||
oauth2Token, err := oauth2Config.Exchange(ctx, r.URL.Query().Get("code"))
|
|
||||||
if err != nil {
|
|
||||||
// handle error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the ID Token from OAuth2 token.
|
|
||||||
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
|
|
||||||
if !ok {
|
|
||||||
// handle missing token
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse and verify ID Token payload.
|
|
||||||
idToken, err := verifier.Verify(ctx, rawIDToken)
|
|
||||||
if err != nil {
|
|
||||||
// handle error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract custom claims
|
|
||||||
var claims struct {
|
|
||||||
Email string `json:"email"`
|
|
||||||
Verified bool `json:"email_verified"`
|
|
||||||
}
|
|
||||||
if err := idToken.Claims(&claims); err != nil {
|
|
||||||
// handle error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
61
vendor/github.com/coreos/go-oidc/code-of-conduct.md
generated
vendored
61
vendor/github.com/coreos/go-oidc/code-of-conduct.md
generated
vendored
@ -1,61 +0,0 @@
|
|||||||
## CoreOS Community Code of Conduct
|
|
||||||
|
|
||||||
### Contributor Code of Conduct
|
|
||||||
|
|
||||||
As contributors and maintainers of this project, and in the interest of
|
|
||||||
fostering an open and welcoming community, we pledge to respect all people who
|
|
||||||
contribute through reporting issues, posting feature requests, updating
|
|
||||||
documentation, submitting pull requests or patches, and other activities.
|
|
||||||
|
|
||||||
We are committed to making participation in this project a harassment-free
|
|
||||||
experience for everyone, regardless of level of experience, gender, gender
|
|
||||||
identity and expression, sexual orientation, disability, personal appearance,
|
|
||||||
body size, race, ethnicity, age, religion, or nationality.
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery
|
|
||||||
* Personal attacks
|
|
||||||
* Trolling or insulting/derogatory comments
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as physical or electronic addresses, without explicit permission
|
|
||||||
* Other unethical or unprofessional conduct.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or
|
|
||||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
||||||
that are not aligned to this Code of Conduct. By adopting this Code of Conduct,
|
|
||||||
project maintainers commit themselves to fairly and consistently applying these
|
|
||||||
principles to every aspect of managing this project. Project maintainers who do
|
|
||||||
not follow or enforce the Code of Conduct may be permanently removed from the
|
|
||||||
project team.
|
|
||||||
|
|
||||||
This code of conduct applies both within project spaces and in public spaces
|
|
||||||
when an individual is representing the project or its community.
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported by contacting a project maintainer, Brandon Philips
|
|
||||||
<brandon.philips@coreos.com>, and/or Rithu John <rithu.john@coreos.com>.
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the Contributor Covenant
|
|
||||||
(http://contributor-covenant.org), version 1.2.0, available at
|
|
||||||
http://contributor-covenant.org/version/1/2/0/
|
|
||||||
|
|
||||||
### CoreOS Events Code of Conduct
|
|
||||||
|
|
||||||
CoreOS events are working conferences intended for professional networking and
|
|
||||||
collaboration in the CoreOS community. Attendees are expected to behave
|
|
||||||
according to professional standards and in accordance with their employer’s
|
|
||||||
policies on appropriate workplace behavior.
|
|
||||||
|
|
||||||
While at CoreOS events or related social networking opportunities, attendees
|
|
||||||
should not engage in discriminatory or offensive speech or actions including
|
|
||||||
but not limited to gender, sexuality, race, age, disability, or religion.
|
|
||||||
Speakers should be especially aware of these concerns.
|
|
||||||
|
|
||||||
CoreOS does not condone any statements by speakers contrary to these standards.
|
|
||||||
CoreOS reserves the right to deny entrance and/or eject from an event (without
|
|
||||||
refund) any individual found to be engaging in discriminatory or offensive
|
|
||||||
speech or actions.
|
|
||||||
|
|
||||||
Please bring any concerns to the immediate attention of designated on-site
|
|
||||||
staff, Brandon Philips <brandon.philips@coreos.com>, and/or Rithu John <rithu.john@coreos.com>.
|
|
20
vendor/github.com/coreos/go-oidc/jose.go
generated
vendored
20
vendor/github.com/coreos/go-oidc/jose.go
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
// +build !golint
|
|
||||||
|
|
||||||
// Don't lint this file. We don't want to have to add a comment to each constant.
|
|
||||||
|
|
||||||
package oidc
|
|
||||||
|
|
||||||
const (
|
|
||||||
// JOSE asymmetric signing algorithm values as defined by RFC 7518
|
|
||||||
//
|
|
||||||
// see: https://tools.ietf.org/html/rfc7518#section-3.1
|
|
||||||
RS256 = "RS256" // RSASSA-PKCS-v1.5 using SHA-256
|
|
||||||
RS384 = "RS384" // RSASSA-PKCS-v1.5 using SHA-384
|
|
||||||
RS512 = "RS512" // RSASSA-PKCS-v1.5 using SHA-512
|
|
||||||
ES256 = "ES256" // ECDSA using P-256 and SHA-256
|
|
||||||
ES384 = "ES384" // ECDSA using P-384 and SHA-384
|
|
||||||
ES512 = "ES512" // ECDSA using P-521 and SHA-512
|
|
||||||
PS256 = "PS256" // RSASSA-PSS using SHA256 and MGF1-SHA256
|
|
||||||
PS384 = "PS384" // RSASSA-PSS using SHA384 and MGF1-SHA384
|
|
||||||
PS512 = "PS512" // RSASSA-PSS using SHA512 and MGF1-SHA512
|
|
||||||
)
|
|
228
vendor/github.com/coreos/go-oidc/jwks.go
generated
vendored
228
vendor/github.com/coreos/go-oidc/jwks.go
generated
vendored
@ -1,228 +0,0 @@
|
|||||||
package oidc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pquerna/cachecontrol"
|
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// keysExpiryDelta is the allowed clock skew between a client and the OpenID Connect
|
|
||||||
// server.
|
|
||||||
//
|
|
||||||
// When keys expire, they are valid for this amount of time after.
|
|
||||||
//
|
|
||||||
// If the keys have not expired, and an ID Token claims it was signed by a key not in
|
|
||||||
// the cache, if and only if the keys expire in this amount of time, the keys will be
|
|
||||||
// updated.
|
|
||||||
const keysExpiryDelta = 30 * time.Second
|
|
||||||
|
|
||||||
// NewRemoteKeySet returns a KeySet that can validate JSON web tokens by using HTTP
|
|
||||||
// GETs to fetch JSON web token sets hosted at a remote URL. This is automatically
|
|
||||||
// used by NewProvider using the URLs returned by OpenID Connect discovery, but is
|
|
||||||
// exposed for providers that don't support discovery or to prevent round trips to the
|
|
||||||
// discovery URL.
|
|
||||||
//
|
|
||||||
// The returned KeySet is a long lived verifier that caches keys based on cache-control
|
|
||||||
// headers. Reuse a common remote key set instead of creating new ones as needed.
|
|
||||||
//
|
|
||||||
// The behavior of the returned KeySet is undefined once the context is canceled.
|
|
||||||
func NewRemoteKeySet(ctx context.Context, jwksURL string) KeySet {
|
|
||||||
return newRemoteKeySet(ctx, jwksURL, time.Now)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRemoteKeySet(ctx context.Context, jwksURL string, now func() time.Time) *remoteKeySet {
|
|
||||||
if now == nil {
|
|
||||||
now = time.Now
|
|
||||||
}
|
|
||||||
return &remoteKeySet{jwksURL: jwksURL, ctx: ctx, now: now}
|
|
||||||
}
|
|
||||||
|
|
||||||
type remoteKeySet struct {
|
|
||||||
jwksURL string
|
|
||||||
ctx context.Context
|
|
||||||
now func() time.Time
|
|
||||||
|
|
||||||
// guard all other fields
|
|
||||||
mu sync.Mutex
|
|
||||||
|
|
||||||
// inflight suppresses parallel execution of updateKeys and allows
|
|
||||||
// multiple goroutines to wait for its result.
|
|
||||||
inflight *inflight
|
|
||||||
|
|
||||||
// A set of cached keys and their expiry.
|
|
||||||
cachedKeys []jose.JSONWebKey
|
|
||||||
expiry time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// inflight is used to wait on some in-flight request from multiple goroutines.
|
|
||||||
type inflight struct {
|
|
||||||
doneCh chan struct{}
|
|
||||||
|
|
||||||
keys []jose.JSONWebKey
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func newInflight() *inflight {
|
|
||||||
return &inflight{doneCh: make(chan struct{})}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait returns a channel that multiple goroutines can receive on. Once it returns
|
|
||||||
// a value, the inflight request is done and result() can be inspected.
|
|
||||||
func (i *inflight) wait() <-chan struct{} {
|
|
||||||
return i.doneCh
|
|
||||||
}
|
|
||||||
|
|
||||||
// done can only be called by a single goroutine. It records the result of the
|
|
||||||
// inflight request and signals other goroutines that the result is safe to
|
|
||||||
// inspect.
|
|
||||||
func (i *inflight) done(keys []jose.JSONWebKey, err error) {
|
|
||||||
i.keys = keys
|
|
||||||
i.err = err
|
|
||||||
close(i.doneCh)
|
|
||||||
}
|
|
||||||
|
|
||||||
// result cannot be called until the wait() channel has returned a value.
|
|
||||||
func (i *inflight) result() ([]jose.JSONWebKey, error) {
|
|
||||||
return i.keys, i.err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *remoteKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
|
|
||||||
jws, err := jose.ParseSigned(jwt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
|
|
||||||
}
|
|
||||||
return r.verify(ctx, jws)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *remoteKeySet) verify(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) {
|
|
||||||
// We don't support JWTs signed with multiple signatures.
|
|
||||||
keyID := ""
|
|
||||||
for _, sig := range jws.Signatures {
|
|
||||||
keyID = sig.Header.KeyID
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
keys, expiry := r.keysFromCache()
|
|
||||||
|
|
||||||
// Don't check expiry yet. This optimizes for when the provider is unavailable.
|
|
||||||
for _, key := range keys {
|
|
||||||
if keyID == "" || key.KeyID == keyID {
|
|
||||||
if payload, err := jws.Verify(&key); err == nil {
|
|
||||||
return payload, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !r.now().Add(keysExpiryDelta).After(expiry) {
|
|
||||||
// Keys haven't expired, don't refresh.
|
|
||||||
return nil, errors.New("failed to verify id token signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
keys, err := r.keysFromRemote(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("fetching keys %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, key := range keys {
|
|
||||||
if keyID == "" || key.KeyID == keyID {
|
|
||||||
if payload, err := jws.Verify(&key); err == nil {
|
|
||||||
return payload, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, errors.New("failed to verify id token signature")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *remoteKeySet) keysFromCache() (keys []jose.JSONWebKey, expiry time.Time) {
|
|
||||||
r.mu.Lock()
|
|
||||||
defer r.mu.Unlock()
|
|
||||||
return r.cachedKeys, r.expiry
|
|
||||||
}
|
|
||||||
|
|
||||||
// keysFromRemote syncs the key set from the remote set, records the values in the
|
|
||||||
// cache, and returns the key set.
|
|
||||||
func (r *remoteKeySet) keysFromRemote(ctx context.Context) ([]jose.JSONWebKey, error) {
|
|
||||||
// Need to lock to inspect the inflight request field.
|
|
||||||
r.mu.Lock()
|
|
||||||
// If there's not a current inflight request, create one.
|
|
||||||
if r.inflight == nil {
|
|
||||||
r.inflight = newInflight()
|
|
||||||
|
|
||||||
// This goroutine has exclusive ownership over the current inflight
|
|
||||||
// request. It releases the resource by nil'ing the inflight field
|
|
||||||
// once the goroutine is done.
|
|
||||||
go func() {
|
|
||||||
// Sync keys and finish inflight when that's done.
|
|
||||||
keys, expiry, err := r.updateKeys()
|
|
||||||
|
|
||||||
r.inflight.done(keys, err)
|
|
||||||
|
|
||||||
// Lock to update the keys and indicate that there is no longer an
|
|
||||||
// inflight request.
|
|
||||||
r.mu.Lock()
|
|
||||||
defer r.mu.Unlock()
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
r.cachedKeys = keys
|
|
||||||
r.expiry = expiry
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free inflight so a different request can run.
|
|
||||||
r.inflight = nil
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
inflight := r.inflight
|
|
||||||
r.mu.Unlock()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case <-inflight.wait():
|
|
||||||
return inflight.result()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *remoteKeySet) updateKeys() ([]jose.JSONWebKey, time.Time, error) {
|
|
||||||
req, err := http.NewRequest("GET", r.jwksURL, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, fmt.Errorf("oidc: can't create request: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := doRequest(r.ctx, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, fmt.Errorf("oidc: get keys failed %v", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, fmt.Errorf("unable to read response body: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, time.Time{}, fmt.Errorf("oidc: get keys failed: %s %s", resp.Status, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
var keySet jose.JSONWebKeySet
|
|
||||||
err = unmarshalResp(resp, body, &keySet)
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, fmt.Errorf("oidc: failed to decode keys: %v %s", err, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the server doesn't provide cache control headers, assume the
|
|
||||||
// keys expire immediately.
|
|
||||||
expiry := r.now()
|
|
||||||
|
|
||||||
_, e, err := cachecontrol.CachableResponse(req, resp, cachecontrol.Options{})
|
|
||||||
if err == nil && e.After(expiry) {
|
|
||||||
expiry = e
|
|
||||||
}
|
|
||||||
return keySet.Keys, expiry, nil
|
|
||||||
}
|
|
409
vendor/github.com/coreos/go-oidc/oidc.go
generated
vendored
409
vendor/github.com/coreos/go-oidc/oidc.go
generated
vendored
@ -1,409 +0,0 @@
|
|||||||
// Package oidc implements OpenID Connect client logic for the golang.org/x/oauth2 package.
|
|
||||||
package oidc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"hash"
|
|
||||||
"io/ioutil"
|
|
||||||
"mime"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// ScopeOpenID is the mandatory scope for all OpenID Connect OAuth2 requests.
|
|
||||||
ScopeOpenID = "openid"
|
|
||||||
|
|
||||||
// ScopeOfflineAccess is an optional scope defined by OpenID Connect for requesting
|
|
||||||
// OAuth2 refresh tokens.
|
|
||||||
//
|
|
||||||
// Support for this scope differs between OpenID Connect providers. For instance
|
|
||||||
// Google rejects it, favoring appending "access_type=offline" as part of the
|
|
||||||
// authorization request instead.
|
|
||||||
//
|
|
||||||
// See: https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
|
|
||||||
ScopeOfflineAccess = "offline_access"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errNoAtHash = errors.New("id token did not have an access token hash")
|
|
||||||
errInvalidAtHash = errors.New("access token hash does not match value in ID token")
|
|
||||||
)
|
|
||||||
|
|
||||||
// ClientContext returns a new Context that carries the provided HTTP client.
|
|
||||||
//
|
|
||||||
// This method sets the same context key used by the golang.org/x/oauth2 package,
|
|
||||||
// so the returned context works for that package too.
|
|
||||||
//
|
|
||||||
// myClient := &http.Client{}
|
|
||||||
// ctx := oidc.ClientContext(parentContext, myClient)
|
|
||||||
//
|
|
||||||
// // This will use the custom client
|
|
||||||
// provider, err := oidc.NewProvider(ctx, "https://accounts.example.com")
|
|
||||||
//
|
|
||||||
func ClientContext(ctx context.Context, client *http.Client) context.Context {
|
|
||||||
return context.WithValue(ctx, oauth2.HTTPClient, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
func doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
|
|
||||||
client := http.DefaultClient
|
|
||||||
if c, ok := ctx.Value(oauth2.HTTPClient).(*http.Client); ok {
|
|
||||||
client = c
|
|
||||||
}
|
|
||||||
return client.Do(req.WithContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provider represents an OpenID Connect server's configuration.
|
|
||||||
type Provider struct {
|
|
||||||
issuer string
|
|
||||||
authURL string
|
|
||||||
tokenURL string
|
|
||||||
userInfoURL string
|
|
||||||
algorithms []string
|
|
||||||
|
|
||||||
// Raw claims returned by the server.
|
|
||||||
rawClaims []byte
|
|
||||||
|
|
||||||
remoteKeySet KeySet
|
|
||||||
}
|
|
||||||
|
|
||||||
type cachedKeys struct {
|
|
||||||
keys []jose.JSONWebKey
|
|
||||||
expiry time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type providerJSON struct {
|
|
||||||
Issuer string `json:"issuer"`
|
|
||||||
AuthURL string `json:"authorization_endpoint"`
|
|
||||||
TokenURL string `json:"token_endpoint"`
|
|
||||||
JWKSURL string `json:"jwks_uri"`
|
|
||||||
UserInfoURL string `json:"userinfo_endpoint"`
|
|
||||||
Algorithms []string `json:"id_token_signing_alg_values_supported"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// supportedAlgorithms is a list of algorithms explicitly supported by this
|
|
||||||
// package. If a provider supports other algorithms, such as HS256 or none,
|
|
||||||
// those values won't be passed to the IDTokenVerifier.
|
|
||||||
var supportedAlgorithms = map[string]bool{
|
|
||||||
RS256: true,
|
|
||||||
RS384: true,
|
|
||||||
RS512: true,
|
|
||||||
ES256: true,
|
|
||||||
ES384: true,
|
|
||||||
ES512: true,
|
|
||||||
PS256: true,
|
|
||||||
PS384: true,
|
|
||||||
PS512: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewProvider uses the OpenID Connect discovery mechanism to construct a Provider.
|
|
||||||
//
|
|
||||||
// The issuer is the URL identifier for the service. For example: "https://accounts.google.com"
|
|
||||||
// or "https://login.salesforce.com".
|
|
||||||
func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
|
|
||||||
wellKnown := strings.TrimSuffix(issuer, "/") + "/.well-known/openid-configuration"
|
|
||||||
req, err := http.NewRequest("GET", wellKnown, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
resp, err := doRequest(ctx, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to read response body: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("%s: %s", resp.Status, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
var p providerJSON
|
|
||||||
err = unmarshalResp(resp, body, &p)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: failed to decode provider discovery object: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Issuer != issuer {
|
|
||||||
return nil, fmt.Errorf("oidc: issuer did not match the issuer returned by provider, expected %q got %q", issuer, p.Issuer)
|
|
||||||
}
|
|
||||||
var algs []string
|
|
||||||
for _, a := range p.Algorithms {
|
|
||||||
if supportedAlgorithms[a] {
|
|
||||||
algs = append(algs, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &Provider{
|
|
||||||
issuer: p.Issuer,
|
|
||||||
authURL: p.AuthURL,
|
|
||||||
tokenURL: p.TokenURL,
|
|
||||||
userInfoURL: p.UserInfoURL,
|
|
||||||
algorithms: algs,
|
|
||||||
rawClaims: body,
|
|
||||||
remoteKeySet: NewRemoteKeySet(ctx, p.JWKSURL),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Claims unmarshals raw fields returned by the server during discovery.
|
|
||||||
//
|
|
||||||
// var claims struct {
|
|
||||||
// ScopesSupported []string `json:"scopes_supported"`
|
|
||||||
// ClaimsSupported []string `json:"claims_supported"`
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if err := provider.Claims(&claims); err != nil {
|
|
||||||
// // handle unmarshaling error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// For a list of fields defined by the OpenID Connect spec see:
|
|
||||||
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
|
||||||
func (p *Provider) Claims(v interface{}) error {
|
|
||||||
if p.rawClaims == nil {
|
|
||||||
return errors.New("oidc: claims not set")
|
|
||||||
}
|
|
||||||
return json.Unmarshal(p.rawClaims, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Endpoint returns the OAuth2 auth and token endpoints for the given provider.
|
|
||||||
func (p *Provider) Endpoint() oauth2.Endpoint {
|
|
||||||
return oauth2.Endpoint{AuthURL: p.authURL, TokenURL: p.tokenURL}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserInfo represents the OpenID Connect userinfo claims.
|
|
||||||
type UserInfo struct {
|
|
||||||
Subject string `json:"sub"`
|
|
||||||
Profile string `json:"profile"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
EmailVerified bool `json:"email_verified"`
|
|
||||||
|
|
||||||
claims []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Claims unmarshals the raw JSON object claims into the provided object.
|
|
||||||
func (u *UserInfo) Claims(v interface{}) error {
|
|
||||||
if u.claims == nil {
|
|
||||||
return errors.New("oidc: claims not set")
|
|
||||||
}
|
|
||||||
return json.Unmarshal(u.claims, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserInfo uses the token source to query the provider's user info endpoint.
|
|
||||||
func (p *Provider) UserInfo(ctx context.Context, tokenSource oauth2.TokenSource) (*UserInfo, error) {
|
|
||||||
if p.userInfoURL == "" {
|
|
||||||
return nil, errors.New("oidc: user info endpoint is not supported by this provider")
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", p.userInfoURL, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: create GET request: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := tokenSource.Token()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: get access token: %v", err)
|
|
||||||
}
|
|
||||||
token.SetAuthHeader(req)
|
|
||||||
|
|
||||||
resp, err := doRequest(ctx, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("%s: %s", resp.Status, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
var userInfo UserInfo
|
|
||||||
if err := json.Unmarshal(body, &userInfo); err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: failed to decode userinfo: %v", err)
|
|
||||||
}
|
|
||||||
userInfo.claims = body
|
|
||||||
return &userInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IDToken is an OpenID Connect extension that provides a predictable representation
|
|
||||||
// of an authorization event.
|
|
||||||
//
|
|
||||||
// The ID Token only holds fields OpenID Connect requires. To access additional
|
|
||||||
// claims returned by the server, use the Claims method.
|
|
||||||
type IDToken struct {
|
|
||||||
// The URL of the server which issued this token. OpenID Connect
|
|
||||||
// requires this value always be identical to the URL used for
|
|
||||||
// initial discovery.
|
|
||||||
//
|
|
||||||
// Note: Because of a known issue with Google Accounts' implementation
|
|
||||||
// this value may differ when using Google.
|
|
||||||
//
|
|
||||||
// See: https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
|
|
||||||
Issuer string
|
|
||||||
|
|
||||||
// The client ID, or set of client IDs, that this token is issued for. For
|
|
||||||
// common uses, this is the client that initialized the auth flow.
|
|
||||||
//
|
|
||||||
// This package ensures the audience contains an expected value.
|
|
||||||
Audience []string
|
|
||||||
|
|
||||||
// A unique string which identifies the end user.
|
|
||||||
Subject string
|
|
||||||
|
|
||||||
// Expiry of the token. Ths package will not process tokens that have
|
|
||||||
// expired unless that validation is explicitly turned off.
|
|
||||||
Expiry time.Time
|
|
||||||
// When the token was issued by the provider.
|
|
||||||
IssuedAt time.Time
|
|
||||||
|
|
||||||
// Initial nonce provided during the authentication redirect.
|
|
||||||
//
|
|
||||||
// This package does NOT provided verification on the value of this field
|
|
||||||
// and it's the user's responsibility to ensure it contains a valid value.
|
|
||||||
Nonce string
|
|
||||||
|
|
||||||
// at_hash claim, if set in the ID token. Callers can verify an access token
|
|
||||||
// that corresponds to the ID token using the VerifyAccessToken method.
|
|
||||||
AccessTokenHash string
|
|
||||||
|
|
||||||
// signature algorithm used for ID token, needed to compute a verification hash of an
|
|
||||||
// access token
|
|
||||||
sigAlgorithm string
|
|
||||||
|
|
||||||
// Raw payload of the id_token.
|
|
||||||
claims []byte
|
|
||||||
|
|
||||||
// Map of distributed claim names to claim sources
|
|
||||||
distributedClaims map[string]claimSource
|
|
||||||
}
|
|
||||||
|
|
||||||
// Claims unmarshals the raw JSON payload of the ID Token into a provided struct.
|
|
||||||
//
|
|
||||||
// idToken, err := idTokenVerifier.Verify(rawIDToken)
|
|
||||||
// if err != nil {
|
|
||||||
// // handle error
|
|
||||||
// }
|
|
||||||
// var claims struct {
|
|
||||||
// Email string `json:"email"`
|
|
||||||
// EmailVerified bool `json:"email_verified"`
|
|
||||||
// }
|
|
||||||
// if err := idToken.Claims(&claims); err != nil {
|
|
||||||
// // handle error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
func (i *IDToken) Claims(v interface{}) error {
|
|
||||||
if i.claims == nil {
|
|
||||||
return errors.New("oidc: claims not set")
|
|
||||||
}
|
|
||||||
return json.Unmarshal(i.claims, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyAccessToken verifies that the hash of the access token that corresponds to the iD token
|
|
||||||
// matches the hash in the id token. It returns an error if the hashes don't match.
|
|
||||||
// It is the caller's responsibility to ensure that the optional access token hash is present for the ID token
|
|
||||||
// before calling this method. See https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
|
|
||||||
func (i *IDToken) VerifyAccessToken(accessToken string) error {
|
|
||||||
if i.AccessTokenHash == "" {
|
|
||||||
return errNoAtHash
|
|
||||||
}
|
|
||||||
var h hash.Hash
|
|
||||||
switch i.sigAlgorithm {
|
|
||||||
case RS256, ES256, PS256:
|
|
||||||
h = sha256.New()
|
|
||||||
case RS384, ES384, PS384:
|
|
||||||
h = sha512.New384()
|
|
||||||
case RS512, ES512, PS512:
|
|
||||||
h = sha512.New()
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("oidc: unsupported signing algorithm %q", i.sigAlgorithm)
|
|
||||||
}
|
|
||||||
h.Write([]byte(accessToken)) // hash documents that Write will never return an error
|
|
||||||
sum := h.Sum(nil)[:h.Size()/2]
|
|
||||||
actual := base64.RawURLEncoding.EncodeToString(sum)
|
|
||||||
if actual != i.AccessTokenHash {
|
|
||||||
return errInvalidAtHash
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type idToken struct {
|
|
||||||
Issuer string `json:"iss"`
|
|
||||||
Subject string `json:"sub"`
|
|
||||||
Audience audience `json:"aud"`
|
|
||||||
Expiry jsonTime `json:"exp"`
|
|
||||||
IssuedAt jsonTime `json:"iat"`
|
|
||||||
NotBefore *jsonTime `json:"nbf"`
|
|
||||||
Nonce string `json:"nonce"`
|
|
||||||
AtHash string `json:"at_hash"`
|
|
||||||
ClaimNames map[string]string `json:"_claim_names"`
|
|
||||||
ClaimSources map[string]claimSource `json:"_claim_sources"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type claimSource struct {
|
|
||||||
Endpoint string `json:"endpoint"`
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type audience []string
|
|
||||||
|
|
||||||
func (a *audience) UnmarshalJSON(b []byte) error {
|
|
||||||
var s string
|
|
||||||
if json.Unmarshal(b, &s) == nil {
|
|
||||||
*a = audience{s}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var auds []string
|
|
||||||
if err := json.Unmarshal(b, &auds); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*a = audience(auds)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type jsonTime time.Time
|
|
||||||
|
|
||||||
func (j *jsonTime) UnmarshalJSON(b []byte) error {
|
|
||||||
var n json.Number
|
|
||||||
if err := json.Unmarshal(b, &n); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var unix int64
|
|
||||||
|
|
||||||
if t, err := n.Int64(); err == nil {
|
|
||||||
unix = t
|
|
||||||
} else {
|
|
||||||
f, err := n.Float64()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
unix = int64(f)
|
|
||||||
}
|
|
||||||
*j = jsonTime(time.Unix(unix, 0))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshalResp(r *http.Response, body []byte, v interface{}) error {
|
|
||||||
err := json.Unmarshal(body, &v)
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ct := r.Header.Get("Content-Type")
|
|
||||||
mediaType, _, parseErr := mime.ParseMediaType(ct)
|
|
||||||
if parseErr == nil && mediaType == "application/json" {
|
|
||||||
return fmt.Errorf("got Content-Type = application/json, but could not unmarshal as JSON: %v", err)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("expected Content-Type = application/json, got %q: %v", ct, err)
|
|
||||||
}
|
|
16
vendor/github.com/coreos/go-oidc/test
generated
vendored
16
vendor/github.com/coreos/go-oidc/test
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Filter out any files with a !golint build tag.
|
|
||||||
LINTABLE=$( go list -tags=golint -f '
|
|
||||||
{{- range $i, $file := .GoFiles -}}
|
|
||||||
{{ $file }} {{ end }}
|
|
||||||
{{ range $i, $file := .TestGoFiles -}}
|
|
||||||
{{ $file }} {{ end }}' github.com/coreos/go-oidc )
|
|
||||||
|
|
||||||
go test -v -i -race github.com/coreos/go-oidc/...
|
|
||||||
go test -v -race github.com/coreos/go-oidc/...
|
|
||||||
golint -set_exit_status $LINTABLE
|
|
||||||
go vet github.com/coreos/go-oidc/...
|
|
||||||
go build -v ./example/...
|
|
336
vendor/github.com/coreos/go-oidc/verify.go
generated
vendored
336
vendor/github.com/coreos/go-oidc/verify.go
generated
vendored
@ -1,336 +0,0 @@
|
|||||||
package oidc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
jose "gopkg.in/square/go-jose.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
issuerGoogleAccounts = "https://accounts.google.com"
|
|
||||||
issuerGoogleAccountsNoScheme = "accounts.google.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
// KeySet is a set of publc JSON Web Keys that can be used to validate the signature
|
|
||||||
// of JSON web tokens. This is expected to be backed by a remote key set through
|
|
||||||
// provider metadata discovery or an in-memory set of keys delivered out-of-band.
|
|
||||||
type KeySet interface {
|
|
||||||
// VerifySignature parses the JSON web token, verifies the signature, and returns
|
|
||||||
// the raw payload. Header and claim fields are validated by other parts of the
|
|
||||||
// package. For example, the KeySet does not need to check values such as signature
|
|
||||||
// algorithm, issuer, and audience since the IDTokenVerifier validates these values
|
|
||||||
// independently.
|
|
||||||
//
|
|
||||||
// If VerifySignature makes HTTP requests to verify the token, it's expected to
|
|
||||||
// use any HTTP client associated with the context through ClientContext.
|
|
||||||
VerifySignature(ctx context.Context, jwt string) (payload []byte, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IDTokenVerifier provides verification for ID Tokens.
|
|
||||||
type IDTokenVerifier struct {
|
|
||||||
keySet KeySet
|
|
||||||
config *Config
|
|
||||||
issuer string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVerifier returns a verifier manually constructed from a key set and issuer URL.
|
|
||||||
//
|
|
||||||
// It's easier to use provider discovery to construct an IDTokenVerifier than creating
|
|
||||||
// one directly. This method is intended to be used with provider that don't support
|
|
||||||
// metadata discovery, or avoiding round trips when the key set URL is already known.
|
|
||||||
//
|
|
||||||
// This constructor can be used to create a verifier directly using the issuer URL and
|
|
||||||
// JSON Web Key Set URL without using discovery:
|
|
||||||
//
|
|
||||||
// keySet := oidc.NewRemoteKeySet(ctx, "https://www.googleapis.com/oauth2/v3/certs")
|
|
||||||
// verifier := oidc.NewVerifier("https://accounts.google.com", keySet, config)
|
|
||||||
//
|
|
||||||
// Since KeySet is an interface, this constructor can also be used to supply custom
|
|
||||||
// public key sources. For example, if a user wanted to supply public keys out-of-band
|
|
||||||
// and hold them statically in-memory:
|
|
||||||
//
|
|
||||||
// // Custom KeySet implementation.
|
|
||||||
// keySet := newStatisKeySet(publicKeys...)
|
|
||||||
//
|
|
||||||
// // Verifier uses the custom KeySet implementation.
|
|
||||||
// verifier := oidc.NewVerifier("https://auth.example.com", keySet, config)
|
|
||||||
//
|
|
||||||
func NewVerifier(issuerURL string, keySet KeySet, config *Config) *IDTokenVerifier {
|
|
||||||
return &IDTokenVerifier{keySet: keySet, config: config, issuer: issuerURL}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config is the configuration for an IDTokenVerifier.
|
|
||||||
type Config struct {
|
|
||||||
// Expected audience of the token. For a majority of the cases this is expected to be
|
|
||||||
// the ID of the client that initialized the login flow. It may occasionally differ if
|
|
||||||
// the provider supports the authorizing party (azp) claim.
|
|
||||||
//
|
|
||||||
// If not provided, users must explicitly set SkipClientIDCheck.
|
|
||||||
ClientID string
|
|
||||||
// If specified, only this set of algorithms may be used to sign the JWT.
|
|
||||||
//
|
|
||||||
// If the IDTokenVerifier is created from a provider with (*Provider).Verifier, this
|
|
||||||
// defaults to the set of algorithms the provider supports. Otherwise this values
|
|
||||||
// defaults to RS256.
|
|
||||||
SupportedSigningAlgs []string
|
|
||||||
|
|
||||||
// If true, no ClientID check performed. Must be true if ClientID field is empty.
|
|
||||||
SkipClientIDCheck bool
|
|
||||||
// If true, token expiry is not checked.
|
|
||||||
SkipExpiryCheck bool
|
|
||||||
|
|
||||||
// SkipIssuerCheck is intended for specialized cases where the the caller wishes to
|
|
||||||
// defer issuer validation. When enabled, callers MUST independently verify the Token's
|
|
||||||
// Issuer is a known good value.
|
|
||||||
//
|
|
||||||
// Mismatched issuers often indicate client mis-configuration. If mismatches are
|
|
||||||
// unexpected, evaluate if the provided issuer URL is incorrect instead of enabling
|
|
||||||
// this option.
|
|
||||||
SkipIssuerCheck bool
|
|
||||||
|
|
||||||
// Time function to check Token expiry. Defaults to time.Now
|
|
||||||
Now func() time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verifier returns an IDTokenVerifier that uses the provider's key set to verify JWTs.
|
|
||||||
//
|
|
||||||
// The returned IDTokenVerifier is tied to the Provider's context and its behavior is
|
|
||||||
// undefined once the Provider's context is canceled.
|
|
||||||
func (p *Provider) Verifier(config *Config) *IDTokenVerifier {
|
|
||||||
if len(config.SupportedSigningAlgs) == 0 && len(p.algorithms) > 0 {
|
|
||||||
// Make a copy so we don't modify the config values.
|
|
||||||
cp := &Config{}
|
|
||||||
*cp = *config
|
|
||||||
cp.SupportedSigningAlgs = p.algorithms
|
|
||||||
config = cp
|
|
||||||
}
|
|
||||||
return NewVerifier(p.issuer, p.remoteKeySet, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseJWT(p string) ([]byte, error) {
|
|
||||||
parts := strings.Split(p, ".")
|
|
||||||
if len(parts) < 2 {
|
|
||||||
return nil, fmt.Errorf("oidc: malformed jwt, expected 3 parts got %d", len(parts))
|
|
||||||
}
|
|
||||||
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: malformed jwt payload: %v", err)
|
|
||||||
}
|
|
||||||
return payload, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func contains(sli []string, ele string) bool {
|
|
||||||
for _, s := range sli {
|
|
||||||
if s == ele {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the Claims from the distributed JWT token
|
|
||||||
func resolveDistributedClaim(ctx context.Context, verifier *IDTokenVerifier, src claimSource) ([]byte, error) {
|
|
||||||
req, err := http.NewRequest("GET", src.Endpoint, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("malformed request: %v", err)
|
|
||||||
}
|
|
||||||
if src.AccessToken != "" {
|
|
||||||
req.Header.Set("Authorization", "Bearer "+src.AccessToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := doRequest(ctx, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: Request to endpoint failed: %v", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to read response body: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("oidc: request failed: %v", resp.StatusCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := verifier.Verify(ctx, string(body))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("malformed response body: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return token.claims, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseClaim(raw []byte, name string, v interface{}) error {
|
|
||||||
var parsed map[string]json.RawMessage
|
|
||||||
if err := json.Unmarshal(raw, &parsed); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok := parsed[name]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("claim doesn't exist: %s", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.Unmarshal([]byte(val), v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify parses a raw ID Token, verifies it's been signed by the provider, preforms
|
|
||||||
// any additional checks depending on the Config, and returns the payload.
|
|
||||||
//
|
|
||||||
// Verify does NOT do nonce validation, which is the callers responsibility.
|
|
||||||
//
|
|
||||||
// See: https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
|
|
||||||
//
|
|
||||||
// oauth2Token, err := oauth2Config.Exchange(ctx, r.URL.Query().Get("code"))
|
|
||||||
// if err != nil {
|
|
||||||
// // handle error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Extract the ID Token from oauth2 token.
|
|
||||||
// rawIDToken, ok := oauth2Token.Extra("id_token").(string)
|
|
||||||
// if !ok {
|
|
||||||
// // handle error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// token, err := verifier.Verify(ctx, rawIDToken)
|
|
||||||
//
|
|
||||||
func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDToken, error) {
|
|
||||||
jws, err := jose.ParseSigned(rawIDToken)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throw out tokens with invalid claims before trying to verify the token. This lets
|
|
||||||
// us do cheap checks before possibly re-syncing keys.
|
|
||||||
payload, err := parseJWT(rawIDToken)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
|
|
||||||
}
|
|
||||||
var token idToken
|
|
||||||
if err := json.Unmarshal(payload, &token); err != nil {
|
|
||||||
return nil, fmt.Errorf("oidc: failed to unmarshal claims: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
distributedClaims := make(map[string]claimSource)
|
|
||||||
|
|
||||||
//step through the token to map claim names to claim sources"
|
|
||||||
for cn, src := range token.ClaimNames {
|
|
||||||
if src == "" {
|
|
||||||
return nil, fmt.Errorf("oidc: failed to obtain source from claim name")
|
|
||||||
}
|
|
||||||
s, ok := token.ClaimSources[src]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("oidc: source does not exist")
|
|
||||||
}
|
|
||||||
distributedClaims[cn] = s
|
|
||||||
}
|
|
||||||
|
|
||||||
t := &IDToken{
|
|
||||||
Issuer: token.Issuer,
|
|
||||||
Subject: token.Subject,
|
|
||||||
Audience: []string(token.Audience),
|
|
||||||
Expiry: time.Time(token.Expiry),
|
|
||||||
IssuedAt: time.Time(token.IssuedAt),
|
|
||||||
Nonce: token.Nonce,
|
|
||||||
AccessTokenHash: token.AtHash,
|
|
||||||
claims: payload,
|
|
||||||
distributedClaims: distributedClaims,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check issuer.
|
|
||||||
if !v.config.SkipIssuerCheck && t.Issuer != v.issuer {
|
|
||||||
// Google sometimes returns "accounts.google.com" as the issuer claim instead of
|
|
||||||
// the required "https://accounts.google.com". Detect this case and allow it only
|
|
||||||
// for Google.
|
|
||||||
//
|
|
||||||
// We will not add hooks to let other providers go off spec like this.
|
|
||||||
if !(v.issuer == issuerGoogleAccounts && t.Issuer == issuerGoogleAccountsNoScheme) {
|
|
||||||
return nil, fmt.Errorf("oidc: id token issued by a different provider, expected %q got %q", v.issuer, t.Issuer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a client ID has been provided, make sure it's part of the audience. SkipClientIDCheck must be true if ClientID is empty.
|
|
||||||
//
|
|
||||||
// This check DOES NOT ensure that the ClientID is the party to which the ID Token was issued (i.e. Authorized party).
|
|
||||||
if !v.config.SkipClientIDCheck {
|
|
||||||
if v.config.ClientID != "" {
|
|
||||||
if !contains(t.Audience, v.config.ClientID) {
|
|
||||||
return nil, fmt.Errorf("oidc: expected audience %q got %q", v.config.ClientID, t.Audience)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("oidc: invalid configuration, clientID must be provided or SkipClientIDCheck must be set")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a SkipExpiryCheck is false, make sure token is not expired.
|
|
||||||
if !v.config.SkipExpiryCheck {
|
|
||||||
now := time.Now
|
|
||||||
if v.config.Now != nil {
|
|
||||||
now = v.config.Now
|
|
||||||
}
|
|
||||||
nowTime := now()
|
|
||||||
|
|
||||||
if t.Expiry.Before(nowTime) {
|
|
||||||
return nil, fmt.Errorf("oidc: token is expired (Token Expiry: %v)", t.Expiry)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If nbf claim is provided in token, ensure that it is indeed in the past.
|
|
||||||
if token.NotBefore != nil {
|
|
||||||
nbfTime := time.Time(*token.NotBefore)
|
|
||||||
leeway := 1 * time.Minute
|
|
||||||
|
|
||||||
if nowTime.Add(leeway).Before(nbfTime) {
|
|
||||||
return nil, fmt.Errorf("oidc: current time %v before the nbf (not before) time: %v", nowTime, nbfTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(jws.Signatures) {
|
|
||||||
case 0:
|
|
||||||
return nil, fmt.Errorf("oidc: id token not signed")
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("oidc: multiple signatures on id token not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
sig := jws.Signatures[0]
|
|
||||||
supportedSigAlgs := v.config.SupportedSigningAlgs
|
|
||||||
if len(supportedSigAlgs) == 0 {
|
|
||||||
supportedSigAlgs = []string{RS256}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !contains(supportedSigAlgs, sig.Header.Algorithm) {
|
|
||||||
return nil, fmt.Errorf("oidc: id token signed with unsupported algorithm, expected %q got %q", supportedSigAlgs, sig.Header.Algorithm)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.sigAlgorithm = sig.Header.Algorithm
|
|
||||||
|
|
||||||
gotPayload, err := v.keySet.VerifySignature(ctx, rawIDToken)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to verify signature: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that the payload returned by the square actually matches the payload parsed earlier.
|
|
||||||
if !bytes.Equal(gotPayload, payload) {
|
|
||||||
return nil, errors.New("oidc: internal error, payload parsed did not match previous payload")
|
|
||||||
}
|
|
||||||
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nonce returns an auth code option which requires the ID Token created by the
|
|
||||||
// OpenID Connect provider to contain the specified nonce.
|
|
||||||
func Nonce(nonce string) oauth2.AuthCodeOption {
|
|
||||||
return oauth2.SetAuthURLParam("nonce", nonce)
|
|
||||||
}
|
|
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
3
vendor/github.com/golang/protobuf/AUTHORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code refers to The Go Authors for copyright purposes.
|
|
||||||
# The master list of authors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/AUTHORS.
|
|
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
3
vendor/github.com/golang/protobuf/CONTRIBUTORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code was written by the Go contributors.
|
|
||||||
# The master list of contributors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
|
28
vendor/github.com/golang/protobuf/LICENSE
generated
vendored
28
vendor/github.com/golang/protobuf/LICENSE
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
253
vendor/github.com/golang/protobuf/proto/clone.go
generated
vendored
253
vendor/github.com/golang/protobuf/proto/clone.go
generated
vendored
@ -1,253 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Protocol buffer deep copy and merge.
|
|
||||||
// TODO: RawMessage.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Clone returns a deep copy of a protocol buffer.
|
|
||||||
func Clone(src Message) Message {
|
|
||||||
in := reflect.ValueOf(src)
|
|
||||||
if in.IsNil() {
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
out := reflect.New(in.Type().Elem())
|
|
||||||
dst := out.Interface().(Message)
|
|
||||||
Merge(dst, src)
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merger is the interface representing objects that can merge messages of the same type.
|
|
||||||
type Merger interface {
|
|
||||||
// Merge merges src into this message.
|
|
||||||
// Required and optional fields that are set in src will be set to that value in dst.
|
|
||||||
// Elements of repeated fields will be appended.
|
|
||||||
//
|
|
||||||
// Merge may panic if called with a different argument type than the receiver.
|
|
||||||
Merge(src Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// generatedMerger is the custom merge method that generated protos will have.
|
|
||||||
// We must add this method since a generate Merge method will conflict with
|
|
||||||
// many existing protos that have a Merge data field already defined.
|
|
||||||
type generatedMerger interface {
|
|
||||||
XXX_Merge(src Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge merges src into dst.
|
|
||||||
// Required and optional fields that are set in src will be set to that value in dst.
|
|
||||||
// Elements of repeated fields will be appended.
|
|
||||||
// Merge panics if src and dst are not the same type, or if dst is nil.
|
|
||||||
func Merge(dst, src Message) {
|
|
||||||
if m, ok := dst.(Merger); ok {
|
|
||||||
m.Merge(src)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
in := reflect.ValueOf(src)
|
|
||||||
out := reflect.ValueOf(dst)
|
|
||||||
if out.IsNil() {
|
|
||||||
panic("proto: nil destination")
|
|
||||||
}
|
|
||||||
if in.Type() != out.Type() {
|
|
||||||
panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
|
|
||||||
}
|
|
||||||
if in.IsNil() {
|
|
||||||
return // Merge from nil src is a noop
|
|
||||||
}
|
|
||||||
if m, ok := dst.(generatedMerger); ok {
|
|
||||||
m.XXX_Merge(src)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mergeStruct(out.Elem(), in.Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
func mergeStruct(out, in reflect.Value) {
|
|
||||||
sprop := GetProperties(in.Type())
|
|
||||||
for i := 0; i < in.NumField(); i++ {
|
|
||||||
f := in.Type().Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
if emIn, err := extendable(in.Addr().Interface()); err == nil {
|
|
||||||
emOut, _ := extendable(out.Addr().Interface())
|
|
||||||
mIn, muIn := emIn.extensionsRead()
|
|
||||||
if mIn != nil {
|
|
||||||
mOut := emOut.extensionsWrite()
|
|
||||||
muIn.Lock()
|
|
||||||
mergeExtension(mOut, mIn)
|
|
||||||
muIn.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uf := in.FieldByName("XXX_unrecognized")
|
|
||||||
if !uf.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uin := uf.Bytes()
|
|
||||||
if len(uin) > 0 {
|
|
||||||
out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mergeAny performs a merge between two values of the same type.
|
|
||||||
// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
|
|
||||||
// prop is set if this is a struct field (it may be nil).
|
|
||||||
func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
|
|
||||||
if in.Type() == protoMessageType {
|
|
||||||
if !in.IsNil() {
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
|
|
||||||
} else {
|
|
||||||
Merge(out.Interface().(Message), in.Interface().(Message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch in.Kind() {
|
|
||||||
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.String, reflect.Uint32, reflect.Uint64:
|
|
||||||
if !viaPtr && isProto3Zero(in) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
out.Set(in)
|
|
||||||
case reflect.Interface:
|
|
||||||
// Probably a oneof field; copy non-nil values.
|
|
||||||
if in.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Allocate destination if it is not set, or set to a different type.
|
|
||||||
// Otherwise we will merge as normal.
|
|
||||||
if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
|
|
||||||
out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
|
|
||||||
}
|
|
||||||
mergeAny(out.Elem(), in.Elem(), false, nil)
|
|
||||||
case reflect.Map:
|
|
||||||
if in.Len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.MakeMap(in.Type()))
|
|
||||||
}
|
|
||||||
// For maps with value types of *T or []byte we need to deep copy each value.
|
|
||||||
elemKind := in.Type().Elem().Kind()
|
|
||||||
for _, key := range in.MapKeys() {
|
|
||||||
var val reflect.Value
|
|
||||||
switch elemKind {
|
|
||||||
case reflect.Ptr:
|
|
||||||
val = reflect.New(in.Type().Elem().Elem())
|
|
||||||
mergeAny(val, in.MapIndex(key), false, nil)
|
|
||||||
case reflect.Slice:
|
|
||||||
val = in.MapIndex(key)
|
|
||||||
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
|
|
||||||
default:
|
|
||||||
val = in.MapIndex(key)
|
|
||||||
}
|
|
||||||
out.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
case reflect.Ptr:
|
|
||||||
if in.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.New(in.Elem().Type()))
|
|
||||||
}
|
|
||||||
mergeAny(out.Elem(), in.Elem(), true, nil)
|
|
||||||
case reflect.Slice:
|
|
||||||
if in.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if in.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
// []byte is a scalar bytes field, not a repeated field.
|
|
||||||
|
|
||||||
// Edge case: if this is in a proto3 message, a zero length
|
|
||||||
// bytes field is considered the zero value, and should not
|
|
||||||
// be merged.
|
|
||||||
if prop != nil && prop.proto3 && in.Len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a deep copy.
|
|
||||||
// Append to []byte{} instead of []byte(nil) so that we never end up
|
|
||||||
// with a nil result.
|
|
||||||
out.SetBytes(append([]byte{}, in.Bytes()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n := in.Len()
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.MakeSlice(in.Type(), 0, n))
|
|
||||||
}
|
|
||||||
switch in.Type().Elem().Kind() {
|
|
||||||
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.String, reflect.Uint32, reflect.Uint64:
|
|
||||||
out.Set(reflect.AppendSlice(out, in))
|
|
||||||
default:
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
x := reflect.Indirect(reflect.New(in.Type().Elem()))
|
|
||||||
mergeAny(x, in.Index(i), false, nil)
|
|
||||||
out.Set(reflect.Append(out, x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
mergeStruct(out, in)
|
|
||||||
default:
|
|
||||||
// unknown type, so not a protocol buffer
|
|
||||||
log.Printf("proto: don't know how to copy %v", in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mergeExtension(out, in map[int32]Extension) {
|
|
||||||
for extNum, eIn := range in {
|
|
||||||
eOut := Extension{desc: eIn.desc}
|
|
||||||
if eIn.value != nil {
|
|
||||||
v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
|
|
||||||
mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
|
|
||||||
eOut.value = v.Interface()
|
|
||||||
}
|
|
||||||
if eIn.enc != nil {
|
|
||||||
eOut.enc = make([]byte, len(eIn.enc))
|
|
||||||
copy(eOut.enc, eIn.enc)
|
|
||||||
}
|
|
||||||
|
|
||||||
out[extNum] = eOut
|
|
||||||
}
|
|
||||||
}
|
|
428
vendor/github.com/golang/protobuf/proto/decode.go
generated
vendored
428
vendor/github.com/golang/protobuf/proto/decode.go
generated
vendored
@ -1,428 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Routines for decoding protocol buffer data to construct in-memory representations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// errOverflow is returned when an integer is too large to be represented.
|
|
||||||
var errOverflow = errors.New("proto: integer overflow")
|
|
||||||
|
|
||||||
// ErrInternalBadWireType is returned by generated code when an incorrect
|
|
||||||
// wire type is encountered. It does not get returned to user code.
|
|
||||||
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
|
|
||||||
|
|
||||||
// DecodeVarint reads a varint-encoded integer from the slice.
|
|
||||||
// It returns the integer and the number of bytes consumed, or
|
|
||||||
// zero if there is not enough.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
func DecodeVarint(buf []byte) (x uint64, n int) {
|
|
||||||
for shift := uint(0); shift < 64; shift += 7 {
|
|
||||||
if n >= len(buf) {
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
b := uint64(buf[n])
|
|
||||||
n++
|
|
||||||
x |= (b & 0x7F) << shift
|
|
||||||
if (b & 0x80) == 0 {
|
|
||||||
return x, n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The number is too large to represent in a 64-bit value.
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
|
|
||||||
i := p.index
|
|
||||||
l := len(p.buf)
|
|
||||||
|
|
||||||
for shift := uint(0); shift < 64; shift += 7 {
|
|
||||||
if i >= l {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b := p.buf[i]
|
|
||||||
i++
|
|
||||||
x |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
p.index = i
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The number is too large to represent in a 64-bit value.
|
|
||||||
err = errOverflow
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeVarint reads a varint-encoded integer from the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
func (p *Buffer) DecodeVarint() (x uint64, err error) {
|
|
||||||
i := p.index
|
|
||||||
buf := p.buf
|
|
||||||
|
|
||||||
if i >= len(buf) {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
} else if buf[i] < 0x80 {
|
|
||||||
p.index++
|
|
||||||
return uint64(buf[i]), nil
|
|
||||||
} else if len(buf)-i < 10 {
|
|
||||||
return p.decodeVarintSlow()
|
|
||||||
}
|
|
||||||
|
|
||||||
var b uint64
|
|
||||||
// we already checked the first byte
|
|
||||||
x = uint64(buf[i]) - 0x80
|
|
||||||
i++
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 7
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 7
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 14
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 14
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 21
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 21
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 28
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 28
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 35
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 35
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 42
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 42
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 49
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 49
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 56
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 56
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 63
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
// x -= 0x80 << 63 // Always zero.
|
|
||||||
|
|
||||||
return 0, errOverflow
|
|
||||||
|
|
||||||
done:
|
|
||||||
p.index = i
|
|
||||||
return x, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeFixed64 reads a 64-bit integer from the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed64, sfixed64, and double protocol buffer types.
|
|
||||||
func (p *Buffer) DecodeFixed64() (x uint64, err error) {
|
|
||||||
// x, err already 0
|
|
||||||
i := p.index + 8
|
|
||||||
if i < 0 || i > len(p.buf) {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.index = i
|
|
||||||
|
|
||||||
x = uint64(p.buf[i-8])
|
|
||||||
x |= uint64(p.buf[i-7]) << 8
|
|
||||||
x |= uint64(p.buf[i-6]) << 16
|
|
||||||
x |= uint64(p.buf[i-5]) << 24
|
|
||||||
x |= uint64(p.buf[i-4]) << 32
|
|
||||||
x |= uint64(p.buf[i-3]) << 40
|
|
||||||
x |= uint64(p.buf[i-2]) << 48
|
|
||||||
x |= uint64(p.buf[i-1]) << 56
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeFixed32 reads a 32-bit integer from the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed32, sfixed32, and float protocol buffer types.
|
|
||||||
func (p *Buffer) DecodeFixed32() (x uint64, err error) {
|
|
||||||
// x, err already 0
|
|
||||||
i := p.index + 4
|
|
||||||
if i < 0 || i > len(p.buf) {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.index = i
|
|
||||||
|
|
||||||
x = uint64(p.buf[i-4])
|
|
||||||
x |= uint64(p.buf[i-3]) << 8
|
|
||||||
x |= uint64(p.buf[i-2]) << 16
|
|
||||||
x |= uint64(p.buf[i-1]) << 24
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
|
|
||||||
// from the Buffer.
|
|
||||||
// This is the format used for the sint64 protocol buffer type.
|
|
||||||
func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
|
|
||||||
x, err = p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
|
|
||||||
// from the Buffer.
|
|
||||||
// This is the format used for the sint32 protocol buffer type.
|
|
||||||
func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
|
|
||||||
x, err = p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
|
|
||||||
// This is the format used for the bytes protocol buffer
|
|
||||||
// type and for embedded messages.
|
|
||||||
func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
|
|
||||||
n, err := p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nb := int(n)
|
|
||||||
if nb < 0 {
|
|
||||||
return nil, fmt.Errorf("proto: bad byte length %d", nb)
|
|
||||||
}
|
|
||||||
end := p.index + nb
|
|
||||||
if end < p.index || end > len(p.buf) {
|
|
||||||
return nil, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
|
|
||||||
if !alloc {
|
|
||||||
// todo: check if can get more uses of alloc=false
|
|
||||||
buf = p.buf[p.index:end]
|
|
||||||
p.index += nb
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = make([]byte, nb)
|
|
||||||
copy(buf, p.buf[p.index:])
|
|
||||||
p.index += nb
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeStringBytes reads an encoded string from the Buffer.
|
|
||||||
// This is the format used for the proto2 string type.
|
|
||||||
func (p *Buffer) DecodeStringBytes() (s string, err error) {
|
|
||||||
buf, err := p.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return string(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshaler is the interface representing objects that can
|
|
||||||
// unmarshal themselves. The argument points to data that may be
|
|
||||||
// overwritten, so implementations should not keep references to the
|
|
||||||
// buffer.
|
|
||||||
// Unmarshal implementations should not clear the receiver.
|
|
||||||
// Any unmarshaled data should be merged into the receiver.
|
|
||||||
// Callers of Unmarshal that do not want to retain existing data
|
|
||||||
// should Reset the receiver before calling Unmarshal.
|
|
||||||
type Unmarshaler interface {
|
|
||||||
Unmarshal([]byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// newUnmarshaler is the interface representing objects that can
|
|
||||||
// unmarshal themselves. The semantics are identical to Unmarshaler.
|
|
||||||
//
|
|
||||||
// This exists to support protoc-gen-go generated messages.
|
|
||||||
// The proto package will stop type-asserting to this interface in the future.
|
|
||||||
//
|
|
||||||
// DO NOT DEPEND ON THIS.
|
|
||||||
type newUnmarshaler interface {
|
|
||||||
XXX_Unmarshal([]byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal parses the protocol buffer representation in buf and places the
|
|
||||||
// decoded result in pb. If the struct underlying pb does not match
|
|
||||||
// the data in buf, the results can be unpredictable.
|
|
||||||
//
|
|
||||||
// Unmarshal resets pb before starting to unmarshal, so any
|
|
||||||
// existing data in pb is always removed. Use UnmarshalMerge
|
|
||||||
// to preserve and append to existing data.
|
|
||||||
func Unmarshal(buf []byte, pb Message) error {
|
|
||||||
pb.Reset()
|
|
||||||
if u, ok := pb.(newUnmarshaler); ok {
|
|
||||||
return u.XXX_Unmarshal(buf)
|
|
||||||
}
|
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
|
||||||
return u.Unmarshal(buf)
|
|
||||||
}
|
|
||||||
return NewBuffer(buf).Unmarshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalMerge parses the protocol buffer representation in buf and
|
|
||||||
// writes the decoded result to pb. If the struct underlying pb does not match
|
|
||||||
// the data in buf, the results can be unpredictable.
|
|
||||||
//
|
|
||||||
// UnmarshalMerge merges into existing data in pb.
|
|
||||||
// Most code should use Unmarshal instead.
|
|
||||||
func UnmarshalMerge(buf []byte, pb Message) error {
|
|
||||||
if u, ok := pb.(newUnmarshaler); ok {
|
|
||||||
return u.XXX_Unmarshal(buf)
|
|
||||||
}
|
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
|
||||||
// NOTE: The history of proto have unfortunately been inconsistent
|
|
||||||
// whether Unmarshaler should or should not implicitly clear itself.
|
|
||||||
// Some implementations do, most do not.
|
|
||||||
// Thus, calling this here may or may not do what people want.
|
|
||||||
//
|
|
||||||
// See https://github.com/golang/protobuf/issues/424
|
|
||||||
return u.Unmarshal(buf)
|
|
||||||
}
|
|
||||||
return NewBuffer(buf).Unmarshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeMessage reads a count-delimited message from the Buffer.
|
|
||||||
func (p *Buffer) DecodeMessage(pb Message) error {
|
|
||||||
enc, err := p.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return NewBuffer(enc).Unmarshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeGroup reads a tag-delimited group from the Buffer.
|
|
||||||
// StartGroup tag is already consumed. This function consumes
|
|
||||||
// EndGroup tag.
|
|
||||||
func (p *Buffer) DecodeGroup(pb Message) error {
|
|
||||||
b := p.buf[p.index:]
|
|
||||||
x, y := findEndGroup(b)
|
|
||||||
if x < 0 {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
err := Unmarshal(b[:x], pb)
|
|
||||||
p.index += y
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal parses the protocol buffer representation in the
|
|
||||||
// Buffer and places the decoded result in pb. If the struct
|
|
||||||
// underlying pb does not match the data in the buffer, the results can be
|
|
||||||
// unpredictable.
|
|
||||||
//
|
|
||||||
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
|
|
||||||
func (p *Buffer) Unmarshal(pb Message) error {
|
|
||||||
// If the object can unmarshal itself, let it.
|
|
||||||
if u, ok := pb.(newUnmarshaler); ok {
|
|
||||||
err := u.XXX_Unmarshal(p.buf[p.index:])
|
|
||||||
p.index = len(p.buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
|
||||||
// NOTE: The history of proto have unfortunately been inconsistent
|
|
||||||
// whether Unmarshaler should or should not implicitly clear itself.
|
|
||||||
// Some implementations do, most do not.
|
|
||||||
// Thus, calling this here may or may not do what people want.
|
|
||||||
//
|
|
||||||
// See https://github.com/golang/protobuf/issues/424
|
|
||||||
err := u.Unmarshal(p.buf[p.index:])
|
|
||||||
p.index = len(p.buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slow workaround for messages that aren't Unmarshalers.
|
|
||||||
// This includes some hand-coded .pb.go files and
|
|
||||||
// bootstrap protos.
|
|
||||||
// TODO: fix all of those and then add Unmarshal to
|
|
||||||
// the Message interface. Then:
|
|
||||||
// The cast above and code below can be deleted.
|
|
||||||
// The old unmarshaler can be deleted.
|
|
||||||
// Clients can call Unmarshal directly (can already do that, actually).
|
|
||||||
var info InternalMessageInfo
|
|
||||||
err := info.Unmarshal(pb, p.buf[p.index:])
|
|
||||||
p.index = len(p.buf)
|
|
||||||
return err
|
|
||||||
}
|
|
350
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
350
vendor/github.com/golang/protobuf/proto/discard.go
generated
vendored
@ -1,350 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
type generatedDiscarder interface {
|
|
||||||
XXX_DiscardUnknown()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiscardUnknown recursively discards all unknown fields from this message
|
|
||||||
// and all embedded messages.
|
|
||||||
//
|
|
||||||
// When unmarshaling a message with unrecognized fields, the tags and values
|
|
||||||
// of such fields are preserved in the Message. This allows a later call to
|
|
||||||
// marshal to be able to produce a message that continues to have those
|
|
||||||
// unrecognized fields. To avoid this, DiscardUnknown is used to
|
|
||||||
// explicitly clear the unknown fields after unmarshaling.
|
|
||||||
//
|
|
||||||
// For proto2 messages, the unknown fields of message extensions are only
|
|
||||||
// discarded from messages that have been accessed via GetExtension.
|
|
||||||
func DiscardUnknown(m Message) {
|
|
||||||
if m, ok := m.(generatedDiscarder); ok {
|
|
||||||
m.XXX_DiscardUnknown()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
|
|
||||||
// but the master branch has no implementation for InternalMessageInfo,
|
|
||||||
// so it would be more work to replicate that approach.
|
|
||||||
discardLegacy(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiscardUnknown recursively discards all unknown fields.
|
|
||||||
func (a *InternalMessageInfo) DiscardUnknown(m Message) {
|
|
||||||
di := atomicLoadDiscardInfo(&a.discard)
|
|
||||||
if di == nil {
|
|
||||||
di = getDiscardInfo(reflect.TypeOf(m).Elem())
|
|
||||||
atomicStoreDiscardInfo(&a.discard, di)
|
|
||||||
}
|
|
||||||
di.discard(toPointer(&m))
|
|
||||||
}
|
|
||||||
|
|
||||||
type discardInfo struct {
|
|
||||||
typ reflect.Type
|
|
||||||
|
|
||||||
initialized int32 // 0: only typ is valid, 1: everything is valid
|
|
||||||
lock sync.Mutex
|
|
||||||
|
|
||||||
fields []discardFieldInfo
|
|
||||||
unrecognized field
|
|
||||||
}
|
|
||||||
|
|
||||||
type discardFieldInfo struct {
|
|
||||||
field field // Offset of field, guaranteed to be valid
|
|
||||||
discard func(src pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
discardInfoMap = map[reflect.Type]*discardInfo{}
|
|
||||||
discardInfoLock sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func getDiscardInfo(t reflect.Type) *discardInfo {
|
|
||||||
discardInfoLock.Lock()
|
|
||||||
defer discardInfoLock.Unlock()
|
|
||||||
di := discardInfoMap[t]
|
|
||||||
if di == nil {
|
|
||||||
di = &discardInfo{typ: t}
|
|
||||||
discardInfoMap[t] = di
|
|
||||||
}
|
|
||||||
return di
|
|
||||||
}
|
|
||||||
|
|
||||||
func (di *discardInfo) discard(src pointer) {
|
|
||||||
if src.isNil() {
|
|
||||||
return // Nothing to do.
|
|
||||||
}
|
|
||||||
|
|
||||||
if atomic.LoadInt32(&di.initialized) == 0 {
|
|
||||||
di.computeDiscardInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, fi := range di.fields {
|
|
||||||
sfp := src.offset(fi.field)
|
|
||||||
fi.discard(sfp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// For proto2 messages, only discard unknown fields in message extensions
|
|
||||||
// that have been accessed via GetExtension.
|
|
||||||
if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
|
|
||||||
// Ignore lock since DiscardUnknown is not concurrency safe.
|
|
||||||
emm, _ := em.extensionsRead()
|
|
||||||
for _, mx := range emm {
|
|
||||||
if m, ok := mx.value.(Message); ok {
|
|
||||||
DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if di.unrecognized.IsValid() {
|
|
||||||
*src.offset(di.unrecognized).toBytes() = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (di *discardInfo) computeDiscardInfo() {
|
|
||||||
di.lock.Lock()
|
|
||||||
defer di.lock.Unlock()
|
|
||||||
if di.initialized != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := di.typ
|
|
||||||
n := t.NumField()
|
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
dfi := discardFieldInfo{field: toField(&f)}
|
|
||||||
tf := f.Type
|
|
||||||
|
|
||||||
// Unwrap tf to get its most basic type.
|
|
||||||
var isPointer, isSlice bool
|
|
||||||
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
|
|
||||||
isSlice = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if tf.Kind() == reflect.Ptr {
|
|
||||||
isPointer = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if isPointer && isSlice && tf.Kind() != reflect.Struct {
|
|
||||||
panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tf.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
switch {
|
|
||||||
case !isPointer:
|
|
||||||
panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
|
|
||||||
case isSlice: // E.g., []*pb.T
|
|
||||||
di := getDiscardInfo(tf)
|
|
||||||
dfi.discard = func(src pointer) {
|
|
||||||
sps := src.getPointerSlice()
|
|
||||||
for _, sp := range sps {
|
|
||||||
if !sp.isNil() {
|
|
||||||
di.discard(sp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., *pb.T
|
|
||||||
di := getDiscardInfo(tf)
|
|
||||||
dfi.discard = func(src pointer) {
|
|
||||||
sp := src.getPointer()
|
|
||||||
if !sp.isNil() {
|
|
||||||
di.discard(sp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
|
|
||||||
default: // E.g., map[K]V
|
|
||||||
if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
|
|
||||||
dfi.discard = func(src pointer) {
|
|
||||||
sm := src.asPointerTo(tf).Elem()
|
|
||||||
if sm.Len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, key := range sm.MapKeys() {
|
|
||||||
val := sm.MapIndex(key)
|
|
||||||
DiscardUnknown(val.Interface().(Message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dfi.discard = func(pointer) {} // Noop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
|
||||||
// Must be oneof field.
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
|
|
||||||
default: // E.g., interface{}
|
|
||||||
// TODO: Make this faster?
|
|
||||||
dfi.discard = func(src pointer) {
|
|
||||||
su := src.asPointerTo(tf).Elem()
|
|
||||||
if !su.IsNil() {
|
|
||||||
sv := su.Elem().Elem().Field(0)
|
|
||||||
if sv.Kind() == reflect.Ptr && sv.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch sv.Type().Kind() {
|
|
||||||
case reflect.Ptr: // Proto struct (e.g., *T)
|
|
||||||
DiscardUnknown(sv.Interface().(Message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
di.fields = append(di.fields, dfi)
|
|
||||||
}
|
|
||||||
|
|
||||||
di.unrecognized = invalidField
|
|
||||||
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
|
|
||||||
if f.Type != reflect.TypeOf([]byte{}) {
|
|
||||||
panic("expected XXX_unrecognized to be of type []byte")
|
|
||||||
}
|
|
||||||
di.unrecognized = toField(&f)
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.StoreInt32(&di.initialized, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func discardLegacy(m Message) {
|
|
||||||
v := reflect.ValueOf(m)
|
|
||||||
if v.Kind() != reflect.Ptr || v.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
v = v.Elem()
|
|
||||||
if v.Kind() != reflect.Struct {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := v.Type()
|
|
||||||
|
|
||||||
for i := 0; i < v.NumField(); i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
vf := v.Field(i)
|
|
||||||
tf := f.Type
|
|
||||||
|
|
||||||
// Unwrap tf to get its most basic type.
|
|
||||||
var isPointer, isSlice bool
|
|
||||||
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
|
|
||||||
isSlice = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if tf.Kind() == reflect.Ptr {
|
|
||||||
isPointer = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if isPointer && isSlice && tf.Kind() != reflect.Struct {
|
|
||||||
panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tf.Kind() {
|
|
||||||
case reflect.Struct:
|
|
||||||
switch {
|
|
||||||
case !isPointer:
|
|
||||||
panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
|
|
||||||
case isSlice: // E.g., []*pb.T
|
|
||||||
for j := 0; j < vf.Len(); j++ {
|
|
||||||
discardLegacy(vf.Index(j).Interface().(Message))
|
|
||||||
}
|
|
||||||
default: // E.g., *pb.T
|
|
||||||
discardLegacy(vf.Interface().(Message))
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
|
|
||||||
default: // E.g., map[K]V
|
|
||||||
tv := vf.Type().Elem()
|
|
||||||
if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
|
|
||||||
for _, key := range vf.MapKeys() {
|
|
||||||
val := vf.MapIndex(key)
|
|
||||||
discardLegacy(val.Interface().(Message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
|
||||||
// Must be oneof field.
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
|
|
||||||
default: // E.g., test_proto.isCommunique_Union interface
|
|
||||||
if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
|
|
||||||
vf = vf.Elem() // E.g., *test_proto.Communique_Msg
|
|
||||||
if !vf.IsNil() {
|
|
||||||
vf = vf.Elem() // E.g., test_proto.Communique_Msg
|
|
||||||
vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
|
|
||||||
if vf.Kind() == reflect.Ptr {
|
|
||||||
discardLegacy(vf.Interface().(Message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
|
|
||||||
if vf.Type() != reflect.TypeOf([]byte{}) {
|
|
||||||
panic("expected XXX_unrecognized to be of type []byte")
|
|
||||||
}
|
|
||||||
vf.Set(reflect.ValueOf([]byte(nil)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// For proto2 messages, only discard unknown fields in message extensions
|
|
||||||
// that have been accessed via GetExtension.
|
|
||||||
if em, err := extendable(m); err == nil {
|
|
||||||
// Ignore lock since discardLegacy is not concurrency safe.
|
|
||||||
emm, _ := em.extensionsRead()
|
|
||||||
for _, mx := range emm {
|
|
||||||
if m, ok := mx.value.(Message); ok {
|
|
||||||
discardLegacy(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
203
vendor/github.com/golang/protobuf/proto/encode.go
generated
vendored
203
vendor/github.com/golang/protobuf/proto/encode.go
generated
vendored
@ -1,203 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Routines for encoding data into the wire format for protocol buffers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// errRepeatedHasNil is the error returned if Marshal is called with
|
|
||||||
// a struct with a repeated field containing a nil element.
|
|
||||||
errRepeatedHasNil = errors.New("proto: repeated field has nil element")
|
|
||||||
|
|
||||||
// errOneofHasNil is the error returned if Marshal is called with
|
|
||||||
// a struct with a oneof field containing a nil element.
|
|
||||||
errOneofHasNil = errors.New("proto: oneof field has nil value")
|
|
||||||
|
|
||||||
// ErrNil is the error returned if Marshal is called with nil.
|
|
||||||
ErrNil = errors.New("proto: Marshal called with nil")
|
|
||||||
|
|
||||||
// ErrTooLarge is the error returned if Marshal is called with a
|
|
||||||
// message that encodes to >2GB.
|
|
||||||
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
|
|
||||||
)
|
|
||||||
|
|
||||||
// The fundamental encoders that put bytes on the wire.
|
|
||||||
// Those that take integer types all accept uint64 and are
|
|
||||||
// therefore of type valueEncoder.
|
|
||||||
|
|
||||||
const maxVarintBytes = 10 // maximum length of a varint
|
|
||||||
|
|
||||||
// EncodeVarint returns the varint encoding of x.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
// Not used by the package itself, but helpful to clients
|
|
||||||
// wishing to use the same encoding.
|
|
||||||
func EncodeVarint(x uint64) []byte {
|
|
||||||
var buf [maxVarintBytes]byte
|
|
||||||
var n int
|
|
||||||
for n = 0; x > 127; n++ {
|
|
||||||
buf[n] = 0x80 | uint8(x&0x7F)
|
|
||||||
x >>= 7
|
|
||||||
}
|
|
||||||
buf[n] = uint8(x)
|
|
||||||
n++
|
|
||||||
return buf[0:n]
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeVarint writes a varint-encoded integer to the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
func (p *Buffer) EncodeVarint(x uint64) error {
|
|
||||||
for x >= 1<<7 {
|
|
||||||
p.buf = append(p.buf, uint8(x&0x7f|0x80))
|
|
||||||
x >>= 7
|
|
||||||
}
|
|
||||||
p.buf = append(p.buf, uint8(x))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SizeVarint returns the varint encoding size of an integer.
|
|
||||||
func SizeVarint(x uint64) int {
|
|
||||||
switch {
|
|
||||||
case x < 1<<7:
|
|
||||||
return 1
|
|
||||||
case x < 1<<14:
|
|
||||||
return 2
|
|
||||||
case x < 1<<21:
|
|
||||||
return 3
|
|
||||||
case x < 1<<28:
|
|
||||||
return 4
|
|
||||||
case x < 1<<35:
|
|
||||||
return 5
|
|
||||||
case x < 1<<42:
|
|
||||||
return 6
|
|
||||||
case x < 1<<49:
|
|
||||||
return 7
|
|
||||||
case x < 1<<56:
|
|
||||||
return 8
|
|
||||||
case x < 1<<63:
|
|
||||||
return 9
|
|
||||||
}
|
|
||||||
return 10
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeFixed64 writes a 64-bit integer to the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed64, sfixed64, and double protocol buffer types.
|
|
||||||
func (p *Buffer) EncodeFixed64(x uint64) error {
|
|
||||||
p.buf = append(p.buf,
|
|
||||||
uint8(x),
|
|
||||||
uint8(x>>8),
|
|
||||||
uint8(x>>16),
|
|
||||||
uint8(x>>24),
|
|
||||||
uint8(x>>32),
|
|
||||||
uint8(x>>40),
|
|
||||||
uint8(x>>48),
|
|
||||||
uint8(x>>56))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeFixed32 writes a 32-bit integer to the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed32, sfixed32, and float protocol buffer types.
|
|
||||||
func (p *Buffer) EncodeFixed32(x uint64) error {
|
|
||||||
p.buf = append(p.buf,
|
|
||||||
uint8(x),
|
|
||||||
uint8(x>>8),
|
|
||||||
uint8(x>>16),
|
|
||||||
uint8(x>>24))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
|
|
||||||
// to the Buffer.
|
|
||||||
// This is the format used for the sint64 protocol buffer type.
|
|
||||||
func (p *Buffer) EncodeZigzag64(x uint64) error {
|
|
||||||
// use signed number to get arithmetic right shift.
|
|
||||||
return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
|
|
||||||
// to the Buffer.
|
|
||||||
// This is the format used for the sint32 protocol buffer type.
|
|
||||||
func (p *Buffer) EncodeZigzag32(x uint64) error {
|
|
||||||
// use signed number to get arithmetic right shift.
|
|
||||||
return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
|
|
||||||
// This is the format used for the bytes protocol buffer
|
|
||||||
// type and for embedded messages.
|
|
||||||
func (p *Buffer) EncodeRawBytes(b []byte) error {
|
|
||||||
p.EncodeVarint(uint64(len(b)))
|
|
||||||
p.buf = append(p.buf, b...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeStringBytes writes an encoded string to the Buffer.
|
|
||||||
// This is the format used for the proto2 string type.
|
|
||||||
func (p *Buffer) EncodeStringBytes(s string) error {
|
|
||||||
p.EncodeVarint(uint64(len(s)))
|
|
||||||
p.buf = append(p.buf, s...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshaler is the interface representing objects that can marshal themselves.
|
|
||||||
type Marshaler interface {
|
|
||||||
Marshal() ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeMessage writes the protocol buffer to the Buffer,
|
|
||||||
// prefixed by a varint-encoded length.
|
|
||||||
func (p *Buffer) EncodeMessage(pb Message) error {
|
|
||||||
siz := Size(pb)
|
|
||||||
p.EncodeVarint(uint64(siz))
|
|
||||||
return p.Marshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// All protocol buffer fields are nillable, but be careful.
|
|
||||||
func isNil(v reflect.Value) bool {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
|
||||||
return v.IsNil()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
300
vendor/github.com/golang/protobuf/proto/equal.go
generated
vendored
300
vendor/github.com/golang/protobuf/proto/equal.go
generated
vendored
@ -1,300 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Protocol buffer comparison.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"log"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Equal returns true iff protocol buffers a and b are equal.
|
|
||||||
The arguments must both be pointers to protocol buffer structs.
|
|
||||||
|
|
||||||
Equality is defined in this way:
|
|
||||||
- Two messages are equal iff they are the same type,
|
|
||||||
corresponding fields are equal, unknown field sets
|
|
||||||
are equal, and extensions sets are equal.
|
|
||||||
- Two set scalar fields are equal iff their values are equal.
|
|
||||||
If the fields are of a floating-point type, remember that
|
|
||||||
NaN != x for all x, including NaN. If the message is defined
|
|
||||||
in a proto3 .proto file, fields are not "set"; specifically,
|
|
||||||
zero length proto3 "bytes" fields are equal (nil == {}).
|
|
||||||
- Two repeated fields are equal iff their lengths are the same,
|
|
||||||
and their corresponding elements are equal. Note a "bytes" field,
|
|
||||||
although represented by []byte, is not a repeated field and the
|
|
||||||
rule for the scalar fields described above applies.
|
|
||||||
- Two unset fields are equal.
|
|
||||||
- Two unknown field sets are equal if their current
|
|
||||||
encoded state is equal.
|
|
||||||
- Two extension sets are equal iff they have corresponding
|
|
||||||
elements that are pairwise equal.
|
|
||||||
- Two map fields are equal iff their lengths are the same,
|
|
||||||
and they contain the same set of elements. Zero-length map
|
|
||||||
fields are equal.
|
|
||||||
- Every other combination of things are not equal.
|
|
||||||
|
|
||||||
The return value is undefined if a and b are not protocol buffers.
|
|
||||||
*/
|
|
||||||
func Equal(a, b Message) bool {
|
|
||||||
if a == nil || b == nil {
|
|
||||||
return a == b
|
|
||||||
}
|
|
||||||
v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
|
|
||||||
if v1.Type() != v2.Type() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if v1.Kind() == reflect.Ptr {
|
|
||||||
if v1.IsNil() {
|
|
||||||
return v2.IsNil()
|
|
||||||
}
|
|
||||||
if v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
v1, v2 = v1.Elem(), v2.Elem()
|
|
||||||
}
|
|
||||||
if v1.Kind() != reflect.Struct {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return equalStruct(v1, v2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// v1 and v2 are known to have the same type.
|
|
||||||
func equalStruct(v1, v2 reflect.Value) bool {
|
|
||||||
sprop := GetProperties(v1.Type())
|
|
||||||
for i := 0; i < v1.NumField(); i++ {
|
|
||||||
f := v1.Type().Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f1, f2 := v1.Field(i), v2.Field(i)
|
|
||||||
if f.Type.Kind() == reflect.Ptr {
|
|
||||||
if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
|
|
||||||
// both unset
|
|
||||||
continue
|
|
||||||
} else if n1 != n2 {
|
|
||||||
// set/unset mismatch
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
f1, f2 = f1.Elem(), f2.Elem()
|
|
||||||
}
|
|
||||||
if !equalAny(f1, f2, sprop.Prop[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
|
|
||||||
em2 := v2.FieldByName("XXX_InternalExtensions")
|
|
||||||
if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
|
|
||||||
em2 := v2.FieldByName("XXX_extensions")
|
|
||||||
if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uf := v1.FieldByName("XXX_unrecognized")
|
|
||||||
if !uf.IsValid() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
u1 := uf.Bytes()
|
|
||||||
u2 := v2.FieldByName("XXX_unrecognized").Bytes()
|
|
||||||
return bytes.Equal(u1, u2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// v1 and v2 are known to have the same type.
|
|
||||||
// prop may be nil.
|
|
||||||
func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
|
|
||||||
if v1.Type() == protoMessageType {
|
|
||||||
m1, _ := v1.Interface().(Message)
|
|
||||||
m2, _ := v2.Interface().(Message)
|
|
||||||
return Equal(m1, m2)
|
|
||||||
}
|
|
||||||
switch v1.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return v1.Bool() == v2.Bool()
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return v1.Float() == v2.Float()
|
|
||||||
case reflect.Int32, reflect.Int64:
|
|
||||||
return v1.Int() == v2.Int()
|
|
||||||
case reflect.Interface:
|
|
||||||
// Probably a oneof field; compare the inner values.
|
|
||||||
n1, n2 := v1.IsNil(), v2.IsNil()
|
|
||||||
if n1 || n2 {
|
|
||||||
return n1 == n2
|
|
||||||
}
|
|
||||||
e1, e2 := v1.Elem(), v2.Elem()
|
|
||||||
if e1.Type() != e2.Type() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return equalAny(e1, e2, nil)
|
|
||||||
case reflect.Map:
|
|
||||||
if v1.Len() != v2.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, key := range v1.MapKeys() {
|
|
||||||
val2 := v2.MapIndex(key)
|
|
||||||
if !val2.IsValid() {
|
|
||||||
// This key was not found in the second map.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !equalAny(v1.MapIndex(key), val2, nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case reflect.Ptr:
|
|
||||||
// Maps may have nil values in them, so check for nil.
|
|
||||||
if v1.IsNil() && v2.IsNil() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if v1.IsNil() != v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return equalAny(v1.Elem(), v2.Elem(), prop)
|
|
||||||
case reflect.Slice:
|
|
||||||
if v1.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
// short circuit: []byte
|
|
||||||
|
|
||||||
// Edge case: if this is in a proto3 message, a zero length
|
|
||||||
// bytes field is considered the zero value.
|
|
||||||
if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if v1.IsNil() != v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
|
|
||||||
}
|
|
||||||
|
|
||||||
if v1.Len() != v2.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := 0; i < v1.Len(); i++ {
|
|
||||||
if !equalAny(v1.Index(i), v2.Index(i), prop) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case reflect.String:
|
|
||||||
return v1.Interface().(string) == v2.Interface().(string)
|
|
||||||
case reflect.Struct:
|
|
||||||
return equalStruct(v1, v2)
|
|
||||||
case reflect.Uint32, reflect.Uint64:
|
|
||||||
return v1.Uint() == v2.Uint()
|
|
||||||
}
|
|
||||||
|
|
||||||
// unknown type, so not a protocol buffer
|
|
||||||
log.Printf("proto: don't know how to compare %v", v1)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// base is the struct type that the extensions are based on.
|
|
||||||
// x1 and x2 are InternalExtensions.
|
|
||||||
func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
|
|
||||||
em1, _ := x1.extensionsRead()
|
|
||||||
em2, _ := x2.extensionsRead()
|
|
||||||
return equalExtMap(base, em1, em2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|
||||||
if len(em1) != len(em2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for extNum, e1 := range em1 {
|
|
||||||
e2, ok := em2[extNum]
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
m1, m2 := e1.value, e2.value
|
|
||||||
|
|
||||||
if m1 == nil && m2 == nil {
|
|
||||||
// Both have only encoded form.
|
|
||||||
if bytes.Equal(e1.enc, e2.enc) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// The bytes are different, but the extensions might still be
|
|
||||||
// equal. We need to decode them to compare.
|
|
||||||
}
|
|
||||||
|
|
||||||
if m1 != nil && m2 != nil {
|
|
||||||
// Both are unencoded.
|
|
||||||
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// At least one is encoded. To do a semantically correct comparison
|
|
||||||
// we need to unmarshal them first.
|
|
||||||
var desc *ExtensionDesc
|
|
||||||
if m := extensionMaps[base]; m != nil {
|
|
||||||
desc = m[extNum]
|
|
||||||
}
|
|
||||||
if desc == nil {
|
|
||||||
// If both have only encoded form and the bytes are the same,
|
|
||||||
// it is handled above. We get here when the bytes are different.
|
|
||||||
// We don't know how to decode it, so just compare them as byte
|
|
||||||
// slices.
|
|
||||||
log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
if m1 == nil {
|
|
||||||
m1, err = decodeExtension(e1.enc, desc)
|
|
||||||
}
|
|
||||||
if m2 == nil && err == nil {
|
|
||||||
m2, err = decodeExtension(e2.enc, desc)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
// The encoded form is invalid.
|
|
||||||
log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
543
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
543
vendor/github.com/golang/protobuf/proto/extensions.go
generated
vendored
@ -1,543 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types and routines for supporting protocol buffer extensions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
|
|
||||||
var ErrMissingExtension = errors.New("proto: missing extension")
|
|
||||||
|
|
||||||
// ExtensionRange represents a range of message extensions for a protocol buffer.
|
|
||||||
// Used in code generated by the protocol compiler.
|
|
||||||
type ExtensionRange struct {
|
|
||||||
Start, End int32 // both inclusive
|
|
||||||
}
|
|
||||||
|
|
||||||
// extendableProto is an interface implemented by any protocol buffer generated by the current
|
|
||||||
// proto compiler that may be extended.
|
|
||||||
type extendableProto interface {
|
|
||||||
Message
|
|
||||||
ExtensionRangeArray() []ExtensionRange
|
|
||||||
extensionsWrite() map[int32]Extension
|
|
||||||
extensionsRead() (map[int32]Extension, sync.Locker)
|
|
||||||
}
|
|
||||||
|
|
||||||
// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
|
|
||||||
// version of the proto compiler that may be extended.
|
|
||||||
type extendableProtoV1 interface {
|
|
||||||
Message
|
|
||||||
ExtensionRangeArray() []ExtensionRange
|
|
||||||
ExtensionMap() map[int32]Extension
|
|
||||||
}
|
|
||||||
|
|
||||||
// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
|
|
||||||
type extensionAdapter struct {
|
|
||||||
extendableProtoV1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e extensionAdapter) extensionsWrite() map[int32]Extension {
|
|
||||||
return e.ExtensionMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
|
|
||||||
return e.ExtensionMap(), notLocker{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
|
|
||||||
type notLocker struct{}
|
|
||||||
|
|
||||||
func (n notLocker) Lock() {}
|
|
||||||
func (n notLocker) Unlock() {}
|
|
||||||
|
|
||||||
// extendable returns the extendableProto interface for the given generated proto message.
|
|
||||||
// If the proto message has the old extension format, it returns a wrapper that implements
|
|
||||||
// the extendableProto interface.
|
|
||||||
func extendable(p interface{}) (extendableProto, error) {
|
|
||||||
switch p := p.(type) {
|
|
||||||
case extendableProto:
|
|
||||||
if isNilPtr(p) {
|
|
||||||
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
|
|
||||||
}
|
|
||||||
return p, nil
|
|
||||||
case extendableProtoV1:
|
|
||||||
if isNilPtr(p) {
|
|
||||||
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
|
|
||||||
}
|
|
||||||
return extensionAdapter{p}, nil
|
|
||||||
}
|
|
||||||
// Don't allocate a specific error containing %T:
|
|
||||||
// this is the hot path for Clone and MarshalText.
|
|
||||||
return nil, errNotExtendable
|
|
||||||
}
|
|
||||||
|
|
||||||
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
|
|
||||||
|
|
||||||
func isNilPtr(x interface{}) bool {
|
|
||||||
v := reflect.ValueOf(x)
|
|
||||||
return v.Kind() == reflect.Ptr && v.IsNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX_InternalExtensions is an internal representation of proto extensions.
|
|
||||||
//
|
|
||||||
// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
|
|
||||||
// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
|
|
||||||
//
|
|
||||||
// The methods of XXX_InternalExtensions are not concurrency safe in general,
|
|
||||||
// but calls to logically read-only methods such as has and get may be executed concurrently.
|
|
||||||
type XXX_InternalExtensions struct {
|
|
||||||
// The struct must be indirect so that if a user inadvertently copies a
|
|
||||||
// generated message and its embedded XXX_InternalExtensions, they
|
|
||||||
// avoid the mayhem of a copied mutex.
|
|
||||||
//
|
|
||||||
// The mutex serializes all logically read-only operations to p.extensionMap.
|
|
||||||
// It is up to the client to ensure that write operations to p.extensionMap are
|
|
||||||
// mutually exclusive with other accesses.
|
|
||||||
p *struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
extensionMap map[int32]Extension
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// extensionsWrite returns the extension map, creating it on first use.
|
|
||||||
func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
|
|
||||||
if e.p == nil {
|
|
||||||
e.p = new(struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
extensionMap map[int32]Extension
|
|
||||||
})
|
|
||||||
e.p.extensionMap = make(map[int32]Extension)
|
|
||||||
}
|
|
||||||
return e.p.extensionMap
|
|
||||||
}
|
|
||||||
|
|
||||||
// extensionsRead returns the extensions map for read-only use. It may be nil.
|
|
||||||
// The caller must hold the returned mutex's lock when accessing Elements within the map.
|
|
||||||
func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
|
|
||||||
if e.p == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return e.p.extensionMap, &e.p.mu
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtensionDesc represents an extension specification.
|
|
||||||
// Used in generated code from the protocol compiler.
|
|
||||||
type ExtensionDesc struct {
|
|
||||||
ExtendedType Message // nil pointer to the type that is being extended
|
|
||||||
ExtensionType interface{} // nil pointer to the extension type
|
|
||||||
Field int32 // field number
|
|
||||||
Name string // fully-qualified name of extension, for text formatting
|
|
||||||
Tag string // protobuf tag style
|
|
||||||
Filename string // name of the file in which the extension is defined
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ed *ExtensionDesc) repeated() bool {
|
|
||||||
t := reflect.TypeOf(ed.ExtensionType)
|
|
||||||
return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extension represents an extension in a message.
|
|
||||||
type Extension struct {
|
|
||||||
// When an extension is stored in a message using SetExtension
|
|
||||||
// only desc and value are set. When the message is marshaled
|
|
||||||
// enc will be set to the encoded form of the message.
|
|
||||||
//
|
|
||||||
// When a message is unmarshaled and contains extensions, each
|
|
||||||
// extension will have only enc set. When such an extension is
|
|
||||||
// accessed using GetExtension (or GetExtensions) desc and value
|
|
||||||
// will be set.
|
|
||||||
desc *ExtensionDesc
|
|
||||||
value interface{}
|
|
||||||
enc []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetRawExtension is for testing only.
|
|
||||||
func SetRawExtension(base Message, id int32, b []byte) {
|
|
||||||
epb, err := extendable(base)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
extmap := epb.extensionsWrite()
|
|
||||||
extmap[id] = Extension{enc: b}
|
|
||||||
}
|
|
||||||
|
|
||||||
// isExtensionField returns true iff the given field number is in an extension range.
|
|
||||||
func isExtensionField(pb extendableProto, field int32) bool {
|
|
||||||
for _, er := range pb.ExtensionRangeArray() {
|
|
||||||
if er.Start <= field && field <= er.End {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkExtensionTypes checks that the given extension is valid for pb.
|
|
||||||
func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
|
|
||||||
var pbi interface{} = pb
|
|
||||||
// Check the extended type.
|
|
||||||
if ea, ok := pbi.(extensionAdapter); ok {
|
|
||||||
pbi = ea.extendableProtoV1
|
|
||||||
}
|
|
||||||
if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
|
|
||||||
return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
|
|
||||||
}
|
|
||||||
// Check the range.
|
|
||||||
if !isExtensionField(pb, extension.Field) {
|
|
||||||
return errors.New("proto: bad extension number; not in declared ranges")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// extPropKey is sufficient to uniquely identify an extension.
|
|
||||||
type extPropKey struct {
|
|
||||||
base reflect.Type
|
|
||||||
field int32
|
|
||||||
}
|
|
||||||
|
|
||||||
var extProp = struct {
|
|
||||||
sync.RWMutex
|
|
||||||
m map[extPropKey]*Properties
|
|
||||||
}{
|
|
||||||
m: make(map[extPropKey]*Properties),
|
|
||||||
}
|
|
||||||
|
|
||||||
func extensionProperties(ed *ExtensionDesc) *Properties {
|
|
||||||
key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
|
|
||||||
|
|
||||||
extProp.RLock()
|
|
||||||
if prop, ok := extProp.m[key]; ok {
|
|
||||||
extProp.RUnlock()
|
|
||||||
return prop
|
|
||||||
}
|
|
||||||
extProp.RUnlock()
|
|
||||||
|
|
||||||
extProp.Lock()
|
|
||||||
defer extProp.Unlock()
|
|
||||||
// Check again.
|
|
||||||
if prop, ok := extProp.m[key]; ok {
|
|
||||||
return prop
|
|
||||||
}
|
|
||||||
|
|
||||||
prop := new(Properties)
|
|
||||||
prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
|
|
||||||
extProp.m[key] = prop
|
|
||||||
return prop
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasExtension returns whether the given extension is present in pb.
|
|
||||||
func HasExtension(pb Message, extension *ExtensionDesc) bool {
|
|
||||||
// TODO: Check types, field numbers, etc.?
|
|
||||||
epb, err := extendable(pb)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
extmap, mu := epb.extensionsRead()
|
|
||||||
if extmap == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
_, ok := extmap[extension.Field]
|
|
||||||
mu.Unlock()
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearExtension removes the given extension from pb.
|
|
||||||
func ClearExtension(pb Message, extension *ExtensionDesc) {
|
|
||||||
epb, err := extendable(pb)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO: Check types, field numbers, etc.?
|
|
||||||
extmap := epb.extensionsWrite()
|
|
||||||
delete(extmap, extension.Field)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetExtension retrieves a proto2 extended field from pb.
|
|
||||||
//
|
|
||||||
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
|
|
||||||
// then GetExtension parses the encoded field and returns a Go value of the specified type.
|
|
||||||
// If the field is not present, then the default value is returned (if one is specified),
|
|
||||||
// otherwise ErrMissingExtension is reported.
|
|
||||||
//
|
|
||||||
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
|
|
||||||
// then GetExtension returns the raw encoded bytes of the field extension.
|
|
||||||
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|
||||||
epb, err := extendable(pb)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if extension.ExtendedType != nil {
|
|
||||||
// can only check type if this is a complete descriptor
|
|
||||||
if err := checkExtensionTypes(epb, extension); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emap, mu := epb.extensionsRead()
|
|
||||||
if emap == nil {
|
|
||||||
return defaultExtensionValue(extension)
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
e, ok := emap[extension.Field]
|
|
||||||
if !ok {
|
|
||||||
// defaultExtensionValue returns the default value or
|
|
||||||
// ErrMissingExtension if there is no default.
|
|
||||||
return defaultExtensionValue(extension)
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.value != nil {
|
|
||||||
// Already decoded. Check the descriptor, though.
|
|
||||||
if e.desc != extension {
|
|
||||||
// This shouldn't happen. If it does, it means that
|
|
||||||
// GetExtension was called twice with two different
|
|
||||||
// descriptors with the same field number.
|
|
||||||
return nil, errors.New("proto: descriptor conflict")
|
|
||||||
}
|
|
||||||
return e.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if extension.ExtensionType == nil {
|
|
||||||
// incomplete descriptor
|
|
||||||
return e.enc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
v, err := decodeExtension(e.enc, extension)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember the decoded version and drop the encoded version.
|
|
||||||
// That way it is safe to mutate what we return.
|
|
||||||
e.value = v
|
|
||||||
e.desc = extension
|
|
||||||
e.enc = nil
|
|
||||||
emap[extension.Field] = e
|
|
||||||
return e.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultExtensionValue returns the default value for extension.
|
|
||||||
// If no default for an extension is defined ErrMissingExtension is returned.
|
|
||||||
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
|
|
||||||
if extension.ExtensionType == nil {
|
|
||||||
// incomplete descriptor, so no default
|
|
||||||
return nil, ErrMissingExtension
|
|
||||||
}
|
|
||||||
|
|
||||||
t := reflect.TypeOf(extension.ExtensionType)
|
|
||||||
props := extensionProperties(extension)
|
|
||||||
|
|
||||||
sf, _, err := fieldDefault(t, props)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if sf == nil || sf.value == nil {
|
|
||||||
// There is no default value.
|
|
||||||
return nil, ErrMissingExtension
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.Kind() != reflect.Ptr {
|
|
||||||
// We do not need to return a Ptr, we can directly return sf.value.
|
|
||||||
return sf.value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to return an interface{} that is a pointer to sf.value.
|
|
||||||
value := reflect.New(t).Elem()
|
|
||||||
value.Set(reflect.New(value.Type().Elem()))
|
|
||||||
if sf.kind == reflect.Int32 {
|
|
||||||
// We may have an int32 or an enum, but the underlying data is int32.
|
|
||||||
// Since we can't set an int32 into a non int32 reflect.value directly
|
|
||||||
// set it as a int32.
|
|
||||||
value.Elem().SetInt(int64(sf.value.(int32)))
|
|
||||||
} else {
|
|
||||||
value.Elem().Set(reflect.ValueOf(sf.value))
|
|
||||||
}
|
|
||||||
return value.Interface(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// decodeExtension decodes an extension encoded in b.
|
|
||||||
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
|
|
||||||
t := reflect.TypeOf(extension.ExtensionType)
|
|
||||||
unmarshal := typeUnmarshaler(t, extension.Tag)
|
|
||||||
|
|
||||||
// t is a pointer to a struct, pointer to basic type or a slice.
|
|
||||||
// Allocate space to store the pointer/slice.
|
|
||||||
value := reflect.New(t).Elem()
|
|
||||||
|
|
||||||
var err error
|
|
||||||
for {
|
|
||||||
x, n := decodeVarint(b)
|
|
||||||
if n == 0 {
|
|
||||||
return nil, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b = b[n:]
|
|
||||||
wire := int(x) & 7
|
|
||||||
|
|
||||||
b, err = unmarshal(b, valToPointer(value.Addr()), wire)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(b) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value.Interface(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
|
|
||||||
// The returned slice has the same length as es; missing extensions will appear as nil elements.
|
|
||||||
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
|
|
||||||
epb, err := extendable(pb)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
extensions = make([]interface{}, len(es))
|
|
||||||
for i, e := range es {
|
|
||||||
extensions[i], err = GetExtension(epb, e)
|
|
||||||
if err == ErrMissingExtension {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
|
|
||||||
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
|
|
||||||
// just the Field field, which defines the extension's field number.
|
|
||||||
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
|
|
||||||
epb, err := extendable(pb)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
registeredExtensions := RegisteredExtensions(pb)
|
|
||||||
|
|
||||||
emap, mu := epb.extensionsRead()
|
|
||||||
if emap == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
extensions := make([]*ExtensionDesc, 0, len(emap))
|
|
||||||
for extid, e := range emap {
|
|
||||||
desc := e.desc
|
|
||||||
if desc == nil {
|
|
||||||
desc = registeredExtensions[extid]
|
|
||||||
if desc == nil {
|
|
||||||
desc = &ExtensionDesc{Field: extid}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions = append(extensions, desc)
|
|
||||||
}
|
|
||||||
return extensions, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetExtension sets the specified extension of pb to the specified value.
|
|
||||||
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
|
|
||||||
epb, err := extendable(pb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := checkExtensionTypes(epb, extension); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
typ := reflect.TypeOf(extension.ExtensionType)
|
|
||||||
if typ != reflect.TypeOf(value) {
|
|
||||||
return errors.New("proto: bad extension value type")
|
|
||||||
}
|
|
||||||
// nil extension values need to be caught early, because the
|
|
||||||
// encoder can't distinguish an ErrNil due to a nil extension
|
|
||||||
// from an ErrNil due to a missing field. Extensions are
|
|
||||||
// always optional, so the encoder would just swallow the error
|
|
||||||
// and drop all the extensions from the encoded message.
|
|
||||||
if reflect.ValueOf(value).IsNil() {
|
|
||||||
return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
extmap := epb.extensionsWrite()
|
|
||||||
extmap[extension.Field] = Extension{desc: extension, value: value}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearAllExtensions clears all extensions from pb.
|
|
||||||
func ClearAllExtensions(pb Message) {
|
|
||||||
epb, err := extendable(pb)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
m := epb.extensionsWrite()
|
|
||||||
for k := range m {
|
|
||||||
delete(m, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A global registry of extensions.
|
|
||||||
// The generated code will register the generated descriptors by calling RegisterExtension.
|
|
||||||
|
|
||||||
var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
|
|
||||||
|
|
||||||
// RegisterExtension is called from the generated code.
|
|
||||||
func RegisterExtension(desc *ExtensionDesc) {
|
|
||||||
st := reflect.TypeOf(desc.ExtendedType).Elem()
|
|
||||||
m := extensionMaps[st]
|
|
||||||
if m == nil {
|
|
||||||
m = make(map[int32]*ExtensionDesc)
|
|
||||||
extensionMaps[st] = m
|
|
||||||
}
|
|
||||||
if _, ok := m[desc.Field]; ok {
|
|
||||||
panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
|
|
||||||
}
|
|
||||||
m[desc.Field] = desc
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisteredExtensions returns a map of the registered extensions of a
|
|
||||||
// protocol buffer struct, indexed by the extension number.
|
|
||||||
// The argument pb should be a nil pointer to the struct type.
|
|
||||||
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
|
|
||||||
return extensionMaps[reflect.TypeOf(pb).Elem()]
|
|
||||||
}
|
|
979
vendor/github.com/golang/protobuf/proto/lib.go
generated
vendored
979
vendor/github.com/golang/protobuf/proto/lib.go
generated
vendored
@ -1,979 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package proto converts data structures to and from the wire format of
|
|
||||||
protocol buffers. It works in concert with the Go source code generated
|
|
||||||
for .proto files by the protocol compiler.
|
|
||||||
|
|
||||||
A summary of the properties of the protocol buffer interface
|
|
||||||
for a protocol buffer variable v:
|
|
||||||
|
|
||||||
- Names are turned from camel_case to CamelCase for export.
|
|
||||||
- There are no methods on v to set fields; just treat
|
|
||||||
them as structure fields.
|
|
||||||
- There are getters that return a field's value if set,
|
|
||||||
and return the field's default value if unset.
|
|
||||||
The getters work even if the receiver is a nil message.
|
|
||||||
- The zero value for a struct is its correct initialization state.
|
|
||||||
All desired fields must be set before marshaling.
|
|
||||||
- A Reset() method will restore a protobuf struct to its zero state.
|
|
||||||
- Non-repeated fields are pointers to the values; nil means unset.
|
|
||||||
That is, optional or required field int32 f becomes F *int32.
|
|
||||||
- Repeated fields are slices.
|
|
||||||
- Helper functions are available to aid the setting of fields.
|
|
||||||
msg.Foo = proto.String("hello") // set field
|
|
||||||
- Constants are defined to hold the default values of all fields that
|
|
||||||
have them. They have the form Default_StructName_FieldName.
|
|
||||||
Because the getter methods handle defaulted values,
|
|
||||||
direct use of these constants should be rare.
|
|
||||||
- Enums are given type names and maps from names to values.
|
|
||||||
Enum values are prefixed by the enclosing message's name, or by the
|
|
||||||
enum's type name if it is a top-level enum. Enum types have a String
|
|
||||||
method, and a Enum method to assist in message construction.
|
|
||||||
- Nested messages, groups and enums have type names prefixed with the name of
|
|
||||||
the surrounding message type.
|
|
||||||
- Extensions are given descriptor names that start with E_,
|
|
||||||
followed by an underscore-delimited list of the nested messages
|
|
||||||
that contain it (if any) followed by the CamelCased name of the
|
|
||||||
extension field itself. HasExtension, ClearExtension, GetExtension
|
|
||||||
and SetExtension are functions for manipulating extensions.
|
|
||||||
- Oneof field sets are given a single field in their message,
|
|
||||||
with distinguished wrapper types for each possible field value.
|
|
||||||
- Marshal and Unmarshal are functions to encode and decode the wire format.
|
|
||||||
|
|
||||||
When the .proto file specifies `syntax="proto3"`, there are some differences:
|
|
||||||
|
|
||||||
- Non-repeated fields of non-message type are values instead of pointers.
|
|
||||||
- Enum types do not get an Enum method.
|
|
||||||
|
|
||||||
The simplest way to describe this is to see an example.
|
|
||||||
Given file test.proto, containing
|
|
||||||
|
|
||||||
package example;
|
|
||||||
|
|
||||||
enum FOO { X = 17; }
|
|
||||||
|
|
||||||
message Test {
|
|
||||||
required string label = 1;
|
|
||||||
optional int32 type = 2 [default=77];
|
|
||||||
repeated int64 reps = 3;
|
|
||||||
optional group OptionalGroup = 4 {
|
|
||||||
required string RequiredField = 5;
|
|
||||||
}
|
|
||||||
oneof union {
|
|
||||||
int32 number = 6;
|
|
||||||
string name = 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
The resulting file, test.pb.go, is:
|
|
||||||
|
|
||||||
package example
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import math "math"
|
|
||||||
|
|
||||||
type FOO int32
|
|
||||||
const (
|
|
||||||
FOO_X FOO = 17
|
|
||||||
)
|
|
||||||
var FOO_name = map[int32]string{
|
|
||||||
17: "X",
|
|
||||||
}
|
|
||||||
var FOO_value = map[string]int32{
|
|
||||||
"X": 17,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x FOO) Enum() *FOO {
|
|
||||||
p := new(FOO)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x FOO) String() string {
|
|
||||||
return proto.EnumName(FOO_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *FOO) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(FOO_value, data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = FOO(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Test struct {
|
|
||||||
Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
|
|
||||||
Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
|
|
||||||
Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
|
|
||||||
Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
|
|
||||||
// Types that are valid to be assigned to Union:
|
|
||||||
// *Test_Number
|
|
||||||
// *Test_Name
|
|
||||||
Union isTest_Union `protobuf_oneof:"union"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
func (m *Test) Reset() { *m = Test{} }
|
|
||||||
func (m *Test) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Test) ProtoMessage() {}
|
|
||||||
|
|
||||||
type isTest_Union interface {
|
|
||||||
isTest_Union()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Test_Number struct {
|
|
||||||
Number int32 `protobuf:"varint,6,opt,name=number"`
|
|
||||||
}
|
|
||||||
type Test_Name struct {
|
|
||||||
Name string `protobuf:"bytes,7,opt,name=name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Test_Number) isTest_Union() {}
|
|
||||||
func (*Test_Name) isTest_Union() {}
|
|
||||||
|
|
||||||
func (m *Test) GetUnion() isTest_Union {
|
|
||||||
if m != nil {
|
|
||||||
return m.Union
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
const Default_Test_Type int32 = 77
|
|
||||||
|
|
||||||
func (m *Test) GetLabel() string {
|
|
||||||
if m != nil && m.Label != nil {
|
|
||||||
return *m.Label
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetType() int32 {
|
|
||||||
if m != nil && m.Type != nil {
|
|
||||||
return *m.Type
|
|
||||||
}
|
|
||||||
return Default_Test_Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
|
|
||||||
if m != nil {
|
|
||||||
return m.Optionalgroup
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Test_OptionalGroup struct {
|
|
||||||
RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
|
|
||||||
}
|
|
||||||
func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
|
|
||||||
func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
|
|
||||||
|
|
||||||
func (m *Test_OptionalGroup) GetRequiredField() string {
|
|
||||||
if m != nil && m.RequiredField != nil {
|
|
||||||
return *m.RequiredField
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetNumber() int32 {
|
|
||||||
if x, ok := m.GetUnion().(*Test_Number); ok {
|
|
||||||
return x.Number
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetName() string {
|
|
||||||
if x, ok := m.GetUnion().(*Test_Name); ok {
|
|
||||||
return x.Name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
To create and play with a Test object:
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
pb "./example.pb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
test := &pb.Test{
|
|
||||||
Label: proto.String("hello"),
|
|
||||||
Type: proto.Int32(17),
|
|
||||||
Reps: []int64{1, 2, 3},
|
|
||||||
Optionalgroup: &pb.Test_OptionalGroup{
|
|
||||||
RequiredField: proto.String("good bye"),
|
|
||||||
},
|
|
||||||
Union: &pb.Test_Name{"fred"},
|
|
||||||
}
|
|
||||||
data, err := proto.Marshal(test)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("marshaling error: ", err)
|
|
||||||
}
|
|
||||||
newTest := &pb.Test{}
|
|
||||||
err = proto.Unmarshal(data, newTest)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("unmarshaling error: ", err)
|
|
||||||
}
|
|
||||||
// Now test and newTest contain the same data.
|
|
||||||
if test.GetLabel() != newTest.GetLabel() {
|
|
||||||
log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
|
|
||||||
}
|
|
||||||
// Use a type switch to determine which oneof was set.
|
|
||||||
switch u := test.Union.(type) {
|
|
||||||
case *pb.Test_Number: // u.Number contains the number.
|
|
||||||
case *pb.Test_Name: // u.Name contains the string.
|
|
||||||
}
|
|
||||||
// etc.
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
|
|
||||||
// Marshal reports this when a required field is not initialized.
|
|
||||||
// Unmarshal reports this when a required field is missing from the wire data.
|
|
||||||
type RequiredNotSetError struct{ field string }
|
|
||||||
|
|
||||||
func (e *RequiredNotSetError) Error() string {
|
|
||||||
if e.field == "" {
|
|
||||||
return fmt.Sprintf("proto: required field not set")
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("proto: required field %q not set", e.field)
|
|
||||||
}
|
|
||||||
func (e *RequiredNotSetError) RequiredNotSet() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type invalidUTF8Error struct{ field string }
|
|
||||||
|
|
||||||
func (e *invalidUTF8Error) Error() string {
|
|
||||||
if e.field == "" {
|
|
||||||
return "proto: invalid UTF-8 detected"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
|
|
||||||
}
|
|
||||||
func (e *invalidUTF8Error) InvalidUTF8() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
|
|
||||||
// This error should not be exposed to the external API as such errors should
|
|
||||||
// be recreated with the field information.
|
|
||||||
var errInvalidUTF8 = &invalidUTF8Error{}
|
|
||||||
|
|
||||||
// isNonFatal reports whether the error is either a RequiredNotSet error
|
|
||||||
// or a InvalidUTF8 error.
|
|
||||||
func isNonFatal(err error) bool {
|
|
||||||
if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type nonFatal struct{ E error }
|
|
||||||
|
|
||||||
// Merge merges err into nf and reports whether it was successful.
|
|
||||||
// Otherwise it returns false for any fatal non-nil errors.
|
|
||||||
func (nf *nonFatal) Merge(err error) (ok bool) {
|
|
||||||
if err == nil {
|
|
||||||
return true // not an error
|
|
||||||
}
|
|
||||||
if !isNonFatal(err) {
|
|
||||||
return false // fatal error
|
|
||||||
}
|
|
||||||
if nf.E == nil {
|
|
||||||
nf.E = err // store first instance of non-fatal error
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message is implemented by generated protocol buffer messages.
|
|
||||||
type Message interface {
|
|
||||||
Reset()
|
|
||||||
String() string
|
|
||||||
ProtoMessage()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stats records allocation details about the protocol buffer encoders
|
|
||||||
// and decoders. Useful for tuning the library itself.
|
|
||||||
type Stats struct {
|
|
||||||
Emalloc uint64 // mallocs in encode
|
|
||||||
Dmalloc uint64 // mallocs in decode
|
|
||||||
Encode uint64 // number of encodes
|
|
||||||
Decode uint64 // number of decodes
|
|
||||||
Chit uint64 // number of cache hits
|
|
||||||
Cmiss uint64 // number of cache misses
|
|
||||||
Size uint64 // number of sizes
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set to true to enable stats collection.
|
|
||||||
const collectStats = false
|
|
||||||
|
|
||||||
var stats Stats
|
|
||||||
|
|
||||||
// GetStats returns a copy of the global Stats structure.
|
|
||||||
func GetStats() Stats { return stats }
|
|
||||||
|
|
||||||
// A Buffer is a buffer manager for marshaling and unmarshaling
|
|
||||||
// protocol buffers. It may be reused between invocations to
|
|
||||||
// reduce memory usage. It is not necessary to use a Buffer;
|
|
||||||
// the global functions Marshal and Unmarshal create a
|
|
||||||
// temporary Buffer and are fine for most applications.
|
|
||||||
type Buffer struct {
|
|
||||||
buf []byte // encode/decode byte stream
|
|
||||||
index int // read point
|
|
||||||
|
|
||||||
deterministic bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBuffer allocates a new Buffer and initializes its internal data to
|
|
||||||
// the contents of the argument slice.
|
|
||||||
func NewBuffer(e []byte) *Buffer {
|
|
||||||
return &Buffer{buf: e}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
|
|
||||||
func (p *Buffer) Reset() {
|
|
||||||
p.buf = p.buf[0:0] // for reading/writing
|
|
||||||
p.index = 0 // for reading
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBuf replaces the internal buffer with the slice,
|
|
||||||
// ready for unmarshaling the contents of the slice.
|
|
||||||
func (p *Buffer) SetBuf(s []byte) {
|
|
||||||
p.buf = s
|
|
||||||
p.index = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns the contents of the Buffer.
|
|
||||||
func (p *Buffer) Bytes() []byte { return p.buf }
|
|
||||||
|
|
||||||
// SetDeterministic sets whether to use deterministic serialization.
|
|
||||||
//
|
|
||||||
// Deterministic serialization guarantees that for a given binary, equal
|
|
||||||
// messages will always be serialized to the same bytes. This implies:
|
|
||||||
//
|
|
||||||
// - Repeated serialization of a message will return the same bytes.
|
|
||||||
// - Different processes of the same binary (which may be executing on
|
|
||||||
// different machines) will serialize equal messages to the same bytes.
|
|
||||||
//
|
|
||||||
// Note that the deterministic serialization is NOT canonical across
|
|
||||||
// languages. It is not guaranteed to remain stable over time. It is unstable
|
|
||||||
// across different builds with schema changes due to unknown fields.
|
|
||||||
// Users who need canonical serialization (e.g., persistent storage in a
|
|
||||||
// canonical form, fingerprinting, etc.) should define their own
|
|
||||||
// canonicalization specification and implement their own serializer rather
|
|
||||||
// than relying on this API.
|
|
||||||
//
|
|
||||||
// If deterministic serialization is requested, map entries will be sorted
|
|
||||||
// by keys in lexographical order. This is an implementation detail and
|
|
||||||
// subject to change.
|
|
||||||
func (p *Buffer) SetDeterministic(deterministic bool) {
|
|
||||||
p.deterministic = deterministic
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper routines for simplifying the creation of optional fields of basic type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Bool is a helper routine that allocates a new bool value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Bool(v bool) *bool {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32 is a helper routine that allocates a new int32 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Int32(v int32) *int32 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int is a helper routine that allocates a new int32 value
|
|
||||||
// to store v and returns a pointer to it, but unlike Int32
|
|
||||||
// its argument value is an int.
|
|
||||||
func Int(v int) *int32 {
|
|
||||||
p := new(int32)
|
|
||||||
*p = int32(v)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64 is a helper routine that allocates a new int64 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Int64(v int64) *int64 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32 is a helper routine that allocates a new float32 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Float32(v float32) *float32 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64 is a helper routine that allocates a new float64 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Float64(v float64) *float64 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32 is a helper routine that allocates a new uint32 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Uint32(v uint32) *uint32 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64 is a helper routine that allocates a new uint64 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Uint64(v uint64) *uint64 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// String is a helper routine that allocates a new string value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func String(v string) *string {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnumName is a helper function to simplify printing protocol buffer enums
|
|
||||||
// by name. Given an enum map and a value, it returns a useful string.
|
|
||||||
func EnumName(m map[int32]string, v int32) string {
|
|
||||||
s, ok := m[v]
|
|
||||||
if ok {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return strconv.Itoa(int(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
|
|
||||||
// from their JSON-encoded representation. Given a map from the enum's symbolic
|
|
||||||
// names to its int values, and a byte buffer containing the JSON-encoded
|
|
||||||
// value, it returns an int32 that can be cast to the enum type by the caller.
|
|
||||||
//
|
|
||||||
// The function can deal with both JSON representations, numeric and symbolic.
|
|
||||||
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
|
|
||||||
if data[0] == '"' {
|
|
||||||
// New style: enums are strings.
|
|
||||||
var repr string
|
|
||||||
if err := json.Unmarshal(data, &repr); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
val, ok := m[repr]
|
|
||||||
if !ok {
|
|
||||||
return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
|
|
||||||
}
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
// Old style: enums are ints.
|
|
||||||
var val int32
|
|
||||||
if err := json.Unmarshal(data, &val); err != nil {
|
|
||||||
return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
|
|
||||||
}
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DebugPrint dumps the encoded data in b in a debugging format with a header
|
|
||||||
// including the string s. Used in testing but made available for general debugging.
|
|
||||||
func (p *Buffer) DebugPrint(s string, b []byte) {
|
|
||||||
var u uint64
|
|
||||||
|
|
||||||
obuf := p.buf
|
|
||||||
index := p.index
|
|
||||||
p.buf = b
|
|
||||||
p.index = 0
|
|
||||||
depth := 0
|
|
||||||
|
|
||||||
fmt.Printf("\n--- %s ---\n", s)
|
|
||||||
|
|
||||||
out:
|
|
||||||
for {
|
|
||||||
for i := 0; i < depth; i++ {
|
|
||||||
fmt.Print(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
index := p.index
|
|
||||||
if index == len(p.buf) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
op, err := p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: fetching op err %v\n", index, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
tag := op >> 3
|
|
||||||
wire := op & 7
|
|
||||||
|
|
||||||
switch wire {
|
|
||||||
default:
|
|
||||||
fmt.Printf("%3d: t=%3d unknown wire=%d\n",
|
|
||||||
index, tag, wire)
|
|
||||||
break out
|
|
||||||
|
|
||||||
case WireBytes:
|
|
||||||
var r []byte
|
|
||||||
|
|
||||||
r, err = p.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
|
|
||||||
if len(r) <= 6 {
|
|
||||||
for i := 0; i < len(r); i++ {
|
|
||||||
fmt.Printf(" %.2x", r[i])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
fmt.Printf(" %.2x", r[i])
|
|
||||||
}
|
|
||||||
fmt.Printf(" ..")
|
|
||||||
for i := len(r) - 3; i < len(r); i++ {
|
|
||||||
fmt.Printf(" %.2x", r[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Printf("\n")
|
|
||||||
|
|
||||||
case WireFixed32:
|
|
||||||
u, err = p.DecodeFixed32()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
|
|
||||||
|
|
||||||
case WireFixed64:
|
|
||||||
u, err = p.DecodeFixed64()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
|
|
||||||
|
|
||||||
case WireVarint:
|
|
||||||
u, err = p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
|
|
||||||
|
|
||||||
case WireStartGroup:
|
|
||||||
fmt.Printf("%3d: t=%3d start\n", index, tag)
|
|
||||||
depth++
|
|
||||||
|
|
||||||
case WireEndGroup:
|
|
||||||
depth--
|
|
||||||
fmt.Printf("%3d: t=%3d end\n", index, tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if depth != 0 {
|
|
||||||
fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
|
|
||||||
}
|
|
||||||
fmt.Printf("\n")
|
|
||||||
|
|
||||||
p.buf = obuf
|
|
||||||
p.index = index
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDefaults sets unset protocol buffer fields to their default values.
|
|
||||||
// It only modifies fields that are both unset and have defined defaults.
|
|
||||||
// It recursively sets default values in any non-nil sub-messages.
|
|
||||||
func SetDefaults(pb Message) {
|
|
||||||
setDefaults(reflect.ValueOf(pb), true, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// v is a pointer to a struct.
|
|
||||||
func setDefaults(v reflect.Value, recur, zeros bool) {
|
|
||||||
v = v.Elem()
|
|
||||||
|
|
||||||
defaultMu.RLock()
|
|
||||||
dm, ok := defaults[v.Type()]
|
|
||||||
defaultMu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
dm = buildDefaultMessage(v.Type())
|
|
||||||
defaultMu.Lock()
|
|
||||||
defaults[v.Type()] = dm
|
|
||||||
defaultMu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sf := range dm.scalars {
|
|
||||||
f := v.Field(sf.index)
|
|
||||||
if !f.IsNil() {
|
|
||||||
// field already set
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dv := sf.value
|
|
||||||
if dv == nil && !zeros {
|
|
||||||
// no explicit default, and don't want to set zeros
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fptr := f.Addr().Interface() // **T
|
|
||||||
// TODO: Consider batching the allocations we do here.
|
|
||||||
switch sf.kind {
|
|
||||||
case reflect.Bool:
|
|
||||||
b := new(bool)
|
|
||||||
if dv != nil {
|
|
||||||
*b = dv.(bool)
|
|
||||||
}
|
|
||||||
*(fptr.(**bool)) = b
|
|
||||||
case reflect.Float32:
|
|
||||||
f := new(float32)
|
|
||||||
if dv != nil {
|
|
||||||
*f = dv.(float32)
|
|
||||||
}
|
|
||||||
*(fptr.(**float32)) = f
|
|
||||||
case reflect.Float64:
|
|
||||||
f := new(float64)
|
|
||||||
if dv != nil {
|
|
||||||
*f = dv.(float64)
|
|
||||||
}
|
|
||||||
*(fptr.(**float64)) = f
|
|
||||||
case reflect.Int32:
|
|
||||||
// might be an enum
|
|
||||||
if ft := f.Type(); ft != int32PtrType {
|
|
||||||
// enum
|
|
||||||
f.Set(reflect.New(ft.Elem()))
|
|
||||||
if dv != nil {
|
|
||||||
f.Elem().SetInt(int64(dv.(int32)))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// int32 field
|
|
||||||
i := new(int32)
|
|
||||||
if dv != nil {
|
|
||||||
*i = dv.(int32)
|
|
||||||
}
|
|
||||||
*(fptr.(**int32)) = i
|
|
||||||
}
|
|
||||||
case reflect.Int64:
|
|
||||||
i := new(int64)
|
|
||||||
if dv != nil {
|
|
||||||
*i = dv.(int64)
|
|
||||||
}
|
|
||||||
*(fptr.(**int64)) = i
|
|
||||||
case reflect.String:
|
|
||||||
s := new(string)
|
|
||||||
if dv != nil {
|
|
||||||
*s = dv.(string)
|
|
||||||
}
|
|
||||||
*(fptr.(**string)) = s
|
|
||||||
case reflect.Uint8:
|
|
||||||
// exceptional case: []byte
|
|
||||||
var b []byte
|
|
||||||
if dv != nil {
|
|
||||||
db := dv.([]byte)
|
|
||||||
b = make([]byte, len(db))
|
|
||||||
copy(b, db)
|
|
||||||
} else {
|
|
||||||
b = []byte{}
|
|
||||||
}
|
|
||||||
*(fptr.(*[]byte)) = b
|
|
||||||
case reflect.Uint32:
|
|
||||||
u := new(uint32)
|
|
||||||
if dv != nil {
|
|
||||||
*u = dv.(uint32)
|
|
||||||
}
|
|
||||||
*(fptr.(**uint32)) = u
|
|
||||||
case reflect.Uint64:
|
|
||||||
u := new(uint64)
|
|
||||||
if dv != nil {
|
|
||||||
*u = dv.(uint64)
|
|
||||||
}
|
|
||||||
*(fptr.(**uint64)) = u
|
|
||||||
default:
|
|
||||||
log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ni := range dm.nested {
|
|
||||||
f := v.Field(ni)
|
|
||||||
// f is *T or []*T or map[T]*T
|
|
||||||
switch f.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if f.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
setDefaults(f, recur, zeros)
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
for i := 0; i < f.Len(); i++ {
|
|
||||||
e := f.Index(i)
|
|
||||||
if e.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
setDefaults(e, recur, zeros)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
for _, k := range f.MapKeys() {
|
|
||||||
e := f.MapIndex(k)
|
|
||||||
if e.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
setDefaults(e, recur, zeros)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// defaults maps a protocol buffer struct type to a slice of the fields,
|
|
||||||
// with its scalar fields set to their proto-declared non-zero default values.
|
|
||||||
defaultMu sync.RWMutex
|
|
||||||
defaults = make(map[reflect.Type]defaultMessage)
|
|
||||||
|
|
||||||
int32PtrType = reflect.TypeOf((*int32)(nil))
|
|
||||||
)
|
|
||||||
|
|
||||||
// defaultMessage represents information about the default values of a message.
|
|
||||||
type defaultMessage struct {
|
|
||||||
scalars []scalarField
|
|
||||||
nested []int // struct field index of nested messages
|
|
||||||
}
|
|
||||||
|
|
||||||
type scalarField struct {
|
|
||||||
index int // struct field index
|
|
||||||
kind reflect.Kind // element type (the T in *T or []T)
|
|
||||||
value interface{} // the proto-declared default value, or nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// t is a struct type.
|
|
||||||
func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
|
|
||||||
sprop := GetProperties(t)
|
|
||||||
for _, prop := range sprop.Prop {
|
|
||||||
fi, ok := sprop.decoderTags.get(prop.Tag)
|
|
||||||
if !ok {
|
|
||||||
// XXX_unrecognized
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ft := t.Field(fi).Type
|
|
||||||
|
|
||||||
sf, nested, err := fieldDefault(ft, prop)
|
|
||||||
switch {
|
|
||||||
case err != nil:
|
|
||||||
log.Print(err)
|
|
||||||
case nested:
|
|
||||||
dm.nested = append(dm.nested, fi)
|
|
||||||
case sf != nil:
|
|
||||||
sf.index = fi
|
|
||||||
dm.scalars = append(dm.scalars, *sf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dm
|
|
||||||
}
|
|
||||||
|
|
||||||
// fieldDefault returns the scalarField for field type ft.
|
|
||||||
// sf will be nil if the field can not have a default.
|
|
||||||
// nestedMessage will be true if this is a nested message.
|
|
||||||
// Note that sf.index is not set on return.
|
|
||||||
func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
|
|
||||||
var canHaveDefault bool
|
|
||||||
switch ft.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if ft.Elem().Kind() == reflect.Struct {
|
|
||||||
nestedMessage = true
|
|
||||||
} else {
|
|
||||||
canHaveDefault = true // proto2 scalar field
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
switch ft.Elem().Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
nestedMessage = true // repeated message
|
|
||||||
case reflect.Uint8:
|
|
||||||
canHaveDefault = true // bytes field
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
if ft.Elem().Kind() == reflect.Ptr {
|
|
||||||
nestedMessage = true // map with message values
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !canHaveDefault {
|
|
||||||
if nestedMessage {
|
|
||||||
return nil, true, nil
|
|
||||||
}
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We now know that ft is a pointer or slice.
|
|
||||||
sf = &scalarField{kind: ft.Elem().Kind()}
|
|
||||||
|
|
||||||
// scalar fields without defaults
|
|
||||||
if !prop.HasDefault {
|
|
||||||
return sf, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// a scalar field: either *T or []byte
|
|
||||||
switch ft.Elem().Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
x, err := strconv.ParseBool(prop.Default)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
case reflect.Float32:
|
|
||||||
x, err := strconv.ParseFloat(prop.Default, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = float32(x)
|
|
||||||
case reflect.Float64:
|
|
||||||
x, err := strconv.ParseFloat(prop.Default, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
case reflect.Int32:
|
|
||||||
x, err := strconv.ParseInt(prop.Default, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = int32(x)
|
|
||||||
case reflect.Int64:
|
|
||||||
x, err := strconv.ParseInt(prop.Default, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
case reflect.String:
|
|
||||||
sf.value = prop.Default
|
|
||||||
case reflect.Uint8:
|
|
||||||
// []byte (not *uint8)
|
|
||||||
sf.value = []byte(prop.Default)
|
|
||||||
case reflect.Uint32:
|
|
||||||
x, err := strconv.ParseUint(prop.Default, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = uint32(x)
|
|
||||||
case reflect.Uint64:
|
|
||||||
x, err := strconv.ParseUint(prop.Default, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
default:
|
|
||||||
return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
return sf, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// mapKeys returns a sort.Interface to be used for sorting the map keys.
|
|
||||||
// Map fields may have key types of non-float scalars, strings and enums.
|
|
||||||
func mapKeys(vs []reflect.Value) sort.Interface {
|
|
||||||
s := mapKeySorter{vs: vs}
|
|
||||||
|
|
||||||
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
|
|
||||||
if len(vs) == 0 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
switch vs[0].Kind() {
|
|
||||||
case reflect.Int32, reflect.Int64:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
|
|
||||||
case reflect.Uint32, reflect.Uint64:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
|
|
||||||
case reflect.Bool:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
|
|
||||||
case reflect.String:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
type mapKeySorter struct {
|
|
||||||
vs []reflect.Value
|
|
||||||
less func(a, b reflect.Value) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s mapKeySorter) Len() int { return len(s.vs) }
|
|
||||||
func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
|
|
||||||
func (s mapKeySorter) Less(i, j int) bool {
|
|
||||||
return s.less(s.vs[i], s.vs[j])
|
|
||||||
}
|
|
||||||
|
|
||||||
// isProto3Zero reports whether v is a zero proto3 value.
|
|
||||||
func isProto3Zero(v reflect.Value) bool {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return !v.Bool()
|
|
||||||
case reflect.Int32, reflect.Int64:
|
|
||||||
return v.Int() == 0
|
|
||||||
case reflect.Uint32, reflect.Uint64:
|
|
||||||
return v.Uint() == 0
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return v.Float() == 0
|
|
||||||
case reflect.String:
|
|
||||||
return v.String() == ""
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
|
||||||
// to assert that that code is compatible with this version of the proto package.
|
|
||||||
const ProtoPackageIsVersion2 = true
|
|
||||||
|
|
||||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
|
||||||
// to assert that that code is compatible with this version of the proto package.
|
|
||||||
const ProtoPackageIsVersion1 = true
|
|
||||||
|
|
||||||
// InternalMessageInfo is a type used internally by generated .pb.go files.
|
|
||||||
// This type is not intended to be used by non-generated code.
|
|
||||||
// This type is not subject to any compatibility guarantee.
|
|
||||||
type InternalMessageInfo struct {
|
|
||||||
marshal *marshalInfo
|
|
||||||
unmarshal *unmarshalInfo
|
|
||||||
merge *mergeInfo
|
|
||||||
discard *discardInfo
|
|
||||||
}
|
|
314
vendor/github.com/golang/protobuf/proto/message_set.go
generated
vendored
314
vendor/github.com/golang/protobuf/proto/message_set.go
generated
vendored
@ -1,314 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Support for message sets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
|
|
||||||
// A message type ID is required for storing a protocol buffer in a message set.
|
|
||||||
var errNoMessageTypeID = errors.New("proto does not have a message type ID")
|
|
||||||
|
|
||||||
// The first two types (_MessageSet_Item and messageSet)
|
|
||||||
// model what the protocol compiler produces for the following protocol message:
|
|
||||||
// message MessageSet {
|
|
||||||
// repeated group Item = 1 {
|
|
||||||
// required int32 type_id = 2;
|
|
||||||
// required string message = 3;
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// That is the MessageSet wire format. We can't use a proto to generate these
|
|
||||||
// because that would introduce a circular dependency between it and this package.
|
|
||||||
|
|
||||||
type _MessageSet_Item struct {
|
|
||||||
TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
|
|
||||||
Message []byte `protobuf:"bytes,3,req,name=message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type messageSet struct {
|
|
||||||
Item []*_MessageSet_Item `protobuf:"group,1,rep"`
|
|
||||||
XXX_unrecognized []byte
|
|
||||||
// TODO: caching?
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure messageSet is a Message.
|
|
||||||
var _ Message = (*messageSet)(nil)
|
|
||||||
|
|
||||||
// messageTypeIder is an interface satisfied by a protocol buffer type
|
|
||||||
// that may be stored in a MessageSet.
|
|
||||||
type messageTypeIder interface {
|
|
||||||
MessageTypeId() int32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) find(pb Message) *_MessageSet_Item {
|
|
||||||
mti, ok := pb.(messageTypeIder)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
id := mti.MessageTypeId()
|
|
||||||
for _, item := range ms.Item {
|
|
||||||
if *item.TypeId == id {
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Has(pb Message) bool {
|
|
||||||
return ms.find(pb) != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Unmarshal(pb Message) error {
|
|
||||||
if item := ms.find(pb); item != nil {
|
|
||||||
return Unmarshal(item.Message, pb)
|
|
||||||
}
|
|
||||||
if _, ok := pb.(messageTypeIder); !ok {
|
|
||||||
return errNoMessageTypeID
|
|
||||||
}
|
|
||||||
return nil // TODO: return error instead?
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Marshal(pb Message) error {
|
|
||||||
msg, err := Marshal(pb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if item := ms.find(pb); item != nil {
|
|
||||||
// reuse existing item
|
|
||||||
item.Message = msg
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mti, ok := pb.(messageTypeIder)
|
|
||||||
if !ok {
|
|
||||||
return errNoMessageTypeID
|
|
||||||
}
|
|
||||||
|
|
||||||
mtid := mti.MessageTypeId()
|
|
||||||
ms.Item = append(ms.Item, &_MessageSet_Item{
|
|
||||||
TypeId: &mtid,
|
|
||||||
Message: msg,
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Reset() { *ms = messageSet{} }
|
|
||||||
func (ms *messageSet) String() string { return CompactTextString(ms) }
|
|
||||||
func (*messageSet) ProtoMessage() {}
|
|
||||||
|
|
||||||
// Support for the message_set_wire_format message option.
|
|
||||||
|
|
||||||
func skipVarint(buf []byte) []byte {
|
|
||||||
i := 0
|
|
||||||
for ; buf[i]&0x80 != 0; i++ {
|
|
||||||
}
|
|
||||||
return buf[i+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
|
|
||||||
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
|
|
||||||
func MarshalMessageSet(exts interface{}) ([]byte, error) {
|
|
||||||
return marshalMessageSet(exts, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
|
|
||||||
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
|
|
||||||
switch exts := exts.(type) {
|
|
||||||
case *XXX_InternalExtensions:
|
|
||||||
var u marshalInfo
|
|
||||||
siz := u.sizeMessageSet(exts)
|
|
||||||
b := make([]byte, 0, siz)
|
|
||||||
return u.appendMessageSet(b, exts, deterministic)
|
|
||||||
|
|
||||||
case map[int32]Extension:
|
|
||||||
// This is an old-style extension map.
|
|
||||||
// Wrap it in a new-style XXX_InternalExtensions.
|
|
||||||
ie := XXX_InternalExtensions{
|
|
||||||
p: &struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
extensionMap map[int32]Extension
|
|
||||||
}{
|
|
||||||
extensionMap: exts,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var u marshalInfo
|
|
||||||
siz := u.sizeMessageSet(&ie)
|
|
||||||
b := make([]byte, 0, siz)
|
|
||||||
return u.appendMessageSet(b, &ie, deterministic)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, errors.New("proto: not an extension map")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
|
||||||
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
|
|
||||||
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
|
||||||
var m map[int32]Extension
|
|
||||||
switch exts := exts.(type) {
|
|
||||||
case *XXX_InternalExtensions:
|
|
||||||
m = exts.extensionsWrite()
|
|
||||||
case map[int32]Extension:
|
|
||||||
m = exts
|
|
||||||
default:
|
|
||||||
return errors.New("proto: not an extension map")
|
|
||||||
}
|
|
||||||
|
|
||||||
ms := new(messageSet)
|
|
||||||
if err := Unmarshal(buf, ms); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, item := range ms.Item {
|
|
||||||
id := *item.TypeId
|
|
||||||
msg := item.Message
|
|
||||||
|
|
||||||
// Restore wire type and field number varint, plus length varint.
|
|
||||||
// Be careful to preserve duplicate items.
|
|
||||||
b := EncodeVarint(uint64(id)<<3 | WireBytes)
|
|
||||||
if ext, ok := m[id]; ok {
|
|
||||||
// Existing data; rip off the tag and length varint
|
|
||||||
// so we join the new data correctly.
|
|
||||||
// We can assume that ext.enc is set because we are unmarshaling.
|
|
||||||
o := ext.enc[len(b):] // skip wire type and field number
|
|
||||||
_, n := DecodeVarint(o) // calculate length of length varint
|
|
||||||
o = o[n:] // skip length varint
|
|
||||||
msg = append(o, msg...) // join old data and new data
|
|
||||||
}
|
|
||||||
b = append(b, EncodeVarint(uint64(len(msg)))...)
|
|
||||||
b = append(b, msg...)
|
|
||||||
|
|
||||||
m[id] = Extension{enc: b}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
|
|
||||||
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
|
|
||||||
func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
|
|
||||||
var m map[int32]Extension
|
|
||||||
switch exts := exts.(type) {
|
|
||||||
case *XXX_InternalExtensions:
|
|
||||||
var mu sync.Locker
|
|
||||||
m, mu = exts.extensionsRead()
|
|
||||||
if m != nil {
|
|
||||||
// Keep the extensions map locked until we're done marshaling to prevent
|
|
||||||
// races between marshaling and unmarshaling the lazily-{en,de}coded
|
|
||||||
// values.
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
}
|
|
||||||
case map[int32]Extension:
|
|
||||||
m = exts
|
|
||||||
default:
|
|
||||||
return nil, errors.New("proto: not an extension map")
|
|
||||||
}
|
|
||||||
var b bytes.Buffer
|
|
||||||
b.WriteByte('{')
|
|
||||||
|
|
||||||
// Process the map in key order for deterministic output.
|
|
||||||
ids := make([]int32, 0, len(m))
|
|
||||||
for id := range m {
|
|
||||||
ids = append(ids, id)
|
|
||||||
}
|
|
||||||
sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
|
|
||||||
|
|
||||||
for i, id := range ids {
|
|
||||||
ext := m[id]
|
|
||||||
msd, ok := messageSetMap[id]
|
|
||||||
if !ok {
|
|
||||||
// Unknown type; we can't render it, so skip it.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i > 0 && b.Len() > 1 {
|
|
||||||
b.WriteByte(',')
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(&b, `"[%s]":`, msd.name)
|
|
||||||
|
|
||||||
x := ext.value
|
|
||||||
if x == nil {
|
|
||||||
x = reflect.New(msd.t.Elem()).Interface()
|
|
||||||
if err := Unmarshal(ext.enc, x.(Message)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d, err := json.Marshal(x)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
b.Write(d)
|
|
||||||
}
|
|
||||||
b.WriteByte('}')
|
|
||||||
return b.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
|
|
||||||
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
|
|
||||||
func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
|
|
||||||
// Common-case fast path.
|
|
||||||
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is fairly tricky, and it's not clear that it is needed.
|
|
||||||
return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// A global registry of types that can be used in a MessageSet.
|
|
||||||
|
|
||||||
var messageSetMap = make(map[int32]messageSetDesc)
|
|
||||||
|
|
||||||
type messageSetDesc struct {
|
|
||||||
t reflect.Type // pointer to struct
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterMessageSetType is called from the generated code.
|
|
||||||
func RegisterMessageSetType(m Message, fieldNum int32, name string) {
|
|
||||||
messageSetMap[fieldNum] = messageSetDesc{
|
|
||||||
t: reflect.TypeOf(m),
|
|
||||||
name: name,
|
|
||||||
}
|
|
||||||
}
|
|
357
vendor/github.com/golang/protobuf/proto/pointer_reflect.go
generated
vendored
357
vendor/github.com/golang/protobuf/proto/pointer_reflect.go
generated
vendored
@ -1,357 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// +build purego appengine js
|
|
||||||
|
|
||||||
// This file contains an implementation of proto field accesses using package reflect.
|
|
||||||
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
|
|
||||||
// be used on App Engine.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const unsafeAllowed = false
|
|
||||||
|
|
||||||
// A field identifies a field in a struct, accessible from a pointer.
|
|
||||||
// In this implementation, a field is identified by the sequence of field indices
|
|
||||||
// passed to reflect's FieldByIndex.
|
|
||||||
type field []int
|
|
||||||
|
|
||||||
// toField returns a field equivalent to the given reflect field.
|
|
||||||
func toField(f *reflect.StructField) field {
|
|
||||||
return f.Index
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalidField is an invalid field identifier.
|
|
||||||
var invalidField = field(nil)
|
|
||||||
|
|
||||||
// zeroField is a noop when calling pointer.offset.
|
|
||||||
var zeroField = field([]int{})
|
|
||||||
|
|
||||||
// IsValid reports whether the field identifier is valid.
|
|
||||||
func (f field) IsValid() bool { return f != nil }
|
|
||||||
|
|
||||||
// The pointer type is for the table-driven decoder.
|
|
||||||
// The implementation here uses a reflect.Value of pointer type to
|
|
||||||
// create a generic pointer. In pointer_unsafe.go we use unsafe
|
|
||||||
// instead of reflect to implement the same (but faster) interface.
|
|
||||||
type pointer struct {
|
|
||||||
v reflect.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// toPointer converts an interface of pointer type to a pointer
|
|
||||||
// that points to the same target.
|
|
||||||
func toPointer(i *Message) pointer {
|
|
||||||
return pointer{v: reflect.ValueOf(*i)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// toAddrPointer converts an interface to a pointer that points to
|
|
||||||
// the interface data.
|
|
||||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
|
||||||
v := reflect.ValueOf(*i)
|
|
||||||
u := reflect.New(v.Type())
|
|
||||||
u.Elem().Set(v)
|
|
||||||
return pointer{v: u}
|
|
||||||
}
|
|
||||||
|
|
||||||
// valToPointer converts v to a pointer. v must be of pointer type.
|
|
||||||
func valToPointer(v reflect.Value) pointer {
|
|
||||||
return pointer{v: v}
|
|
||||||
}
|
|
||||||
|
|
||||||
// offset converts from a pointer to a structure to a pointer to
|
|
||||||
// one of its fields.
|
|
||||||
func (p pointer) offset(f field) pointer {
|
|
||||||
return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) isNil() bool {
|
|
||||||
return p.v.IsNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
// grow updates the slice s in place to make it one element longer.
|
|
||||||
// s must be addressable.
|
|
||||||
// Returns the (addressable) new element.
|
|
||||||
func grow(s reflect.Value) reflect.Value {
|
|
||||||
n, m := s.Len(), s.Cap()
|
|
||||||
if n < m {
|
|
||||||
s.SetLen(n + 1)
|
|
||||||
} else {
|
|
||||||
s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
|
|
||||||
}
|
|
||||||
return s.Index(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toInt64() *int64 {
|
|
||||||
return p.v.Interface().(*int64)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Ptr() **int64 {
|
|
||||||
return p.v.Interface().(**int64)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Slice() *[]int64 {
|
|
||||||
return p.v.Interface().(*[]int64)
|
|
||||||
}
|
|
||||||
|
|
||||||
var int32ptr = reflect.TypeOf((*int32)(nil))
|
|
||||||
|
|
||||||
func (p pointer) toInt32() *int32 {
|
|
||||||
return p.v.Convert(int32ptr).Interface().(*int32)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The toInt32Ptr/Slice methods don't work because of enums.
|
|
||||||
// Instead, we must use set/get methods for the int32ptr/slice case.
|
|
||||||
/*
|
|
||||||
func (p pointer) toInt32Ptr() **int32 {
|
|
||||||
return p.v.Interface().(**int32)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt32Slice() *[]int32 {
|
|
||||||
return p.v.Interface().(*[]int32)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (p pointer) getInt32Ptr() *int32 {
|
|
||||||
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
|
||||||
// raw int32 type
|
|
||||||
return p.v.Elem().Interface().(*int32)
|
|
||||||
}
|
|
||||||
// an enum
|
|
||||||
return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
|
|
||||||
}
|
|
||||||
func (p pointer) setInt32Ptr(v int32) {
|
|
||||||
// Allocate value in a *int32. Possibly convert that to a *enum.
|
|
||||||
// Then assign it to a **int32 or **enum.
|
|
||||||
// Note: we can convert *int32 to *enum, but we can't convert
|
|
||||||
// **int32 to **enum!
|
|
||||||
p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInt32Slice copies []int32 from p as a new slice.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) getInt32Slice() []int32 {
|
|
||||||
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
|
||||||
// raw int32 type
|
|
||||||
return p.v.Elem().Interface().([]int32)
|
|
||||||
}
|
|
||||||
// an enum
|
|
||||||
// Allocate a []int32, then assign []enum's values into it.
|
|
||||||
// Note: we can't convert []enum to []int32.
|
|
||||||
slice := p.v.Elem()
|
|
||||||
s := make([]int32, slice.Len())
|
|
||||||
for i := 0; i < slice.Len(); i++ {
|
|
||||||
s[i] = int32(slice.Index(i).Int())
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// setInt32Slice copies []int32 into p as a new slice.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) setInt32Slice(v []int32) {
|
|
||||||
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
|
||||||
// raw int32 type
|
|
||||||
p.v.Elem().Set(reflect.ValueOf(v))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// an enum
|
|
||||||
// Allocate a []enum, then assign []int32's values into it.
|
|
||||||
// Note: we can't convert []enum to []int32.
|
|
||||||
slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
|
|
||||||
for i, x := range v {
|
|
||||||
slice.Index(i).SetInt(int64(x))
|
|
||||||
}
|
|
||||||
p.v.Elem().Set(slice)
|
|
||||||
}
|
|
||||||
func (p pointer) appendInt32Slice(v int32) {
|
|
||||||
grow(p.v.Elem()).SetInt(int64(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toUint64() *uint64 {
|
|
||||||
return p.v.Interface().(*uint64)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Ptr() **uint64 {
|
|
||||||
return p.v.Interface().(**uint64)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Slice() *[]uint64 {
|
|
||||||
return p.v.Interface().(*[]uint64)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32() *uint32 {
|
|
||||||
return p.v.Interface().(*uint32)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Ptr() **uint32 {
|
|
||||||
return p.v.Interface().(**uint32)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Slice() *[]uint32 {
|
|
||||||
return p.v.Interface().(*[]uint32)
|
|
||||||
}
|
|
||||||
func (p pointer) toBool() *bool {
|
|
||||||
return p.v.Interface().(*bool)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolPtr() **bool {
|
|
||||||
return p.v.Interface().(**bool)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolSlice() *[]bool {
|
|
||||||
return p.v.Interface().(*[]bool)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64() *float64 {
|
|
||||||
return p.v.Interface().(*float64)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Ptr() **float64 {
|
|
||||||
return p.v.Interface().(**float64)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Slice() *[]float64 {
|
|
||||||
return p.v.Interface().(*[]float64)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32() *float32 {
|
|
||||||
return p.v.Interface().(*float32)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Ptr() **float32 {
|
|
||||||
return p.v.Interface().(**float32)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Slice() *[]float32 {
|
|
||||||
return p.v.Interface().(*[]float32)
|
|
||||||
}
|
|
||||||
func (p pointer) toString() *string {
|
|
||||||
return p.v.Interface().(*string)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringPtr() **string {
|
|
||||||
return p.v.Interface().(**string)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringSlice() *[]string {
|
|
||||||
return p.v.Interface().(*[]string)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytes() *[]byte {
|
|
||||||
return p.v.Interface().(*[]byte)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytesSlice() *[][]byte {
|
|
||||||
return p.v.Interface().(*[][]byte)
|
|
||||||
}
|
|
||||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
|
|
||||||
return p.v.Interface().(*XXX_InternalExtensions)
|
|
||||||
}
|
|
||||||
func (p pointer) toOldExtensions() *map[int32]Extension {
|
|
||||||
return p.v.Interface().(*map[int32]Extension)
|
|
||||||
}
|
|
||||||
func (p pointer) getPointer() pointer {
|
|
||||||
return pointer{v: p.v.Elem()}
|
|
||||||
}
|
|
||||||
func (p pointer) setPointer(q pointer) {
|
|
||||||
p.v.Elem().Set(q.v)
|
|
||||||
}
|
|
||||||
func (p pointer) appendPointer(q pointer) {
|
|
||||||
grow(p.v.Elem()).Set(q.v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPointerSlice copies []*T from p as a new []pointer.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) getPointerSlice() []pointer {
|
|
||||||
if p.v.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
n := p.v.Elem().Len()
|
|
||||||
s := make([]pointer, n)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
s[i] = pointer{v: p.v.Elem().Index(i)}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPointerSlice copies []pointer into p as a new []*T.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) setPointerSlice(v []pointer) {
|
|
||||||
if v == nil {
|
|
||||||
p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
|
|
||||||
for _, p := range v {
|
|
||||||
s = reflect.Append(s, p.v)
|
|
||||||
}
|
|
||||||
p.v.Elem().Set(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInterfacePointer returns a pointer that points to the
|
|
||||||
// interface data of the interface pointed by p.
|
|
||||||
func (p pointer) getInterfacePointer() pointer {
|
|
||||||
if p.v.Elem().IsNil() {
|
|
||||||
return pointer{v: p.v.Elem()}
|
|
||||||
}
|
|
||||||
return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
|
|
||||||
// TODO: check that p.v.Type().Elem() == t?
|
|
||||||
return p.v
|
|
||||||
}
|
|
||||||
|
|
||||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
|
|
||||||
var atomicLock sync.Mutex
|
|
308
vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
generated
vendored
308
vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
generated
vendored
@ -1,308 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// +build !purego,!appengine,!js
|
|
||||||
|
|
||||||
// This file contains the implementation of the proto field accesses using package unsafe.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"sync/atomic"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const unsafeAllowed = true
|
|
||||||
|
|
||||||
// A field identifies a field in a struct, accessible from a pointer.
|
|
||||||
// In this implementation, a field is identified by its byte offset from the start of the struct.
|
|
||||||
type field uintptr
|
|
||||||
|
|
||||||
// toField returns a field equivalent to the given reflect field.
|
|
||||||
func toField(f *reflect.StructField) field {
|
|
||||||
return field(f.Offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalidField is an invalid field identifier.
|
|
||||||
const invalidField = ^field(0)
|
|
||||||
|
|
||||||
// zeroField is a noop when calling pointer.offset.
|
|
||||||
const zeroField = field(0)
|
|
||||||
|
|
||||||
// IsValid reports whether the field identifier is valid.
|
|
||||||
func (f field) IsValid() bool {
|
|
||||||
return f != invalidField
|
|
||||||
}
|
|
||||||
|
|
||||||
// The pointer type below is for the new table-driven encoder/decoder.
|
|
||||||
// The implementation here uses unsafe.Pointer to create a generic pointer.
|
|
||||||
// In pointer_reflect.go we use reflect instead of unsafe to implement
|
|
||||||
// the same (but slower) interface.
|
|
||||||
type pointer struct {
|
|
||||||
p unsafe.Pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
// size of pointer
|
|
||||||
var ptrSize = unsafe.Sizeof(uintptr(0))
|
|
||||||
|
|
||||||
// toPointer converts an interface of pointer type to a pointer
|
|
||||||
// that points to the same target.
|
|
||||||
func toPointer(i *Message) pointer {
|
|
||||||
// Super-tricky - read pointer out of data word of interface value.
|
|
||||||
// Saves ~25ns over the equivalent:
|
|
||||||
// return valToPointer(reflect.ValueOf(*i))
|
|
||||||
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
|
||||||
}
|
|
||||||
|
|
||||||
// toAddrPointer converts an interface to a pointer that points to
|
|
||||||
// the interface data.
|
|
||||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
|
||||||
// Super-tricky - read or get the address of data word of interface value.
|
|
||||||
if isptr {
|
|
||||||
// The interface is of pointer type, thus it is a direct interface.
|
|
||||||
// The data word is the pointer data itself. We take its address.
|
|
||||||
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
|
|
||||||
}
|
|
||||||
// The interface is not of pointer type. The data word is the pointer
|
|
||||||
// to the data.
|
|
||||||
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
|
||||||
}
|
|
||||||
|
|
||||||
// valToPointer converts v to a pointer. v must be of pointer type.
|
|
||||||
func valToPointer(v reflect.Value) pointer {
|
|
||||||
return pointer{p: unsafe.Pointer(v.Pointer())}
|
|
||||||
}
|
|
||||||
|
|
||||||
// offset converts from a pointer to a structure to a pointer to
|
|
||||||
// one of its fields.
|
|
||||||
func (p pointer) offset(f field) pointer {
|
|
||||||
// For safety, we should panic if !f.IsValid, however calling panic causes
|
|
||||||
// this to no longer be inlineable, which is a serious performance cost.
|
|
||||||
/*
|
|
||||||
if !f.IsValid() {
|
|
||||||
panic("invalid field")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) isNil() bool {
|
|
||||||
return p.p == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toInt64() *int64 {
|
|
||||||
return (*int64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Ptr() **int64 {
|
|
||||||
return (**int64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Slice() *[]int64 {
|
|
||||||
return (*[]int64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt32() *int32 {
|
|
||||||
return (*int32)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
|
|
||||||
/*
|
|
||||||
func (p pointer) toInt32Ptr() **int32 {
|
|
||||||
return (**int32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt32Slice() *[]int32 {
|
|
||||||
return (*[]int32)(p.p)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (p pointer) getInt32Ptr() *int32 {
|
|
||||||
return *(**int32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) setInt32Ptr(v int32) {
|
|
||||||
*(**int32)(p.p) = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInt32Slice loads a []int32 from p.
|
|
||||||
// The value returned is aliased with the original slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) getInt32Slice() []int32 {
|
|
||||||
return *(*[]int32)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setInt32Slice stores a []int32 to p.
|
|
||||||
// The value set is aliased with the input slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) setInt32Slice(v []int32) {
|
|
||||||
*(*[]int32)(p.p) = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
|
|
||||||
func (p pointer) appendInt32Slice(v int32) {
|
|
||||||
s := (*[]int32)(p.p)
|
|
||||||
*s = append(*s, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toUint64() *uint64 {
|
|
||||||
return (*uint64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Ptr() **uint64 {
|
|
||||||
return (**uint64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Slice() *[]uint64 {
|
|
||||||
return (*[]uint64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32() *uint32 {
|
|
||||||
return (*uint32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Ptr() **uint32 {
|
|
||||||
return (**uint32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Slice() *[]uint32 {
|
|
||||||
return (*[]uint32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBool() *bool {
|
|
||||||
return (*bool)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolPtr() **bool {
|
|
||||||
return (**bool)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolSlice() *[]bool {
|
|
||||||
return (*[]bool)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64() *float64 {
|
|
||||||
return (*float64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Ptr() **float64 {
|
|
||||||
return (**float64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Slice() *[]float64 {
|
|
||||||
return (*[]float64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32() *float32 {
|
|
||||||
return (*float32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Ptr() **float32 {
|
|
||||||
return (**float32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Slice() *[]float32 {
|
|
||||||
return (*[]float32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toString() *string {
|
|
||||||
return (*string)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringPtr() **string {
|
|
||||||
return (**string)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringSlice() *[]string {
|
|
||||||
return (*[]string)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytes() *[]byte {
|
|
||||||
return (*[]byte)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytesSlice() *[][]byte {
|
|
||||||
return (*[][]byte)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
|
|
||||||
return (*XXX_InternalExtensions)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toOldExtensions() *map[int32]Extension {
|
|
||||||
return (*map[int32]Extension)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPointerSlice loads []*T from p as a []pointer.
|
|
||||||
// The value returned is aliased with the original slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) getPointerSlice() []pointer {
|
|
||||||
// Super-tricky - p should point to a []*T where T is a
|
|
||||||
// message type. We load it as []pointer.
|
|
||||||
return *(*[]pointer)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPointerSlice stores []pointer into p as a []*T.
|
|
||||||
// The value set is aliased with the input slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) setPointerSlice(v []pointer) {
|
|
||||||
// Super-tricky - p should point to a []*T where T is a
|
|
||||||
// message type. We store it as []pointer.
|
|
||||||
*(*[]pointer)(p.p) = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPointer loads the pointer at p and returns it.
|
|
||||||
func (p pointer) getPointer() pointer {
|
|
||||||
return pointer{p: *(*unsafe.Pointer)(p.p)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPointer stores the pointer q at p.
|
|
||||||
func (p pointer) setPointer(q pointer) {
|
|
||||||
*(*unsafe.Pointer)(p.p) = q.p
|
|
||||||
}
|
|
||||||
|
|
||||||
// append q to the slice pointed to by p.
|
|
||||||
func (p pointer) appendPointer(q pointer) {
|
|
||||||
s := (*[]unsafe.Pointer)(p.p)
|
|
||||||
*s = append(*s, q.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInterfacePointer returns a pointer that points to the
|
|
||||||
// interface data of the interface pointed by p.
|
|
||||||
func (p pointer) getInterfacePointer() pointer {
|
|
||||||
// Super-tricky - read pointer out of data word of interface value.
|
|
||||||
return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
|
|
||||||
}
|
|
||||||
|
|
||||||
// asPointerTo returns a reflect.Value that is a pointer to an
|
|
||||||
// object of type t stored at p.
|
|
||||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
|
|
||||||
return reflect.NewAt(t, p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
|
|
||||||
return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
||||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
|
|
||||||
return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
||||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
|
|
||||||
return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
||||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
|
|
||||||
return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
544
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
544
vendor/github.com/golang/protobuf/proto/properties.go
generated
vendored
@ -1,544 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Routines for encoding data into the wire format for protocol buffers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const debug bool = false
|
|
||||||
|
|
||||||
// Constants that identify the encoding of a value on the wire.
|
|
||||||
const (
|
|
||||||
WireVarint = 0
|
|
||||||
WireFixed64 = 1
|
|
||||||
WireBytes = 2
|
|
||||||
WireStartGroup = 3
|
|
||||||
WireEndGroup = 4
|
|
||||||
WireFixed32 = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// tagMap is an optimization over map[int]int for typical protocol buffer
|
|
||||||
// use-cases. Encoded protocol buffers are often in tag order with small tag
|
|
||||||
// numbers.
|
|
||||||
type tagMap struct {
|
|
||||||
fastTags []int
|
|
||||||
slowTags map[int]int
|
|
||||||
}
|
|
||||||
|
|
||||||
// tagMapFastLimit is the upper bound on the tag number that will be stored in
|
|
||||||
// the tagMap slice rather than its map.
|
|
||||||
const tagMapFastLimit = 1024
|
|
||||||
|
|
||||||
func (p *tagMap) get(t int) (int, bool) {
|
|
||||||
if t > 0 && t < tagMapFastLimit {
|
|
||||||
if t >= len(p.fastTags) {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
fi := p.fastTags[t]
|
|
||||||
return fi, fi >= 0
|
|
||||||
}
|
|
||||||
fi, ok := p.slowTags[t]
|
|
||||||
return fi, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *tagMap) put(t int, fi int) {
|
|
||||||
if t > 0 && t < tagMapFastLimit {
|
|
||||||
for len(p.fastTags) < t+1 {
|
|
||||||
p.fastTags = append(p.fastTags, -1)
|
|
||||||
}
|
|
||||||
p.fastTags[t] = fi
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.slowTags == nil {
|
|
||||||
p.slowTags = make(map[int]int)
|
|
||||||
}
|
|
||||||
p.slowTags[t] = fi
|
|
||||||
}
|
|
||||||
|
|
||||||
// StructProperties represents properties for all the fields of a struct.
|
|
||||||
// decoderTags and decoderOrigNames should only be used by the decoder.
|
|
||||||
type StructProperties struct {
|
|
||||||
Prop []*Properties // properties for each field
|
|
||||||
reqCount int // required count
|
|
||||||
decoderTags tagMap // map from proto tag to struct field number
|
|
||||||
decoderOrigNames map[string]int // map from original name to struct field number
|
|
||||||
order []int // list of struct field numbers in tag order
|
|
||||||
|
|
||||||
// OneofTypes contains information about the oneof fields in this message.
|
|
||||||
// It is keyed by the original name of a field.
|
|
||||||
OneofTypes map[string]*OneofProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
// OneofProperties represents information about a specific field in a oneof.
|
|
||||||
type OneofProperties struct {
|
|
||||||
Type reflect.Type // pointer to generated struct type for this oneof field
|
|
||||||
Field int // struct field number of the containing oneof in the message
|
|
||||||
Prop *Properties
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
|
|
||||||
// See encode.go, (*Buffer).enc_struct.
|
|
||||||
|
|
||||||
func (sp *StructProperties) Len() int { return len(sp.order) }
|
|
||||||
func (sp *StructProperties) Less(i, j int) bool {
|
|
||||||
return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
|
|
||||||
}
|
|
||||||
func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
|
|
||||||
|
|
||||||
// Properties represents the protocol-specific behavior of a single struct field.
|
|
||||||
type Properties struct {
|
|
||||||
Name string // name of the field, for error messages
|
|
||||||
OrigName string // original name before protocol compiler (always set)
|
|
||||||
JSONName string // name to use for JSON; determined by protoc
|
|
||||||
Wire string
|
|
||||||
WireType int
|
|
||||||
Tag int
|
|
||||||
Required bool
|
|
||||||
Optional bool
|
|
||||||
Repeated bool
|
|
||||||
Packed bool // relevant for repeated primitives only
|
|
||||||
Enum string // set for enum types only
|
|
||||||
proto3 bool // whether this is known to be a proto3 field
|
|
||||||
oneof bool // whether this is a oneof field
|
|
||||||
|
|
||||||
Default string // default value
|
|
||||||
HasDefault bool // whether an explicit default was provided
|
|
||||||
|
|
||||||
stype reflect.Type // set for struct types only
|
|
||||||
sprop *StructProperties // set for struct types only
|
|
||||||
|
|
||||||
mtype reflect.Type // set for map types only
|
|
||||||
MapKeyProp *Properties // set for map types only
|
|
||||||
MapValProp *Properties // set for map types only
|
|
||||||
}
|
|
||||||
|
|
||||||
// String formats the properties in the protobuf struct field tag style.
|
|
||||||
func (p *Properties) String() string {
|
|
||||||
s := p.Wire
|
|
||||||
s += ","
|
|
||||||
s += strconv.Itoa(p.Tag)
|
|
||||||
if p.Required {
|
|
||||||
s += ",req"
|
|
||||||
}
|
|
||||||
if p.Optional {
|
|
||||||
s += ",opt"
|
|
||||||
}
|
|
||||||
if p.Repeated {
|
|
||||||
s += ",rep"
|
|
||||||
}
|
|
||||||
if p.Packed {
|
|
||||||
s += ",packed"
|
|
||||||
}
|
|
||||||
s += ",name=" + p.OrigName
|
|
||||||
if p.JSONName != p.OrigName {
|
|
||||||
s += ",json=" + p.JSONName
|
|
||||||
}
|
|
||||||
if p.proto3 {
|
|
||||||
s += ",proto3"
|
|
||||||
}
|
|
||||||
if p.oneof {
|
|
||||||
s += ",oneof"
|
|
||||||
}
|
|
||||||
if len(p.Enum) > 0 {
|
|
||||||
s += ",enum=" + p.Enum
|
|
||||||
}
|
|
||||||
if p.HasDefault {
|
|
||||||
s += ",def=" + p.Default
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse populates p by parsing a string in the protobuf struct field tag style.
|
|
||||||
func (p *Properties) Parse(s string) {
|
|
||||||
// "bytes,49,opt,name=foo,def=hello!"
|
|
||||||
fields := strings.Split(s, ",") // breaks def=, but handled below.
|
|
||||||
if len(fields) < 2 {
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Wire = fields[0]
|
|
||||||
switch p.Wire {
|
|
||||||
case "varint":
|
|
||||||
p.WireType = WireVarint
|
|
||||||
case "fixed32":
|
|
||||||
p.WireType = WireFixed32
|
|
||||||
case "fixed64":
|
|
||||||
p.WireType = WireFixed64
|
|
||||||
case "zigzag32":
|
|
||||||
p.WireType = WireVarint
|
|
||||||
case "zigzag64":
|
|
||||||
p.WireType = WireVarint
|
|
||||||
case "bytes", "group":
|
|
||||||
p.WireType = WireBytes
|
|
||||||
// no numeric converter for non-numeric types
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
p.Tag, err = strconv.Atoi(fields[1])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
outer:
|
|
||||||
for i := 2; i < len(fields); i++ {
|
|
||||||
f := fields[i]
|
|
||||||
switch {
|
|
||||||
case f == "req":
|
|
||||||
p.Required = true
|
|
||||||
case f == "opt":
|
|
||||||
p.Optional = true
|
|
||||||
case f == "rep":
|
|
||||||
p.Repeated = true
|
|
||||||
case f == "packed":
|
|
||||||
p.Packed = true
|
|
||||||
case strings.HasPrefix(f, "name="):
|
|
||||||
p.OrigName = f[5:]
|
|
||||||
case strings.HasPrefix(f, "json="):
|
|
||||||
p.JSONName = f[5:]
|
|
||||||
case strings.HasPrefix(f, "enum="):
|
|
||||||
p.Enum = f[5:]
|
|
||||||
case f == "proto3":
|
|
||||||
p.proto3 = true
|
|
||||||
case f == "oneof":
|
|
||||||
p.oneof = true
|
|
||||||
case strings.HasPrefix(f, "def="):
|
|
||||||
p.HasDefault = true
|
|
||||||
p.Default = f[4:] // rest of string
|
|
||||||
if i+1 < len(fields) {
|
|
||||||
// Commas aren't escaped, and def is always last.
|
|
||||||
p.Default += "," + strings.Join(fields[i+1:], ",")
|
|
||||||
break outer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
|
|
||||||
|
|
||||||
// setFieldProps initializes the field properties for submessages and maps.
|
|
||||||
func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
|
|
||||||
switch t1 := typ; t1.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if t1.Elem().Kind() == reflect.Struct {
|
|
||||||
p.stype = t1.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
|
|
||||||
p.stype = t2.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
p.mtype = t1
|
|
||||||
p.MapKeyProp = &Properties{}
|
|
||||||
p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
|
|
||||||
p.MapValProp = &Properties{}
|
|
||||||
vtype := p.mtype.Elem()
|
|
||||||
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
|
|
||||||
// The value type is not a message (*T) or bytes ([]byte),
|
|
||||||
// so we need encoders for the pointer to this type.
|
|
||||||
vtype = reflect.PtrTo(vtype)
|
|
||||||
}
|
|
||||||
p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.stype != nil {
|
|
||||||
if lockGetProp {
|
|
||||||
p.sprop = GetProperties(p.stype)
|
|
||||||
} else {
|
|
||||||
p.sprop = getPropertiesLocked(p.stype)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
|
||||||
)
|
|
||||||
|
|
||||||
// Init populates the properties from a protocol buffer struct tag.
|
|
||||||
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
|
|
||||||
p.init(typ, name, tag, f, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
|
|
||||||
// "bytes,49,opt,def=hello!"
|
|
||||||
p.Name = name
|
|
||||||
p.OrigName = name
|
|
||||||
if tag == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.Parse(tag)
|
|
||||||
p.setFieldProps(typ, f, lockGetProp)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
propertiesMu sync.RWMutex
|
|
||||||
propertiesMap = make(map[reflect.Type]*StructProperties)
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetProperties returns the list of properties for the type represented by t.
|
|
||||||
// t must represent a generated struct type of a protocol message.
|
|
||||||
func GetProperties(t reflect.Type) *StructProperties {
|
|
||||||
if t.Kind() != reflect.Struct {
|
|
||||||
panic("proto: type must have kind struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Most calls to GetProperties in a long-running program will be
|
|
||||||
// retrieving details for types we have seen before.
|
|
||||||
propertiesMu.RLock()
|
|
||||||
sprop, ok := propertiesMap[t]
|
|
||||||
propertiesMu.RUnlock()
|
|
||||||
if ok {
|
|
||||||
if collectStats {
|
|
||||||
stats.Chit++
|
|
||||||
}
|
|
||||||
return sprop
|
|
||||||
}
|
|
||||||
|
|
||||||
propertiesMu.Lock()
|
|
||||||
sprop = getPropertiesLocked(t)
|
|
||||||
propertiesMu.Unlock()
|
|
||||||
return sprop
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPropertiesLocked requires that propertiesMu is held.
|
|
||||||
func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|
||||||
if prop, ok := propertiesMap[t]; ok {
|
|
||||||
if collectStats {
|
|
||||||
stats.Chit++
|
|
||||||
}
|
|
||||||
return prop
|
|
||||||
}
|
|
||||||
if collectStats {
|
|
||||||
stats.Cmiss++
|
|
||||||
}
|
|
||||||
|
|
||||||
prop := new(StructProperties)
|
|
||||||
// in case of recursive protos, fill this in now.
|
|
||||||
propertiesMap[t] = prop
|
|
||||||
|
|
||||||
// build properties
|
|
||||||
prop.Prop = make([]*Properties, t.NumField())
|
|
||||||
prop.order = make([]int, t.NumField())
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
p := new(Properties)
|
|
||||||
name := f.Name
|
|
||||||
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
|
|
||||||
|
|
||||||
oneof := f.Tag.Get("protobuf_oneof") // special case
|
|
||||||
if oneof != "" {
|
|
||||||
// Oneof fields don't use the traditional protobuf tag.
|
|
||||||
p.OrigName = oneof
|
|
||||||
}
|
|
||||||
prop.Prop[i] = p
|
|
||||||
prop.order[i] = i
|
|
||||||
if debug {
|
|
||||||
print(i, " ", f.Name, " ", t.String(), " ")
|
|
||||||
if p.Tag > 0 {
|
|
||||||
print(p.String())
|
|
||||||
}
|
|
||||||
print("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-order prop.order.
|
|
||||||
sort.Sort(prop)
|
|
||||||
|
|
||||||
type oneofMessage interface {
|
|
||||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
|
||||||
}
|
|
||||||
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
|
||||||
var oots []interface{}
|
|
||||||
_, _, _, oots = om.XXX_OneofFuncs()
|
|
||||||
|
|
||||||
// Interpret oneof metadata.
|
|
||||||
prop.OneofTypes = make(map[string]*OneofProperties)
|
|
||||||
for _, oot := range oots {
|
|
||||||
oop := &OneofProperties{
|
|
||||||
Type: reflect.ValueOf(oot).Type(), // *T
|
|
||||||
Prop: new(Properties),
|
|
||||||
}
|
|
||||||
sft := oop.Type.Elem().Field(0)
|
|
||||||
oop.Prop.Name = sft.Name
|
|
||||||
oop.Prop.Parse(sft.Tag.Get("protobuf"))
|
|
||||||
// There will be exactly one interface field that
|
|
||||||
// this new value is assignable to.
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
if f.Type.Kind() != reflect.Interface {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !oop.Type.AssignableTo(f.Type) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
oop.Field = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
prop.OneofTypes[oop.Prop.OrigName] = oop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// build required counts
|
|
||||||
// build tags
|
|
||||||
reqCount := 0
|
|
||||||
prop.decoderOrigNames = make(map[string]int)
|
|
||||||
for i, p := range prop.Prop {
|
|
||||||
if strings.HasPrefix(p.Name, "XXX_") {
|
|
||||||
// Internal fields should not appear in tags/origNames maps.
|
|
||||||
// They are handled specially when encoding and decoding.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if p.Required {
|
|
||||||
reqCount++
|
|
||||||
}
|
|
||||||
prop.decoderTags.put(p.Tag, i)
|
|
||||||
prop.decoderOrigNames[p.OrigName] = i
|
|
||||||
}
|
|
||||||
prop.reqCount = reqCount
|
|
||||||
|
|
||||||
return prop
|
|
||||||
}
|
|
||||||
|
|
||||||
// A global registry of enum types.
|
|
||||||
// The generated code will register the generated maps by calling RegisterEnum.
|
|
||||||
|
|
||||||
var enumValueMaps = make(map[string]map[string]int32)
|
|
||||||
|
|
||||||
// RegisterEnum is called from the generated code to install the enum descriptor
|
|
||||||
// maps into the global table to aid parsing text format protocol buffers.
|
|
||||||
func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
|
|
||||||
if _, ok := enumValueMaps[typeName]; ok {
|
|
||||||
panic("proto: duplicate enum registered: " + typeName)
|
|
||||||
}
|
|
||||||
enumValueMaps[typeName] = valueMap
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnumValueMap returns the mapping from names to integers of the
|
|
||||||
// enum type enumType, or a nil if not found.
|
|
||||||
func EnumValueMap(enumType string) map[string]int32 {
|
|
||||||
return enumValueMaps[enumType]
|
|
||||||
}
|
|
||||||
|
|
||||||
// A registry of all linked message types.
|
|
||||||
// The string is a fully-qualified proto name ("pkg.Message").
|
|
||||||
var (
|
|
||||||
protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
|
|
||||||
protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
|
|
||||||
revProtoTypes = make(map[reflect.Type]string)
|
|
||||||
)
|
|
||||||
|
|
||||||
// RegisterType is called from generated code and maps from the fully qualified
|
|
||||||
// proto name to the type (pointer to struct) of the protocol buffer.
|
|
||||||
func RegisterType(x Message, name string) {
|
|
||||||
if _, ok := protoTypedNils[name]; ok {
|
|
||||||
// TODO: Some day, make this a panic.
|
|
||||||
log.Printf("proto: duplicate proto type registered: %s", name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := reflect.TypeOf(x)
|
|
||||||
if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
|
|
||||||
// Generated code always calls RegisterType with nil x.
|
|
||||||
// This check is just for extra safety.
|
|
||||||
protoTypedNils[name] = x
|
|
||||||
} else {
|
|
||||||
protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
|
|
||||||
}
|
|
||||||
revProtoTypes[t] = name
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterMapType is called from generated code and maps from the fully qualified
|
|
||||||
// proto name to the native map type of the proto map definition.
|
|
||||||
func RegisterMapType(x interface{}, name string) {
|
|
||||||
if reflect.TypeOf(x).Kind() != reflect.Map {
|
|
||||||
panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
|
|
||||||
}
|
|
||||||
if _, ok := protoMapTypes[name]; ok {
|
|
||||||
log.Printf("proto: duplicate proto type registered: %s", name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := reflect.TypeOf(x)
|
|
||||||
protoMapTypes[name] = t
|
|
||||||
revProtoTypes[t] = name
|
|
||||||
}
|
|
||||||
|
|
||||||
// MessageName returns the fully-qualified proto name for the given message type.
|
|
||||||
func MessageName(x Message) string {
|
|
||||||
type xname interface {
|
|
||||||
XXX_MessageName() string
|
|
||||||
}
|
|
||||||
if m, ok := x.(xname); ok {
|
|
||||||
return m.XXX_MessageName()
|
|
||||||
}
|
|
||||||
return revProtoTypes[reflect.TypeOf(x)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// MessageType returns the message type (pointer to struct) for a named message.
|
|
||||||
// The type is not guaranteed to implement proto.Message if the name refers to a
|
|
||||||
// map entry.
|
|
||||||
func MessageType(name string) reflect.Type {
|
|
||||||
if t, ok := protoTypedNils[name]; ok {
|
|
||||||
return reflect.TypeOf(t)
|
|
||||||
}
|
|
||||||
return protoMapTypes[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
// A registry of all linked proto files.
|
|
||||||
var (
|
|
||||||
protoFiles = make(map[string][]byte) // file name => fileDescriptor
|
|
||||||
)
|
|
||||||
|
|
||||||
// RegisterFile is called from generated code and maps from the
|
|
||||||
// full file name of a .proto file to its compressed FileDescriptorProto.
|
|
||||||
func RegisterFile(filename string, fileDescriptor []byte) {
|
|
||||||
protoFiles[filename] = fileDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
|
|
||||||
func FileDescriptor(filename string) []byte { return protoFiles[filename] }
|
|
2767
vendor/github.com/golang/protobuf/proto/table_marshal.go
generated
vendored
2767
vendor/github.com/golang/protobuf/proto/table_marshal.go
generated
vendored
File diff suppressed because it is too large
Load Diff
654
vendor/github.com/golang/protobuf/proto/table_merge.go
generated
vendored
654
vendor/github.com/golang/protobuf/proto/table_merge.go
generated
vendored
@ -1,654 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Merge merges the src message into dst.
|
|
||||||
// This assumes that dst and src of the same type and are non-nil.
|
|
||||||
func (a *InternalMessageInfo) Merge(dst, src Message) {
|
|
||||||
mi := atomicLoadMergeInfo(&a.merge)
|
|
||||||
if mi == nil {
|
|
||||||
mi = getMergeInfo(reflect.TypeOf(dst).Elem())
|
|
||||||
atomicStoreMergeInfo(&a.merge, mi)
|
|
||||||
}
|
|
||||||
mi.merge(toPointer(&dst), toPointer(&src))
|
|
||||||
}
|
|
||||||
|
|
||||||
type mergeInfo struct {
|
|
||||||
typ reflect.Type
|
|
||||||
|
|
||||||
initialized int32 // 0: only typ is valid, 1: everything is valid
|
|
||||||
lock sync.Mutex
|
|
||||||
|
|
||||||
fields []mergeFieldInfo
|
|
||||||
unrecognized field // Offset of XXX_unrecognized
|
|
||||||
}
|
|
||||||
|
|
||||||
type mergeFieldInfo struct {
|
|
||||||
field field // Offset of field, guaranteed to be valid
|
|
||||||
|
|
||||||
// isPointer reports whether the value in the field is a pointer.
|
|
||||||
// This is true for the following situations:
|
|
||||||
// * Pointer to struct
|
|
||||||
// * Pointer to basic type (proto2 only)
|
|
||||||
// * Slice (first value in slice header is a pointer)
|
|
||||||
// * String (first value in string header is a pointer)
|
|
||||||
isPointer bool
|
|
||||||
|
|
||||||
// basicWidth reports the width of the field assuming that it is directly
|
|
||||||
// embedded in the struct (as is the case for basic types in proto3).
|
|
||||||
// The possible values are:
|
|
||||||
// 0: invalid
|
|
||||||
// 1: bool
|
|
||||||
// 4: int32, uint32, float32
|
|
||||||
// 8: int64, uint64, float64
|
|
||||||
basicWidth int
|
|
||||||
|
|
||||||
// Where dst and src are pointers to the types being merged.
|
|
||||||
merge func(dst, src pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
mergeInfoMap = map[reflect.Type]*mergeInfo{}
|
|
||||||
mergeInfoLock sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func getMergeInfo(t reflect.Type) *mergeInfo {
|
|
||||||
mergeInfoLock.Lock()
|
|
||||||
defer mergeInfoLock.Unlock()
|
|
||||||
mi := mergeInfoMap[t]
|
|
||||||
if mi == nil {
|
|
||||||
mi = &mergeInfo{typ: t}
|
|
||||||
mergeInfoMap[t] = mi
|
|
||||||
}
|
|
||||||
return mi
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge merges src into dst assuming they are both of type *mi.typ.
|
|
||||||
func (mi *mergeInfo) merge(dst, src pointer) {
|
|
||||||
if dst.isNil() {
|
|
||||||
panic("proto: nil destination")
|
|
||||||
}
|
|
||||||
if src.isNil() {
|
|
||||||
return // Nothing to do.
|
|
||||||
}
|
|
||||||
|
|
||||||
if atomic.LoadInt32(&mi.initialized) == 0 {
|
|
||||||
mi.computeMergeInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, fi := range mi.fields {
|
|
||||||
sfp := src.offset(fi.field)
|
|
||||||
|
|
||||||
// As an optimization, we can avoid the merge function call cost
|
|
||||||
// if we know for sure that the source will have no effect
|
|
||||||
// by checking if it is the zero value.
|
|
||||||
if unsafeAllowed {
|
|
||||||
if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fi.basicWidth > 0 {
|
|
||||||
switch {
|
|
||||||
case fi.basicWidth == 1 && !*sfp.toBool():
|
|
||||||
continue
|
|
||||||
case fi.basicWidth == 4 && *sfp.toUint32() == 0:
|
|
||||||
continue
|
|
||||||
case fi.basicWidth == 8 && *sfp.toUint64() == 0:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dfp := dst.offset(fi.field)
|
|
||||||
fi.merge(dfp, sfp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make this faster?
|
|
||||||
out := dst.asPointerTo(mi.typ).Elem()
|
|
||||||
in := src.asPointerTo(mi.typ).Elem()
|
|
||||||
if emIn, err := extendable(in.Addr().Interface()); err == nil {
|
|
||||||
emOut, _ := extendable(out.Addr().Interface())
|
|
||||||
mIn, muIn := emIn.extensionsRead()
|
|
||||||
if mIn != nil {
|
|
||||||
mOut := emOut.extensionsWrite()
|
|
||||||
muIn.Lock()
|
|
||||||
mergeExtension(mOut, mIn)
|
|
||||||
muIn.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if mi.unrecognized.IsValid() {
|
|
||||||
if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
|
|
||||||
*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mi *mergeInfo) computeMergeInfo() {
|
|
||||||
mi.lock.Lock()
|
|
||||||
defer mi.lock.Unlock()
|
|
||||||
if mi.initialized != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := mi.typ
|
|
||||||
n := t.NumField()
|
|
||||||
|
|
||||||
props := GetProperties(t)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mfi := mergeFieldInfo{field: toField(&f)}
|
|
||||||
tf := f.Type
|
|
||||||
|
|
||||||
// As an optimization, we can avoid the merge function call cost
|
|
||||||
// if we know for sure that the source will have no effect
|
|
||||||
// by checking if it is the zero value.
|
|
||||||
if unsafeAllowed {
|
|
||||||
switch tf.Kind() {
|
|
||||||
case reflect.Ptr, reflect.Slice, reflect.String:
|
|
||||||
// As a special case, we assume slices and strings are pointers
|
|
||||||
// since we know that the first field in the SliceSlice or
|
|
||||||
// StringHeader is a data pointer.
|
|
||||||
mfi.isPointer = true
|
|
||||||
case reflect.Bool:
|
|
||||||
mfi.basicWidth = 1
|
|
||||||
case reflect.Int32, reflect.Uint32, reflect.Float32:
|
|
||||||
mfi.basicWidth = 4
|
|
||||||
case reflect.Int64, reflect.Uint64, reflect.Float64:
|
|
||||||
mfi.basicWidth = 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap tf to get at its most basic type.
|
|
||||||
var isPointer, isSlice bool
|
|
||||||
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
|
|
||||||
isSlice = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if tf.Kind() == reflect.Ptr {
|
|
||||||
isPointer = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if isPointer && isSlice && tf.Kind() != reflect.Struct {
|
|
||||||
panic("both pointer and slice for basic type in " + tf.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tf.Kind() {
|
|
||||||
case reflect.Int32:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []int32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
|
|
||||||
/*
|
|
||||||
sfsp := src.toInt32Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toInt32Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []int64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
sfs := src.getInt32Slice()
|
|
||||||
if sfs != nil {
|
|
||||||
dfs := dst.getInt32Slice()
|
|
||||||
dfs = append(dfs, sfs...)
|
|
||||||
if dfs == nil {
|
|
||||||
dfs = []int32{}
|
|
||||||
}
|
|
||||||
dst.setInt32Slice(dfs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *int32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
|
|
||||||
/*
|
|
||||||
sfpp := src.toInt32Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toInt32Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Int32(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
sfp := src.getInt32Ptr()
|
|
||||||
if sfp != nil {
|
|
||||||
dfp := dst.getInt32Ptr()
|
|
||||||
if dfp == nil {
|
|
||||||
dst.setInt32Ptr(*sfp)
|
|
||||||
} else {
|
|
||||||
*dfp = *sfp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., int32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toInt32(); v != 0 {
|
|
||||||
*dst.toInt32() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Int64:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []int64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toInt64Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toInt64Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []int64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *int64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toInt64Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toInt64Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Int64(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., int64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toInt64(); v != 0 {
|
|
||||||
*dst.toInt64() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Uint32:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []uint32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toUint32Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toUint32Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []uint32{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *uint32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toUint32Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toUint32Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Uint32(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., uint32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toUint32(); v != 0 {
|
|
||||||
*dst.toUint32() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Uint64:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []uint64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toUint64Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toUint64Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []uint64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *uint64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toUint64Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toUint64Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Uint64(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., uint64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toUint64(); v != 0 {
|
|
||||||
*dst.toUint64() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Float32:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []float32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toFloat32Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toFloat32Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []float32{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *float32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toFloat32Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toFloat32Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Float32(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., float32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toFloat32(); v != 0 {
|
|
||||||
*dst.toFloat32() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Float64:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []float64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toFloat64Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toFloat64Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []float64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *float64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toFloat64Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toFloat64Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Float64(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., float64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toFloat64(); v != 0 {
|
|
||||||
*dst.toFloat64() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Bool:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []bool
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toBoolSlice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toBoolSlice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []bool{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *bool
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toBoolPtr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toBoolPtr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Bool(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., bool
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toBool(); v {
|
|
||||||
*dst.toBool() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []string
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toStringSlice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toStringSlice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []string{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *string
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toStringPtr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toStringPtr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = String(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., string
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toString(); v != "" {
|
|
||||||
*dst.toString() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Slice:
|
|
||||||
isProto3 := props.Prop[i].proto3
|
|
||||||
switch {
|
|
||||||
case isPointer:
|
|
||||||
panic("bad pointer in byte slice case in " + tf.Name())
|
|
||||||
case tf.Elem().Kind() != reflect.Uint8:
|
|
||||||
panic("bad element kind in byte slice case in " + tf.Name())
|
|
||||||
case isSlice: // E.g., [][]byte
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sbsp := src.toBytesSlice()
|
|
||||||
if *sbsp != nil {
|
|
||||||
dbsp := dst.toBytesSlice()
|
|
||||||
for _, sb := range *sbsp {
|
|
||||||
if sb == nil {
|
|
||||||
*dbsp = append(*dbsp, nil)
|
|
||||||
} else {
|
|
||||||
*dbsp = append(*dbsp, append([]byte{}, sb...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if *dbsp == nil {
|
|
||||||
*dbsp = [][]byte{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., []byte
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sbp := src.toBytes()
|
|
||||||
if *sbp != nil {
|
|
||||||
dbp := dst.toBytes()
|
|
||||||
if !isProto3 || len(*sbp) > 0 {
|
|
||||||
*dbp = append([]byte{}, *sbp...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
switch {
|
|
||||||
case !isPointer:
|
|
||||||
panic(fmt.Sprintf("message field %s without pointer", tf))
|
|
||||||
case isSlice: // E.g., []*pb.T
|
|
||||||
mi := getMergeInfo(tf)
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sps := src.getPointerSlice()
|
|
||||||
if sps != nil {
|
|
||||||
dps := dst.getPointerSlice()
|
|
||||||
for _, sp := range sps {
|
|
||||||
var dp pointer
|
|
||||||
if !sp.isNil() {
|
|
||||||
dp = valToPointer(reflect.New(tf))
|
|
||||||
mi.merge(dp, sp)
|
|
||||||
}
|
|
||||||
dps = append(dps, dp)
|
|
||||||
}
|
|
||||||
if dps == nil {
|
|
||||||
dps = []pointer{}
|
|
||||||
}
|
|
||||||
dst.setPointerSlice(dps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., *pb.T
|
|
||||||
mi := getMergeInfo(tf)
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sp := src.getPointer()
|
|
||||||
if !sp.isNil() {
|
|
||||||
dp := dst.getPointer()
|
|
||||||
if dp.isNil() {
|
|
||||||
dp = valToPointer(reflect.New(tf))
|
|
||||||
dst.setPointer(dp)
|
|
||||||
}
|
|
||||||
mi.merge(dp, sp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic("bad pointer or slice in map case in " + tf.Name())
|
|
||||||
default: // E.g., map[K]V
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sm := src.asPointerTo(tf).Elem()
|
|
||||||
if sm.Len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dm := dst.asPointerTo(tf).Elem()
|
|
||||||
if dm.IsNil() {
|
|
||||||
dm.Set(reflect.MakeMap(tf))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tf.Elem().Kind() {
|
|
||||||
case reflect.Ptr: // Proto struct (e.g., *T)
|
|
||||||
for _, key := range sm.MapKeys() {
|
|
||||||
val := sm.MapIndex(key)
|
|
||||||
val = reflect.ValueOf(Clone(val.Interface().(Message)))
|
|
||||||
dm.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
|
|
||||||
for _, key := range sm.MapKeys() {
|
|
||||||
val := sm.MapIndex(key)
|
|
||||||
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
|
|
||||||
dm.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
default: // Basic type (e.g., string)
|
|
||||||
for _, key := range sm.MapKeys() {
|
|
||||||
val := sm.MapIndex(key)
|
|
||||||
dm.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
|
||||||
// Must be oneof field.
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic("bad pointer or slice in interface case in " + tf.Name())
|
|
||||||
default: // E.g., interface{}
|
|
||||||
// TODO: Make this faster?
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
su := src.asPointerTo(tf).Elem()
|
|
||||||
if !su.IsNil() {
|
|
||||||
du := dst.asPointerTo(tf).Elem()
|
|
||||||
typ := su.Elem().Type()
|
|
||||||
if du.IsNil() || du.Elem().Type() != typ {
|
|
||||||
du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
|
|
||||||
}
|
|
||||||
sv := su.Elem().Elem().Field(0)
|
|
||||||
if sv.Kind() == reflect.Ptr && sv.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dv := du.Elem().Elem().Field(0)
|
|
||||||
if dv.Kind() == reflect.Ptr && dv.IsNil() {
|
|
||||||
dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
|
|
||||||
}
|
|
||||||
switch sv.Type().Kind() {
|
|
||||||
case reflect.Ptr: // Proto struct (e.g., *T)
|
|
||||||
Merge(dv.Interface().(Message), sv.Interface().(Message))
|
|
||||||
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
|
|
||||||
dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
|
|
||||||
default: // Basic type (e.g., string)
|
|
||||||
dv.Set(sv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("merger not found for type:%s", tf))
|
|
||||||
}
|
|
||||||
mi.fields = append(mi.fields, mfi)
|
|
||||||
}
|
|
||||||
|
|
||||||
mi.unrecognized = invalidField
|
|
||||||
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
|
|
||||||
if f.Type != reflect.TypeOf([]byte{}) {
|
|
||||||
panic("expected XXX_unrecognized to be of type []byte")
|
|
||||||
}
|
|
||||||
mi.unrecognized = toField(&f)
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.StoreInt32(&mi.initialized, 1)
|
|
||||||
}
|
|
2051
vendor/github.com/golang/protobuf/proto/table_unmarshal.go
generated
vendored
2051
vendor/github.com/golang/protobuf/proto/table_unmarshal.go
generated
vendored
File diff suppressed because it is too large
Load Diff
843
vendor/github.com/golang/protobuf/proto/text.go
generated
vendored
843
vendor/github.com/golang/protobuf/proto/text.go
generated
vendored
@ -1,843 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
// Functions for writing the text protocol buffer format.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
newline = []byte("\n")
|
|
||||||
spaces = []byte(" ")
|
|
||||||
endBraceNewline = []byte("}\n")
|
|
||||||
backslashN = []byte{'\\', 'n'}
|
|
||||||
backslashR = []byte{'\\', 'r'}
|
|
||||||
backslashT = []byte{'\\', 't'}
|
|
||||||
backslashDQ = []byte{'\\', '"'}
|
|
||||||
backslashBS = []byte{'\\', '\\'}
|
|
||||||
posInf = []byte("inf")
|
|
||||||
negInf = []byte("-inf")
|
|
||||||
nan = []byte("nan")
|
|
||||||
)
|
|
||||||
|
|
||||||
type writer interface {
|
|
||||||
io.Writer
|
|
||||||
WriteByte(byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// textWriter is an io.Writer that tracks its indentation level.
|
|
||||||
type textWriter struct {
|
|
||||||
ind int
|
|
||||||
complete bool // if the current position is a complete line
|
|
||||||
compact bool // whether to write out as a one-liner
|
|
||||||
w writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) WriteString(s string) (n int, err error) {
|
|
||||||
if !strings.Contains(s, "\n") {
|
|
||||||
if !w.compact && w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
w.complete = false
|
|
||||||
return io.WriteString(w.w, s)
|
|
||||||
}
|
|
||||||
// WriteString is typically called without newlines, so this
|
|
||||||
// codepath and its copy are rare. We copy to avoid
|
|
||||||
// duplicating all of Write's logic here.
|
|
||||||
return w.Write([]byte(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) Write(p []byte) (n int, err error) {
|
|
||||||
newlines := bytes.Count(p, newline)
|
|
||||||
if newlines == 0 {
|
|
||||||
if !w.compact && w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
n, err = w.w.Write(p)
|
|
||||||
w.complete = false
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
frags := bytes.SplitN(p, newline, newlines+1)
|
|
||||||
if w.compact {
|
|
||||||
for i, frag := range frags {
|
|
||||||
if i > 0 {
|
|
||||||
if err := w.w.WriteByte(' '); err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
nn, err := w.w.Write(frag)
|
|
||||||
n += nn
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, frag := range frags {
|
|
||||||
if w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
nn, err := w.w.Write(frag)
|
|
||||||
n += nn
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
if i+1 < len(frags) {
|
|
||||||
if err := w.w.WriteByte('\n'); err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.complete = len(frags[len(frags)-1]) == 0
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) WriteByte(c byte) error {
|
|
||||||
if w.compact && c == '\n' {
|
|
||||||
c = ' '
|
|
||||||
}
|
|
||||||
if !w.compact && w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
err := w.w.WriteByte(c)
|
|
||||||
w.complete = c == '\n'
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) indent() { w.ind++ }
|
|
||||||
|
|
||||||
func (w *textWriter) unindent() {
|
|
||||||
if w.ind == 0 {
|
|
||||||
log.Print("proto: textWriter unindented too far")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.ind--
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeName(w *textWriter, props *Properties) error {
|
|
||||||
if _, err := w.WriteString(props.OrigName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if props.Wire != "group" {
|
|
||||||
return w.WriteByte(':')
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func requiresQuotes(u string) bool {
|
|
||||||
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
|
|
||||||
for _, ch := range u {
|
|
||||||
switch {
|
|
||||||
case ch == '.' || ch == '/' || ch == '_':
|
|
||||||
continue
|
|
||||||
case '0' <= ch && ch <= '9':
|
|
||||||
continue
|
|
||||||
case 'A' <= ch && ch <= 'Z':
|
|
||||||
continue
|
|
||||||
case 'a' <= ch && ch <= 'z':
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// isAny reports whether sv is a google.protobuf.Any message
|
|
||||||
func isAny(sv reflect.Value) bool {
|
|
||||||
type wkt interface {
|
|
||||||
XXX_WellKnownType() string
|
|
||||||
}
|
|
||||||
t, ok := sv.Addr().Interface().(wkt)
|
|
||||||
return ok && t.XXX_WellKnownType() == "Any"
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeProto3Any writes an expanded google.protobuf.Any message.
|
|
||||||
//
|
|
||||||
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
|
|
||||||
// required messages are not linked in).
|
|
||||||
//
|
|
||||||
// It returns (true, error) when sv was written in expanded format or an error
|
|
||||||
// was encountered.
|
|
||||||
func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
|
|
||||||
turl := sv.FieldByName("TypeUrl")
|
|
||||||
val := sv.FieldByName("Value")
|
|
||||||
if !turl.IsValid() || !val.IsValid() {
|
|
||||||
return true, errors.New("proto: invalid google.protobuf.Any message")
|
|
||||||
}
|
|
||||||
|
|
||||||
b, ok := val.Interface().([]byte)
|
|
||||||
if !ok {
|
|
||||||
return true, errors.New("proto: invalid google.protobuf.Any message")
|
|
||||||
}
|
|
||||||
|
|
||||||
parts := strings.Split(turl.String(), "/")
|
|
||||||
mt := MessageType(parts[len(parts)-1])
|
|
||||||
if mt == nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
m := reflect.New(mt.Elem())
|
|
||||||
if err := Unmarshal(b, m.Interface().(Message)); err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
w.Write([]byte("["))
|
|
||||||
u := turl.String()
|
|
||||||
if requiresQuotes(u) {
|
|
||||||
writeString(w, u)
|
|
||||||
} else {
|
|
||||||
w.Write([]byte(u))
|
|
||||||
}
|
|
||||||
if w.compact {
|
|
||||||
w.Write([]byte("]:<"))
|
|
||||||
} else {
|
|
||||||
w.Write([]byte("]: <\n"))
|
|
||||||
w.ind++
|
|
||||||
}
|
|
||||||
if err := tm.writeStruct(w, m.Elem()); err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
if w.compact {
|
|
||||||
w.Write([]byte("> "))
|
|
||||||
} else {
|
|
||||||
w.ind--
|
|
||||||
w.Write([]byte(">\n"))
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|
||||||
if tm.ExpandAny && isAny(sv) {
|
|
||||||
if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st := sv.Type()
|
|
||||||
sprops := GetProperties(st)
|
|
||||||
for i := 0; i < sv.NumField(); i++ {
|
|
||||||
fv := sv.Field(i)
|
|
||||||
props := sprops.Prop[i]
|
|
||||||
name := st.Field(i).Name
|
|
||||||
|
|
||||||
if name == "XXX_NoUnkeyedLiteral" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(name, "XXX_") {
|
|
||||||
// There are two XXX_ fields:
|
|
||||||
// XXX_unrecognized []byte
|
|
||||||
// XXX_extensions map[int32]proto.Extension
|
|
||||||
// The first is handled here;
|
|
||||||
// the second is handled at the bottom of this function.
|
|
||||||
if name == "XXX_unrecognized" && !fv.IsNil() {
|
|
||||||
if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() == reflect.Ptr && fv.IsNil() {
|
|
||||||
// Field not filled in. This could be an optional field or
|
|
||||||
// a required field that wasn't filled in. Either way, there
|
|
||||||
// isn't anything we can show for it.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() == reflect.Slice && fv.IsNil() {
|
|
||||||
// Repeated field that is empty, or a bytes field that is unused.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if props.Repeated && fv.Kind() == reflect.Slice {
|
|
||||||
// Repeated field.
|
|
||||||
for j := 0; j < fv.Len(); j++ {
|
|
||||||
if err := writeName(w, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v := fv.Index(j)
|
|
||||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
|
||||||
// A nil message in a repeated field is not valid,
|
|
||||||
// but we can handle that more gracefully than panicking.
|
|
||||||
if _, err := w.Write([]byte("<nil>\n")); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, v, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() == reflect.Map {
|
|
||||||
// Map fields are rendered as a repeated struct with key/value fields.
|
|
||||||
keys := fv.MapKeys()
|
|
||||||
sort.Sort(mapKeys(keys))
|
|
||||||
for _, key := range keys {
|
|
||||||
val := fv.MapIndex(key)
|
|
||||||
if err := writeName(w, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// open struct
|
|
||||||
if err := w.WriteByte('<'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.indent()
|
|
||||||
// key
|
|
||||||
if _, err := w.WriteString("key:"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// nil values aren't legal, but we can avoid panicking because of them.
|
|
||||||
if val.Kind() != reflect.Ptr || !val.IsNil() {
|
|
||||||
// value
|
|
||||||
if _, err := w.WriteString("value:"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, val, props.MapValProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// close struct
|
|
||||||
w.unindent()
|
|
||||||
if err := w.WriteByte('>'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
|
|
||||||
// empty bytes field
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
|
|
||||||
// proto3 non-repeated scalar field; skip if zero value
|
|
||||||
if isProto3Zero(fv) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if fv.Kind() == reflect.Interface {
|
|
||||||
// Check if it is a oneof.
|
|
||||||
if st.Field(i).Tag.Get("protobuf_oneof") != "" {
|
|
||||||
// fv is nil, or holds a pointer to generated struct.
|
|
||||||
// That generated struct has exactly one field,
|
|
||||||
// which has a protobuf struct tag.
|
|
||||||
if fv.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inner := fv.Elem().Elem() // interface -> *T -> T
|
|
||||||
tag := inner.Type().Field(0).Tag.Get("protobuf")
|
|
||||||
props = new(Properties) // Overwrite the outer props var, but not its pointee.
|
|
||||||
props.Parse(tag)
|
|
||||||
// Write the value in the oneof, not the oneof itself.
|
|
||||||
fv = inner.Field(0)
|
|
||||||
|
|
||||||
// Special case to cope with malformed messages gracefully:
|
|
||||||
// If the value in the oneof is a nil pointer, don't panic
|
|
||||||
// in writeAny.
|
|
||||||
if fv.Kind() == reflect.Ptr && fv.IsNil() {
|
|
||||||
// Use errors.New so writeAny won't render quotes.
|
|
||||||
msg := errors.New("/* nil */")
|
|
||||||
fv = reflect.ValueOf(&msg).Elem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := writeName(w, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enums have a String method, so writeAny will work fine.
|
|
||||||
if err := tm.writeAny(w, fv, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extensions (the XXX_extensions field).
|
|
||||||
pv := sv.Addr()
|
|
||||||
if _, err := extendable(pv.Interface()); err == nil {
|
|
||||||
if err := tm.writeExtensions(w, pv); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeAny writes an arbitrary field.
|
|
||||||
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
|
||||||
v = reflect.Indirect(v)
|
|
||||||
|
|
||||||
// Floats have special cases.
|
|
||||||
if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
|
|
||||||
x := v.Float()
|
|
||||||
var b []byte
|
|
||||||
switch {
|
|
||||||
case math.IsInf(x, 1):
|
|
||||||
b = posInf
|
|
||||||
case math.IsInf(x, -1):
|
|
||||||
b = negInf
|
|
||||||
case math.IsNaN(x):
|
|
||||||
b = nan
|
|
||||||
}
|
|
||||||
if b != nil {
|
|
||||||
_, err := w.Write(b)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Other values are handled below.
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't attempt to serialise every possible value type; only those
|
|
||||||
// that can occur in protocol buffers.
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
// Should only be a []byte; repeated fields are handled in writeStruct.
|
|
||||||
if err := writeString(w, string(v.Bytes())); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
if err := writeString(w, v.String()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
// Required/optional group/message.
|
|
||||||
var bra, ket byte = '<', '>'
|
|
||||||
if props != nil && props.Wire == "group" {
|
|
||||||
bra, ket = '{', '}'
|
|
||||||
}
|
|
||||||
if err := w.WriteByte(bra); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.indent()
|
|
||||||
if v.CanAddr() {
|
|
||||||
// Calling v.Interface on a struct causes the reflect package to
|
|
||||||
// copy the entire struct. This is racy with the new Marshaler
|
|
||||||
// since we atomically update the XXX_sizecache.
|
|
||||||
//
|
|
||||||
// Thus, we retrieve a pointer to the struct if possible to avoid
|
|
||||||
// a race since v.Interface on the pointer doesn't copy the struct.
|
|
||||||
//
|
|
||||||
// If v is not addressable, then we are not worried about a race
|
|
||||||
// since it implies that the binary Marshaler cannot possibly be
|
|
||||||
// mutating this value.
|
|
||||||
v = v.Addr()
|
|
||||||
}
|
|
||||||
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
|
|
||||||
text, err := etm.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = w.Write(text); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
if err := tm.writeStruct(w, v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.unindent()
|
|
||||||
if err := w.WriteByte(ket); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
_, err := fmt.Fprint(w, v.Interface())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// equivalent to C's isprint.
|
|
||||||
func isprint(c byte) bool {
|
|
||||||
return c >= 0x20 && c < 0x7f
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeString writes a string in the protocol buffer text format.
|
|
||||||
// It is similar to strconv.Quote except we don't use Go escape sequences,
|
|
||||||
// we treat the string as a byte sequence, and we use octal escapes.
|
|
||||||
// These differences are to maintain interoperability with the other
|
|
||||||
// languages' implementations of the text format.
|
|
||||||
func writeString(w *textWriter, s string) error {
|
|
||||||
// use WriteByte here to get any needed indent
|
|
||||||
if err := w.WriteByte('"'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Loop over the bytes, not the runes.
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
var err error
|
|
||||||
// Divergence from C++: we don't escape apostrophes.
|
|
||||||
// There's no need to escape them, and the C++ parser
|
|
||||||
// copes with a naked apostrophe.
|
|
||||||
switch c := s[i]; c {
|
|
||||||
case '\n':
|
|
||||||
_, err = w.w.Write(backslashN)
|
|
||||||
case '\r':
|
|
||||||
_, err = w.w.Write(backslashR)
|
|
||||||
case '\t':
|
|
||||||
_, err = w.w.Write(backslashT)
|
|
||||||
case '"':
|
|
||||||
_, err = w.w.Write(backslashDQ)
|
|
||||||
case '\\':
|
|
||||||
_, err = w.w.Write(backslashBS)
|
|
||||||
default:
|
|
||||||
if isprint(c) {
|
|
||||||
err = w.w.WriteByte(c)
|
|
||||||
} else {
|
|
||||||
_, err = fmt.Fprintf(w.w, "\\%03o", c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.WriteByte('"')
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeUnknownStruct(w *textWriter, data []byte) (err error) {
|
|
||||||
if !w.compact {
|
|
||||||
if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b := NewBuffer(data)
|
|
||||||
for b.index < len(b.buf) {
|
|
||||||
x, err := b.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
_, err := fmt.Fprintf(w, "/* %v */\n", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
wire, tag := x&7, x>>3
|
|
||||||
if wire == WireEndGroup {
|
|
||||||
w.unindent()
|
|
||||||
if _, err := w.Write(endBraceNewline); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := fmt.Fprint(w, tag); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if wire != WireStartGroup {
|
|
||||||
if err := w.WriteByte(':'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !w.compact || wire == WireStartGroup {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch wire {
|
|
||||||
case WireBytes:
|
|
||||||
buf, e := b.DecodeRawBytes(false)
|
|
||||||
if e == nil {
|
|
||||||
_, err = fmt.Fprintf(w, "%q", buf)
|
|
||||||
} else {
|
|
||||||
_, err = fmt.Fprintf(w, "/* %v */", e)
|
|
||||||
}
|
|
||||||
case WireFixed32:
|
|
||||||
x, err = b.DecodeFixed32()
|
|
||||||
err = writeUnknownInt(w, x, err)
|
|
||||||
case WireFixed64:
|
|
||||||
x, err = b.DecodeFixed64()
|
|
||||||
err = writeUnknownInt(w, x, err)
|
|
||||||
case WireStartGroup:
|
|
||||||
err = w.WriteByte('{')
|
|
||||||
w.indent()
|
|
||||||
case WireVarint:
|
|
||||||
x, err = b.DecodeVarint()
|
|
||||||
err = writeUnknownInt(w, x, err)
|
|
||||||
default:
|
|
||||||
_, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeUnknownInt(w *textWriter, x uint64, err error) error {
|
|
||||||
if err == nil {
|
|
||||||
_, err = fmt.Fprint(w, x)
|
|
||||||
} else {
|
|
||||||
_, err = fmt.Fprintf(w, "/* %v */", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type int32Slice []int32
|
|
||||||
|
|
||||||
func (s int32Slice) Len() int { return len(s) }
|
|
||||||
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
|
|
||||||
func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
|
|
||||||
// writeExtensions writes all the extensions in pv.
|
|
||||||
// pv is assumed to be a pointer to a protocol message struct that is extendable.
|
|
||||||
func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
|
|
||||||
emap := extensionMaps[pv.Type().Elem()]
|
|
||||||
ep, _ := extendable(pv.Interface())
|
|
||||||
|
|
||||||
// Order the extensions by ID.
|
|
||||||
// This isn't strictly necessary, but it will give us
|
|
||||||
// canonical output, which will also make testing easier.
|
|
||||||
m, mu := ep.extensionsRead()
|
|
||||||
if m == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
ids := make([]int32, 0, len(m))
|
|
||||||
for id := range m {
|
|
||||||
ids = append(ids, id)
|
|
||||||
}
|
|
||||||
sort.Sort(int32Slice(ids))
|
|
||||||
mu.Unlock()
|
|
||||||
|
|
||||||
for _, extNum := range ids {
|
|
||||||
ext := m[extNum]
|
|
||||||
var desc *ExtensionDesc
|
|
||||||
if emap != nil {
|
|
||||||
desc = emap[extNum]
|
|
||||||
}
|
|
||||||
if desc == nil {
|
|
||||||
// Unknown extension.
|
|
||||||
if err := writeUnknownStruct(w, ext.enc); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pb, err := GetExtension(ep, desc)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed getting extension: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeated extensions will appear as a slice.
|
|
||||||
if !desc.repeated() {
|
|
||||||
if err := tm.writeExtension(w, desc.Name, pb); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v := reflect.ValueOf(pb)
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
|
|
||||||
if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) writeIndent() {
|
|
||||||
if !w.complete {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
remain := w.ind * 2
|
|
||||||
for remain > 0 {
|
|
||||||
n := remain
|
|
||||||
if n > len(spaces) {
|
|
||||||
n = len(spaces)
|
|
||||||
}
|
|
||||||
w.w.Write(spaces[:n])
|
|
||||||
remain -= n
|
|
||||||
}
|
|
||||||
w.complete = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextMarshaler is a configurable text format marshaler.
|
|
||||||
type TextMarshaler struct {
|
|
||||||
Compact bool // use compact text format (one line).
|
|
||||||
ExpandAny bool // expand google.protobuf.Any messages of known types
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal writes a given protocol buffer in text format.
|
|
||||||
// The only errors returned are from w.
|
|
||||||
func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
|
||||||
val := reflect.ValueOf(pb)
|
|
||||||
if pb == nil || val.IsNil() {
|
|
||||||
w.Write([]byte("<nil>"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var bw *bufio.Writer
|
|
||||||
ww, ok := w.(writer)
|
|
||||||
if !ok {
|
|
||||||
bw = bufio.NewWriter(w)
|
|
||||||
ww = bw
|
|
||||||
}
|
|
||||||
aw := &textWriter{
|
|
||||||
w: ww,
|
|
||||||
complete: true,
|
|
||||||
compact: tm.Compact,
|
|
||||||
}
|
|
||||||
|
|
||||||
if etm, ok := pb.(encoding.TextMarshaler); ok {
|
|
||||||
text, err := etm.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = aw.Write(text); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if bw != nil {
|
|
||||||
return bw.Flush()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Dereference the received pointer so we don't have outer < and >.
|
|
||||||
v := reflect.Indirect(val)
|
|
||||||
if err := tm.writeStruct(aw, v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if bw != nil {
|
|
||||||
return bw.Flush()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text is the same as Marshal, but returns the string directly.
|
|
||||||
func (tm *TextMarshaler) Text(pb Message) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
tm.Marshal(&buf, pb)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
defaultTextMarshaler = TextMarshaler{}
|
|
||||||
compactTextMarshaler = TextMarshaler{Compact: true}
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: consider removing some of the Marshal functions below.
|
|
||||||
|
|
||||||
// MarshalText writes a given protocol buffer in text format.
|
|
||||||
// The only errors returned are from w.
|
|
||||||
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
|
|
||||||
|
|
||||||
// MarshalTextString is the same as MarshalText, but returns the string directly.
|
|
||||||
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
|
|
||||||
|
|
||||||
// CompactText writes a given protocol buffer in compact text format (one line).
|
|
||||||
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
|
|
||||||
|
|
||||||
// CompactTextString is the same as CompactText, but returns the string directly.
|
|
||||||
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
|
|
880
vendor/github.com/golang/protobuf/proto/text_parser.go
generated
vendored
880
vendor/github.com/golang/protobuf/proto/text_parser.go
generated
vendored
@ -1,880 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
// Functions for parsing the Text protocol buffer format.
|
|
||||||
// TODO: message sets.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error string emitted when deserializing Any and fields are already set
|
|
||||||
const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set"
|
|
||||||
|
|
||||||
type ParseError struct {
|
|
||||||
Message string
|
|
||||||
Line int // 1-based line number
|
|
||||||
Offset int // 0-based byte offset from start of input
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParseError) Error() string {
|
|
||||||
if p.Line == 1 {
|
|
||||||
// show offset only for first line
|
|
||||||
return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("line %d: %v", p.Line, p.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
type token struct {
|
|
||||||
value string
|
|
||||||
err *ParseError
|
|
||||||
line int // line number
|
|
||||||
offset int // byte number from start of input, not start of line
|
|
||||||
unquoted string // the unquoted version of value, if it was a quoted string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *token) String() string {
|
|
||||||
if t.err == nil {
|
|
||||||
return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("parse error: %v", t.err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type textParser struct {
|
|
||||||
s string // remaining input
|
|
||||||
done bool // whether the parsing is finished (success or error)
|
|
||||||
backed bool // whether back() was called
|
|
||||||
offset, line int
|
|
||||||
cur token
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTextParser(s string) *textParser {
|
|
||||||
p := new(textParser)
|
|
||||||
p.s = s
|
|
||||||
p.line = 1
|
|
||||||
p.cur.line = 1
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
|
|
||||||
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
|
|
||||||
p.cur.err = pe
|
|
||||||
p.done = true
|
|
||||||
return pe
|
|
||||||
}
|
|
||||||
|
|
||||||
// Numbers and identifiers are matched by [-+._A-Za-z0-9]
|
|
||||||
func isIdentOrNumberChar(c byte) bool {
|
|
||||||
switch {
|
|
||||||
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
|
|
||||||
return true
|
|
||||||
case '0' <= c && c <= '9':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
switch c {
|
|
||||||
case '-', '+', '.', '_':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isWhitespace(c byte) bool {
|
|
||||||
switch c {
|
|
||||||
case ' ', '\t', '\n', '\r':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isQuote(c byte) bool {
|
|
||||||
switch c {
|
|
||||||
case '"', '\'':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) skipWhitespace() {
|
|
||||||
i := 0
|
|
||||||
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
|
|
||||||
if p.s[i] == '#' {
|
|
||||||
// comment; skip to end of line or input
|
|
||||||
for i < len(p.s) && p.s[i] != '\n' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i == len(p.s) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if p.s[i] == '\n' {
|
|
||||||
p.line++
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
p.offset += i
|
|
||||||
p.s = p.s[i:len(p.s)]
|
|
||||||
if len(p.s) == 0 {
|
|
||||||
p.done = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) advance() {
|
|
||||||
// Skip whitespace
|
|
||||||
p.skipWhitespace()
|
|
||||||
if p.done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start of non-whitespace
|
|
||||||
p.cur.err = nil
|
|
||||||
p.cur.offset, p.cur.line = p.offset, p.line
|
|
||||||
p.cur.unquoted = ""
|
|
||||||
switch p.s[0] {
|
|
||||||
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
|
|
||||||
// Single symbol
|
|
||||||
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
|
|
||||||
case '"', '\'':
|
|
||||||
// Quoted string
|
|
||||||
i := 1
|
|
||||||
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
|
|
||||||
if p.s[i] == '\\' && i+1 < len(p.s) {
|
|
||||||
// skip escaped char
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i >= len(p.s) || p.s[i] != p.s[0] {
|
|
||||||
p.errorf("unmatched quote")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
|
|
||||||
if err != nil {
|
|
||||||
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
|
|
||||||
p.cur.unquoted = unq
|
|
||||||
default:
|
|
||||||
i := 0
|
|
||||||
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
p.errorf("unexpected byte %#x", p.s[0])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
|
|
||||||
}
|
|
||||||
p.offset += len(p.cur.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
errBadUTF8 = errors.New("proto: bad UTF-8")
|
|
||||||
)
|
|
||||||
|
|
||||||
func unquoteC(s string, quote rune) (string, error) {
|
|
||||||
// This is based on C++'s tokenizer.cc.
|
|
||||||
// Despite its name, this is *not* parsing C syntax.
|
|
||||||
// For instance, "\0" is an invalid quoted string.
|
|
||||||
|
|
||||||
// Avoid allocation in trivial cases.
|
|
||||||
simple := true
|
|
||||||
for _, r := range s {
|
|
||||||
if r == '\\' || r == quote {
|
|
||||||
simple = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if simple {
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, 0, 3*len(s)/2)
|
|
||||||
for len(s) > 0 {
|
|
||||||
r, n := utf8.DecodeRuneInString(s)
|
|
||||||
if r == utf8.RuneError && n == 1 {
|
|
||||||
return "", errBadUTF8
|
|
||||||
}
|
|
||||||
s = s[n:]
|
|
||||||
if r != '\\' {
|
|
||||||
if r < utf8.RuneSelf {
|
|
||||||
buf = append(buf, byte(r))
|
|
||||||
} else {
|
|
||||||
buf = append(buf, string(r)...)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ch, tail, err := unescape(s)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
buf = append(buf, ch...)
|
|
||||||
s = tail
|
|
||||||
}
|
|
||||||
return string(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unescape(s string) (ch string, tail string, err error) {
|
|
||||||
r, n := utf8.DecodeRuneInString(s)
|
|
||||||
if r == utf8.RuneError && n == 1 {
|
|
||||||
return "", "", errBadUTF8
|
|
||||||
}
|
|
||||||
s = s[n:]
|
|
||||||
switch r {
|
|
||||||
case 'a':
|
|
||||||
return "\a", s, nil
|
|
||||||
case 'b':
|
|
||||||
return "\b", s, nil
|
|
||||||
case 'f':
|
|
||||||
return "\f", s, nil
|
|
||||||
case 'n':
|
|
||||||
return "\n", s, nil
|
|
||||||
case 'r':
|
|
||||||
return "\r", s, nil
|
|
||||||
case 't':
|
|
||||||
return "\t", s, nil
|
|
||||||
case 'v':
|
|
||||||
return "\v", s, nil
|
|
||||||
case '?':
|
|
||||||
return "?", s, nil // trigraph workaround
|
|
||||||
case '\'', '"', '\\':
|
|
||||||
return string(r), s, nil
|
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
|
||||||
if len(s) < 2 {
|
|
||||||
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
|
|
||||||
}
|
|
||||||
ss := string(r) + s[:2]
|
|
||||||
s = s[2:]
|
|
||||||
i, err := strconv.ParseUint(ss, 8, 8)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
|
|
||||||
}
|
|
||||||
return string([]byte{byte(i)}), s, nil
|
|
||||||
case 'x', 'X', 'u', 'U':
|
|
||||||
var n int
|
|
||||||
switch r {
|
|
||||||
case 'x', 'X':
|
|
||||||
n = 2
|
|
||||||
case 'u':
|
|
||||||
n = 4
|
|
||||||
case 'U':
|
|
||||||
n = 8
|
|
||||||
}
|
|
||||||
if len(s) < n {
|
|
||||||
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
|
|
||||||
}
|
|
||||||
ss := s[:n]
|
|
||||||
s = s[n:]
|
|
||||||
i, err := strconv.ParseUint(ss, 16, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
|
|
||||||
}
|
|
||||||
if r == 'x' || r == 'X' {
|
|
||||||
return string([]byte{byte(i)}), s, nil
|
|
||||||
}
|
|
||||||
if i > utf8.MaxRune {
|
|
||||||
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
|
||||||
}
|
|
||||||
return string(i), s, nil
|
|
||||||
}
|
|
||||||
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Back off the parser by one token. Can only be done between calls to next().
|
|
||||||
// It makes the next advance() a no-op.
|
|
||||||
func (p *textParser) back() { p.backed = true }
|
|
||||||
|
|
||||||
// Advances the parser and returns the new current token.
|
|
||||||
func (p *textParser) next() *token {
|
|
||||||
if p.backed || p.done {
|
|
||||||
p.backed = false
|
|
||||||
return &p.cur
|
|
||||||
}
|
|
||||||
p.advance()
|
|
||||||
if p.done {
|
|
||||||
p.cur.value = ""
|
|
||||||
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
|
|
||||||
// Look for multiple quoted strings separated by whitespace,
|
|
||||||
// and concatenate them.
|
|
||||||
cat := p.cur
|
|
||||||
for {
|
|
||||||
p.skipWhitespace()
|
|
||||||
if p.done || !isQuote(p.s[0]) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
p.advance()
|
|
||||||
if p.cur.err != nil {
|
|
||||||
return &p.cur
|
|
||||||
}
|
|
||||||
cat.value += " " + p.cur.value
|
|
||||||
cat.unquoted += p.cur.unquoted
|
|
||||||
}
|
|
||||||
p.done = false // parser may have seen EOF, but we want to return cat
|
|
||||||
p.cur = cat
|
|
||||||
}
|
|
||||||
return &p.cur
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) consumeToken(s string) error {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value != s {
|
|
||||||
p.back()
|
|
||||||
return p.errorf("expected %q, found %q", s, tok.value)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a RequiredNotSetError indicating which required field was not set.
|
|
||||||
func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError {
|
|
||||||
st := sv.Type()
|
|
||||||
sprops := GetProperties(st)
|
|
||||||
for i := 0; i < st.NumField(); i++ {
|
|
||||||
if !isNil(sv.Field(i)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
props := sprops.Prop[i]
|
|
||||||
if props.Required {
|
|
||||||
return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &RequiredNotSetError{fmt.Sprintf("%v.<unknown field name>", st)} // should not happen
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the index in the struct for the named field, as well as the parsed tag properties.
|
|
||||||
func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
|
|
||||||
i, ok := sprops.decoderOrigNames[name]
|
|
||||||
if ok {
|
|
||||||
return i, sprops.Prop[i], true
|
|
||||||
}
|
|
||||||
return -1, nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume a ':' from the input stream (if the next token is a colon),
|
|
||||||
// returning an error if a colon is needed but not present.
|
|
||||||
func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value != ":" {
|
|
||||||
// Colon is optional when the field is a group or message.
|
|
||||||
needColon := true
|
|
||||||
switch props.Wire {
|
|
||||||
case "group":
|
|
||||||
needColon = false
|
|
||||||
case "bytes":
|
|
||||||
// A "bytes" field is either a message, a string, or a repeated field;
|
|
||||||
// those three become *T, *string and []T respectively, so we can check for
|
|
||||||
// this field being a pointer to a non-string.
|
|
||||||
if typ.Kind() == reflect.Ptr {
|
|
||||||
// *T or *string
|
|
||||||
if typ.Elem().Kind() == reflect.String {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else if typ.Kind() == reflect.Slice {
|
|
||||||
// []T or []*T
|
|
||||||
if typ.Elem().Kind() != reflect.Ptr {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else if typ.Kind() == reflect.String {
|
|
||||||
// The proto3 exception is for a string field,
|
|
||||||
// which requires a colon.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
needColon = false
|
|
||||||
}
|
|
||||||
if needColon {
|
|
||||||
return p.errorf("expected ':', found %q", tok.value)
|
|
||||||
}
|
|
||||||
p.back()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
|
||||||
st := sv.Type()
|
|
||||||
sprops := GetProperties(st)
|
|
||||||
reqCount := sprops.reqCount
|
|
||||||
var reqFieldErr error
|
|
||||||
fieldSet := make(map[string]bool)
|
|
||||||
// A struct is a sequence of "name: value", terminated by one of
|
|
||||||
// '>' or '}', or the end of the input. A name may also be
|
|
||||||
// "[extension]" or "[type/url]".
|
|
||||||
//
|
|
||||||
// The whole struct can also be an expanded Any message, like:
|
|
||||||
// [type/url] < ... struct contents ... >
|
|
||||||
for {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == terminator {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if tok.value == "[" {
|
|
||||||
// Looks like an extension or an Any.
|
|
||||||
//
|
|
||||||
// TODO: Check whether we need to handle
|
|
||||||
// namespace rooted names (e.g. ".something.Foo").
|
|
||||||
extName, err := p.consumeExtName()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if s := strings.LastIndex(extName, "/"); s >= 0 {
|
|
||||||
// If it contains a slash, it's an Any type URL.
|
|
||||||
messageName := extName[s+1:]
|
|
||||||
mt := MessageType(messageName)
|
|
||||||
if mt == nil {
|
|
||||||
return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
|
|
||||||
}
|
|
||||||
tok = p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
// consume an optional colon
|
|
||||||
if tok.value == ":" {
|
|
||||||
tok = p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var terminator string
|
|
||||||
switch tok.value {
|
|
||||||
case "<":
|
|
||||||
terminator = ">"
|
|
||||||
case "{":
|
|
||||||
terminator = "}"
|
|
||||||
default:
|
|
||||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
||||||
}
|
|
||||||
v := reflect.New(mt.Elem())
|
|
||||||
if pe := p.readStruct(v.Elem(), terminator); pe != nil {
|
|
||||||
return pe
|
|
||||||
}
|
|
||||||
b, err := Marshal(v.Interface().(Message))
|
|
||||||
if err != nil {
|
|
||||||
return p.errorf("failed to marshal message of type %q: %v", messageName, err)
|
|
||||||
}
|
|
||||||
if fieldSet["type_url"] {
|
|
||||||
return p.errorf(anyRepeatedlyUnpacked, "type_url")
|
|
||||||
}
|
|
||||||
if fieldSet["value"] {
|
|
||||||
return p.errorf(anyRepeatedlyUnpacked, "value")
|
|
||||||
}
|
|
||||||
sv.FieldByName("TypeUrl").SetString(extName)
|
|
||||||
sv.FieldByName("Value").SetBytes(b)
|
|
||||||
fieldSet["type_url"] = true
|
|
||||||
fieldSet["value"] = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var desc *ExtensionDesc
|
|
||||||
// This could be faster, but it's functional.
|
|
||||||
// TODO: Do something smarter than a linear scan.
|
|
||||||
for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
|
|
||||||
if d.Name == extName {
|
|
||||||
desc = d
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if desc == nil {
|
|
||||||
return p.errorf("unrecognized extension %q", extName)
|
|
||||||
}
|
|
||||||
|
|
||||||
props := &Properties{}
|
|
||||||
props.Parse(desc.Tag)
|
|
||||||
|
|
||||||
typ := reflect.TypeOf(desc.ExtensionType)
|
|
||||||
if err := p.checkForColon(props, typ); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rep := desc.repeated()
|
|
||||||
|
|
||||||
// Read the extension structure, and set it in
|
|
||||||
// the value we're constructing.
|
|
||||||
var ext reflect.Value
|
|
||||||
if !rep {
|
|
||||||
ext = reflect.New(typ).Elem()
|
|
||||||
} else {
|
|
||||||
ext = reflect.New(typ.Elem()).Elem()
|
|
||||||
}
|
|
||||||
if err := p.readAny(ext, props); err != nil {
|
|
||||||
if _, ok := err.(*RequiredNotSetError); !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
reqFieldErr = err
|
|
||||||
}
|
|
||||||
ep := sv.Addr().Interface().(Message)
|
|
||||||
if !rep {
|
|
||||||
SetExtension(ep, desc, ext.Interface())
|
|
||||||
} else {
|
|
||||||
old, err := GetExtension(ep, desc)
|
|
||||||
var sl reflect.Value
|
|
||||||
if err == nil {
|
|
||||||
sl = reflect.ValueOf(old) // existing slice
|
|
||||||
} else {
|
|
||||||
sl = reflect.MakeSlice(typ, 0, 1)
|
|
||||||
}
|
|
||||||
sl = reflect.Append(sl, ext)
|
|
||||||
SetExtension(ep, desc, sl.Interface())
|
|
||||||
}
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a normal, non-extension field.
|
|
||||||
name := tok.value
|
|
||||||
var dst reflect.Value
|
|
||||||
fi, props, ok := structFieldByName(sprops, name)
|
|
||||||
if ok {
|
|
||||||
dst = sv.Field(fi)
|
|
||||||
} else if oop, ok := sprops.OneofTypes[name]; ok {
|
|
||||||
// It is a oneof.
|
|
||||||
props = oop.Prop
|
|
||||||
nv := reflect.New(oop.Type.Elem())
|
|
||||||
dst = nv.Elem().Field(0)
|
|
||||||
field := sv.Field(oop.Field)
|
|
||||||
if !field.IsNil() {
|
|
||||||
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name)
|
|
||||||
}
|
|
||||||
field.Set(nv)
|
|
||||||
}
|
|
||||||
if !dst.IsValid() {
|
|
||||||
return p.errorf("unknown field name %q in %v", name, st)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dst.Kind() == reflect.Map {
|
|
||||||
// Consume any colon.
|
|
||||||
if err := p.checkForColon(props, dst.Type()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct the map if it doesn't already exist.
|
|
||||||
if dst.IsNil() {
|
|
||||||
dst.Set(reflect.MakeMap(dst.Type()))
|
|
||||||
}
|
|
||||||
key := reflect.New(dst.Type().Key()).Elem()
|
|
||||||
val := reflect.New(dst.Type().Elem()).Elem()
|
|
||||||
|
|
||||||
// The map entry should be this sequence of tokens:
|
|
||||||
// < key : KEY value : VALUE >
|
|
||||||
// However, implementations may omit key or value, and technically
|
|
||||||
// we should support them in any order. See b/28924776 for a time
|
|
||||||
// this went wrong.
|
|
||||||
|
|
||||||
tok := p.next()
|
|
||||||
var terminator string
|
|
||||||
switch tok.value {
|
|
||||||
case "<":
|
|
||||||
terminator = ">"
|
|
||||||
case "{":
|
|
||||||
terminator = "}"
|
|
||||||
default:
|
|
||||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == terminator {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
switch tok.value {
|
|
||||||
case "key":
|
|
||||||
if err := p.consumeToken(":"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.readAny(key, props.MapKeyProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "value":
|
|
||||||
if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.readAny(val, props.MapValProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
p.back()
|
|
||||||
return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.SetMapIndex(key, val)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that it's not already set if it's not a repeated field.
|
|
||||||
if !props.Repeated && fieldSet[name] {
|
|
||||||
return p.errorf("non-repeated field %q was repeated", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.checkForColon(props, dst.Type()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse into the field.
|
|
||||||
fieldSet[name] = true
|
|
||||||
if err := p.readAny(dst, props); err != nil {
|
|
||||||
if _, ok := err.(*RequiredNotSetError); !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
reqFieldErr = err
|
|
||||||
}
|
|
||||||
if props.Required {
|
|
||||||
reqCount--
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if reqCount > 0 {
|
|
||||||
return p.missingRequiredFieldError(sv)
|
|
||||||
}
|
|
||||||
return reqFieldErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// consumeExtName consumes extension name or expanded Any type URL and the
|
|
||||||
// following ']'. It returns the name or URL consumed.
|
|
||||||
func (p *textParser) consumeExtName() (string, error) {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return "", tok.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If extension name or type url is quoted, it's a single token.
|
|
||||||
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
|
|
||||||
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return name, p.consumeToken("]")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume everything up to "]"
|
|
||||||
var parts []string
|
|
||||||
for tok.value != "]" {
|
|
||||||
parts = append(parts, tok.value)
|
|
||||||
tok = p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
|
|
||||||
}
|
|
||||||
if p.done && tok.value != "]" {
|
|
||||||
return "", p.errorf("unclosed type_url or extension name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(parts, ""), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// consumeOptionalSeparator consumes an optional semicolon or comma.
|
|
||||||
// It is used in readStruct to provide backward compatibility.
|
|
||||||
func (p *textParser) consumeOptionalSeparator() error {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value != ";" && tok.value != "," {
|
|
||||||
p.back()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == "" {
|
|
||||||
return p.errorf("unexpected EOF")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch fv := v; fv.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
at := v.Type()
|
|
||||||
if at.Elem().Kind() == reflect.Uint8 {
|
|
||||||
// Special case for []byte
|
|
||||||
if tok.value[0] != '"' && tok.value[0] != '\'' {
|
|
||||||
// Deliberately written out here, as the error after
|
|
||||||
// this switch statement would write "invalid []byte: ...",
|
|
||||||
// which is not as user-friendly.
|
|
||||||
return p.errorf("invalid string: %v", tok.value)
|
|
||||||
}
|
|
||||||
bytes := []byte(tok.unquoted)
|
|
||||||
fv.Set(reflect.ValueOf(bytes))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Repeated field.
|
|
||||||
if tok.value == "[" {
|
|
||||||
// Repeated field with list notation, like [1,2,3].
|
|
||||||
for {
|
|
||||||
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
|
|
||||||
err := p.readAny(fv.Index(fv.Len()-1), props)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == "]" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if tok.value != "," {
|
|
||||||
return p.errorf("Expected ']' or ',' found %q", tok.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// One value of the repeated field.
|
|
||||||
p.back()
|
|
||||||
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
|
|
||||||
return p.readAny(fv.Index(fv.Len()-1), props)
|
|
||||||
case reflect.Bool:
|
|
||||||
// true/1/t/True or false/f/0/False.
|
|
||||||
switch tok.value {
|
|
||||||
case "true", "1", "t", "True":
|
|
||||||
fv.SetBool(true)
|
|
||||||
return nil
|
|
||||||
case "false", "0", "f", "False":
|
|
||||||
fv.SetBool(false)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
v := tok.value
|
|
||||||
// Ignore 'f' for compatibility with output generated by C++, but don't
|
|
||||||
// remove 'f' when the value is "-inf" or "inf".
|
|
||||||
if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" {
|
|
||||||
v = v[:len(v)-1]
|
|
||||||
}
|
|
||||||
if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil {
|
|
||||||
fv.SetFloat(f)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Int32:
|
|
||||||
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
|
||||||
fv.SetInt(x)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(props.Enum) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m, ok := enumValueMaps[props.Enum]
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
x, ok := m[tok.value]
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fv.SetInt(int64(x))
|
|
||||||
return nil
|
|
||||||
case reflect.Int64:
|
|
||||||
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
|
|
||||||
fv.SetInt(x)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Ptr:
|
|
||||||
// A basic field (indirected through pointer), or a repeated message/group
|
|
||||||
p.back()
|
|
||||||
fv.Set(reflect.New(fv.Type().Elem()))
|
|
||||||
return p.readAny(fv.Elem(), props)
|
|
||||||
case reflect.String:
|
|
||||||
if tok.value[0] == '"' || tok.value[0] == '\'' {
|
|
||||||
fv.SetString(tok.unquoted)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
var terminator string
|
|
||||||
switch tok.value {
|
|
||||||
case "{":
|
|
||||||
terminator = "}"
|
|
||||||
case "<":
|
|
||||||
terminator = ">"
|
|
||||||
default:
|
|
||||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
||||||
}
|
|
||||||
// TODO: Handle nested messages which implement encoding.TextUnmarshaler.
|
|
||||||
return p.readStruct(fv, terminator)
|
|
||||||
case reflect.Uint32:
|
|
||||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
|
||||||
fv.SetUint(uint64(x))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Uint64:
|
|
||||||
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
|
||||||
fv.SetUint(x)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p.errorf("invalid %v: %v", v.Type(), tok.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
|
|
||||||
// before starting to unmarshal, so any existing data in pb is always removed.
|
|
||||||
// If a required field is not set and no other error occurs,
|
|
||||||
// UnmarshalText returns *RequiredNotSetError.
|
|
||||||
func UnmarshalText(s string, pb Message) error {
|
|
||||||
if um, ok := pb.(encoding.TextUnmarshaler); ok {
|
|
||||||
return um.UnmarshalText([]byte(s))
|
|
||||||
}
|
|
||||||
pb.Reset()
|
|
||||||
v := reflect.ValueOf(pb)
|
|
||||||
return newTextParser(s).readStruct(v.Elem(), "")
|
|
||||||
}
|
|
476
vendor/github.com/klauspost/cpuid/private-gen.go
generated
vendored
476
vendor/github.com/klauspost/cpuid/private-gen.go
generated
vendored
@ -1,476 +0,0 @@
|
|||||||
// +build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
|
||||||
"go/parser"
|
|
||||||
"go/printer"
|
|
||||||
"go/token"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
var inFiles = []string{"cpuid.go", "cpuid_test.go"}
|
|
||||||
var copyFiles = []string{"cpuid_amd64.s", "cpuid_386.s", "detect_ref.go", "detect_intel.go"}
|
|
||||||
var fileSet = token.NewFileSet()
|
|
||||||
var reWrites = []rewrite{
|
|
||||||
initRewrite("CPUInfo -> cpuInfo"),
|
|
||||||
initRewrite("Vendor -> vendor"),
|
|
||||||
initRewrite("Flags -> flags"),
|
|
||||||
initRewrite("Detect -> detect"),
|
|
||||||
initRewrite("CPU -> cpu"),
|
|
||||||
}
|
|
||||||
var excludeNames = map[string]bool{"string": true, "join": true, "trim": true,
|
|
||||||
// cpuid_test.go
|
|
||||||
"t": true, "println": true, "logf": true, "log": true, "fatalf": true, "fatal": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
var excludePrefixes = []string{"test", "benchmark"}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
Package := "private"
|
|
||||||
parserMode := parser.ParseComments
|
|
||||||
exported := make(map[string]rewrite)
|
|
||||||
for _, file := range inFiles {
|
|
||||||
in, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("opening input", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
src, err := ioutil.ReadAll(in)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("reading input", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
astfile, err := parser.ParseFile(fileSet, file, src, parserMode)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("parsing input", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rw := range reWrites {
|
|
||||||
astfile = rw(astfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inspect the AST and print all identifiers and literals.
|
|
||||||
var startDecl token.Pos
|
|
||||||
var endDecl token.Pos
|
|
||||||
ast.Inspect(astfile, func(n ast.Node) bool {
|
|
||||||
var s string
|
|
||||||
switch x := n.(type) {
|
|
||||||
case *ast.Ident:
|
|
||||||
if x.IsExported() {
|
|
||||||
t := strings.ToLower(x.Name)
|
|
||||||
for _, pre := range excludePrefixes {
|
|
||||||
if strings.HasPrefix(t, pre) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if excludeNames[t] != true {
|
|
||||||
//if x.Pos() > startDecl && x.Pos() < endDecl {
|
|
||||||
exported[x.Name] = initRewrite(x.Name + " -> " + t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *ast.GenDecl:
|
|
||||||
if x.Tok == token.CONST && x.Lparen > 0 {
|
|
||||||
startDecl = x.Lparen
|
|
||||||
endDecl = x.Rparen
|
|
||||||
// fmt.Printf("Decl:%s -> %s\n", fileSet.Position(startDecl), fileSet.Position(endDecl))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if s != "" {
|
|
||||||
fmt.Printf("%s:\t%s\n", fileSet.Position(n.Pos()), s)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, rw := range exported {
|
|
||||||
astfile = rw(astfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
printer.Fprint(&buf, fileSet, astfile)
|
|
||||||
|
|
||||||
// Remove package documentation and insert information
|
|
||||||
s := buf.String()
|
|
||||||
ind := strings.Index(buf.String(), "\npackage cpuid")
|
|
||||||
s = s[ind:]
|
|
||||||
s = "// Generated, DO NOT EDIT,\n" +
|
|
||||||
"// but copy it to your own project and rename the package.\n" +
|
|
||||||
"// See more at http://github.com/klauspost/cpuid\n" +
|
|
||||||
s
|
|
||||||
|
|
||||||
outputName := Package + string(os.PathSeparator) + file
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(outputName, []byte(s), 0644)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("writing output: %s", err)
|
|
||||||
}
|
|
||||||
log.Println("Generated", outputName)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range copyFiles {
|
|
||||||
dst := ""
|
|
||||||
if strings.HasPrefix(file, "cpuid") {
|
|
||||||
dst = Package + string(os.PathSeparator) + file
|
|
||||||
} else {
|
|
||||||
dst = Package + string(os.PathSeparator) + "cpuid_" + file
|
|
||||||
}
|
|
||||||
err := copyFile(file, dst)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("copying file: %s", err)
|
|
||||||
}
|
|
||||||
log.Println("Copied", dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyFile copies a file from src to dst. If src and dst files exist, and are
|
|
||||||
// the same, then return success. Copy the file contents from src to dst.
|
|
||||||
func copyFile(src, dst string) (err error) {
|
|
||||||
sfi, err := os.Stat(src)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !sfi.Mode().IsRegular() {
|
|
||||||
// cannot copy non-regular files (e.g., directories,
|
|
||||||
// symlinks, devices, etc.)
|
|
||||||
return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
|
|
||||||
}
|
|
||||||
dfi, err := os.Stat(dst)
|
|
||||||
if err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if !(dfi.Mode().IsRegular()) {
|
|
||||||
return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
|
|
||||||
}
|
|
||||||
if os.SameFile(sfi, dfi) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = copyFileContents(src, dst)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// copyFileContents copies the contents of the file named src to the file named
|
|
||||||
// by dst. The file will be created if it does not already exist. If the
|
|
||||||
// destination file exists, all it's contents will be replaced by the contents
|
|
||||||
// of the source file.
|
|
||||||
func copyFileContents(src, dst string) (err error) {
|
|
||||||
in, err := os.Open(src)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer in.Close()
|
|
||||||
out, err := os.Create(dst)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
cerr := out.Close()
|
|
||||||
if err == nil {
|
|
||||||
err = cerr
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if _, err = io.Copy(out, in); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = out.Sync()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type rewrite func(*ast.File) *ast.File
|
|
||||||
|
|
||||||
// Mostly copied from gofmt
|
|
||||||
func initRewrite(rewriteRule string) rewrite {
|
|
||||||
f := strings.Split(rewriteRule, "->")
|
|
||||||
if len(f) != 2 {
|
|
||||||
fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n")
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
pattern := parseExpr(f[0], "pattern")
|
|
||||||
replace := parseExpr(f[1], "replacement")
|
|
||||||
return func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseExpr parses s as an expression.
|
|
||||||
// It might make sense to expand this to allow statement patterns,
|
|
||||||
// but there are problems with preserving formatting and also
|
|
||||||
// with what a wildcard for a statement looks like.
|
|
||||||
func parseExpr(s, what string) ast.Expr {
|
|
||||||
x, err := parser.ParseExpr(s)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err)
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep this function for debugging.
|
|
||||||
/*
|
|
||||||
func dump(msg string, val reflect.Value) {
|
|
||||||
fmt.Printf("%s:\n", msg)
|
|
||||||
ast.Print(fileSet, val.Interface())
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file.
|
|
||||||
func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
|
|
||||||
cmap := ast.NewCommentMap(fileSet, p, p.Comments)
|
|
||||||
m := make(map[string]reflect.Value)
|
|
||||||
pat := reflect.ValueOf(pattern)
|
|
||||||
repl := reflect.ValueOf(replace)
|
|
||||||
|
|
||||||
var rewriteVal func(val reflect.Value) reflect.Value
|
|
||||||
rewriteVal = func(val reflect.Value) reflect.Value {
|
|
||||||
// don't bother if val is invalid to start with
|
|
||||||
if !val.IsValid() {
|
|
||||||
return reflect.Value{}
|
|
||||||
}
|
|
||||||
for k := range m {
|
|
||||||
delete(m, k)
|
|
||||||
}
|
|
||||||
val = apply(rewriteVal, val)
|
|
||||||
if match(m, pat, val) {
|
|
||||||
val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
|
|
||||||
}
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File)
|
|
||||||
r.Comments = cmap.Filter(r).Comments() // recreate comments list
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y.
|
|
||||||
func set(x, y reflect.Value) {
|
|
||||||
// don't bother if x cannot be set or y is invalid
|
|
||||||
if !x.CanSet() || !y.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if x := recover(); x != nil {
|
|
||||||
if s, ok := x.(string); ok &&
|
|
||||||
(strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) {
|
|
||||||
// x cannot be set to y - ignore this rewrite
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(x)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
x.Set(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values/types for special cases.
|
|
||||||
var (
|
|
||||||
objectPtrNil = reflect.ValueOf((*ast.Object)(nil))
|
|
||||||
scopePtrNil = reflect.ValueOf((*ast.Scope)(nil))
|
|
||||||
|
|
||||||
identType = reflect.TypeOf((*ast.Ident)(nil))
|
|
||||||
objectPtrType = reflect.TypeOf((*ast.Object)(nil))
|
|
||||||
positionType = reflect.TypeOf(token.NoPos)
|
|
||||||
callExprType = reflect.TypeOf((*ast.CallExpr)(nil))
|
|
||||||
scopePtrType = reflect.TypeOf((*ast.Scope)(nil))
|
|
||||||
)
|
|
||||||
|
|
||||||
// apply replaces each AST field x in val with f(x), returning val.
|
|
||||||
// To avoid extra conversions, f operates on the reflect.Value form.
|
|
||||||
func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value {
|
|
||||||
if !val.IsValid() {
|
|
||||||
return reflect.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// *ast.Objects introduce cycles and are likely incorrect after
|
|
||||||
// rewrite; don't follow them but replace with nil instead
|
|
||||||
if val.Type() == objectPtrType {
|
|
||||||
return objectPtrNil
|
|
||||||
}
|
|
||||||
|
|
||||||
// similarly for scopes: they are likely incorrect after a rewrite;
|
|
||||||
// replace them with nil
|
|
||||||
if val.Type() == scopePtrType {
|
|
||||||
return scopePtrNil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v := reflect.Indirect(val); v.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
e := v.Index(i)
|
|
||||||
set(e, f(e))
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
for i := 0; i < v.NumField(); i++ {
|
|
||||||
e := v.Field(i)
|
|
||||||
set(e, f(e))
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
|
||||||
e := v.Elem()
|
|
||||||
set(v, f(e))
|
|
||||||
}
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
func isWildcard(s string) bool {
|
|
||||||
rune, size := utf8.DecodeRuneInString(s)
|
|
||||||
return size == len(s) && unicode.IsLower(rune)
|
|
||||||
}
|
|
||||||
|
|
||||||
// match returns true if pattern matches val,
|
|
||||||
// recording wildcard submatches in m.
|
|
||||||
// If m == nil, match checks whether pattern == val.
|
|
||||||
func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
|
|
||||||
// Wildcard matches any expression. If it appears multiple
|
|
||||||
// times in the pattern, it must match the same expression
|
|
||||||
// each time.
|
|
||||||
if m != nil && pattern.IsValid() && pattern.Type() == identType {
|
|
||||||
name := pattern.Interface().(*ast.Ident).Name
|
|
||||||
if isWildcard(name) && val.IsValid() {
|
|
||||||
// wildcards only match valid (non-nil) expressions.
|
|
||||||
if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() {
|
|
||||||
if old, ok := m[name]; ok {
|
|
||||||
return match(nil, old, val)
|
|
||||||
}
|
|
||||||
m[name] = val
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, pattern and val must match recursively.
|
|
||||||
if !pattern.IsValid() || !val.IsValid() {
|
|
||||||
return !pattern.IsValid() && !val.IsValid()
|
|
||||||
}
|
|
||||||
if pattern.Type() != val.Type() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special cases.
|
|
||||||
switch pattern.Type() {
|
|
||||||
case identType:
|
|
||||||
// For identifiers, only the names need to match
|
|
||||||
// (and none of the other *ast.Object information).
|
|
||||||
// This is a common case, handle it all here instead
|
|
||||||
// of recursing down any further via reflection.
|
|
||||||
p := pattern.Interface().(*ast.Ident)
|
|
||||||
v := val.Interface().(*ast.Ident)
|
|
||||||
return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
|
|
||||||
case objectPtrType, positionType:
|
|
||||||
// object pointers and token positions always match
|
|
||||||
return true
|
|
||||||
case callExprType:
|
|
||||||
// For calls, the Ellipsis fields (token.Position) must
|
|
||||||
// match since that is how f(x) and f(x...) are different.
|
|
||||||
// Check them here but fall through for the remaining fields.
|
|
||||||
p := pattern.Interface().(*ast.CallExpr)
|
|
||||||
v := val.Interface().(*ast.CallExpr)
|
|
||||||
if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p := reflect.Indirect(pattern)
|
|
||||||
v := reflect.Indirect(val)
|
|
||||||
if !p.IsValid() || !v.IsValid() {
|
|
||||||
return !p.IsValid() && !v.IsValid()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch p.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
if p.Len() != v.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := 0; i < p.Len(); i++ {
|
|
||||||
if !match(m, p.Index(i), v.Index(i)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
for i := 0; i < p.NumField(); i++ {
|
|
||||||
if !match(m, p.Field(i), v.Field(i)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
|
|
||||||
case reflect.Interface:
|
|
||||||
return match(m, p.Elem(), v.Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle token integers, etc.
|
|
||||||
return p.Interface() == v.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
// subst returns a copy of pattern with values from m substituted in place
|
|
||||||
// of wildcards and pos used as the position of tokens from the pattern.
|
|
||||||
// if m == nil, subst returns a copy of pattern and doesn't change the line
|
|
||||||
// number information.
|
|
||||||
func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value {
|
|
||||||
if !pattern.IsValid() {
|
|
||||||
return reflect.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wildcard gets replaced with map value.
|
|
||||||
if m != nil && pattern.Type() == identType {
|
|
||||||
name := pattern.Interface().(*ast.Ident).Name
|
|
||||||
if isWildcard(name) {
|
|
||||||
if old, ok := m[name]; ok {
|
|
||||||
return subst(nil, old, reflect.Value{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pos.IsValid() && pattern.Type() == positionType {
|
|
||||||
// use new position only if old position was valid in the first place
|
|
||||||
if old := pattern.Interface().(token.Pos); !old.IsValid() {
|
|
||||||
return pattern
|
|
||||||
}
|
|
||||||
return pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise copy.
|
|
||||||
switch p := pattern; p.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
v := reflect.MakeSlice(p.Type(), p.Len(), p.Len())
|
|
||||||
for i := 0; i < p.Len(); i++ {
|
|
||||||
v.Index(i).Set(subst(m, p.Index(i), pos))
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
v := reflect.New(p.Type()).Elem()
|
|
||||||
for i := 0; i < p.NumField(); i++ {
|
|
||||||
v.Field(i).Set(subst(m, p.Field(i), pos))
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
|
|
||||||
case reflect.Ptr:
|
|
||||||
v := reflect.New(p.Type()).Elem()
|
|
||||||
if elem := p.Elem(); elem.IsValid() {
|
|
||||||
v.Set(subst(m, elem, pos).Addr())
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
|
|
||||||
case reflect.Interface:
|
|
||||||
v := reflect.New(p.Type()).Elem()
|
|
||||||
if elem := p.Elem(); elem.IsValid() {
|
|
||||||
v.Set(subst(m, elem, pos))
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
return pattern
|
|
||||||
}
|
|
132
vendor/github.com/klauspost/reedsolomon/gentables.go
generated
vendored
132
vendor/github.com/klauspost/reedsolomon/gentables.go
generated
vendored
@ -1,132 +0,0 @@
|
|||||||
//+build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var logTable = [fieldSize]int16{
|
|
||||||
-1, 0, 1, 25, 2, 50, 26, 198,
|
|
||||||
3, 223, 51, 238, 27, 104, 199, 75,
|
|
||||||
4, 100, 224, 14, 52, 141, 239, 129,
|
|
||||||
28, 193, 105, 248, 200, 8, 76, 113,
|
|
||||||
5, 138, 101, 47, 225, 36, 15, 33,
|
|
||||||
53, 147, 142, 218, 240, 18, 130, 69,
|
|
||||||
29, 181, 194, 125, 106, 39, 249, 185,
|
|
||||||
201, 154, 9, 120, 77, 228, 114, 166,
|
|
||||||
6, 191, 139, 98, 102, 221, 48, 253,
|
|
||||||
226, 152, 37, 179, 16, 145, 34, 136,
|
|
||||||
54, 208, 148, 206, 143, 150, 219, 189,
|
|
||||||
241, 210, 19, 92, 131, 56, 70, 64,
|
|
||||||
30, 66, 182, 163, 195, 72, 126, 110,
|
|
||||||
107, 58, 40, 84, 250, 133, 186, 61,
|
|
||||||
202, 94, 155, 159, 10, 21, 121, 43,
|
|
||||||
78, 212, 229, 172, 115, 243, 167, 87,
|
|
||||||
7, 112, 192, 247, 140, 128, 99, 13,
|
|
||||||
103, 74, 222, 237, 49, 197, 254, 24,
|
|
||||||
227, 165, 153, 119, 38, 184, 180, 124,
|
|
||||||
17, 68, 146, 217, 35, 32, 137, 46,
|
|
||||||
55, 63, 209, 91, 149, 188, 207, 205,
|
|
||||||
144, 135, 151, 178, 220, 252, 190, 97,
|
|
||||||
242, 86, 211, 171, 20, 42, 93, 158,
|
|
||||||
132, 60, 57, 83, 71, 109, 65, 162,
|
|
||||||
31, 45, 67, 216, 183, 123, 164, 118,
|
|
||||||
196, 23, 73, 236, 127, 12, 111, 246,
|
|
||||||
108, 161, 59, 82, 41, 157, 85, 170,
|
|
||||||
251, 96, 134, 177, 187, 204, 62, 90,
|
|
||||||
203, 89, 95, 176, 156, 169, 160, 81,
|
|
||||||
11, 245, 22, 235, 122, 117, 44, 215,
|
|
||||||
79, 174, 213, 233, 230, 231, 173, 232,
|
|
||||||
116, 214, 244, 234, 168, 80, 88, 175,
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
// The number of elements in the field.
|
|
||||||
fieldSize = 256
|
|
||||||
|
|
||||||
// The polynomial used to generate the logarithm table.
|
|
||||||
//
|
|
||||||
// There are a number of polynomials that work to generate
|
|
||||||
// a Galois field of 256 elements. The choice is arbitrary,
|
|
||||||
// and we just use the first one.
|
|
||||||
//
|
|
||||||
// The possibilities are: 29, 43, 45, 77, 95, 99, 101, 105,
|
|
||||||
//* 113, 135, 141, 169, 195, 207, 231, and 245.
|
|
||||||
generatingPolynomial = 29
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
t := generateExpTable()
|
|
||||||
fmt.Printf("var expTable = %#v\n", t)
|
|
||||||
//t2 := generateMulTableSplit(t)
|
|
||||||
//fmt.Printf("var mulTable = %#v\n", t2)
|
|
||||||
low, high := generateMulTableHalf(t)
|
|
||||||
fmt.Printf("var mulTableLow = %#v\n", low)
|
|
||||||
fmt.Printf("var mulTableHigh = %#v\n", high)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the inverse log table.
|
|
||||||
*/
|
|
||||||
func generateExpTable() []byte {
|
|
||||||
result := make([]byte, fieldSize*2-2)
|
|
||||||
for i := 1; i < fieldSize; i++ {
|
|
||||||
log := logTable[i]
|
|
||||||
result[log] = byte(i)
|
|
||||||
result[log+fieldSize-1] = byte(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateMulTable(expTable []byte) []byte {
|
|
||||||
result := make([]byte, 256*256)
|
|
||||||
for v := range result {
|
|
||||||
a := byte(v & 0xff)
|
|
||||||
b := byte(v >> 8)
|
|
||||||
if a == 0 || b == 0 {
|
|
||||||
result[v] = 0
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
logA := int(logTable[a])
|
|
||||||
logB := int(logTable[b])
|
|
||||||
result[v] = expTable[logA+logB]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateMulTableSplit(expTable []byte) [256][256]byte {
|
|
||||||
var result [256][256]byte
|
|
||||||
for a := range result {
|
|
||||||
for b := range result[a] {
|
|
||||||
if a == 0 || b == 0 {
|
|
||||||
result[a][b] = 0
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
logA := int(logTable[a])
|
|
||||||
logB := int(logTable[b])
|
|
||||||
result[a][b] = expTable[logA+logB]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateMulTableHalf(expTable []byte) (low [256][16]byte, high [256][16]byte) {
|
|
||||||
for a := range low {
|
|
||||||
for b := range low {
|
|
||||||
result := 0
|
|
||||||
if !(a == 0 || b == 0) {
|
|
||||||
logA := int(logTable[a])
|
|
||||||
logB := int(logTable[b])
|
|
||||||
result = int(expTable[logA+logB])
|
|
||||||
}
|
|
||||||
if (b & 0xf) == b {
|
|
||||||
low[a][b] = byte(result)
|
|
||||||
}
|
|
||||||
if (b & 0xf0) == b {
|
|
||||||
high[a][b>>4] = byte(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
10
vendor/github.com/pquerna/cachecontrol/.travis.yml
generated
vendored
10
vendor/github.com/pquerna/cachecontrol/.travis.yml
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
install:
|
|
||||||
- go get -d -v ./...
|
|
||||||
- go get -u github.com/stretchr/testify/require
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.7
|
|
||||||
- 1.8
|
|
||||||
- tip
|
|
202
vendor/github.com/pquerna/cachecontrol/LICENSE
generated
vendored
202
vendor/github.com/pquerna/cachecontrol/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
107
vendor/github.com/pquerna/cachecontrol/README.md
generated
vendored
107
vendor/github.com/pquerna/cachecontrol/README.md
generated
vendored
@ -1,107 +0,0 @@
|
|||||||
# cachecontrol: HTTP Caching Parser and Interpretation
|
|
||||||
|
|
||||||
[![GoDoc](https://godoc.org/github.com/pquerna/cachecontrol?status.svg)](https://godoc.org/github.com/pquerna/cachecontrol)[![Build Status](https://travis-ci.org/pquerna/cachecontrol.svg?branch=master)](https://travis-ci.org/pquerna/cachecontrol)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
`cachecontrol` implements [RFC 7234](http://tools.ietf.org/html/rfc7234) __Hypertext Transfer Protocol (HTTP/1.1): Caching__. It does this by parsing the `Cache-Control` and other headers, providing information about requests and responses -- but `cachecontrol` does not implement an actual cache backend, just the control plane to make decisions about if a particular response is cachable.
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
|
|
||||||
`cachecontrol.CachableResponse` returns an array of [reasons](https://godoc.org/github.com/pquerna/cachecontrol/cacheobject#Reason) why a response should not be cached and when it expires. In the case that `len(reasons) == 0`, the response is cachable according to the RFC. However, some people want non-compliant caches for various business use cases, so each reason is specifically named, so if your cache wants to cache `POST` requests, it can easily do that, but still be RFC compliant in other situations.
|
|
||||||
|
|
||||||
# Examples
|
|
||||||
|
|
||||||
## Can you cache Example.com?
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/pquerna/cachecontrol"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
req, _ := http.NewRequest("GET", "http://www.example.com/", nil)
|
|
||||||
|
|
||||||
res, _ := http.DefaultClient.Do(req)
|
|
||||||
_, _ = ioutil.ReadAll(res.Body)
|
|
||||||
|
|
||||||
reasons, expires, _ := cachecontrol.CachableResponse(req, res, cachecontrol.Options{})
|
|
||||||
|
|
||||||
fmt.Println("Reasons to not cache: ", reasons)
|
|
||||||
fmt.Println("Expiration: ", expires.String())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Can I use this in a high performance caching server?
|
|
||||||
|
|
||||||
`cachecontrol` is divided into two packages: `cachecontrol` with a high level API, and a lower level `cacheobject` package. Use [Object](https://godoc.org/github.com/pquerna/cachecontrol/cacheobject#Object) in a high performance use case where you have previously parsed headers containing dates or would like to avoid memory allocations.
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/pquerna/cachecontrol/cacheobject"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
req, _ := http.NewRequest("GET", "http://www.example.com/", nil)
|
|
||||||
|
|
||||||
res, _ := http.DefaultClient.Do(req)
|
|
||||||
_, _ = ioutil.ReadAll(res.Body)
|
|
||||||
|
|
||||||
reqDir, _ := cacheobject.ParseRequestCacheControl(req.Header.Get("Cache-Control"))
|
|
||||||
|
|
||||||
resDir, _ := cacheobject.ParseResponseCacheControl(res.Header.Get("Cache-Control"))
|
|
||||||
expiresHeader, _ := http.ParseTime(res.Header.Get("Expires"))
|
|
||||||
dateHeader, _ := http.ParseTime(res.Header.Get("Date"))
|
|
||||||
lastModifiedHeader, _ := http.ParseTime(res.Header.Get("Last-Modified"))
|
|
||||||
|
|
||||||
obj := cacheobject.Object{
|
|
||||||
RespDirectives: resDir,
|
|
||||||
RespHeaders: res.Header,
|
|
||||||
RespStatusCode: res.StatusCode,
|
|
||||||
RespExpiresHeader: expiresHeader,
|
|
||||||
RespDateHeader: dateHeader,
|
|
||||||
RespLastModifiedHeader: lastModifiedHeader,
|
|
||||||
|
|
||||||
ReqDirectives: reqDir,
|
|
||||||
ReqHeaders: req.Header,
|
|
||||||
ReqMethod: req.Method,
|
|
||||||
|
|
||||||
NowUTC: time.Now().UTC(),
|
|
||||||
}
|
|
||||||
rv := cacheobject.ObjectResults{}
|
|
||||||
|
|
||||||
cacheobject.CachableObject(&obj, &rv)
|
|
||||||
cacheobject.ExpirationObject(&obj, &rv)
|
|
||||||
|
|
||||||
fmt.Println("Errors: ", rv.OutErr)
|
|
||||||
fmt.Println("Reasons to not cache: ", rv.OutReasons)
|
|
||||||
fmt.Println("Warning headers to add: ", rv.OutWarnings)
|
|
||||||
fmt.Println("Expiration: ", rv.OutExpirationTime.String())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Improvements, bugs, adding features, and taking cachecontrol new directions!
|
|
||||||
|
|
||||||
Please [open issues in Github](https://github.com/pquerna/cachecontrol/issues) for ideas, bugs, and general thoughts. Pull requests are of course preferred :)
|
|
||||||
|
|
||||||
# Credits
|
|
||||||
|
|
||||||
`cachecontrol` has recieved significant contributions from:
|
|
||||||
|
|
||||||
* [Paul Querna](https://github.com/pquerna)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
`cachecontrol` is licensed under the [Apache License, Version 2.0](./LICENSE)
|
|
48
vendor/github.com/pquerna/cachecontrol/api.go
generated
vendored
48
vendor/github.com/pquerna/cachecontrol/api.go
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2015 Paul Querna
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cachecontrol
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/pquerna/cachecontrol/cacheobject"
|
|
||||||
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Options struct {
|
|
||||||
// Set to True for a prviate cache, which is not shared amoung users (eg, in a browser)
|
|
||||||
// Set to False for a "shared" cache, which is more common in a server context.
|
|
||||||
PrivateCache bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given an HTTP Request, the future Status Code, and an ResponseWriter,
|
|
||||||
// determine the possible reasons a response SHOULD NOT be cached.
|
|
||||||
func CachableResponseWriter(req *http.Request,
|
|
||||||
statusCode int,
|
|
||||||
resp http.ResponseWriter,
|
|
||||||
opts Options) ([]cacheobject.Reason, time.Time, error) {
|
|
||||||
return cacheobject.UsingRequestResponse(req, statusCode, resp.Header(), opts.PrivateCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given an HTTP Request and Response, determine the possible reasons a response SHOULD NOT
|
|
||||||
// be cached.
|
|
||||||
func CachableResponse(req *http.Request,
|
|
||||||
resp *http.Response,
|
|
||||||
opts Options) ([]cacheobject.Reason, time.Time, error) {
|
|
||||||
return cacheobject.UsingRequestResponse(req, resp.StatusCode, resp.Header, opts.PrivateCache)
|
|
||||||
}
|
|
546
vendor/github.com/pquerna/cachecontrol/cacheobject/directive.go
generated
vendored
546
vendor/github.com/pquerna/cachecontrol/cacheobject/directive.go
generated
vendored
@ -1,546 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2015 Paul Querna
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cacheobject
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"math"
|
|
||||||
"net/http"
|
|
||||||
"net/textproto"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO(pquerna): add extensions from here: http://www.iana.org/assignments/http-cache-directives/http-cache-directives.xhtml
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrQuoteMismatch = errors.New("Missing closing quote")
|
|
||||||
ErrMaxAgeDeltaSeconds = errors.New("Failed to parse delta-seconds in `max-age`")
|
|
||||||
ErrSMaxAgeDeltaSeconds = errors.New("Failed to parse delta-seconds in `s-maxage`")
|
|
||||||
ErrMaxStaleDeltaSeconds = errors.New("Failed to parse delta-seconds in `min-fresh`")
|
|
||||||
ErrMinFreshDeltaSeconds = errors.New("Failed to parse delta-seconds in `min-fresh`")
|
|
||||||
ErrNoCacheNoArgs = errors.New("Unexpected argument to `no-cache`")
|
|
||||||
ErrNoStoreNoArgs = errors.New("Unexpected argument to `no-store`")
|
|
||||||
ErrNoTransformNoArgs = errors.New("Unexpected argument to `no-transform`")
|
|
||||||
ErrOnlyIfCachedNoArgs = errors.New("Unexpected argument to `only-if-cached`")
|
|
||||||
ErrMustRevalidateNoArgs = errors.New("Unexpected argument to `must-revalidate`")
|
|
||||||
ErrPublicNoArgs = errors.New("Unexpected argument to `public`")
|
|
||||||
ErrProxyRevalidateNoArgs = errors.New("Unexpected argument to `proxy-revalidate`")
|
|
||||||
// Experimental
|
|
||||||
ErrImmutableNoArgs = errors.New("Unexpected argument to `immutable`")
|
|
||||||
ErrStaleIfErrorDeltaSeconds = errors.New("Failed to parse delta-seconds in `stale-if-error`")
|
|
||||||
ErrStaleWhileRevalidateDeltaSeconds = errors.New("Failed to parse delta-seconds in `stale-while-revalidate`")
|
|
||||||
)
|
|
||||||
|
|
||||||
func whitespace(b byte) bool {
|
|
||||||
if b == '\t' || b == ' ' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse(value string, cd cacheDirective) error {
|
|
||||||
var err error = nil
|
|
||||||
i := 0
|
|
||||||
|
|
||||||
for i < len(value) && err == nil {
|
|
||||||
// eat leading whitespace or commas
|
|
||||||
if whitespace(value[i]) || value[i] == ',' {
|
|
||||||
i++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
j := i + 1
|
|
||||||
|
|
||||||
for j < len(value) {
|
|
||||||
if !isToken(value[j]) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
|
|
||||||
token := strings.ToLower(value[i:j])
|
|
||||||
tokenHasFields := hasFieldNames(token)
|
|
||||||
/*
|
|
||||||
println("GOT TOKEN:")
|
|
||||||
println(" i -> ", i)
|
|
||||||
println(" j -> ", j)
|
|
||||||
println(" token -> ", token)
|
|
||||||
*/
|
|
||||||
|
|
||||||
if j+1 < len(value) && value[j] == '=' {
|
|
||||||
k := j + 1
|
|
||||||
// minimum size two bytes of "", but we let httpUnquote handle it.
|
|
||||||
if k < len(value) && value[k] == '"' {
|
|
||||||
eaten, result := httpUnquote(value[k:])
|
|
||||||
if eaten == -1 {
|
|
||||||
return ErrQuoteMismatch
|
|
||||||
}
|
|
||||||
i = k + eaten
|
|
||||||
|
|
||||||
err = cd.addPair(token, result)
|
|
||||||
} else {
|
|
||||||
z := k
|
|
||||||
for z < len(value) {
|
|
||||||
if tokenHasFields {
|
|
||||||
if whitespace(value[z]) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if whitespace(value[z]) || value[z] == ',' {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
z++
|
|
||||||
}
|
|
||||||
i = z
|
|
||||||
|
|
||||||
result := value[k:z]
|
|
||||||
if result != "" && result[len(result)-1] == ',' {
|
|
||||||
result = result[:len(result)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cd.addPair(token, result)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if token != "," {
|
|
||||||
err = cd.addToken(token)
|
|
||||||
}
|
|
||||||
i = j
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeltaSeconds specifies a non-negative integer, representing
|
|
||||||
// time in seconds: http://tools.ietf.org/html/rfc7234#section-1.2.1
|
|
||||||
//
|
|
||||||
// When set to -1, this means unset.
|
|
||||||
//
|
|
||||||
type DeltaSeconds int32
|
|
||||||
|
|
||||||
// Parser for delta-seconds, a uint31, more or less:
|
|
||||||
// http://tools.ietf.org/html/rfc7234#section-1.2.1
|
|
||||||
func parseDeltaSeconds(v string) (DeltaSeconds, error) {
|
|
||||||
n, err := strconv.ParseUint(v, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
if numError, ok := err.(*strconv.NumError); ok {
|
|
||||||
if numError.Err == strconv.ErrRange {
|
|
||||||
return DeltaSeconds(math.MaxInt32), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DeltaSeconds(-1), err
|
|
||||||
} else {
|
|
||||||
if n > math.MaxInt32 {
|
|
||||||
return DeltaSeconds(math.MaxInt32), nil
|
|
||||||
} else {
|
|
||||||
return DeltaSeconds(n), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields present in a header.
|
|
||||||
type FieldNames map[string]bool
|
|
||||||
|
|
||||||
// internal interface for shared methods of RequestCacheDirectives and ResponseCacheDirectives
|
|
||||||
type cacheDirective interface {
|
|
||||||
addToken(s string) error
|
|
||||||
addPair(s string, v string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOW LEVEL API: Repersentation of possible request directives in a `Cache-Control` header: http://tools.ietf.org/html/rfc7234#section-5.2.1
|
|
||||||
//
|
|
||||||
// Note: Many fields will be `nil` in practice.
|
|
||||||
//
|
|
||||||
type RequestCacheDirectives struct {
|
|
||||||
|
|
||||||
// max-age(delta seconds): http://tools.ietf.org/html/rfc7234#section-5.2.1.1
|
|
||||||
//
|
|
||||||
// The "max-age" request directive indicates that the client is
|
|
||||||
// unwilling to accept a response whose age is greater than the
|
|
||||||
// specified number of seconds. Unless the max-stale request directive
|
|
||||||
// is also present, the client is not willing to accept a stale
|
|
||||||
// response.
|
|
||||||
MaxAge DeltaSeconds
|
|
||||||
|
|
||||||
// max-stale(delta seconds): http://tools.ietf.org/html/rfc7234#section-5.2.1.2
|
|
||||||
//
|
|
||||||
// The "max-stale" request directive indicates that the client is
|
|
||||||
// willing to accept a response that has exceeded its freshness
|
|
||||||
// lifetime. If max-stale is assigned a value, then the client is
|
|
||||||
// willing to accept a response that has exceeded its freshness lifetime
|
|
||||||
// by no more than the specified number of seconds. If no value is
|
|
||||||
// assigned to max-stale, then the client is willing to accept a stale
|
|
||||||
// response of any age.
|
|
||||||
MaxStale DeltaSeconds
|
|
||||||
|
|
||||||
// min-fresh(delta seconds): http://tools.ietf.org/html/rfc7234#section-5.2.1.3
|
|
||||||
//
|
|
||||||
// The "min-fresh" request directive indicates that the client is
|
|
||||||
// willing to accept a response whose freshness lifetime is no less than
|
|
||||||
// its current age plus the specified time in seconds. That is, the
|
|
||||||
// client wants a response that will still be fresh for at least the
|
|
||||||
// specified number of seconds.
|
|
||||||
MinFresh DeltaSeconds
|
|
||||||
|
|
||||||
// no-cache(bool): http://tools.ietf.org/html/rfc7234#section-5.2.1.4
|
|
||||||
//
|
|
||||||
// The "no-cache" request directive indicates that a cache MUST NOT use
|
|
||||||
// a stored response to satisfy the request without successful
|
|
||||||
// validation on the origin server.
|
|
||||||
NoCache bool
|
|
||||||
|
|
||||||
// no-store(bool): http://tools.ietf.org/html/rfc7234#section-5.2.1.5
|
|
||||||
//
|
|
||||||
// The "no-store" request directive indicates that a cache MUST NOT
|
|
||||||
// store any part of either this request or any response to it. This
|
|
||||||
// directive applies to both private and shared caches.
|
|
||||||
NoStore bool
|
|
||||||
|
|
||||||
// no-transform(bool): http://tools.ietf.org/html/rfc7234#section-5.2.1.6
|
|
||||||
//
|
|
||||||
// The "no-transform" request directive indicates that an intermediary
|
|
||||||
// (whether or not it implements a cache) MUST NOT transform the
|
|
||||||
// payload, as defined in Section 5.7.2 of RFC7230.
|
|
||||||
NoTransform bool
|
|
||||||
|
|
||||||
// only-if-cached(bool): http://tools.ietf.org/html/rfc7234#section-5.2.1.7
|
|
||||||
//
|
|
||||||
// The "only-if-cached" request directive indicates that the client only
|
|
||||||
// wishes to obtain a stored response.
|
|
||||||
OnlyIfCached bool
|
|
||||||
|
|
||||||
// Extensions: http://tools.ietf.org/html/rfc7234#section-5.2.3
|
|
||||||
//
|
|
||||||
// The Cache-Control header field can be extended through the use of one
|
|
||||||
// or more cache-extension tokens, each with an optional value. A cache
|
|
||||||
// MUST ignore unrecognized cache directives.
|
|
||||||
Extensions []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cd *RequestCacheDirectives) addToken(token string) error {
|
|
||||||
var err error = nil
|
|
||||||
|
|
||||||
switch token {
|
|
||||||
case "max-age":
|
|
||||||
err = ErrMaxAgeDeltaSeconds
|
|
||||||
case "max-stale":
|
|
||||||
err = ErrMaxStaleDeltaSeconds
|
|
||||||
case "min-fresh":
|
|
||||||
err = ErrMinFreshDeltaSeconds
|
|
||||||
case "no-cache":
|
|
||||||
cd.NoCache = true
|
|
||||||
case "no-store":
|
|
||||||
cd.NoStore = true
|
|
||||||
case "no-transform":
|
|
||||||
cd.NoTransform = true
|
|
||||||
case "only-if-cached":
|
|
||||||
cd.OnlyIfCached = true
|
|
||||||
default:
|
|
||||||
cd.Extensions = append(cd.Extensions, token)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cd *RequestCacheDirectives) addPair(token string, v string) error {
|
|
||||||
var err error = nil
|
|
||||||
|
|
||||||
switch token {
|
|
||||||
case "max-age":
|
|
||||||
cd.MaxAge, err = parseDeltaSeconds(v)
|
|
||||||
if err != nil {
|
|
||||||
err = ErrMaxAgeDeltaSeconds
|
|
||||||
}
|
|
||||||
case "max-stale":
|
|
||||||
cd.MaxStale, err = parseDeltaSeconds(v)
|
|
||||||
if err != nil {
|
|
||||||
err = ErrMaxStaleDeltaSeconds
|
|
||||||
}
|
|
||||||
case "min-fresh":
|
|
||||||
cd.MinFresh, err = parseDeltaSeconds(v)
|
|
||||||
if err != nil {
|
|
||||||
err = ErrMinFreshDeltaSeconds
|
|
||||||
}
|
|
||||||
case "no-cache":
|
|
||||||
err = ErrNoCacheNoArgs
|
|
||||||
case "no-store":
|
|
||||||
err = ErrNoStoreNoArgs
|
|
||||||
case "no-transform":
|
|
||||||
err = ErrNoTransformNoArgs
|
|
||||||
case "only-if-cached":
|
|
||||||
err = ErrOnlyIfCachedNoArgs
|
|
||||||
default:
|
|
||||||
// TODO(pquerna): this sucks, making user re-parse
|
|
||||||
cd.Extensions = append(cd.Extensions, token+"="+v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOW LEVEL API: Parses a Cache Control Header from a Request into a set of directives.
|
|
||||||
func ParseRequestCacheControl(value string) (*RequestCacheDirectives, error) {
|
|
||||||
cd := &RequestCacheDirectives{
|
|
||||||
MaxAge: -1,
|
|
||||||
MaxStale: -1,
|
|
||||||
MinFresh: -1,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := parse(value, cd)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return cd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOW LEVEL API: Repersentation of possible response directives in a `Cache-Control` header: http://tools.ietf.org/html/rfc7234#section-5.2.2
|
|
||||||
//
|
|
||||||
// Note: Many fields will be `nil` in practice.
|
|
||||||
//
|
|
||||||
type ResponseCacheDirectives struct {
|
|
||||||
|
|
||||||
// must-revalidate(bool): http://tools.ietf.org/html/rfc7234#section-5.2.2.1
|
|
||||||
//
|
|
||||||
// The "must-revalidate" response directive indicates that once it has
|
|
||||||
// become stale, a cache MUST NOT use the response to satisfy subsequent
|
|
||||||
// requests without successful validation on the origin server.
|
|
||||||
MustRevalidate bool
|
|
||||||
|
|
||||||
// no-cache(FieldName): http://tools.ietf.org/html/rfc7234#section-5.2.2.2
|
|
||||||
//
|
|
||||||
// The "no-cache" response directive indicates that the response MUST
|
|
||||||
// NOT be used to satisfy a subsequent request without successful
|
|
||||||
// validation on the origin server.
|
|
||||||
//
|
|
||||||
// If the no-cache response directive specifies one or more field-names,
|
|
||||||
// then a cache MAY use the response to satisfy a subsequent request,
|
|
||||||
// subject to any other restrictions on caching. However, any header
|
|
||||||
// fields in the response that have the field-name(s) listed MUST NOT be
|
|
||||||
// sent in the response to a subsequent request without successful
|
|
||||||
// revalidation with the origin server.
|
|
||||||
NoCache FieldNames
|
|
||||||
|
|
||||||
// no-cache(cast-to-bool): http://tools.ietf.org/html/rfc7234#section-5.2.2.2
|
|
||||||
//
|
|
||||||
// While the RFC defines optional field-names on a no-cache directive,
|
|
||||||
// many applications only want to know if any no-cache directives were
|
|
||||||
// present at all.
|
|
||||||
NoCachePresent bool
|
|
||||||
|
|
||||||
// no-store(bool): http://tools.ietf.org/html/rfc7234#section-5.2.2.3
|
|
||||||
//
|
|
||||||
// The "no-store" request directive indicates that a cache MUST NOT
|
|
||||||
// store any part of either this request or any response to it. This
|
|
||||||
// directive applies to both private and shared caches.
|
|
||||||
NoStore bool
|
|
||||||
|
|
||||||
// no-transform(bool): http://tools.ietf.org/html/rfc7234#section-5.2.2.4
|
|
||||||
//
|
|
||||||
// The "no-transform" response directive indicates that an intermediary
|
|
||||||
// (regardless of whether it implements a cache) MUST NOT transform the
|
|
||||||
// payload, as defined in Section 5.7.2 of RFC7230.
|
|
||||||
NoTransform bool
|
|
||||||
|
|
||||||
// public(bool): http://tools.ietf.org/html/rfc7234#section-5.2.2.5
|
|
||||||
//
|
|
||||||
// The "public" response directive indicates that any cache MAY store
|
|
||||||
// the response, even if the response would normally be non-cacheable or
|
|
||||||
// cacheable only within a private cache.
|
|
||||||
Public bool
|
|
||||||
|
|
||||||
// private(FieldName): http://tools.ietf.org/html/rfc7234#section-5.2.2.6
|
|
||||||
//
|
|
||||||
// The "private" response directive indicates that the response message
|
|
||||||
// is intended for a single user and MUST NOT be stored by a shared
|
|
||||||
// cache. A private cache MAY store the response and reuse it for later
|
|
||||||
// requests, even if the response would normally be non-cacheable.
|
|
||||||
//
|
|
||||||
// If the private response directive specifies one or more field-names,
|
|
||||||
// this requirement is limited to the field-values associated with the
|
|
||||||
// listed response header fields. That is, a shared cache MUST NOT
|
|
||||||
// store the specified field-names(s), whereas it MAY store the
|
|
||||||
// remainder of the response message.
|
|
||||||
Private FieldNames
|
|
||||||
|
|
||||||
// private(cast-to-bool): http://tools.ietf.org/html/rfc7234#section-5.2.2.6
|
|
||||||
//
|
|
||||||
// While the RFC defines optional field-names on a private directive,
|
|
||||||
// many applications only want to know if any private directives were
|
|
||||||
// present at all.
|
|
||||||
PrivatePresent bool
|
|
||||||
|
|
||||||
// proxy-revalidate(bool): http://tools.ietf.org/html/rfc7234#section-5.2.2.7
|
|
||||||
//
|
|
||||||
// The "proxy-revalidate" response directive has the same meaning as the
|
|
||||||
// must-revalidate response directive, except that it does not apply to
|
|
||||||
// private caches.
|
|
||||||
ProxyRevalidate bool
|
|
||||||
|
|
||||||
// max-age(delta seconds): http://tools.ietf.org/html/rfc7234#section-5.2.2.8
|
|
||||||
//
|
|
||||||
// The "max-age" response directive indicates that the response is to be
|
|
||||||
// considered stale after its age is greater than the specified number
|
|
||||||
// of seconds.
|
|
||||||
MaxAge DeltaSeconds
|
|
||||||
|
|
||||||
// s-maxage(delta seconds): http://tools.ietf.org/html/rfc7234#section-5.2.2.9
|
|
||||||
//
|
|
||||||
// The "s-maxage" response directive indicates that, in shared caches,
|
|
||||||
// the maximum age specified by this directive overrides the maximum age
|
|
||||||
// specified by either the max-age directive or the Expires header
|
|
||||||
// field. The s-maxage directive also implies the semantics of the
|
|
||||||
// proxy-revalidate response directive.
|
|
||||||
SMaxAge DeltaSeconds
|
|
||||||
|
|
||||||
////
|
|
||||||
// Experimental features
|
|
||||||
// - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Extension_Cache-Control_directives
|
|
||||||
// - https://www.fastly.com/blog/stale-while-revalidate-stale-if-error-available-today
|
|
||||||
////
|
|
||||||
|
|
||||||
// immutable(cast-to-bool): experimental feature
|
|
||||||
Immutable bool
|
|
||||||
|
|
||||||
// stale-if-error(delta seconds): experimental feature
|
|
||||||
StaleIfError DeltaSeconds
|
|
||||||
|
|
||||||
// stale-while-revalidate(delta seconds): experimental feature
|
|
||||||
StaleWhileRevalidate DeltaSeconds
|
|
||||||
|
|
||||||
// Extensions: http://tools.ietf.org/html/rfc7234#section-5.2.3
|
|
||||||
//
|
|
||||||
// The Cache-Control header field can be extended through the use of one
|
|
||||||
// or more cache-extension tokens, each with an optional value. A cache
|
|
||||||
// MUST ignore unrecognized cache directives.
|
|
||||||
Extensions []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOW LEVEL API: Parses a Cache Control Header from a Response into a set of directives.
|
|
||||||
func ParseResponseCacheControl(value string) (*ResponseCacheDirectives, error) {
|
|
||||||
cd := &ResponseCacheDirectives{
|
|
||||||
MaxAge: -1,
|
|
||||||
SMaxAge: -1,
|
|
||||||
// Exerimantal stale timeouts
|
|
||||||
StaleIfError: -1,
|
|
||||||
StaleWhileRevalidate: -1,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := parse(value, cd)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return cd, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cd *ResponseCacheDirectives) addToken(token string) error {
|
|
||||||
var err error = nil
|
|
||||||
switch token {
|
|
||||||
case "must-revalidate":
|
|
||||||
cd.MustRevalidate = true
|
|
||||||
case "no-cache":
|
|
||||||
cd.NoCachePresent = true
|
|
||||||
case "no-store":
|
|
||||||
cd.NoStore = true
|
|
||||||
case "no-transform":
|
|
||||||
cd.NoTransform = true
|
|
||||||
case "public":
|
|
||||||
cd.Public = true
|
|
||||||
case "private":
|
|
||||||
cd.PrivatePresent = true
|
|
||||||
case "proxy-revalidate":
|
|
||||||
cd.ProxyRevalidate = true
|
|
||||||
case "max-age":
|
|
||||||
err = ErrMaxAgeDeltaSeconds
|
|
||||||
case "s-maxage":
|
|
||||||
err = ErrSMaxAgeDeltaSeconds
|
|
||||||
// Experimental
|
|
||||||
case "immutable":
|
|
||||||
cd.Immutable = true
|
|
||||||
case "stale-if-error":
|
|
||||||
err = ErrMaxAgeDeltaSeconds
|
|
||||||
case "stale-while-revalidate":
|
|
||||||
err = ErrMaxAgeDeltaSeconds
|
|
||||||
default:
|
|
||||||
cd.Extensions = append(cd.Extensions, token)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasFieldNames(token string) bool {
|
|
||||||
switch token {
|
|
||||||
case "no-cache":
|
|
||||||
return true
|
|
||||||
case "private":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cd *ResponseCacheDirectives) addPair(token string, v string) error {
|
|
||||||
var err error = nil
|
|
||||||
|
|
||||||
switch token {
|
|
||||||
case "must-revalidate":
|
|
||||||
err = ErrMustRevalidateNoArgs
|
|
||||||
case "no-cache":
|
|
||||||
cd.NoCachePresent = true
|
|
||||||
tokens := strings.Split(v, ",")
|
|
||||||
if cd.NoCache == nil {
|
|
||||||
cd.NoCache = make(FieldNames)
|
|
||||||
}
|
|
||||||
for _, t := range tokens {
|
|
||||||
k := http.CanonicalHeaderKey(textproto.TrimString(t))
|
|
||||||
cd.NoCache[k] = true
|
|
||||||
}
|
|
||||||
case "no-store":
|
|
||||||
err = ErrNoStoreNoArgs
|
|
||||||
case "no-transform":
|
|
||||||
err = ErrNoTransformNoArgs
|
|
||||||
case "public":
|
|
||||||
err = ErrPublicNoArgs
|
|
||||||
case "private":
|
|
||||||
cd.PrivatePresent = true
|
|
||||||
tokens := strings.Split(v, ",")
|
|
||||||
if cd.Private == nil {
|
|
||||||
cd.Private = make(FieldNames)
|
|
||||||
}
|
|
||||||
for _, t := range tokens {
|
|
||||||
k := http.CanonicalHeaderKey(textproto.TrimString(t))
|
|
||||||
cd.Private[k] = true
|
|
||||||
}
|
|
||||||
case "proxy-revalidate":
|
|
||||||
err = ErrProxyRevalidateNoArgs
|
|
||||||
case "max-age":
|
|
||||||
cd.MaxAge, err = parseDeltaSeconds(v)
|
|
||||||
case "s-maxage":
|
|
||||||
cd.SMaxAge, err = parseDeltaSeconds(v)
|
|
||||||
// Experimental
|
|
||||||
case "immutable":
|
|
||||||
err = ErrImmutableNoArgs
|
|
||||||
case "stale-if-error":
|
|
||||||
cd.StaleIfError, err = parseDeltaSeconds(v)
|
|
||||||
case "stale-while-revalidate":
|
|
||||||
cd.StaleWhileRevalidate, err = parseDeltaSeconds(v)
|
|
||||||
default:
|
|
||||||
// TODO(pquerna): this sucks, making user re-parse, and its technically not 'quoted' like the original,
|
|
||||||
// but this is still easier, just a SplitN on "="
|
|
||||||
cd.Extensions = append(cd.Extensions, token+"="+v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
93
vendor/github.com/pquerna/cachecontrol/cacheobject/lex.go
generated
vendored
93
vendor/github.com/pquerna/cachecontrol/cacheobject/lex.go
generated
vendored
@ -1,93 +0,0 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package cacheobject
|
|
||||||
|
|
||||||
// This file deals with lexical matters of HTTP
|
|
||||||
|
|
||||||
func isSeparator(c byte) bool {
|
|
||||||
switch c {
|
|
||||||
case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isCtl(c byte) bool { return (0 <= c && c <= 31) || c == 127 }
|
|
||||||
|
|
||||||
func isChar(c byte) bool { return 0 <= c && c <= 127 }
|
|
||||||
|
|
||||||
func isAnyText(c byte) bool { return !isCtl(c) }
|
|
||||||
|
|
||||||
func isQdText(c byte) bool { return isAnyText(c) && c != '"' }
|
|
||||||
|
|
||||||
func isToken(c byte) bool { return isChar(c) && !isCtl(c) && !isSeparator(c) }
|
|
||||||
|
|
||||||
// Valid escaped sequences are not specified in RFC 2616, so for now, we assume
|
|
||||||
// that they coincide with the common sense ones used by GO. Malformed
|
|
||||||
// characters should probably not be treated as errors by a robust (forgiving)
|
|
||||||
// parser, so we replace them with the '?' character.
|
|
||||||
func httpUnquotePair(b byte) byte {
|
|
||||||
// skip the first byte, which should always be '\'
|
|
||||||
switch b {
|
|
||||||
case 'a':
|
|
||||||
return '\a'
|
|
||||||
case 'b':
|
|
||||||
return '\b'
|
|
||||||
case 'f':
|
|
||||||
return '\f'
|
|
||||||
case 'n':
|
|
||||||
return '\n'
|
|
||||||
case 'r':
|
|
||||||
return '\r'
|
|
||||||
case 't':
|
|
||||||
return '\t'
|
|
||||||
case 'v':
|
|
||||||
return '\v'
|
|
||||||
case '\\':
|
|
||||||
return '\\'
|
|
||||||
case '\'':
|
|
||||||
return '\''
|
|
||||||
case '"':
|
|
||||||
return '"'
|
|
||||||
}
|
|
||||||
return '?'
|
|
||||||
}
|
|
||||||
|
|
||||||
// raw must begin with a valid quoted string. Only the first quoted string is
|
|
||||||
// parsed and is unquoted in result. eaten is the number of bytes parsed, or -1
|
|
||||||
// upon failure.
|
|
||||||
func httpUnquote(raw string) (eaten int, result string) {
|
|
||||||
buf := make([]byte, len(raw))
|
|
||||||
if raw[0] != '"' {
|
|
||||||
return -1, ""
|
|
||||||
}
|
|
||||||
eaten = 1
|
|
||||||
j := 0 // # of bytes written in buf
|
|
||||||
for i := 1; i < len(raw); i++ {
|
|
||||||
switch b := raw[i]; b {
|
|
||||||
case '"':
|
|
||||||
eaten++
|
|
||||||
buf = buf[0:j]
|
|
||||||
return i + 1, string(buf)
|
|
||||||
case '\\':
|
|
||||||
if len(raw) < i+2 {
|
|
||||||
return -1, ""
|
|
||||||
}
|
|
||||||
buf[j] = httpUnquotePair(raw[i+1])
|
|
||||||
eaten += 2
|
|
||||||
j++
|
|
||||||
i++
|
|
||||||
default:
|
|
||||||
if isQdText(b) {
|
|
||||||
buf[j] = b
|
|
||||||
} else {
|
|
||||||
buf[j] = '?'
|
|
||||||
}
|
|
||||||
eaten++
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1, ""
|
|
||||||
}
|
|
387
vendor/github.com/pquerna/cachecontrol/cacheobject/object.go
generated
vendored
387
vendor/github.com/pquerna/cachecontrol/cacheobject/object.go
generated
vendored
@ -1,387 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2015 Paul Querna
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cacheobject
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LOW LEVEL API: Repersents a potentially cachable HTTP object.
|
|
||||||
//
|
|
||||||
// This struct is designed to be serialized efficiently, so in a high
|
|
||||||
// performance caching server, things like Date-Strings don't need to be
|
|
||||||
// parsed for every use of a cached object.
|
|
||||||
type Object struct {
|
|
||||||
CacheIsPrivate bool
|
|
||||||
|
|
||||||
RespDirectives *ResponseCacheDirectives
|
|
||||||
RespHeaders http.Header
|
|
||||||
RespStatusCode int
|
|
||||||
RespExpiresHeader time.Time
|
|
||||||
RespDateHeader time.Time
|
|
||||||
RespLastModifiedHeader time.Time
|
|
||||||
|
|
||||||
ReqDirectives *RequestCacheDirectives
|
|
||||||
ReqHeaders http.Header
|
|
||||||
ReqMethod string
|
|
||||||
|
|
||||||
NowUTC time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOW LEVEL API: Repersents the results of examinig an Object with
|
|
||||||
// CachableObject and ExpirationObject.
|
|
||||||
//
|
|
||||||
// TODO(pquerna): decide if this is a good idea or bad
|
|
||||||
type ObjectResults struct {
|
|
||||||
OutReasons []Reason
|
|
||||||
OutWarnings []Warning
|
|
||||||
OutExpirationTime time.Time
|
|
||||||
OutErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOW LEVEL API: Check if a object is cachable.
|
|
||||||
func CachableObject(obj *Object, rv *ObjectResults) {
|
|
||||||
rv.OutReasons = nil
|
|
||||||
rv.OutWarnings = nil
|
|
||||||
rv.OutErr = nil
|
|
||||||
|
|
||||||
switch obj.ReqMethod {
|
|
||||||
case "GET":
|
|
||||||
break
|
|
||||||
case "HEAD":
|
|
||||||
break
|
|
||||||
case "POST":
|
|
||||||
/**
|
|
||||||
POST: http://tools.ietf.org/html/rfc7231#section-4.3.3
|
|
||||||
|
|
||||||
Responses to POST requests are only cacheable when they include
|
|
||||||
explicit freshness information (see Section 4.2.1 of [RFC7234]).
|
|
||||||
However, POST caching is not widely implemented. For cases where an
|
|
||||||
origin server wishes the client to be able to cache the result of a
|
|
||||||
POST in a way that can be reused by a later GET, the origin server
|
|
||||||
MAY send a 200 (OK) response containing the result and a
|
|
||||||
Content-Location header field that has the same value as the POST's
|
|
||||||
effective request URI (Section 3.1.4.2).
|
|
||||||
*/
|
|
||||||
if !hasFreshness(obj.ReqDirectives, obj.RespDirectives, obj.RespHeaders, obj.RespExpiresHeader, obj.CacheIsPrivate) {
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestMethodPOST)
|
|
||||||
}
|
|
||||||
|
|
||||||
case "PUT":
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestMethodPUT)
|
|
||||||
|
|
||||||
case "DELETE":
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestMethodDELETE)
|
|
||||||
|
|
||||||
case "CONNECT":
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestMethodCONNECT)
|
|
||||||
|
|
||||||
case "OPTIONS":
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestMethodOPTIONS)
|
|
||||||
|
|
||||||
case "TRACE":
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestMethodTRACE)
|
|
||||||
|
|
||||||
// HTTP Extension Methods: http://www.iana.org/assignments/http-methods/http-methods.xhtml
|
|
||||||
//
|
|
||||||
// To my knowledge, none of them are cachable. Please open a ticket if this is not the case!
|
|
||||||
//
|
|
||||||
default:
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestMethodUnkown)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj.ReqDirectives.NoStore {
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestNoStore)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Storing Responses to Authenticated Requests: http://tools.ietf.org/html/rfc7234#section-3.2
|
|
||||||
authz := obj.ReqHeaders.Get("Authorization")
|
|
||||||
if authz != "" {
|
|
||||||
if obj.RespDirectives.MustRevalidate ||
|
|
||||||
obj.RespDirectives.Public ||
|
|
||||||
obj.RespDirectives.SMaxAge != -1 {
|
|
||||||
// Expires of some kind present, this is potentially OK.
|
|
||||||
} else {
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonRequestAuthorizationHeader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj.RespDirectives.PrivatePresent && !obj.CacheIsPrivate {
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonResponsePrivate)
|
|
||||||
}
|
|
||||||
|
|
||||||
if obj.RespDirectives.NoStore {
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonResponseNoStore)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
the response either:
|
|
||||||
|
|
||||||
* contains an Expires header field (see Section 5.3), or
|
|
||||||
|
|
||||||
* contains a max-age response directive (see Section 5.2.2.8), or
|
|
||||||
|
|
||||||
* contains a s-maxage response directive (see Section 5.2.2.9)
|
|
||||||
and the cache is shared, or
|
|
||||||
|
|
||||||
* contains a Cache Control Extension (see Section 5.2.3) that
|
|
||||||
allows it to be cached, or
|
|
||||||
|
|
||||||
* has a status code that is defined as cacheable by default (see
|
|
||||||
Section 4.2.2), or
|
|
||||||
|
|
||||||
* contains a public response directive (see Section 5.2.2.5).
|
|
||||||
*/
|
|
||||||
|
|
||||||
expires := obj.RespHeaders.Get("Expires") != ""
|
|
||||||
statusCachable := cachableStatusCode(obj.RespStatusCode)
|
|
||||||
|
|
||||||
if expires ||
|
|
||||||
obj.RespDirectives.MaxAge != -1 ||
|
|
||||||
(obj.RespDirectives.SMaxAge != -1 && !obj.CacheIsPrivate) ||
|
|
||||||
statusCachable ||
|
|
||||||
obj.RespDirectives.Public {
|
|
||||||
/* cachable by default, at least one of the above conditions was true */
|
|
||||||
} else {
|
|
||||||
rv.OutReasons = append(rv.OutReasons, ReasonResponseUncachableByDefault)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var twentyFourHours = time.Duration(24 * time.Hour)
|
|
||||||
|
|
||||||
const debug = false
|
|
||||||
|
|
||||||
// LOW LEVEL API: Update an objects expiration time.
|
|
||||||
func ExpirationObject(obj *Object, rv *ObjectResults) {
|
|
||||||
/**
|
|
||||||
* Okay, lets calculate Freshness/Expiration now. woo:
|
|
||||||
* http://tools.ietf.org/html/rfc7234#section-4.2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
o If the cache is shared and the s-maxage response directive
|
|
||||||
(Section 5.2.2.9) is present, use its value, or
|
|
||||||
|
|
||||||
o If the max-age response directive (Section 5.2.2.8) is present,
|
|
||||||
use its value, or
|
|
||||||
|
|
||||||
o If the Expires response header field (Section 5.3) is present, use
|
|
||||||
its value minus the value of the Date response header field, or
|
|
||||||
|
|
||||||
o Otherwise, no explicit expiration time is present in the response.
|
|
||||||
A heuristic freshness lifetime might be applicable; see
|
|
||||||
Section 4.2.2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var expiresTime time.Time
|
|
||||||
|
|
||||||
if obj.RespDirectives.SMaxAge != -1 && !obj.CacheIsPrivate {
|
|
||||||
expiresTime = obj.NowUTC.Add(time.Second * time.Duration(obj.RespDirectives.SMaxAge))
|
|
||||||
} else if obj.RespDirectives.MaxAge != -1 {
|
|
||||||
expiresTime = obj.NowUTC.UTC().Add(time.Second * time.Duration(obj.RespDirectives.MaxAge))
|
|
||||||
} else if !obj.RespExpiresHeader.IsZero() {
|
|
||||||
serverDate := obj.RespDateHeader
|
|
||||||
if serverDate.IsZero() {
|
|
||||||
// common enough case when a Date: header has not yet been added to an
|
|
||||||
// active response.
|
|
||||||
serverDate = obj.NowUTC
|
|
||||||
}
|
|
||||||
expiresTime = obj.NowUTC.Add(obj.RespExpiresHeader.Sub(serverDate))
|
|
||||||
} else if !obj.RespLastModifiedHeader.IsZero() {
|
|
||||||
// heuristic freshness lifetime
|
|
||||||
rv.OutWarnings = append(rv.OutWarnings, WarningHeuristicExpiration)
|
|
||||||
|
|
||||||
// http://httpd.apache.org/docs/2.4/mod/mod_cache.html#cachelastmodifiedfactor
|
|
||||||
// CacheMaxExpire defaults to 24 hours
|
|
||||||
// CacheLastModifiedFactor: is 0.1
|
|
||||||
//
|
|
||||||
// expiry-period = MIN(time-since-last-modified-date * factor, 24 hours)
|
|
||||||
//
|
|
||||||
// obj.NowUTC
|
|
||||||
|
|
||||||
since := obj.RespLastModifiedHeader.Sub(obj.NowUTC)
|
|
||||||
since = time.Duration(float64(since) * -0.1)
|
|
||||||
|
|
||||||
if since > twentyFourHours {
|
|
||||||
expiresTime = obj.NowUTC.Add(twentyFourHours)
|
|
||||||
} else {
|
|
||||||
expiresTime = obj.NowUTC.Add(since)
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
println("Now UTC: ", obj.NowUTC.String())
|
|
||||||
println("Last-Modified: ", obj.RespLastModifiedHeader.String())
|
|
||||||
println("Since: ", since.String())
|
|
||||||
println("TwentyFourHours: ", twentyFourHours.String())
|
|
||||||
println("Expiration: ", expiresTime.String())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO(pquerna): what should the default behavoir be for expiration time?
|
|
||||||
}
|
|
||||||
|
|
||||||
rv.OutExpirationTime = expiresTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluate cachability based on an HTTP request, and parts of the response.
|
|
||||||
func UsingRequestResponse(req *http.Request,
|
|
||||||
statusCode int,
|
|
||||||
respHeaders http.Header,
|
|
||||||
privateCache bool) ([]Reason, time.Time, error) {
|
|
||||||
reasons, time, _, _, err := UsingRequestResponseWithObject(req, statusCode, respHeaders, privateCache)
|
|
||||||
return reasons, time, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluate cachability based on an HTTP request, and parts of the response.
|
|
||||||
// Returns the parsed Object as well.
|
|
||||||
func UsingRequestResponseWithObject(req *http.Request,
|
|
||||||
statusCode int,
|
|
||||||
respHeaders http.Header,
|
|
||||||
privateCache bool) ([]Reason, time.Time, []Warning, *Object, error) {
|
|
||||||
var reqHeaders http.Header
|
|
||||||
var reqMethod string
|
|
||||||
|
|
||||||
var reqDir *RequestCacheDirectives = nil
|
|
||||||
respDir, err := ParseResponseCacheControl(respHeaders.Get("Cache-Control"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if req != nil {
|
|
||||||
reqDir, err = ParseRequestCacheControl(req.Header.Get("Cache-Control"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, nil, nil, err
|
|
||||||
}
|
|
||||||
reqHeaders = req.Header
|
|
||||||
reqMethod = req.Method
|
|
||||||
}
|
|
||||||
|
|
||||||
var expiresHeader time.Time
|
|
||||||
var dateHeader time.Time
|
|
||||||
var lastModifiedHeader time.Time
|
|
||||||
|
|
||||||
if respHeaders.Get("Expires") != "" {
|
|
||||||
expiresHeader, err = http.ParseTime(respHeaders.Get("Expires"))
|
|
||||||
if err != nil {
|
|
||||||
// sometimes servers will return `Expires: 0` or `Expires: -1` to
|
|
||||||
// indicate expired content
|
|
||||||
expiresHeader = time.Time{}
|
|
||||||
}
|
|
||||||
expiresHeader = expiresHeader.UTC()
|
|
||||||
}
|
|
||||||
|
|
||||||
if respHeaders.Get("Date") != "" {
|
|
||||||
dateHeader, err = http.ParseTime(respHeaders.Get("Date"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, nil, nil, err
|
|
||||||
}
|
|
||||||
dateHeader = dateHeader.UTC()
|
|
||||||
}
|
|
||||||
|
|
||||||
if respHeaders.Get("Last-Modified") != "" {
|
|
||||||
lastModifiedHeader, err = http.ParseTime(respHeaders.Get("Last-Modified"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, time.Time{}, nil, nil, err
|
|
||||||
}
|
|
||||||
lastModifiedHeader = lastModifiedHeader.UTC()
|
|
||||||
}
|
|
||||||
|
|
||||||
obj := Object{
|
|
||||||
CacheIsPrivate: privateCache,
|
|
||||||
|
|
||||||
RespDirectives: respDir,
|
|
||||||
RespHeaders: respHeaders,
|
|
||||||
RespStatusCode: statusCode,
|
|
||||||
RespExpiresHeader: expiresHeader,
|
|
||||||
RespDateHeader: dateHeader,
|
|
||||||
RespLastModifiedHeader: lastModifiedHeader,
|
|
||||||
|
|
||||||
ReqDirectives: reqDir,
|
|
||||||
ReqHeaders: reqHeaders,
|
|
||||||
ReqMethod: reqMethod,
|
|
||||||
|
|
||||||
NowUTC: time.Now().UTC(),
|
|
||||||
}
|
|
||||||
rv := ObjectResults{}
|
|
||||||
|
|
||||||
CachableObject(&obj, &rv)
|
|
||||||
if rv.OutErr != nil {
|
|
||||||
return nil, time.Time{}, nil, nil, rv.OutErr
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpirationObject(&obj, &rv)
|
|
||||||
if rv.OutErr != nil {
|
|
||||||
return nil, time.Time{}, nil, nil, rv.OutErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv.OutReasons, rv.OutExpirationTime, rv.OutWarnings, &obj, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate if a freshness directive is present: http://tools.ietf.org/html/rfc7234#section-4.2.1
|
|
||||||
func hasFreshness(reqDir *RequestCacheDirectives, respDir *ResponseCacheDirectives, respHeaders http.Header, respExpires time.Time, privateCache bool) bool {
|
|
||||||
if !privateCache && respDir.SMaxAge != -1 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if respDir.MaxAge != -1 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !respExpires.IsZero() || respHeaders.Get("Expires") != "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func cachableStatusCode(statusCode int) bool {
|
|
||||||
/*
|
|
||||||
Responses with status codes that are defined as cacheable by default
|
|
||||||
(e.g., 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 in
|
|
||||||
this specification) can be reused by a cache with heuristic
|
|
||||||
expiration unless otherwise indicated by the method definition or
|
|
||||||
explicit cache controls [RFC7234]; all other status codes are not
|
|
||||||
cacheable by default.
|
|
||||||
*/
|
|
||||||
switch statusCode {
|
|
||||||
case 200:
|
|
||||||
return true
|
|
||||||
case 203:
|
|
||||||
return true
|
|
||||||
case 204:
|
|
||||||
return true
|
|
||||||
case 206:
|
|
||||||
return true
|
|
||||||
case 300:
|
|
||||||
return true
|
|
||||||
case 301:
|
|
||||||
return true
|
|
||||||
case 404:
|
|
||||||
return true
|
|
||||||
case 405:
|
|
||||||
return true
|
|
||||||
case 410:
|
|
||||||
return true
|
|
||||||
case 414:
|
|
||||||
return true
|
|
||||||
case 501:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
95
vendor/github.com/pquerna/cachecontrol/cacheobject/reasons.go
generated
vendored
95
vendor/github.com/pquerna/cachecontrol/cacheobject/reasons.go
generated
vendored
@ -1,95 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2015 Paul Querna
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cacheobject
|
|
||||||
|
|
||||||
// Repersents a potential Reason to not cache an object.
|
|
||||||
//
|
|
||||||
// Applications may wish to ignore specific reasons, which will make them non-RFC
|
|
||||||
// compliant, but this type gives them specific cases they can choose to ignore,
|
|
||||||
// making them compliant in as many cases as they can.
|
|
||||||
type Reason int
|
|
||||||
|
|
||||||
const (
|
|
||||||
|
|
||||||
// The request method was POST and an Expiration header was not supplied.
|
|
||||||
ReasonRequestMethodPOST Reason = iota
|
|
||||||
|
|
||||||
// The request method was PUT and PUTs are not cachable.
|
|
||||||
ReasonRequestMethodPUT
|
|
||||||
|
|
||||||
// The request method was DELETE and DELETEs are not cachable.
|
|
||||||
ReasonRequestMethodDELETE
|
|
||||||
|
|
||||||
// The request method was CONNECT and CONNECTs are not cachable.
|
|
||||||
ReasonRequestMethodCONNECT
|
|
||||||
|
|
||||||
// The request method was OPTIONS and OPTIONS are not cachable.
|
|
||||||
ReasonRequestMethodOPTIONS
|
|
||||||
|
|
||||||
// The request method was TRACE and TRACEs are not cachable.
|
|
||||||
ReasonRequestMethodTRACE
|
|
||||||
|
|
||||||
// The request method was not recognized by cachecontrol, and should not be cached.
|
|
||||||
ReasonRequestMethodUnkown
|
|
||||||
|
|
||||||
// The request included an Cache-Control: no-store header
|
|
||||||
ReasonRequestNoStore
|
|
||||||
|
|
||||||
// The request included an Authorization header without an explicit Public or Expiration time: http://tools.ietf.org/html/rfc7234#section-3.2
|
|
||||||
ReasonRequestAuthorizationHeader
|
|
||||||
|
|
||||||
// The response included an Cache-Control: no-store header
|
|
||||||
ReasonResponseNoStore
|
|
||||||
|
|
||||||
// The response included an Cache-Control: private header and this is not a Private cache
|
|
||||||
ReasonResponsePrivate
|
|
||||||
|
|
||||||
// The response failed to meet at least one of the conditions specified in RFC 7234 section 3: http://tools.ietf.org/html/rfc7234#section-3
|
|
||||||
ReasonResponseUncachableByDefault
|
|
||||||
)
|
|
||||||
|
|
||||||
func (r Reason) String() string {
|
|
||||||
switch r {
|
|
||||||
case ReasonRequestMethodPOST:
|
|
||||||
return "ReasonRequestMethodPOST"
|
|
||||||
case ReasonRequestMethodPUT:
|
|
||||||
return "ReasonRequestMethodPUT"
|
|
||||||
case ReasonRequestMethodDELETE:
|
|
||||||
return "ReasonRequestMethodDELETE"
|
|
||||||
case ReasonRequestMethodCONNECT:
|
|
||||||
return "ReasonRequestMethodCONNECT"
|
|
||||||
case ReasonRequestMethodOPTIONS:
|
|
||||||
return "ReasonRequestMethodOPTIONS"
|
|
||||||
case ReasonRequestMethodTRACE:
|
|
||||||
return "ReasonRequestMethodTRACE"
|
|
||||||
case ReasonRequestMethodUnkown:
|
|
||||||
return "ReasonRequestMethodUnkown"
|
|
||||||
case ReasonRequestNoStore:
|
|
||||||
return "ReasonRequestNoStore"
|
|
||||||
case ReasonRequestAuthorizationHeader:
|
|
||||||
return "ReasonRequestAuthorizationHeader"
|
|
||||||
case ReasonResponseNoStore:
|
|
||||||
return "ReasonResponseNoStore"
|
|
||||||
case ReasonResponsePrivate:
|
|
||||||
return "ReasonResponsePrivate"
|
|
||||||
case ReasonResponseUncachableByDefault:
|
|
||||||
return "ReasonResponseUncachableByDefault"
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(r)
|
|
||||||
}
|
|
107
vendor/github.com/pquerna/cachecontrol/cacheobject/warning.go
generated
vendored
107
vendor/github.com/pquerna/cachecontrol/cacheobject/warning.go
generated
vendored
@ -1,107 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2015 Paul Querna
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package cacheobject
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Repersents an HTTP Warning: http://tools.ietf.org/html/rfc7234#section-5.5
|
|
||||||
type Warning int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Response is Stale
|
|
||||||
// A cache SHOULD generate this whenever the sent response is stale.
|
|
||||||
WarningResponseIsStale Warning = 110
|
|
||||||
|
|
||||||
// Revalidation Failed
|
|
||||||
// A cache SHOULD generate this when sending a stale
|
|
||||||
// response because an attempt to validate the response failed, due to an
|
|
||||||
// inability to reach the server.
|
|
||||||
WarningRevalidationFailed Warning = 111
|
|
||||||
|
|
||||||
// Disconnected Operation
|
|
||||||
// A cache SHOULD generate this if it is intentionally disconnected from
|
|
||||||
// the rest of the network for a period of time.
|
|
||||||
WarningDisconnectedOperation Warning = 112
|
|
||||||
|
|
||||||
// Heuristic Expiration
|
|
||||||
//
|
|
||||||
// A cache SHOULD generate this if it heuristically chose a freshness
|
|
||||||
// lifetime greater than 24 hours and the response's age is greater than
|
|
||||||
// 24 hours.
|
|
||||||
WarningHeuristicExpiration Warning = 113
|
|
||||||
|
|
||||||
// Miscellaneous Warning
|
|
||||||
//
|
|
||||||
// The warning text can include arbitrary information to be presented to
|
|
||||||
// a human user or logged. A system receiving this warning MUST NOT
|
|
||||||
// take any automated action, besides presenting the warning to the
|
|
||||||
// user.
|
|
||||||
WarningMiscellaneousWarning Warning = 199
|
|
||||||
|
|
||||||
// Transformation Applied
|
|
||||||
//
|
|
||||||
// This Warning code MUST be added by a proxy if it applies any
|
|
||||||
// transformation to the representation, such as changing the
|
|
||||||
// content-coding, media-type, or modifying the representation data,
|
|
||||||
// unless this Warning code already appears in the response.
|
|
||||||
WarningTransformationApplied Warning = 214
|
|
||||||
|
|
||||||
// Miscellaneous Persistent Warning
|
|
||||||
//
|
|
||||||
// The warning text can include arbitrary information to be presented to
|
|
||||||
// a human user or logged. A system receiving this warning MUST NOT
|
|
||||||
// take any automated action.
|
|
||||||
WarningMiscellaneousPersistentWarning Warning = 299
|
|
||||||
)
|
|
||||||
|
|
||||||
func (w Warning) HeaderString(agent string, date time.Time) string {
|
|
||||||
if agent == "" {
|
|
||||||
agent = "-"
|
|
||||||
} else {
|
|
||||||
// TODO(pquerna): this doesn't escape agent if it contains bad things.
|
|
||||||
agent = `"` + agent + `"`
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(`%d %s "%s" %s`, w, agent, w.String(), date.Format(http.TimeFormat))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w Warning) String() string {
|
|
||||||
switch w {
|
|
||||||
case WarningResponseIsStale:
|
|
||||||
return "Response is Stale"
|
|
||||||
case WarningRevalidationFailed:
|
|
||||||
return "Revalidation Failed"
|
|
||||||
case WarningDisconnectedOperation:
|
|
||||||
return "Disconnected Operation"
|
|
||||||
case WarningHeuristicExpiration:
|
|
||||||
return "Heuristic Expiration"
|
|
||||||
case WarningMiscellaneousWarning:
|
|
||||||
// TODO(pquerna): ideally had a better way to override this one code.
|
|
||||||
return "Miscellaneous Warning"
|
|
||||||
case WarningTransformationApplied:
|
|
||||||
return "Transformation Applied"
|
|
||||||
case WarningMiscellaneousPersistentWarning:
|
|
||||||
// TODO(pquerna): same as WarningMiscellaneousWarning
|
|
||||||
return "Miscellaneous Persistent Warning"
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(w)
|
|
||||||
}
|
|
25
vendor/github.com/pquerna/cachecontrol/doc.go
generated
vendored
25
vendor/github.com/pquerna/cachecontrol/doc.go
generated
vendored
@ -1,25 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2015 Paul Querna
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package cachecontrol implements the logic for HTTP Caching
|
|
||||||
//
|
|
||||||
// Deciding if an HTTP Response can be cached is often harder
|
|
||||||
// and more bug prone than an actual cache storage backend.
|
|
||||||
// cachecontrol provides a simple interface to determine if
|
|
||||||
// request and response pairs are cachable as defined under
|
|
||||||
// RFC 7234 http://tools.ietf.org/html/rfc7234
|
|
||||||
package cachecontrol
|
|
217
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
217
vendor/golang.org/x/crypto/ed25519/ed25519.go
generated
vendored
@ -1,217 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package ed25519 implements the Ed25519 signature algorithm. See
|
|
||||||
// https://ed25519.cr.yp.to/.
|
|
||||||
//
|
|
||||||
// These functions are also compatible with the “Ed25519” function defined in
|
|
||||||
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
|
|
||||||
// representation includes a public key suffix to make multiple signing
|
|
||||||
// operations with the same key more efficient. This package refers to the RFC
|
|
||||||
// 8032 private key as the “seed”.
|
|
||||||
package ed25519
|
|
||||||
|
|
||||||
// This code is a port of the public domain, “ref10” implementation of ed25519
|
|
||||||
// from SUPERCOP.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto"
|
|
||||||
cryptorand "crypto/rand"
|
|
||||||
"crypto/sha512"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ed25519/internal/edwards25519"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// PublicKeySize is the size, in bytes, of public keys as used in this package.
|
|
||||||
PublicKeySize = 32
|
|
||||||
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
|
|
||||||
PrivateKeySize = 64
|
|
||||||
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
|
|
||||||
SignatureSize = 64
|
|
||||||
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
|
|
||||||
SeedSize = 32
|
|
||||||
)
|
|
||||||
|
|
||||||
// PublicKey is the type of Ed25519 public keys.
|
|
||||||
type PublicKey []byte
|
|
||||||
|
|
||||||
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
|
|
||||||
type PrivateKey []byte
|
|
||||||
|
|
||||||
// Public returns the PublicKey corresponding to priv.
|
|
||||||
func (priv PrivateKey) Public() crypto.PublicKey {
|
|
||||||
publicKey := make([]byte, PublicKeySize)
|
|
||||||
copy(publicKey, priv[32:])
|
|
||||||
return PublicKey(publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seed returns the private key seed corresponding to priv. It is provided for
|
|
||||||
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
|
|
||||||
// in this package.
|
|
||||||
func (priv PrivateKey) Seed() []byte {
|
|
||||||
seed := make([]byte, SeedSize)
|
|
||||||
copy(seed, priv[:32])
|
|
||||||
return seed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign signs the given message with priv.
|
|
||||||
// Ed25519 performs two passes over messages to be signed and therefore cannot
|
|
||||||
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
|
|
||||||
// indicate the message hasn't been hashed. This can be achieved by passing
|
|
||||||
// crypto.Hash(0) as the value for opts.
|
|
||||||
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
|
||||||
if opts.HashFunc() != crypto.Hash(0) {
|
|
||||||
return nil, errors.New("ed25519: cannot sign hashed message")
|
|
||||||
}
|
|
||||||
|
|
||||||
return Sign(priv, message), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateKey generates a public/private key pair using entropy from rand.
|
|
||||||
// If rand is nil, crypto/rand.Reader will be used.
|
|
||||||
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
|
|
||||||
if rand == nil {
|
|
||||||
rand = cryptorand.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
seed := make([]byte, SeedSize)
|
|
||||||
if _, err := io.ReadFull(rand, seed); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
privateKey := NewKeyFromSeed(seed)
|
|
||||||
publicKey := make([]byte, PublicKeySize)
|
|
||||||
copy(publicKey, privateKey[32:])
|
|
||||||
|
|
||||||
return publicKey, privateKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewKeyFromSeed calculates a private key from a seed. It will panic if
|
|
||||||
// len(seed) is not SeedSize. This function is provided for interoperability
|
|
||||||
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
|
|
||||||
// package.
|
|
||||||
func NewKeyFromSeed(seed []byte) PrivateKey {
|
|
||||||
if l := len(seed); l != SeedSize {
|
|
||||||
panic("ed25519: bad seed length: " + strconv.Itoa(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
digest := sha512.Sum512(seed)
|
|
||||||
digest[0] &= 248
|
|
||||||
digest[31] &= 127
|
|
||||||
digest[31] |= 64
|
|
||||||
|
|
||||||
var A edwards25519.ExtendedGroupElement
|
|
||||||
var hBytes [32]byte
|
|
||||||
copy(hBytes[:], digest[:])
|
|
||||||
edwards25519.GeScalarMultBase(&A, &hBytes)
|
|
||||||
var publicKeyBytes [32]byte
|
|
||||||
A.ToBytes(&publicKeyBytes)
|
|
||||||
|
|
||||||
privateKey := make([]byte, PrivateKeySize)
|
|
||||||
copy(privateKey, seed)
|
|
||||||
copy(privateKey[32:], publicKeyBytes[:])
|
|
||||||
|
|
||||||
return privateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign signs the message with privateKey and returns a signature. It will
|
|
||||||
// panic if len(privateKey) is not PrivateKeySize.
|
|
||||||
func Sign(privateKey PrivateKey, message []byte) []byte {
|
|
||||||
if l := len(privateKey); l != PrivateKeySize {
|
|
||||||
panic("ed25519: bad private key length: " + strconv.Itoa(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
h := sha512.New()
|
|
||||||
h.Write(privateKey[:32])
|
|
||||||
|
|
||||||
var digest1, messageDigest, hramDigest [64]byte
|
|
||||||
var expandedSecretKey [32]byte
|
|
||||||
h.Sum(digest1[:0])
|
|
||||||
copy(expandedSecretKey[:], digest1[:])
|
|
||||||
expandedSecretKey[0] &= 248
|
|
||||||
expandedSecretKey[31] &= 63
|
|
||||||
expandedSecretKey[31] |= 64
|
|
||||||
|
|
||||||
h.Reset()
|
|
||||||
h.Write(digest1[32:])
|
|
||||||
h.Write(message)
|
|
||||||
h.Sum(messageDigest[:0])
|
|
||||||
|
|
||||||
var messageDigestReduced [32]byte
|
|
||||||
edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
|
|
||||||
var R edwards25519.ExtendedGroupElement
|
|
||||||
edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
|
|
||||||
|
|
||||||
var encodedR [32]byte
|
|
||||||
R.ToBytes(&encodedR)
|
|
||||||
|
|
||||||
h.Reset()
|
|
||||||
h.Write(encodedR[:])
|
|
||||||
h.Write(privateKey[32:])
|
|
||||||
h.Write(message)
|
|
||||||
h.Sum(hramDigest[:0])
|
|
||||||
var hramDigestReduced [32]byte
|
|
||||||
edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
|
|
||||||
|
|
||||||
var s [32]byte
|
|
||||||
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
|
|
||||||
|
|
||||||
signature := make([]byte, SignatureSize)
|
|
||||||
copy(signature[:], encodedR[:])
|
|
||||||
copy(signature[32:], s[:])
|
|
||||||
|
|
||||||
return signature
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify reports whether sig is a valid signature of message by publicKey. It
|
|
||||||
// will panic if len(publicKey) is not PublicKeySize.
|
|
||||||
func Verify(publicKey PublicKey, message, sig []byte) bool {
|
|
||||||
if l := len(publicKey); l != PublicKeySize {
|
|
||||||
panic("ed25519: bad public key length: " + strconv.Itoa(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sig) != SignatureSize || sig[63]&224 != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var A edwards25519.ExtendedGroupElement
|
|
||||||
var publicKeyBytes [32]byte
|
|
||||||
copy(publicKeyBytes[:], publicKey)
|
|
||||||
if !A.FromBytes(&publicKeyBytes) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
edwards25519.FeNeg(&A.X, &A.X)
|
|
||||||
edwards25519.FeNeg(&A.T, &A.T)
|
|
||||||
|
|
||||||
h := sha512.New()
|
|
||||||
h.Write(sig[:32])
|
|
||||||
h.Write(publicKey[:])
|
|
||||||
h.Write(message)
|
|
||||||
var digest [64]byte
|
|
||||||
h.Sum(digest[:0])
|
|
||||||
|
|
||||||
var hReduced [32]byte
|
|
||||||
edwards25519.ScReduce(&hReduced, &digest)
|
|
||||||
|
|
||||||
var R edwards25519.ProjectiveGroupElement
|
|
||||||
var s [32]byte
|
|
||||||
copy(s[:], sig[32:])
|
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
|
|
||||||
// the range [0, order) in order to prevent signature malleability.
|
|
||||||
if !edwards25519.ScMinimal(&s) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
|
|
||||||
|
|
||||||
var checkR [32]byte
|
|
||||||
R.ToBytes(&checkR)
|
|
||||||
return bytes.Equal(sig[:32], checkR[:])
|
|
||||||
}
|
|
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
1422
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1793
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
1793
vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
generated
vendored
File diff suppressed because it is too large
Load Diff
71
vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
generated
vendored
71
vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
generated
vendored
@ -1,71 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
|
|
||||||
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Do sends an HTTP request with the provided http.Client and returns
|
|
||||||
// an HTTP response.
|
|
||||||
//
|
|
||||||
// If the client is nil, http.DefaultClient is used.
|
|
||||||
//
|
|
||||||
// The provided ctx must be non-nil. If it is canceled or times out,
|
|
||||||
// ctx.Err() will be returned.
|
|
||||||
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
|
|
||||||
if client == nil {
|
|
||||||
client = http.DefaultClient
|
|
||||||
}
|
|
||||||
resp, err := client.Do(req.WithContext(ctx))
|
|
||||||
// If we got an error, and the context has been canceled,
|
|
||||||
// the context's error is probably more useful.
|
|
||||||
if err != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
err = ctx.Err()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get issues a GET request via the Do function.
|
|
||||||
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Head issues a HEAD request via the Do function.
|
|
||||||
func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("HEAD", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Post issues a POST request via the Do function.
|
|
||||||
func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
|
|
||||||
req, err := http.NewRequest("POST", url, body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", bodyType)
|
|
||||||
return Do(ctx, client, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PostForm issues a POST request via the Do function.
|
|
||||||
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
|
|
||||||
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
|
|
||||||
}
|
|
383
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
383
vendor/golang.org/x/net/internal/iana/gen.go
generated
vendored
@ -1,383 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
|
|
||||||
// This program generates internet protocol constants and tables by
|
|
||||||
// reading IANA protocol registries.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registries = []struct {
|
|
||||||
url string
|
|
||||||
parse func(io.Writer, io.Reader) error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
|
||||||
parseDSCPRegistry,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
|
||||||
parseProtocolNumbers,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml",
|
|
||||||
parseAddrFamilyNumbers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var bb bytes.Buffer
|
|
||||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
|
||||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
|
||||||
fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
|
|
||||||
fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
|
|
||||||
for _, r := range registries {
|
|
||||||
resp, err := http.Get(r.url)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := r.parse(&bb, resp.Body); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&bb, "\n")
|
|
||||||
}
|
|
||||||
b, err := format.Source(bb.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var dr dscpRegistry
|
|
||||||
if err := dec.Decode(&dr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, dr := range dr.escapeDSCP() {
|
|
||||||
fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
|
||||||
}
|
|
||||||
for _, er := range dr.escapeECN() {
|
|
||||||
fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", er.OrigDescr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type dscpRegistry struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
Note string `xml:"note"`
|
|
||||||
Registries []struct {
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Registries []struct {
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Records []struct {
|
|
||||||
Name string `xml:"name"`
|
|
||||||
Space string `xml:"space"`
|
|
||||||
} `xml:"record"`
|
|
||||||
} `xml:"registry"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"record"`
|
|
||||||
} `xml:"registry"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonDSCPRecord struct {
|
|
||||||
OrigName string
|
|
||||||
Name string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord {
|
|
||||||
var drs []canonDSCPRecord
|
|
||||||
for _, preg := range drr.Registries {
|
|
||||||
if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, reg := range preg.Registries {
|
|
||||||
if !strings.Contains(reg.Title, "Pool 1 Codepoints") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
drs = make([]canonDSCPRecord, len(reg.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"+", "",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, dr := range reg.Records {
|
|
||||||
s := strings.TrimSpace(dr.Name)
|
|
||||||
drs[i].OrigName = s
|
|
||||||
drs[i].Name = sr.Replace(s)
|
|
||||||
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
drs[i].Value = int(n) << 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return drs
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonECNRecord struct {
|
|
||||||
OrigDescr string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (drr *dscpRegistry) escapeECN() []canonECNRecord {
|
|
||||||
var ers []canonECNRecord
|
|
||||||
for _, reg := range drr.Registries {
|
|
||||||
if !strings.Contains(reg.Title, "ECN Field") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ers = make([]canonECNRecord, len(reg.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"Capable", "",
|
|
||||||
"Not-ECT", "",
|
|
||||||
"ECT(1)", "",
|
|
||||||
"ECT(0)", "",
|
|
||||||
"CE", "",
|
|
||||||
"(", "",
|
|
||||||
")", "",
|
|
||||||
"+", "",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, er := range reg.Records {
|
|
||||||
s := strings.TrimSpace(er.Descr)
|
|
||||||
ers[i].OrigDescr = s
|
|
||||||
ss := strings.Split(s, " ")
|
|
||||||
if len(ss) > 1 {
|
|
||||||
ers[i].Descr = strings.Join(ss[1:], " ")
|
|
||||||
} else {
|
|
||||||
ers[i].Descr = ss[0]
|
|
||||||
}
|
|
||||||
ers[i].Descr = sr.Replace(er.Descr)
|
|
||||||
n, err := strconv.ParseUint(er.Value, 2, 8)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ers[i].Value = int(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ers
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var pn protocolNumbers
|
|
||||||
if err := dec.Decode(&pn); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
prs := pn.escape()
|
|
||||||
prs = append([]canonProtocolRecord{{
|
|
||||||
Name: "IP",
|
|
||||||
Descr: "IPv4 encapsulation, pseudo protocol number",
|
|
||||||
Value: 0,
|
|
||||||
}}, prs...)
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
|
|
||||||
s := pr.Descr
|
|
||||||
if s == "" {
|
|
||||||
s = pr.OrigName
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "// %s\n", s)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type protocolNumbers struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
RegTitle string `xml:"registry>title"`
|
|
||||||
Note string `xml:"registry>note"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Name string `xml:"name"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"registry>record"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonProtocolRecord struct {
|
|
||||||
OrigName string
|
|
||||||
Name string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
|
||||||
prs := make([]canonProtocolRecord, len(pn.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"-in-", "in",
|
|
||||||
"-within-", "within",
|
|
||||||
"-over-", "over",
|
|
||||||
"+", "P",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, pr := range pn.Records {
|
|
||||||
if strings.Contains(pr.Name, "Deprecated") ||
|
|
||||||
strings.Contains(pr.Name, "deprecated") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
prs[i].OrigName = pr.Name
|
|
||||||
s := strings.TrimSpace(pr.Name)
|
|
||||||
switch pr.Name {
|
|
||||||
case "ISIS over IPv4":
|
|
||||||
prs[i].Name = "ISIS"
|
|
||||||
case "manet":
|
|
||||||
prs[i].Name = "MANET"
|
|
||||||
default:
|
|
||||||
prs[i].Name = sr.Replace(s)
|
|
||||||
}
|
|
||||||
ss := strings.Split(pr.Descr, "\n")
|
|
||||||
for i := range ss {
|
|
||||||
ss[i] = strings.TrimSpace(ss[i])
|
|
||||||
}
|
|
||||||
if len(ss) > 1 {
|
|
||||||
prs[i].Descr = strings.Join(ss, " ")
|
|
||||||
} else {
|
|
||||||
prs[i].Descr = ss[0]
|
|
||||||
}
|
|
||||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
|
||||||
}
|
|
||||||
return prs
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var afn addrFamilylNumbers
|
|
||||||
if err := dec.Decode(&afn); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
afrs := afn.escape()
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, afr := range afrs {
|
|
||||||
if afr.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", afr.Descr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type addrFamilylNumbers struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
RegTitle string `xml:"registry>title"`
|
|
||||||
Note string `xml:"registry>note"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"registry>record"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonAddrFamilyRecord struct {
|
|
||||||
Name string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord {
|
|
||||||
afrs := make([]canonAddrFamilyRecord, len(afn.Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"IP version 4", "IPv4",
|
|
||||||
"IP version 6", "IPv6",
|
|
||||||
"Identifier", "ID",
|
|
||||||
"-", "",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, afr := range afn.Records {
|
|
||||||
if strings.Contains(afr.Descr, "Unassigned") ||
|
|
||||||
strings.Contains(afr.Descr, "Reserved") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
afrs[i].Descr = afr.Descr
|
|
||||||
s := strings.TrimSpace(afr.Descr)
|
|
||||||
switch s {
|
|
||||||
case "IP (IP version 4)":
|
|
||||||
afrs[i].Name = "IPv4"
|
|
||||||
case "IP6 (IP version 6)":
|
|
||||||
afrs[i].Name = "IPv6"
|
|
||||||
case "AFI for L2VPN information":
|
|
||||||
afrs[i].Name = "L2VPN"
|
|
||||||
case "E.164 with NSAP format subaddress":
|
|
||||||
afrs[i].Name = "E164withSubaddress"
|
|
||||||
case "MT IP: Multi-Topology IP version 4":
|
|
||||||
afrs[i].Name = "MTIPv4"
|
|
||||||
case "MAC/24":
|
|
||||||
afrs[i].Name = "MACFinal24bits"
|
|
||||||
case "MAC/40":
|
|
||||||
afrs[i].Name = "MACFinal40bits"
|
|
||||||
case "IPv6/64":
|
|
||||||
afrs[i].Name = "IPv6Initial64bits"
|
|
||||||
default:
|
|
||||||
n := strings.Index(s, "(")
|
|
||||||
if n > 0 {
|
|
||||||
s = s[:n]
|
|
||||||
}
|
|
||||||
n = strings.Index(s, ":")
|
|
||||||
if n > 0 {
|
|
||||||
s = s[:n]
|
|
||||||
}
|
|
||||||
afrs[i].Name = sr.Replace(s)
|
|
||||||
}
|
|
||||||
afrs[i].Value, _ = strconv.Atoi(afr.Value)
|
|
||||||
}
|
|
||||||
return afrs
|
|
||||||
}
|
|
39
vendor/golang.org/x/net/internal/socket/defs_aix.go
generated
vendored
39
vendor/golang.org/x/net/internal/socket/defs_aix.go
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type mmsghdr C.struct_mmsghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
36
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
36
vendor/golang.org/x/net/internal/socket/defs_darwin.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
36
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
36
vendor/golang.org/x/net/internal/socket/defs_dragonfly.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
36
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
36
vendor/golang.org/x/net/internal/socket/defs_freebsd.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
41
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
41
vendor/golang.org/x/net/internal/socket/defs_linux.go
generated
vendored
@ -1,41 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <linux/in.h>
|
|
||||||
#include <linux/in6.h>
|
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <sys/socket.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type mmsghdr C.struct_mmsghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
39
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
39
vendor/golang.org/x/net/internal/socket/defs_netbsd.go
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type mmsghdr C.struct_mmsghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofMmsghdr = C.sizeof_struct_mmsghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
36
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
36
vendor/golang.org/x/net/internal/socket/defs_openbsd.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
36
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
36
vendor/golang.org/x/net/internal/socket/defs_solaris.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
type iovec C.struct_iovec
|
|
||||||
|
|
||||||
type msghdr C.struct_msghdr
|
|
||||||
|
|
||||||
type cmsghdr C.struct_cmsghdr
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
const (
|
|
||||||
sizeofIovec = C.sizeof_struct_iovec
|
|
||||||
sizeofMsghdr = C.sizeof_struct_msghdr
|
|
||||||
sizeofCmsghdr = C.sizeof_struct_cmsghdr
|
|
||||||
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
)
|
|
39
vendor/golang.org/x/net/ipv4/defs_aix.go
generated
vendored
39
vendor/golang.org/x/net/ipv4/defs_aix.go
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
// IP_RECVIF is defined on AIX but doesn't work.
|
|
||||||
// IP_RECVINTERFACE must be used instead.
|
|
||||||
sysIP_RECVIF = C.IP_RECVINTERFACE
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
)
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
77
vendor/golang.org/x/net/ipv4/defs_darwin.go
generated
vendored
77
vendor/golang.org/x/net/ipv4/defs_darwin.go
generated
vendored
@ -1,77 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_STRIPHDR = C.IP_STRIPHDR
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
sysIP_BOUND_IF = C.IP_BOUND_IF
|
|
||||||
sysIP_PKTINFO = C.IP_PKTINFO
|
|
||||||
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
|
||||||
sysIP_MULTICAST_IFINDEX = C.IP_MULTICAST_IFINDEX
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type inetPktinfo C.struct_in_pktinfo
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqn C.struct_ip_mreqn
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
38
vendor/golang.org/x/net/ipv4/defs_dragonfly.go
generated
vendored
38
vendor/golang.org/x/net/ipv4/defs_dragonfly.go
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
)
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
75
vendor/golang.org/x/net/ipv4/defs_freebsd.go
generated
vendored
75
vendor/golang.org/x/net/ipv4/defs_freebsd.go
generated
vendored
@ -1,75 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_SENDSRCADDR = C.IP_SENDSRCADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_ONESBCAST = C.IP_ONESBCAST
|
|
||||||
sysIP_BINDANY = C.IP_BINDANY
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
sysIP_MINTTL = C.IP_MINTTL
|
|
||||||
sysIP_DONTFRAG = C.IP_DONTFRAG
|
|
||||||
sysIP_RECVTOS = C.IP_RECVTOS
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_MULTICAST_VIF = C.IP_MULTICAST_VIF
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqn C.struct_ip_mreqn
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
122
vendor/golang.org/x/net/ipv4/defs_linux.go
generated
vendored
122
vendor/golang.org/x/net/ipv4/defs_linux.go
generated
vendored
@ -1,122 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <linux/errqueue.h>
|
|
||||||
#include <linux/icmp.h>
|
|
||||||
#include <linux/in.h>
|
|
||||||
#include <linux/filter.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_ROUTER_ALERT = C.IP_ROUTER_ALERT
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_PKTINFO = C.IP_PKTINFO
|
|
||||||
sysIP_PKTOPTIONS = C.IP_PKTOPTIONS
|
|
||||||
sysIP_MTU_DISCOVER = C.IP_MTU_DISCOVER
|
|
||||||
sysIP_RECVERR = C.IP_RECVERR
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
sysIP_RECVTOS = C.IP_RECVTOS
|
|
||||||
sysIP_MTU = C.IP_MTU
|
|
||||||
sysIP_FREEBIND = C.IP_FREEBIND
|
|
||||||
sysIP_TRANSPARENT = C.IP_TRANSPARENT
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_ORIGDSTADDR = C.IP_ORIGDSTADDR
|
|
||||||
sysIP_RECVORIGDSTADDR = C.IP_RECVORIGDSTADDR
|
|
||||||
sysIP_MINTTL = C.IP_MINTTL
|
|
||||||
sysIP_NODEFRAG = C.IP_NODEFRAG
|
|
||||||
sysIP_UNICAST_IF = C.IP_UNICAST_IF
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_MSFILTER = C.IP_MSFILTER
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_MSFILTER = C.MCAST_MSFILTER
|
|
||||||
sysIP_MULTICAST_ALL = C.IP_MULTICAST_ALL
|
|
||||||
|
|
||||||
//sysIP_PMTUDISC_DONT = C.IP_PMTUDISC_DONT
|
|
||||||
//sysIP_PMTUDISC_WANT = C.IP_PMTUDISC_WANT
|
|
||||||
//sysIP_PMTUDISC_DO = C.IP_PMTUDISC_DO
|
|
||||||
//sysIP_PMTUDISC_PROBE = C.IP_PMTUDISC_PROBE
|
|
||||||
//sysIP_PMTUDISC_INTERFACE = C.IP_PMTUDISC_INTERFACE
|
|
||||||
//sysIP_PMTUDISC_OMIT = C.IP_PMTUDISC_OMIT
|
|
||||||
|
|
||||||
sysICMP_FILTER = C.ICMP_FILTER
|
|
||||||
|
|
||||||
sysSO_EE_ORIGIN_NONE = C.SO_EE_ORIGIN_NONE
|
|
||||||
sysSO_EE_ORIGIN_LOCAL = C.SO_EE_ORIGIN_LOCAL
|
|
||||||
sysSO_EE_ORIGIN_ICMP = C.SO_EE_ORIGIN_ICMP
|
|
||||||
sysSO_EE_ORIGIN_ICMP6 = C.SO_EE_ORIGIN_ICMP6
|
|
||||||
sysSO_EE_ORIGIN_TXSTATUS = C.SO_EE_ORIGIN_TXSTATUS
|
|
||||||
sysSO_EE_ORIGIN_TIMESTAMPING = C.SO_EE_ORIGIN_TIMESTAMPING
|
|
||||||
|
|
||||||
sysSOL_SOCKET = C.SOL_SOCKET
|
|
||||||
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
|
||||||
|
|
||||||
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
|
||||||
sizeofSockExtendedErr = C.sizeof_struct_sock_extended_err
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqn = C.sizeof_struct_ip_mreqn
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPFilter = C.sizeof_struct_icmp_filter
|
|
||||||
|
|
||||||
sizeofSockFprog = C.sizeof_struct_sock_fprog
|
|
||||||
)
|
|
||||||
|
|
||||||
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type inetPktinfo C.struct_in_pktinfo
|
|
||||||
|
|
||||||
type sockExtendedErr C.struct_sock_extended_err
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqn C.struct_ip_mreqn
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
||||||
|
|
||||||
type icmpFilter C.struct_icmp_filter
|
|
||||||
|
|
||||||
type sockFProg C.struct_sock_fprog
|
|
||||||
|
|
||||||
type sockFilter C.struct_sock_filter
|
|
37
vendor/golang.org/x/net/ipv4/defs_netbsd.go
generated
vendored
37
vendor/golang.org/x/net/ipv4/defs_netbsd.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
)
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
37
vendor/golang.org/x/net/ipv4/defs_openbsd.go
generated
vendored
37
vendor/golang.org/x/net/ipv4/defs_openbsd.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
)
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
84
vendor/golang.org/x/net/ipv4/defs_solaris.go
generated
vendored
84
vendor/golang.org/x/net/ipv4/defs_solaris.go
generated
vendored
@ -1,84 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in_addr [4]byte /* in_addr */
|
|
||||||
|
|
||||||
package ipv4
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIP_OPTIONS = C.IP_OPTIONS
|
|
||||||
sysIP_HDRINCL = C.IP_HDRINCL
|
|
||||||
sysIP_TOS = C.IP_TOS
|
|
||||||
sysIP_TTL = C.IP_TTL
|
|
||||||
sysIP_RECVOPTS = C.IP_RECVOPTS
|
|
||||||
sysIP_RECVRETOPTS = C.IP_RECVRETOPTS
|
|
||||||
sysIP_RECVDSTADDR = C.IP_RECVDSTADDR
|
|
||||||
sysIP_RETOPTS = C.IP_RETOPTS
|
|
||||||
sysIP_RECVIF = C.IP_RECVIF
|
|
||||||
sysIP_RECVSLLA = C.IP_RECVSLLA
|
|
||||||
sysIP_RECVTTL = C.IP_RECVTTL
|
|
||||||
|
|
||||||
sysIP_MULTICAST_IF = C.IP_MULTICAST_IF
|
|
||||||
sysIP_MULTICAST_TTL = C.IP_MULTICAST_TTL
|
|
||||||
sysIP_MULTICAST_LOOP = C.IP_MULTICAST_LOOP
|
|
||||||
sysIP_ADD_MEMBERSHIP = C.IP_ADD_MEMBERSHIP
|
|
||||||
sysIP_DROP_MEMBERSHIP = C.IP_DROP_MEMBERSHIP
|
|
||||||
sysIP_BLOCK_SOURCE = C.IP_BLOCK_SOURCE
|
|
||||||
sysIP_UNBLOCK_SOURCE = C.IP_UNBLOCK_SOURCE
|
|
||||||
sysIP_ADD_SOURCE_MEMBERSHIP = C.IP_ADD_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_DROP_SOURCE_MEMBERSHIP = C.IP_DROP_SOURCE_MEMBERSHIP
|
|
||||||
sysIP_NEXTHOP = C.IP_NEXTHOP
|
|
||||||
|
|
||||||
sysIP_PKTINFO = C.IP_PKTINFO
|
|
||||||
sysIP_RECVPKTINFO = C.IP_RECVPKTINFO
|
|
||||||
sysIP_DONTFRAG = C.IP_DONTFRAG
|
|
||||||
|
|
||||||
sysIP_BOUND_IF = C.IP_BOUND_IF
|
|
||||||
sysIP_UNSPEC_SRC = C.IP_UNSPEC_SRC
|
|
||||||
sysIP_BROADCAST_TTL = C.IP_BROADCAST_TTL
|
|
||||||
sysIP_DHCPINIT_IF = C.IP_DHCPINIT_IF
|
|
||||||
|
|
||||||
sysIP_REUSEADDR = C.IP_REUSEADDR
|
|
||||||
sysIP_DONTROUTE = C.IP_DONTROUTE
|
|
||||||
sysIP_BROADCAST = C.IP_BROADCAST
|
|
||||||
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet = C.sizeof_struct_sockaddr_in
|
|
||||||
sizeofInetPktinfo = C.sizeof_struct_in_pktinfo
|
|
||||||
|
|
||||||
sizeofIPMreq = C.sizeof_struct_ip_mreq
|
|
||||||
sizeofIPMreqSource = C.sizeof_struct_ip_mreq_source
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet C.struct_sockaddr_in
|
|
||||||
|
|
||||||
type inetPktinfo C.struct_in_pktinfo
|
|
||||||
|
|
||||||
type ipMreq C.struct_ip_mreq
|
|
||||||
|
|
||||||
type ipMreqSource C.struct_ip_mreq_source
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
199
vendor/golang.org/x/net/ipv4/gen.go
generated
vendored
199
vendor/golang.org/x/net/ipv4/gen.go
generated
vendored
@ -1,199 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
|
|
||||||
// This program generates system adaptation constants and types,
|
|
||||||
// internet protocol constants and tables by reading template files
|
|
||||||
// and IANA protocol registries.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := genzsys(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := geniana(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func genzsys() error {
|
|
||||||
defs := "defs_" + runtime.GOOS + ".go"
|
|
||||||
f, err := os.Open(defs)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.Close()
|
|
||||||
cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
|
|
||||||
b, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b, err = format.Source(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
zsys := "zsys_" + runtime.GOOS + ".go"
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "freebsd", "linux":
|
|
||||||
zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var registries = []struct {
|
|
||||||
url string
|
|
||||||
parse func(io.Writer, io.Reader) error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
|
|
||||||
parseICMPv4Parameters,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func geniana() error {
|
|
||||||
var bb bytes.Buffer
|
|
||||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
|
||||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
|
||||||
fmt.Fprintf(&bb, "package ipv4\n\n")
|
|
||||||
for _, r := range registries {
|
|
||||||
resp, err := http.Get(r.url)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
|
||||||
}
|
|
||||||
if err := r.parse(&bb, resp.Body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&bb, "\n")
|
|
||||||
}
|
|
||||||
b, err := format.Source(bb.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var icp icmpv4Parameters
|
|
||||||
if err := dec.Decode(&icp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
prs := icp.escape()
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Descr == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n\n")
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
|
||||||
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Descr == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "}\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type icmpv4Parameters struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
Registries []struct {
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Descr string `xml:"description"`
|
|
||||||
} `xml:"record"`
|
|
||||||
} `xml:"registry"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonICMPv4ParamRecord struct {
|
|
||||||
OrigDescr string
|
|
||||||
Descr string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
|
|
||||||
id := -1
|
|
||||||
for i, r := range icp.Registries {
|
|
||||||
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
|
||||||
id = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if id < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"Messages", "",
|
|
||||||
"Message", "",
|
|
||||||
"ICMP", "",
|
|
||||||
"+", "P",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, pr := range icp.Registries[id].Records {
|
|
||||||
if strings.Contains(pr.Descr, "Reserved") ||
|
|
||||||
strings.Contains(pr.Descr, "Unassigned") ||
|
|
||||||
strings.Contains(pr.Descr, "Deprecated") ||
|
|
||||||
strings.Contains(pr.Descr, "Experiment") ||
|
|
||||||
strings.Contains(pr.Descr, "experiment") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ss := strings.Split(pr.Descr, "\n")
|
|
||||||
if len(ss) > 1 {
|
|
||||||
prs[i].Descr = strings.Join(ss, " ")
|
|
||||||
} else {
|
|
||||||
prs[i].Descr = ss[0]
|
|
||||||
}
|
|
||||||
s := strings.TrimSpace(prs[i].Descr)
|
|
||||||
prs[i].OrigDescr = s
|
|
||||||
prs[i].Descr = sr.Replace(s)
|
|
||||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
|
||||||
}
|
|
||||||
return prs
|
|
||||||
}
|
|
82
vendor/golang.org/x/net/ipv6/defs_aix.go
generated
vendored
82
vendor/golang.org/x/net/ipv6/defs_aix.go
generated
vendored
@ -1,82 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
112
vendor/golang.org/x/net/ipv6/defs_darwin.go
generated
vendored
112
vendor/golang.org/x/net/ipv6/defs_darwin.go
generated
vendored
@ -1,112 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define __APPLE_USE_RFC_3542
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
|
||||||
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
|
||||||
sysIPV6_2292NEXTHOP = C.IPV6_2292NEXTHOP
|
|
||||||
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
|
||||||
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
|
||||||
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
|
||||||
|
|
||||||
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
|
||||||
|
|
||||||
sysIPV6_MSFILTER = C.IPV6_MSFILTER
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
|
|
||||||
sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
84
vendor/golang.org/x/net/ipv6/defs_dragonfly.go
generated
vendored
84
vendor/golang.org/x/net/ipv6/defs_dragonfly.go
generated
vendored
@ -1,84 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
105
vendor/golang.org/x/net/ipv6/defs_freebsd.go
generated
vendored
105
vendor/golang.org/x/net/ipv6/defs_freebsd.go
generated
vendored
@ -1,105 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PREFER_TEMPADDR = C.IPV6_PREFER_TEMPADDR
|
|
||||||
|
|
||||||
sysIPV6_BINDANY = C.IPV6_BINDANY
|
|
||||||
|
|
||||||
sysIPV6_MSFILTER = C.IPV6_MSFILTER
|
|
||||||
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
147
vendor/golang.org/x/net/ipv6/defs_linux.go
generated
vendored
147
vendor/golang.org/x/net/ipv6/defs_linux.go
generated
vendored
@ -1,147 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <linux/in.h>
|
|
||||||
#include <linux/in6.h>
|
|
||||||
#include <linux/ipv6.h>
|
|
||||||
#include <linux/icmpv6.h>
|
|
||||||
#include <linux/filter.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_ADDRFORM = C.IPV6_ADDRFORM
|
|
||||||
sysIPV6_2292PKTINFO = C.IPV6_2292PKTINFO
|
|
||||||
sysIPV6_2292HOPOPTS = C.IPV6_2292HOPOPTS
|
|
||||||
sysIPV6_2292DSTOPTS = C.IPV6_2292DSTOPTS
|
|
||||||
sysIPV6_2292RTHDR = C.IPV6_2292RTHDR
|
|
||||||
sysIPV6_2292PKTOPTIONS = C.IPV6_2292PKTOPTIONS
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_2292HOPLIMIT = C.IPV6_2292HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_FLOWINFO = C.IPV6_FLOWINFO
|
|
||||||
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_ADD_MEMBERSHIP = C.IPV6_ADD_MEMBERSHIP
|
|
||||||
sysIPV6_DROP_MEMBERSHIP = C.IPV6_DROP_MEMBERSHIP
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_MSFILTER = C.MCAST_MSFILTER
|
|
||||||
sysIPV6_ROUTER_ALERT = C.IPV6_ROUTER_ALERT
|
|
||||||
sysIPV6_MTU_DISCOVER = C.IPV6_MTU_DISCOVER
|
|
||||||
sysIPV6_MTU = C.IPV6_MTU
|
|
||||||
sysIPV6_RECVERR = C.IPV6_RECVERR
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
sysIPV6_JOIN_ANYCAST = C.IPV6_JOIN_ANYCAST
|
|
||||||
sysIPV6_LEAVE_ANYCAST = C.IPV6_LEAVE_ANYCAST
|
|
||||||
|
|
||||||
//sysIPV6_PMTUDISC_DONT = C.IPV6_PMTUDISC_DONT
|
|
||||||
//sysIPV6_PMTUDISC_WANT = C.IPV6_PMTUDISC_WANT
|
|
||||||
//sysIPV6_PMTUDISC_DO = C.IPV6_PMTUDISC_DO
|
|
||||||
//sysIPV6_PMTUDISC_PROBE = C.IPV6_PMTUDISC_PROBE
|
|
||||||
//sysIPV6_PMTUDISC_INTERFACE = C.IPV6_PMTUDISC_INTERFACE
|
|
||||||
//sysIPV6_PMTUDISC_OMIT = C.IPV6_PMTUDISC_OMIT
|
|
||||||
|
|
||||||
sysIPV6_FLOWLABEL_MGR = C.IPV6_FLOWLABEL_MGR
|
|
||||||
sysIPV6_FLOWINFO_SEND = C.IPV6_FLOWINFO_SEND
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
sysIPV6_XFRM_POLICY = C.IPV6_XFRM_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
|
|
||||||
sysIPV6_ADDR_PREFERENCES = C.IPV6_ADDR_PREFERENCES
|
|
||||||
|
|
||||||
sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
|
|
||||||
sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
|
|
||||||
sysIPV6_PREFER_SRC_PUBTMP_DEFAULT = C.IPV6_PREFER_SRC_PUBTMP_DEFAULT
|
|
||||||
sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
|
|
||||||
sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
|
|
||||||
sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
|
|
||||||
sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
|
|
||||||
|
|
||||||
sysIPV6_MINHOPCOUNT = C.IPV6_MINHOPCOUNT
|
|
||||||
|
|
||||||
sysIPV6_ORIGDSTADDR = C.IPV6_ORIGDSTADDR
|
|
||||||
sysIPV6_RECVORIGDSTADDR = C.IPV6_RECVORIGDSTADDR
|
|
||||||
sysIPV6_TRANSPARENT = C.IPV6_TRANSPARENT
|
|
||||||
sysIPV6_UNICAST_IF = C.IPV6_UNICAST_IF
|
|
||||||
|
|
||||||
sysICMPV6_FILTER = C.ICMPV6_FILTER
|
|
||||||
|
|
||||||
sysICMPV6_FILTER_BLOCK = C.ICMPV6_FILTER_BLOCK
|
|
||||||
sysICMPV6_FILTER_PASS = C.ICMPV6_FILTER_PASS
|
|
||||||
sysICMPV6_FILTER_BLOCKOTHERS = C.ICMPV6_FILTER_BLOCKOTHERS
|
|
||||||
sysICMPV6_FILTER_PASSONLY = C.ICMPV6_FILTER_PASSONLY
|
|
||||||
|
|
||||||
sysSOL_SOCKET = C.SOL_SOCKET
|
|
||||||
sysSO_ATTACH_FILTER = C.SO_ATTACH_FILTER
|
|
||||||
|
|
||||||
sizeofKernelSockaddrStorage = C.sizeof_struct___kernel_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
sizeofIPv6FlowlabelReq = C.sizeof_struct_in6_flowlabel_req
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
|
|
||||||
sizeofSockFprog = C.sizeof_struct_sock_fprog
|
|
||||||
)
|
|
||||||
|
|
||||||
type kernelSockaddrStorage C.struct___kernel_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6FlowlabelReq C.struct_in6_flowlabel_req
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
||||||
|
|
||||||
type sockFProg C.struct_sock_fprog
|
|
||||||
|
|
||||||
type sockFilter C.struct_sock_filter
|
|
80
vendor/golang.org/x/net/ipv6/defs_netbsd.go
generated
vendored
80
vendor/golang.org/x/net/ipv6/defs_netbsd.go
generated
vendored
@ -1,80 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_IPSEC_POLICY = C.IPV6_IPSEC_POLICY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
89
vendor/golang.org/x/net/ipv6/defs_openbsd.go
generated
vendored
89
vendor/golang.org/x/net/ipv6/defs_openbsd.go
generated
vendored
@ -1,89 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
sysIPV6_PORTRANGE = C.IPV6_PORTRANGE
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
|
|
||||||
sysIPV6_AUTH_LEVEL = C.IPV6_AUTH_LEVEL
|
|
||||||
sysIPV6_ESP_TRANS_LEVEL = C.IPV6_ESP_TRANS_LEVEL
|
|
||||||
sysIPV6_ESP_NETWORK_LEVEL = C.IPV6_ESP_NETWORK_LEVEL
|
|
||||||
sysIPSEC6_OUTSA = C.IPSEC6_OUTSA
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
|
|
||||||
sysIPV6_AUTOFLOWLABEL = C.IPV6_AUTOFLOWLABEL
|
|
||||||
sysIPV6_IPCOMP_LEVEL = C.IPV6_IPCOMP_LEVEL
|
|
||||||
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
sysIPV6_PIPEX = C.IPV6_PIPEX
|
|
||||||
|
|
||||||
sysIPV6_RTABLE = C.IPV6_RTABLE
|
|
||||||
|
|
||||||
sysIPV6_PORTRANGE_DEFAULT = C.IPV6_PORTRANGE_DEFAULT
|
|
||||||
sysIPV6_PORTRANGE_HIGH = C.IPV6_PORTRANGE_HIGH
|
|
||||||
sysIPV6_PORTRANGE_LOW = C.IPV6_PORTRANGE_LOW
|
|
||||||
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
114
vendor/golang.org/x/net/ipv6/defs_solaris.go
generated
vendored
114
vendor/golang.org/x/net/ipv6/defs_solaris.go
generated
vendored
@ -1,114 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// +godefs map struct_in6_addr [16]byte /* in6_addr */
|
|
||||||
|
|
||||||
package ipv6
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/icmp6.h>
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysIPV6_UNICAST_HOPS = C.IPV6_UNICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_IF = C.IPV6_MULTICAST_IF
|
|
||||||
sysIPV6_MULTICAST_HOPS = C.IPV6_MULTICAST_HOPS
|
|
||||||
sysIPV6_MULTICAST_LOOP = C.IPV6_MULTICAST_LOOP
|
|
||||||
sysIPV6_JOIN_GROUP = C.IPV6_JOIN_GROUP
|
|
||||||
sysIPV6_LEAVE_GROUP = C.IPV6_LEAVE_GROUP
|
|
||||||
|
|
||||||
sysIPV6_PKTINFO = C.IPV6_PKTINFO
|
|
||||||
|
|
||||||
sysIPV6_HOPLIMIT = C.IPV6_HOPLIMIT
|
|
||||||
sysIPV6_NEXTHOP = C.IPV6_NEXTHOP
|
|
||||||
sysIPV6_HOPOPTS = C.IPV6_HOPOPTS
|
|
||||||
sysIPV6_DSTOPTS = C.IPV6_DSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RTHDR = C.IPV6_RTHDR
|
|
||||||
sysIPV6_RTHDRDSTOPTS = C.IPV6_RTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVPKTINFO = C.IPV6_RECVPKTINFO
|
|
||||||
sysIPV6_RECVHOPLIMIT = C.IPV6_RECVHOPLIMIT
|
|
||||||
sysIPV6_RECVHOPOPTS = C.IPV6_RECVHOPOPTS
|
|
||||||
|
|
||||||
sysIPV6_RECVRTHDR = C.IPV6_RECVRTHDR
|
|
||||||
|
|
||||||
sysIPV6_RECVRTHDRDSTOPTS = C.IPV6_RECVRTHDRDSTOPTS
|
|
||||||
|
|
||||||
sysIPV6_CHECKSUM = C.IPV6_CHECKSUM
|
|
||||||
sysIPV6_RECVTCLASS = C.IPV6_RECVTCLASS
|
|
||||||
sysIPV6_USE_MIN_MTU = C.IPV6_USE_MIN_MTU
|
|
||||||
sysIPV6_DONTFRAG = C.IPV6_DONTFRAG
|
|
||||||
sysIPV6_SEC_OPT = C.IPV6_SEC_OPT
|
|
||||||
sysIPV6_SRC_PREFERENCES = C.IPV6_SRC_PREFERENCES
|
|
||||||
sysIPV6_RECVPATHMTU = C.IPV6_RECVPATHMTU
|
|
||||||
sysIPV6_PATHMTU = C.IPV6_PATHMTU
|
|
||||||
sysIPV6_TCLASS = C.IPV6_TCLASS
|
|
||||||
sysIPV6_V6ONLY = C.IPV6_V6ONLY
|
|
||||||
|
|
||||||
sysIPV6_RECVDSTOPTS = C.IPV6_RECVDSTOPTS
|
|
||||||
|
|
||||||
sysMCAST_JOIN_GROUP = C.MCAST_JOIN_GROUP
|
|
||||||
sysMCAST_LEAVE_GROUP = C.MCAST_LEAVE_GROUP
|
|
||||||
sysMCAST_BLOCK_SOURCE = C.MCAST_BLOCK_SOURCE
|
|
||||||
sysMCAST_UNBLOCK_SOURCE = C.MCAST_UNBLOCK_SOURCE
|
|
||||||
sysMCAST_JOIN_SOURCE_GROUP = C.MCAST_JOIN_SOURCE_GROUP
|
|
||||||
sysMCAST_LEAVE_SOURCE_GROUP = C.MCAST_LEAVE_SOURCE_GROUP
|
|
||||||
|
|
||||||
sysIPV6_PREFER_SRC_HOME = C.IPV6_PREFER_SRC_HOME
|
|
||||||
sysIPV6_PREFER_SRC_COA = C.IPV6_PREFER_SRC_COA
|
|
||||||
sysIPV6_PREFER_SRC_PUBLIC = C.IPV6_PREFER_SRC_PUBLIC
|
|
||||||
sysIPV6_PREFER_SRC_TMP = C.IPV6_PREFER_SRC_TMP
|
|
||||||
sysIPV6_PREFER_SRC_NONCGA = C.IPV6_PREFER_SRC_NONCGA
|
|
||||||
sysIPV6_PREFER_SRC_CGA = C.IPV6_PREFER_SRC_CGA
|
|
||||||
|
|
||||||
sysIPV6_PREFER_SRC_MIPMASK = C.IPV6_PREFER_SRC_MIPMASK
|
|
||||||
sysIPV6_PREFER_SRC_MIPDEFAULT = C.IPV6_PREFER_SRC_MIPDEFAULT
|
|
||||||
sysIPV6_PREFER_SRC_TMPMASK = C.IPV6_PREFER_SRC_TMPMASK
|
|
||||||
sysIPV6_PREFER_SRC_TMPDEFAULT = C.IPV6_PREFER_SRC_TMPDEFAULT
|
|
||||||
sysIPV6_PREFER_SRC_CGAMASK = C.IPV6_PREFER_SRC_CGAMASK
|
|
||||||
sysIPV6_PREFER_SRC_CGADEFAULT = C.IPV6_PREFER_SRC_CGADEFAULT
|
|
||||||
|
|
||||||
sysIPV6_PREFER_SRC_MASK = C.IPV6_PREFER_SRC_MASK
|
|
||||||
|
|
||||||
sysIPV6_PREFER_SRC_DEFAULT = C.IPV6_PREFER_SRC_DEFAULT
|
|
||||||
|
|
||||||
sysIPV6_BOUND_IF = C.IPV6_BOUND_IF
|
|
||||||
sysIPV6_UNSPEC_SRC = C.IPV6_UNSPEC_SRC
|
|
||||||
|
|
||||||
sysICMP6_FILTER = C.ICMP6_FILTER
|
|
||||||
|
|
||||||
sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
|
|
||||||
sizeofSockaddrInet6 = C.sizeof_struct_sockaddr_in6
|
|
||||||
sizeofInet6Pktinfo = C.sizeof_struct_in6_pktinfo
|
|
||||||
sizeofIPv6Mtuinfo = C.sizeof_struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
sizeofIPv6Mreq = C.sizeof_struct_ipv6_mreq
|
|
||||||
sizeofGroupReq = C.sizeof_struct_group_req
|
|
||||||
sizeofGroupSourceReq = C.sizeof_struct_group_source_req
|
|
||||||
|
|
||||||
sizeofICMPv6Filter = C.sizeof_struct_icmp6_filter
|
|
||||||
)
|
|
||||||
|
|
||||||
type sockaddrStorage C.struct_sockaddr_storage
|
|
||||||
|
|
||||||
type sockaddrInet6 C.struct_sockaddr_in6
|
|
||||||
|
|
||||||
type inet6Pktinfo C.struct_in6_pktinfo
|
|
||||||
|
|
||||||
type ipv6Mtuinfo C.struct_ip6_mtuinfo
|
|
||||||
|
|
||||||
type ipv6Mreq C.struct_ipv6_mreq
|
|
||||||
|
|
||||||
type groupReq C.struct_group_req
|
|
||||||
|
|
||||||
type groupSourceReq C.struct_group_source_req
|
|
||||||
|
|
||||||
type icmpv6Filter C.struct_icmp6_filter
|
|
199
vendor/golang.org/x/net/ipv6/gen.go
generated
vendored
199
vendor/golang.org/x/net/ipv6/gen.go
generated
vendored
@ -1,199 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
//go:generate go run gen.go
|
|
||||||
|
|
||||||
// This program generates system adaptation constants and types,
|
|
||||||
// internet protocol constants and tables by reading template files
|
|
||||||
// and IANA protocol registries.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := genzsys(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := geniana(); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func genzsys() error {
|
|
||||||
defs := "defs_" + runtime.GOOS + ".go"
|
|
||||||
f, err := os.Open(defs)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.Close()
|
|
||||||
cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
|
|
||||||
b, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b, err = format.Source(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
zsys := "zsys_" + runtime.GOOS + ".go"
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "freebsd", "linux":
|
|
||||||
zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var registries = []struct {
|
|
||||||
url string
|
|
||||||
parse func(io.Writer, io.Reader) error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml",
|
|
||||||
parseICMPv6Parameters,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func geniana() error {
|
|
||||||
var bb bytes.Buffer
|
|
||||||
fmt.Fprintf(&bb, "// go generate gen.go\n")
|
|
||||||
fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
|
|
||||||
fmt.Fprintf(&bb, "package ipv6\n\n")
|
|
||||||
for _, r := range registries {
|
|
||||||
resp, err := http.Get(r.url)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
|
||||||
}
|
|
||||||
if err := r.parse(&bb, resp.Body); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&bb, "\n")
|
|
||||||
}
|
|
||||||
b, err := format.Source(bb.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseICMPv6Parameters(w io.Writer, r io.Reader) error {
|
|
||||||
dec := xml.NewDecoder(r)
|
|
||||||
var icp icmpv6Parameters
|
|
||||||
if err := dec.Decode(&icp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
prs := icp.escape()
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
|
||||||
fmt.Fprintf(w, "const (\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Name, pr.Value)
|
|
||||||
fmt.Fprintf(w, "// %s\n", pr.OrigName)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, ")\n\n")
|
|
||||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
|
||||||
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
|
||||||
for _, pr := range prs {
|
|
||||||
if pr.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigName))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "}\n")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type icmpv6Parameters struct {
|
|
||||||
XMLName xml.Name `xml:"registry"`
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Updated string `xml:"updated"`
|
|
||||||
Registries []struct {
|
|
||||||
Title string `xml:"title"`
|
|
||||||
Records []struct {
|
|
||||||
Value string `xml:"value"`
|
|
||||||
Name string `xml:"name"`
|
|
||||||
} `xml:"record"`
|
|
||||||
} `xml:"registry"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type canonICMPv6ParamRecord struct {
|
|
||||||
OrigName string
|
|
||||||
Name string
|
|
||||||
Value int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord {
|
|
||||||
id := -1
|
|
||||||
for i, r := range icp.Registries {
|
|
||||||
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
|
||||||
id = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if id < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
prs := make([]canonICMPv6ParamRecord, len(icp.Registries[id].Records))
|
|
||||||
sr := strings.NewReplacer(
|
|
||||||
"Messages", "",
|
|
||||||
"Message", "",
|
|
||||||
"ICMP", "",
|
|
||||||
"+", "P",
|
|
||||||
"-", "",
|
|
||||||
"/", "",
|
|
||||||
".", "",
|
|
||||||
" ", "",
|
|
||||||
)
|
|
||||||
for i, pr := range icp.Registries[id].Records {
|
|
||||||
if strings.Contains(pr.Name, "Reserved") ||
|
|
||||||
strings.Contains(pr.Name, "Unassigned") ||
|
|
||||||
strings.Contains(pr.Name, "Deprecated") ||
|
|
||||||
strings.Contains(pr.Name, "Experiment") ||
|
|
||||||
strings.Contains(pr.Name, "experiment") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ss := strings.Split(pr.Name, "\n")
|
|
||||||
if len(ss) > 1 {
|
|
||||||
prs[i].Name = strings.Join(ss, " ")
|
|
||||||
} else {
|
|
||||||
prs[i].Name = ss[0]
|
|
||||||
}
|
|
||||||
s := strings.TrimSpace(prs[i].Name)
|
|
||||||
prs[i].OrigName = s
|
|
||||||
prs[i].Name = sr.Replace(s)
|
|
||||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
|
||||||
}
|
|
||||||
return prs
|
|
||||||
}
|
|
13
vendor/golang.org/x/oauth2/.travis.yml
generated
vendored
13
vendor/golang.org/x/oauth2/.travis.yml
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- tip
|
|
||||||
|
|
||||||
install:
|
|
||||||
- export GOPATH="$HOME/gopath"
|
|
||||||
- mkdir -p "$GOPATH/src/golang.org/x"
|
|
||||||
- mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/golang.org/x/oauth2"
|
|
||||||
- go get -v -t -d golang.org/x/oauth2/...
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v golang.org/x/oauth2/...
|
|
3
vendor/golang.org/x/oauth2/AUTHORS
generated
vendored
3
vendor/golang.org/x/oauth2/AUTHORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code refers to The Go Authors for copyright purposes.
|
|
||||||
# The master list of authors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/AUTHORS.
|
|
26
vendor/golang.org/x/oauth2/CONTRIBUTING.md
generated
vendored
26
vendor/golang.org/x/oauth2/CONTRIBUTING.md
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
# Contributing to Go
|
|
||||||
|
|
||||||
Go is an open source project.
|
|
||||||
|
|
||||||
It is the work of hundreds of contributors. We appreciate your help!
|
|
||||||
|
|
||||||
## Filing issues
|
|
||||||
|
|
||||||
When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions:
|
|
||||||
|
|
||||||
1. What version of Go are you using (`go version`)?
|
|
||||||
2. What operating system and processor architecture are you using?
|
|
||||||
3. What did you do?
|
|
||||||
4. What did you expect to see?
|
|
||||||
5. What did you see instead?
|
|
||||||
|
|
||||||
General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
|
|
||||||
The gophers there will answer or ask you to file an issue if you've tripped over a bug.
|
|
||||||
|
|
||||||
## Contributing code
|
|
||||||
|
|
||||||
Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
|
|
||||||
before sending patches.
|
|
||||||
|
|
||||||
Unless otherwise noted, the Go source files are distributed under
|
|
||||||
the BSD-style license found in the LICENSE file.
|
|
3
vendor/golang.org/x/oauth2/CONTRIBUTORS
generated
vendored
3
vendor/golang.org/x/oauth2/CONTRIBUTORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code was written by the Go contributors.
|
|
||||||
# The master list of contributors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
|
27
vendor/golang.org/x/oauth2/LICENSE
generated
vendored
27
vendor/golang.org/x/oauth2/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
36
vendor/golang.org/x/oauth2/README.md
generated
vendored
36
vendor/golang.org/x/oauth2/README.md
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
# OAuth2 for Go
|
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2)
|
|
||||||
[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2)
|
|
||||||
|
|
||||||
oauth2 package contains a client implementation for OAuth 2.0 spec.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
~~~~
|
|
||||||
go get golang.org/x/oauth2
|
|
||||||
~~~~
|
|
||||||
|
|
||||||
Or you can manually git clone the repository to
|
|
||||||
`$(go env GOPATH)/src/golang.org/x/oauth2`.
|
|
||||||
|
|
||||||
See godoc for further documentation and examples.
|
|
||||||
|
|
||||||
* [godoc.org/golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2)
|
|
||||||
* [godoc.org/golang.org/x/oauth2/google](https://godoc.org/golang.org/x/oauth2/google)
|
|
||||||
|
|
||||||
## Policy for new packages
|
|
||||||
|
|
||||||
We no longer accept new provider-specific packages in this repo if all
|
|
||||||
they do is add a single endpoint variable. If you just want to add a
|
|
||||||
single endpoint, add it to the
|
|
||||||
[godoc.org/golang.org/x/oauth2/endpoints](https://godoc.org/golang.org/x/oauth2/endpoints)
|
|
||||||
package.
|
|
||||||
|
|
||||||
## Report Issues / Send Patches
|
|
||||||
|
|
||||||
This repository uses Gerrit for code changes. To learn how to submit changes to
|
|
||||||
this repository, see https://golang.org/doc/contribute.html.
|
|
||||||
|
|
||||||
The main issue tracker for the oauth2 repository is located at
|
|
||||||
https://github.com/golang/oauth2/issues.
|
|
120
vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
generated
vendored
120
vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
generated
vendored
@ -1,120 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package clientcredentials implements the OAuth2.0 "client credentials" token flow,
|
|
||||||
// also known as the "two-legged OAuth 2.0".
|
|
||||||
//
|
|
||||||
// This should be used when the client is acting on its own behalf or when the client
|
|
||||||
// is the resource owner. It may also be used when requesting access to protected
|
|
||||||
// resources based on an authorization previously arranged with the authorization
|
|
||||||
// server.
|
|
||||||
//
|
|
||||||
// See https://tools.ietf.org/html/rfc6749#section-4.4
|
|
||||||
package clientcredentials // import "golang.org/x/oauth2/clientcredentials"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
"golang.org/x/oauth2/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config describes a 2-legged OAuth2 flow, with both the
|
|
||||||
// client application information and the server's endpoint URLs.
|
|
||||||
type Config struct {
|
|
||||||
// ClientID is the application's ID.
|
|
||||||
ClientID string
|
|
||||||
|
|
||||||
// ClientSecret is the application's secret.
|
|
||||||
ClientSecret string
|
|
||||||
|
|
||||||
// TokenURL is the resource server's token endpoint
|
|
||||||
// URL. This is a constant specific to each server.
|
|
||||||
TokenURL string
|
|
||||||
|
|
||||||
// Scope specifies optional requested permissions.
|
|
||||||
Scopes []string
|
|
||||||
|
|
||||||
// EndpointParams specifies additional parameters for requests to the token endpoint.
|
|
||||||
EndpointParams url.Values
|
|
||||||
|
|
||||||
// AuthStyle optionally specifies how the endpoint wants the
|
|
||||||
// client ID & client secret sent. The zero value means to
|
|
||||||
// auto-detect.
|
|
||||||
AuthStyle oauth2.AuthStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
// Token uses client credentials to retrieve a token.
|
|
||||||
//
|
|
||||||
// The provided context optionally controls which HTTP client is used. See the oauth2.HTTPClient variable.
|
|
||||||
func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) {
|
|
||||||
return c.TokenSource(ctx).Token()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client returns an HTTP client using the provided token.
|
|
||||||
// The token will auto-refresh as necessary.
|
|
||||||
//
|
|
||||||
// The provided context optionally controls which HTTP client
|
|
||||||
// is returned. See the oauth2.HTTPClient variable.
|
|
||||||
//
|
|
||||||
// The returned Client and its Transport should not be modified.
|
|
||||||
func (c *Config) Client(ctx context.Context) *http.Client {
|
|
||||||
return oauth2.NewClient(ctx, c.TokenSource(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TokenSource returns a TokenSource that returns t until t expires,
|
|
||||||
// automatically refreshing it as necessary using the provided context and the
|
|
||||||
// client ID and client secret.
|
|
||||||
//
|
|
||||||
// Most users will use Config.Client instead.
|
|
||||||
func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
|
|
||||||
source := &tokenSource{
|
|
||||||
ctx: ctx,
|
|
||||||
conf: c,
|
|
||||||
}
|
|
||||||
return oauth2.ReuseTokenSource(nil, source)
|
|
||||||
}
|
|
||||||
|
|
||||||
type tokenSource struct {
|
|
||||||
ctx context.Context
|
|
||||||
conf *Config
|
|
||||||
}
|
|
||||||
|
|
||||||
// Token refreshes the token by using a new client credentials request.
|
|
||||||
// tokens received this way do not include a refresh token
|
|
||||||
func (c *tokenSource) Token() (*oauth2.Token, error) {
|
|
||||||
v := url.Values{
|
|
||||||
"grant_type": {"client_credentials"},
|
|
||||||
}
|
|
||||||
if len(c.conf.Scopes) > 0 {
|
|
||||||
v.Set("scope", strings.Join(c.conf.Scopes, " "))
|
|
||||||
}
|
|
||||||
for k, p := range c.conf.EndpointParams {
|
|
||||||
// Allow grant_type to be overridden to allow interoperability with
|
|
||||||
// non-compliant implementations.
|
|
||||||
if _, ok := v[k]; ok && k != "grant_type" {
|
|
||||||
return nil, fmt.Errorf("oauth2: cannot overwrite parameter %q", k)
|
|
||||||
}
|
|
||||||
v[k] = p
|
|
||||||
}
|
|
||||||
|
|
||||||
tk, err := internal.RetrieveToken(c.ctx, c.conf.ClientID, c.conf.ClientSecret, c.conf.TokenURL, v, internal.AuthStyle(c.conf.AuthStyle))
|
|
||||||
if err != nil {
|
|
||||||
if rErr, ok := err.(*internal.RetrieveError); ok {
|
|
||||||
return nil, (*oauth2.RetrieveError)(rErr)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t := &oauth2.Token{
|
|
||||||
AccessToken: tk.AccessToken,
|
|
||||||
TokenType: tk.TokenType,
|
|
||||||
RefreshToken: tk.RefreshToken,
|
|
||||||
Expiry: tk.Expiry,
|
|
||||||
}
|
|
||||||
return t.WithExtra(tk.Raw), nil
|
|
||||||
}
|
|
10
vendor/golang.org/x/oauth2/go.mod
generated
vendored
10
vendor/golang.org/x/oauth2/go.mod
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
module golang.org/x/oauth2
|
|
||||||
|
|
||||||
go 1.11
|
|
||||||
|
|
||||||
require (
|
|
||||||
cloud.google.com/go v0.34.0
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
|
|
||||||
google.golang.org/appengine v1.4.0
|
|
||||||
)
|
|
12
vendor/golang.org/x/oauth2/go.sum
generated
vendored
12
vendor/golang.org/x/oauth2/go.sum
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
|
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg=
|
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
13
vendor/golang.org/x/oauth2/internal/client_appengine.go
generated
vendored
13
vendor/golang.org/x/oauth2/internal/client_appengine.go
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build appengine
|
|
||||||
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import "google.golang.org/appengine/urlfetch"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
appengineClientHook = urlfetch.Client
|
|
||||||
}
|
|
6
vendor/golang.org/x/oauth2/internal/doc.go
generated
vendored
6
vendor/golang.org/x/oauth2/internal/doc.go
generated
vendored
@ -1,6 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package internal contains support packages for oauth2 package.
|
|
||||||
package internal
|
|
37
vendor/golang.org/x/oauth2/internal/oauth2.go
generated
vendored
37
vendor/golang.org/x/oauth2/internal/oauth2.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/pem"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ParseKey converts the binary contents of a private key file
|
|
||||||
// to an *rsa.PrivateKey. It detects whether the private key is in a
|
|
||||||
// PEM container or not. If so, it extracts the the private key
|
|
||||||
// from PEM container before conversion. It only supports PEM
|
|
||||||
// containers with no passphrase.
|
|
||||||
func ParseKey(key []byte) (*rsa.PrivateKey, error) {
|
|
||||||
block, _ := pem.Decode(key)
|
|
||||||
if block != nil {
|
|
||||||
key = block.Bytes
|
|
||||||
}
|
|
||||||
parsedKey, err := x509.ParsePKCS8PrivateKey(key)
|
|
||||||
if err != nil {
|
|
||||||
parsedKey, err = x509.ParsePKCS1PrivateKey(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8; parse error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parsed, ok := parsedKey.(*rsa.PrivateKey)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("private key is invalid")
|
|
||||||
}
|
|
||||||
return parsed, nil
|
|
||||||
}
|
|
294
vendor/golang.org/x/oauth2/internal/token.go
generated
vendored
294
vendor/golang.org/x/oauth2/internal/token.go
generated
vendored
@ -1,294 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
|
||||||
"mime"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/net/context/ctxhttp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Token represents the credentials used to authorize
|
|
||||||
// the requests to access protected resources on the OAuth 2.0
|
|
||||||
// provider's backend.
|
|
||||||
//
|
|
||||||
// This type is a mirror of oauth2.Token and exists to break
|
|
||||||
// an otherwise-circular dependency. Other internal packages
|
|
||||||
// should convert this Token into an oauth2.Token before use.
|
|
||||||
type Token struct {
|
|
||||||
// AccessToken is the token that authorizes and authenticates
|
|
||||||
// the requests.
|
|
||||||
AccessToken string
|
|
||||||
|
|
||||||
// TokenType is the type of token.
|
|
||||||
// The Type method returns either this or "Bearer", the default.
|
|
||||||
TokenType string
|
|
||||||
|
|
||||||
// RefreshToken is a token that's used by the application
|
|
||||||
// (as opposed to the user) to refresh the access token
|
|
||||||
// if it expires.
|
|
||||||
RefreshToken string
|
|
||||||
|
|
||||||
// Expiry is the optional expiration time of the access token.
|
|
||||||
//
|
|
||||||
// If zero, TokenSource implementations will reuse the same
|
|
||||||
// token forever and RefreshToken or equivalent
|
|
||||||
// mechanisms for that TokenSource will not be used.
|
|
||||||
Expiry time.Time
|
|
||||||
|
|
||||||
// Raw optionally contains extra metadata from the server
|
|
||||||
// when updating a token.
|
|
||||||
Raw interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokenJSON is the struct representing the HTTP response from OAuth2
|
|
||||||
// providers returning a token in JSON form.
|
|
||||||
type tokenJSON struct {
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
TokenType string `json:"token_type"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *tokenJSON) expiry() (t time.Time) {
|
|
||||||
if v := e.ExpiresIn; v != 0 {
|
|
||||||
return time.Now().Add(time.Duration(v) * time.Second)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type expirationTime int32
|
|
||||||
|
|
||||||
func (e *expirationTime) UnmarshalJSON(b []byte) error {
|
|
||||||
if len(b) == 0 || string(b) == "null" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var n json.Number
|
|
||||||
err := json.Unmarshal(b, &n)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
i, err := n.Int64()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if i > math.MaxInt32 {
|
|
||||||
i = math.MaxInt32
|
|
||||||
}
|
|
||||||
*e = expirationTime(i)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op.
|
|
||||||
//
|
|
||||||
// Deprecated: this function no longer does anything. Caller code that
|
|
||||||
// wants to avoid potential extra HTTP requests made during
|
|
||||||
// auto-probing of the provider's auth style should set
|
|
||||||
// Endpoint.AuthStyle.
|
|
||||||
func RegisterBrokenAuthHeaderProvider(tokenURL string) {}
|
|
||||||
|
|
||||||
// AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type.
|
|
||||||
type AuthStyle int
|
|
||||||
|
|
||||||
const (
|
|
||||||
AuthStyleUnknown AuthStyle = 0
|
|
||||||
AuthStyleInParams AuthStyle = 1
|
|
||||||
AuthStyleInHeader AuthStyle = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// authStyleCache is the set of tokenURLs we've successfully used via
|
|
||||||
// RetrieveToken and which style auth we ended up using.
|
|
||||||
// It's called a cache, but it doesn't (yet?) shrink. It's expected that
|
|
||||||
// the set of OAuth2 servers a program contacts over time is fixed and
|
|
||||||
// small.
|
|
||||||
var authStyleCache struct {
|
|
||||||
sync.Mutex
|
|
||||||
m map[string]AuthStyle // keyed by tokenURL
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetAuthCache resets the global authentication style cache used
|
|
||||||
// for AuthStyleUnknown token requests.
|
|
||||||
func ResetAuthCache() {
|
|
||||||
authStyleCache.Lock()
|
|
||||||
defer authStyleCache.Unlock()
|
|
||||||
authStyleCache.m = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookupAuthStyle reports which auth style we last used with tokenURL
|
|
||||||
// when calling RetrieveToken and whether we have ever done so.
|
|
||||||
func lookupAuthStyle(tokenURL string) (style AuthStyle, ok bool) {
|
|
||||||
authStyleCache.Lock()
|
|
||||||
defer authStyleCache.Unlock()
|
|
||||||
style, ok = authStyleCache.m[tokenURL]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// setAuthStyle adds an entry to authStyleCache, documented above.
|
|
||||||
func setAuthStyle(tokenURL string, v AuthStyle) {
|
|
||||||
authStyleCache.Lock()
|
|
||||||
defer authStyleCache.Unlock()
|
|
||||||
if authStyleCache.m == nil {
|
|
||||||
authStyleCache.m = make(map[string]AuthStyle)
|
|
||||||
}
|
|
||||||
authStyleCache.m[tokenURL] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// newTokenRequest returns a new *http.Request to retrieve a new token
|
|
||||||
// from tokenURL using the provided clientID, clientSecret, and POST
|
|
||||||
// body parameters.
|
|
||||||
//
|
|
||||||
// inParams is whether the clientID & clientSecret should be encoded
|
|
||||||
// as the POST body. An 'inParams' value of true means to send it in
|
|
||||||
// the POST body (along with any values in v); false means to send it
|
|
||||||
// in the Authorization header.
|
|
||||||
func newTokenRequest(tokenURL, clientID, clientSecret string, v url.Values, authStyle AuthStyle) (*http.Request, error) {
|
|
||||||
if authStyle == AuthStyleInParams {
|
|
||||||
v = cloneURLValues(v)
|
|
||||||
if clientID != "" {
|
|
||||||
v.Set("client_id", clientID)
|
|
||||||
}
|
|
||||||
if clientSecret != "" {
|
|
||||||
v.Set("client_secret", clientSecret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode()))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
if authStyle == AuthStyleInHeader {
|
|
||||||
req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret))
|
|
||||||
}
|
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func cloneURLValues(v url.Values) url.Values {
|
|
||||||
v2 := make(url.Values, len(v))
|
|
||||||
for k, vv := range v {
|
|
||||||
v2[k] = append([]string(nil), vv...)
|
|
||||||
}
|
|
||||||
return v2
|
|
||||||
}
|
|
||||||
|
|
||||||
func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle) (*Token, error) {
|
|
||||||
needsAuthStyleProbe := authStyle == 0
|
|
||||||
if needsAuthStyleProbe {
|
|
||||||
if style, ok := lookupAuthStyle(tokenURL); ok {
|
|
||||||
authStyle = style
|
|
||||||
needsAuthStyleProbe = false
|
|
||||||
} else {
|
|
||||||
authStyle = AuthStyleInHeader // the first way we'll try
|
|
||||||
}
|
|
||||||
}
|
|
||||||
req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
token, err := doTokenRoundTrip(ctx, req)
|
|
||||||
if err != nil && needsAuthStyleProbe {
|
|
||||||
// If we get an error, assume the server wants the
|
|
||||||
// clientID & clientSecret in a different form.
|
|
||||||
// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
|
|
||||||
// In summary:
|
|
||||||
// - Reddit only accepts client secret in the Authorization header
|
|
||||||
// - Dropbox accepts either it in URL param or Auth header, but not both.
|
|
||||||
// - Google only accepts URL param (not spec compliant?), not Auth header
|
|
||||||
// - Stripe only accepts client secret in Auth header with Bearer method, not Basic
|
|
||||||
//
|
|
||||||
// We used to maintain a big table in this code of all the sites and which way
|
|
||||||
// they went, but maintaining it didn't scale & got annoying.
|
|
||||||
// So just try both ways.
|
|
||||||
authStyle = AuthStyleInParams // the second way we'll try
|
|
||||||
req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle)
|
|
||||||
token, err = doTokenRoundTrip(ctx, req)
|
|
||||||
}
|
|
||||||
if needsAuthStyleProbe && err == nil {
|
|
||||||
setAuthStyle(tokenURL, authStyle)
|
|
||||||
}
|
|
||||||
// Don't overwrite `RefreshToken` with an empty value
|
|
||||||
// if this was a token refreshing request.
|
|
||||||
if token != nil && token.RefreshToken == "" {
|
|
||||||
token.RefreshToken = v.Get("refresh_token")
|
|
||||||
}
|
|
||||||
return token, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
|
|
||||||
r, err := ctxhttp.Do(ctx, ContextClient(ctx), req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20))
|
|
||||||
r.Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
|
|
||||||
}
|
|
||||||
if code := r.StatusCode; code < 200 || code > 299 {
|
|
||||||
return nil, &RetrieveError{
|
|
||||||
Response: r,
|
|
||||||
Body: body,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var token *Token
|
|
||||||
content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
|
||||||
switch content {
|
|
||||||
case "application/x-www-form-urlencoded", "text/plain":
|
|
||||||
vals, err := url.ParseQuery(string(body))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
token = &Token{
|
|
||||||
AccessToken: vals.Get("access_token"),
|
|
||||||
TokenType: vals.Get("token_type"),
|
|
||||||
RefreshToken: vals.Get("refresh_token"),
|
|
||||||
Raw: vals,
|
|
||||||
}
|
|
||||||
e := vals.Get("expires_in")
|
|
||||||
expires, _ := strconv.Atoi(e)
|
|
||||||
if expires != 0 {
|
|
||||||
token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
var tj tokenJSON
|
|
||||||
if err = json.Unmarshal(body, &tj); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
token = &Token{
|
|
||||||
AccessToken: tj.AccessToken,
|
|
||||||
TokenType: tj.TokenType,
|
|
||||||
RefreshToken: tj.RefreshToken,
|
|
||||||
Expiry: tj.expiry(),
|
|
||||||
Raw: make(map[string]interface{}),
|
|
||||||
}
|
|
||||||
json.Unmarshal(body, &token.Raw) // no error checks for optional fields
|
|
||||||
}
|
|
||||||
if token.AccessToken == "" {
|
|
||||||
return nil, errors.New("oauth2: server response missing access_token")
|
|
||||||
}
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type RetrieveError struct {
|
|
||||||
Response *http.Response
|
|
||||||
Body []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RetrieveError) Error() string {
|
|
||||||
return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body)
|
|
||||||
}
|
|
33
vendor/golang.org/x/oauth2/internal/transport.go
generated
vendored
33
vendor/golang.org/x/oauth2/internal/transport.go
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HTTPClient is the context key to use with golang.org/x/net/context's
|
|
||||||
// WithValue function to associate an *http.Client value with a context.
|
|
||||||
var HTTPClient ContextKey
|
|
||||||
|
|
||||||
// ContextKey is just an empty struct. It exists so HTTPClient can be
|
|
||||||
// an immutable public variable with a unique type. It's immutable
|
|
||||||
// because nobody else can create a ContextKey, being unexported.
|
|
||||||
type ContextKey struct{}
|
|
||||||
|
|
||||||
var appengineClientHook func(context.Context) *http.Client
|
|
||||||
|
|
||||||
func ContextClient(ctx context.Context) *http.Client {
|
|
||||||
if ctx != nil {
|
|
||||||
if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok {
|
|
||||||
return hc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if appengineClientHook != nil {
|
|
||||||
return appengineClientHook(ctx)
|
|
||||||
}
|
|
||||||
return http.DefaultClient
|
|
||||||
}
|
|
381
vendor/golang.org/x/oauth2/oauth2.go
generated
vendored
381
vendor/golang.org/x/oauth2/oauth2.go
generated
vendored
@ -1,381 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package oauth2 provides support for making
|
|
||||||
// OAuth2 authorized and authenticated HTTP requests,
|
|
||||||
// as specified in RFC 6749.
|
|
||||||
// It can additionally grant authorization with Bearer JWT.
|
|
||||||
package oauth2 // import "golang.org/x/oauth2"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"golang.org/x/oauth2/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NoContext is the default context you should supply if not using
|
|
||||||
// your own context.Context (see https://golang.org/x/net/context).
|
|
||||||
//
|
|
||||||
// Deprecated: Use context.Background() or context.TODO() instead.
|
|
||||||
var NoContext = context.TODO()
|
|
||||||
|
|
||||||
// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op.
|
|
||||||
//
|
|
||||||
// Deprecated: this function no longer does anything. Caller code that
|
|
||||||
// wants to avoid potential extra HTTP requests made during
|
|
||||||
// auto-probing of the provider's auth style should set
|
|
||||||
// Endpoint.AuthStyle.
|
|
||||||
func RegisterBrokenAuthHeaderProvider(tokenURL string) {}
|
|
||||||
|
|
||||||
// Config describes a typical 3-legged OAuth2 flow, with both the
|
|
||||||
// client application information and the server's endpoint URLs.
|
|
||||||
// For the client credentials 2-legged OAuth2 flow, see the clientcredentials
|
|
||||||
// package (https://golang.org/x/oauth2/clientcredentials).
|
|
||||||
type Config struct {
|
|
||||||
// ClientID is the application's ID.
|
|
||||||
ClientID string
|
|
||||||
|
|
||||||
// ClientSecret is the application's secret.
|
|
||||||
ClientSecret string
|
|
||||||
|
|
||||||
// Endpoint contains the resource server's token endpoint
|
|
||||||
// URLs. These are constants specific to each server and are
|
|
||||||
// often available via site-specific packages, such as
|
|
||||||
// google.Endpoint or github.Endpoint.
|
|
||||||
Endpoint Endpoint
|
|
||||||
|
|
||||||
// RedirectURL is the URL to redirect users going through
|
|
||||||
// the OAuth flow, after the resource owner's URLs.
|
|
||||||
RedirectURL string
|
|
||||||
|
|
||||||
// Scope specifies optional requested permissions.
|
|
||||||
Scopes []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// A TokenSource is anything that can return a token.
|
|
||||||
type TokenSource interface {
|
|
||||||
// Token returns a token or an error.
|
|
||||||
// Token must be safe for concurrent use by multiple goroutines.
|
|
||||||
// The returned Token must not be modified.
|
|
||||||
Token() (*Token, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Endpoint represents an OAuth 2.0 provider's authorization and token
|
|
||||||
// endpoint URLs.
|
|
||||||
type Endpoint struct {
|
|
||||||
AuthURL string
|
|
||||||
TokenURL string
|
|
||||||
|
|
||||||
// AuthStyle optionally specifies how the endpoint wants the
|
|
||||||
// client ID & client secret sent. The zero value means to
|
|
||||||
// auto-detect.
|
|
||||||
AuthStyle AuthStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthStyle represents how requests for tokens are authenticated
|
|
||||||
// to the server.
|
|
||||||
type AuthStyle int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// AuthStyleAutoDetect means to auto-detect which authentication
|
|
||||||
// style the provider wants by trying both ways and caching
|
|
||||||
// the successful way for the future.
|
|
||||||
AuthStyleAutoDetect AuthStyle = 0
|
|
||||||
|
|
||||||
// AuthStyleInParams sends the "client_id" and "client_secret"
|
|
||||||
// in the POST body as application/x-www-form-urlencoded parameters.
|
|
||||||
AuthStyleInParams AuthStyle = 1
|
|
||||||
|
|
||||||
// AuthStyleInHeader sends the client_id and client_password
|
|
||||||
// using HTTP Basic Authorization. This is an optional style
|
|
||||||
// described in the OAuth2 RFC 6749 section 2.3.1.
|
|
||||||
AuthStyleInHeader AuthStyle = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// AccessTypeOnline and AccessTypeOffline are options passed
|
|
||||||
// to the Options.AuthCodeURL method. They modify the
|
|
||||||
// "access_type" field that gets sent in the URL returned by
|
|
||||||
// AuthCodeURL.
|
|
||||||
//
|
|
||||||
// Online is the default if neither is specified. If your
|
|
||||||
// application needs to refresh access tokens when the user
|
|
||||||
// is not present at the browser, then use offline. This will
|
|
||||||
// result in your application obtaining a refresh token the
|
|
||||||
// first time your application exchanges an authorization
|
|
||||||
// code for a user.
|
|
||||||
AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online")
|
|
||||||
AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline")
|
|
||||||
|
|
||||||
// ApprovalForce forces the users to view the consent dialog
|
|
||||||
// and confirm the permissions request at the URL returned
|
|
||||||
// from AuthCodeURL, even if they've already done so.
|
|
||||||
ApprovalForce AuthCodeOption = SetAuthURLParam("prompt", "consent")
|
|
||||||
)
|
|
||||||
|
|
||||||
// An AuthCodeOption is passed to Config.AuthCodeURL.
|
|
||||||
type AuthCodeOption interface {
|
|
||||||
setValue(url.Values)
|
|
||||||
}
|
|
||||||
|
|
||||||
type setParam struct{ k, v string }
|
|
||||||
|
|
||||||
func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) }
|
|
||||||
|
|
||||||
// SetAuthURLParam builds an AuthCodeOption which passes key/value parameters
|
|
||||||
// to a provider's authorization endpoint.
|
|
||||||
func SetAuthURLParam(key, value string) AuthCodeOption {
|
|
||||||
return setParam{key, value}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
|
|
||||||
// that asks for permissions for the required scopes explicitly.
|
|
||||||
//
|
|
||||||
// State is a token to protect the user from CSRF attacks. You must
|
|
||||||
// always provide a non-empty string and validate that it matches the
|
|
||||||
// the state query parameter on your redirect callback.
|
|
||||||
// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
|
|
||||||
//
|
|
||||||
// Opts may include AccessTypeOnline or AccessTypeOffline, as well
|
|
||||||
// as ApprovalForce.
|
|
||||||
// It can also be used to pass the PKCE challenge.
|
|
||||||
// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
|
|
||||||
func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
buf.WriteString(c.Endpoint.AuthURL)
|
|
||||||
v := url.Values{
|
|
||||||
"response_type": {"code"},
|
|
||||||
"client_id": {c.ClientID},
|
|
||||||
}
|
|
||||||
if c.RedirectURL != "" {
|
|
||||||
v.Set("redirect_uri", c.RedirectURL)
|
|
||||||
}
|
|
||||||
if len(c.Scopes) > 0 {
|
|
||||||
v.Set("scope", strings.Join(c.Scopes, " "))
|
|
||||||
}
|
|
||||||
if state != "" {
|
|
||||||
// TODO(light): Docs say never to omit state; don't allow empty.
|
|
||||||
v.Set("state", state)
|
|
||||||
}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt.setValue(v)
|
|
||||||
}
|
|
||||||
if strings.Contains(c.Endpoint.AuthURL, "?") {
|
|
||||||
buf.WriteByte('&')
|
|
||||||
} else {
|
|
||||||
buf.WriteByte('?')
|
|
||||||
}
|
|
||||||
buf.WriteString(v.Encode())
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// PasswordCredentialsToken converts a resource owner username and password
|
|
||||||
// pair into a token.
|
|
||||||
//
|
|
||||||
// Per the RFC, this grant type should only be used "when there is a high
|
|
||||||
// degree of trust between the resource owner and the client (e.g., the client
|
|
||||||
// is part of the device operating system or a highly privileged application),
|
|
||||||
// and when other authorization grant types are not available."
|
|
||||||
// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info.
|
|
||||||
//
|
|
||||||
// The provided context optionally controls which HTTP client is used. See the HTTPClient variable.
|
|
||||||
func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) {
|
|
||||||
v := url.Values{
|
|
||||||
"grant_type": {"password"},
|
|
||||||
"username": {username},
|
|
||||||
"password": {password},
|
|
||||||
}
|
|
||||||
if len(c.Scopes) > 0 {
|
|
||||||
v.Set("scope", strings.Join(c.Scopes, " "))
|
|
||||||
}
|
|
||||||
return retrieveToken(ctx, c, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exchange converts an authorization code into a token.
|
|
||||||
//
|
|
||||||
// It is used after a resource provider redirects the user back
|
|
||||||
// to the Redirect URI (the URL obtained from AuthCodeURL).
|
|
||||||
//
|
|
||||||
// The provided context optionally controls which HTTP client is used. See the HTTPClient variable.
|
|
||||||
//
|
|
||||||
// The code will be in the *http.Request.FormValue("code"). Before
|
|
||||||
// calling Exchange, be sure to validate FormValue("state").
|
|
||||||
//
|
|
||||||
// Opts may include the PKCE verifier code if previously used in AuthCodeURL.
|
|
||||||
// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
|
|
||||||
func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) {
|
|
||||||
v := url.Values{
|
|
||||||
"grant_type": {"authorization_code"},
|
|
||||||
"code": {code},
|
|
||||||
}
|
|
||||||
if c.RedirectURL != "" {
|
|
||||||
v.Set("redirect_uri", c.RedirectURL)
|
|
||||||
}
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt.setValue(v)
|
|
||||||
}
|
|
||||||
return retrieveToken(ctx, c, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client returns an HTTP client using the provided token.
|
|
||||||
// The token will auto-refresh as necessary. The underlying
|
|
||||||
// HTTP transport will be obtained using the provided context.
|
|
||||||
// The returned client and its Transport should not be modified.
|
|
||||||
func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
|
|
||||||
return NewClient(ctx, c.TokenSource(ctx, t))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TokenSource returns a TokenSource that returns t until t expires,
|
|
||||||
// automatically refreshing it as necessary using the provided context.
|
|
||||||
//
|
|
||||||
// Most users will use Config.Client instead.
|
|
||||||
func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
|
|
||||||
tkr := &tokenRefresher{
|
|
||||||
ctx: ctx,
|
|
||||||
conf: c,
|
|
||||||
}
|
|
||||||
if t != nil {
|
|
||||||
tkr.refreshToken = t.RefreshToken
|
|
||||||
}
|
|
||||||
return &reuseTokenSource{
|
|
||||||
t: t,
|
|
||||||
new: tkr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token"
|
|
||||||
// HTTP requests to renew a token using a RefreshToken.
|
|
||||||
type tokenRefresher struct {
|
|
||||||
ctx context.Context // used to get HTTP requests
|
|
||||||
conf *Config
|
|
||||||
refreshToken string
|
|
||||||
}
|
|
||||||
|
|
||||||
// WARNING: Token is not safe for concurrent access, as it
|
|
||||||
// updates the tokenRefresher's refreshToken field.
|
|
||||||
// Within this package, it is used by reuseTokenSource which
|
|
||||||
// synchronizes calls to this method with its own mutex.
|
|
||||||
func (tf *tokenRefresher) Token() (*Token, error) {
|
|
||||||
if tf.refreshToken == "" {
|
|
||||||
return nil, errors.New("oauth2: token expired and refresh token is not set")
|
|
||||||
}
|
|
||||||
|
|
||||||
tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{
|
|
||||||
"grant_type": {"refresh_token"},
|
|
||||||
"refresh_token": {tf.refreshToken},
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if tf.refreshToken != tk.RefreshToken {
|
|
||||||
tf.refreshToken = tk.RefreshToken
|
|
||||||
}
|
|
||||||
return tk, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// reuseTokenSource is a TokenSource that holds a single token in memory
|
|
||||||
// and validates its expiry before each call to retrieve it with
|
|
||||||
// Token. If it's expired, it will be auto-refreshed using the
|
|
||||||
// new TokenSource.
|
|
||||||
type reuseTokenSource struct {
|
|
||||||
new TokenSource // called when t is expired.
|
|
||||||
|
|
||||||
mu sync.Mutex // guards t
|
|
||||||
t *Token
|
|
||||||
}
|
|
||||||
|
|
||||||
// Token returns the current token if it's still valid, else will
|
|
||||||
// refresh the current token (using r.Context for HTTP client
|
|
||||||
// information) and return the new one.
|
|
||||||
func (s *reuseTokenSource) Token() (*Token, error) {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
if s.t.Valid() {
|
|
||||||
return s.t, nil
|
|
||||||
}
|
|
||||||
t, err := s.new.Token()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.t = t
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticTokenSource returns a TokenSource that always returns the same token.
|
|
||||||
// Because the provided token t is never refreshed, StaticTokenSource is only
|
|
||||||
// useful for tokens that never expire.
|
|
||||||
func StaticTokenSource(t *Token) TokenSource {
|
|
||||||
return staticTokenSource{t}
|
|
||||||
}
|
|
||||||
|
|
||||||
// staticTokenSource is a TokenSource that always returns the same Token.
|
|
||||||
type staticTokenSource struct {
|
|
||||||
t *Token
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s staticTokenSource) Token() (*Token, error) {
|
|
||||||
return s.t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPClient is the context key to use with golang.org/x/net/context's
|
|
||||||
// WithValue function to associate an *http.Client value with a context.
|
|
||||||
var HTTPClient internal.ContextKey
|
|
||||||
|
|
||||||
// NewClient creates an *http.Client from a Context and TokenSource.
|
|
||||||
// The returned client is not valid beyond the lifetime of the context.
|
|
||||||
//
|
|
||||||
// Note that if a custom *http.Client is provided via the Context it
|
|
||||||
// is used only for token acquisition and is not used to configure the
|
|
||||||
// *http.Client returned from NewClient.
|
|
||||||
//
|
|
||||||
// As a special case, if src is nil, a non-OAuth2 client is returned
|
|
||||||
// using the provided context. This exists to support related OAuth2
|
|
||||||
// packages.
|
|
||||||
func NewClient(ctx context.Context, src TokenSource) *http.Client {
|
|
||||||
if src == nil {
|
|
||||||
return internal.ContextClient(ctx)
|
|
||||||
}
|
|
||||||
return &http.Client{
|
|
||||||
Transport: &Transport{
|
|
||||||
Base: internal.ContextClient(ctx).Transport,
|
|
||||||
Source: ReuseTokenSource(nil, src),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReuseTokenSource returns a TokenSource which repeatedly returns the
|
|
||||||
// same token as long as it's valid, starting with t.
|
|
||||||
// When its cached token is invalid, a new token is obtained from src.
|
|
||||||
//
|
|
||||||
// ReuseTokenSource is typically used to reuse tokens from a cache
|
|
||||||
// (such as a file on disk) between runs of a program, rather than
|
|
||||||
// obtaining new tokens unnecessarily.
|
|
||||||
//
|
|
||||||
// The initial token t may be nil, in which case the TokenSource is
|
|
||||||
// wrapped in a caching version if it isn't one already. This also
|
|
||||||
// means it's always safe to wrap ReuseTokenSource around any other
|
|
||||||
// TokenSource without adverse effects.
|
|
||||||
func ReuseTokenSource(t *Token, src TokenSource) TokenSource {
|
|
||||||
// Don't wrap a reuseTokenSource in itself. That would work,
|
|
||||||
// but cause an unnecessary number of mutex operations.
|
|
||||||
// Just build the equivalent one.
|
|
||||||
if rt, ok := src.(*reuseTokenSource); ok {
|
|
||||||
if t == nil {
|
|
||||||
// Just use it directly.
|
|
||||||
return rt
|
|
||||||
}
|
|
||||||
src = rt.new
|
|
||||||
}
|
|
||||||
return &reuseTokenSource{
|
|
||||||
t: t,
|
|
||||||
new: src,
|
|
||||||
}
|
|
||||||
}
|
|
178
vendor/golang.org/x/oauth2/token.go
generated
vendored
178
vendor/golang.org/x/oauth2/token.go
generated
vendored
@ -1,178 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package oauth2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"golang.org/x/oauth2/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// expiryDelta determines how earlier a token should be considered
|
|
||||||
// expired than its actual expiration time. It is used to avoid late
|
|
||||||
// expirations due to client-server time mismatches.
|
|
||||||
const expiryDelta = 10 * time.Second
|
|
||||||
|
|
||||||
// Token represents the credentials used to authorize
|
|
||||||
// the requests to access protected resources on the OAuth 2.0
|
|
||||||
// provider's backend.
|
|
||||||
//
|
|
||||||
// Most users of this package should not access fields of Token
|
|
||||||
// directly. They're exported mostly for use by related packages
|
|
||||||
// implementing derivative OAuth2 flows.
|
|
||||||
type Token struct {
|
|
||||||
// AccessToken is the token that authorizes and authenticates
|
|
||||||
// the requests.
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
|
|
||||||
// TokenType is the type of token.
|
|
||||||
// The Type method returns either this or "Bearer", the default.
|
|
||||||
TokenType string `json:"token_type,omitempty"`
|
|
||||||
|
|
||||||
// RefreshToken is a token that's used by the application
|
|
||||||
// (as opposed to the user) to refresh the access token
|
|
||||||
// if it expires.
|
|
||||||
RefreshToken string `json:"refresh_token,omitempty"`
|
|
||||||
|
|
||||||
// Expiry is the optional expiration time of the access token.
|
|
||||||
//
|
|
||||||
// If zero, TokenSource implementations will reuse the same
|
|
||||||
// token forever and RefreshToken or equivalent
|
|
||||||
// mechanisms for that TokenSource will not be used.
|
|
||||||
Expiry time.Time `json:"expiry,omitempty"`
|
|
||||||
|
|
||||||
// raw optionally contains extra metadata from the server
|
|
||||||
// when updating a token.
|
|
||||||
raw interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type returns t.TokenType if non-empty, else "Bearer".
|
|
||||||
func (t *Token) Type() string {
|
|
||||||
if strings.EqualFold(t.TokenType, "bearer") {
|
|
||||||
return "Bearer"
|
|
||||||
}
|
|
||||||
if strings.EqualFold(t.TokenType, "mac") {
|
|
||||||
return "MAC"
|
|
||||||
}
|
|
||||||
if strings.EqualFold(t.TokenType, "basic") {
|
|
||||||
return "Basic"
|
|
||||||
}
|
|
||||||
if t.TokenType != "" {
|
|
||||||
return t.TokenType
|
|
||||||
}
|
|
||||||
return "Bearer"
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetAuthHeader sets the Authorization header to r using the access
|
|
||||||
// token in t.
|
|
||||||
//
|
|
||||||
// This method is unnecessary when using Transport or an HTTP Client
|
|
||||||
// returned by this package.
|
|
||||||
func (t *Token) SetAuthHeader(r *http.Request) {
|
|
||||||
r.Header.Set("Authorization", t.Type()+" "+t.AccessToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithExtra returns a new Token that's a clone of t, but using the
|
|
||||||
// provided raw extra map. This is only intended for use by packages
|
|
||||||
// implementing derivative OAuth2 flows.
|
|
||||||
func (t *Token) WithExtra(extra interface{}) *Token {
|
|
||||||
t2 := new(Token)
|
|
||||||
*t2 = *t
|
|
||||||
t2.raw = extra
|
|
||||||
return t2
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extra returns an extra field.
|
|
||||||
// Extra fields are key-value pairs returned by the server as a
|
|
||||||
// part of the token retrieval response.
|
|
||||||
func (t *Token) Extra(key string) interface{} {
|
|
||||||
if raw, ok := t.raw.(map[string]interface{}); ok {
|
|
||||||
return raw[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
vals, ok := t.raw.(url.Values)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
v := vals.Get(key)
|
|
||||||
switch s := strings.TrimSpace(v); strings.Count(s, ".") {
|
|
||||||
case 0: // Contains no "."; try to parse as int
|
|
||||||
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
case 1: // Contains a single "."; try to parse as float
|
|
||||||
if f, err := strconv.ParseFloat(s, 64); err == nil {
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// timeNow is time.Now but pulled out as a variable for tests.
|
|
||||||
var timeNow = time.Now
|
|
||||||
|
|
||||||
// expired reports whether the token is expired.
|
|
||||||
// t must be non-nil.
|
|
||||||
func (t *Token) expired() bool {
|
|
||||||
if t.Expiry.IsZero() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return t.Expiry.Round(0).Add(-expiryDelta).Before(timeNow())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid reports whether t is non-nil, has an AccessToken, and is not expired.
|
|
||||||
func (t *Token) Valid() bool {
|
|
||||||
return t != nil && t.AccessToken != "" && !t.expired()
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokenFromInternal maps an *internal.Token struct into
|
|
||||||
// a *Token struct.
|
|
||||||
func tokenFromInternal(t *internal.Token) *Token {
|
|
||||||
if t == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &Token{
|
|
||||||
AccessToken: t.AccessToken,
|
|
||||||
TokenType: t.TokenType,
|
|
||||||
RefreshToken: t.RefreshToken,
|
|
||||||
Expiry: t.Expiry,
|
|
||||||
raw: t.Raw,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieveToken takes a *Config and uses that to retrieve an *internal.Token.
|
|
||||||
// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along
|
|
||||||
// with an error..
|
|
||||||
func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) {
|
|
||||||
tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle))
|
|
||||||
if err != nil {
|
|
||||||
if rErr, ok := err.(*internal.RetrieveError); ok {
|
|
||||||
return nil, (*RetrieveError)(rErr)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tokenFromInternal(tk), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetrieveError is the error returned when the token endpoint returns a
|
|
||||||
// non-2XX HTTP status code.
|
|
||||||
type RetrieveError struct {
|
|
||||||
Response *http.Response
|
|
||||||
// Body is the body that was consumed by reading Response.Body.
|
|
||||||
// It may be truncated.
|
|
||||||
Body []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RetrieveError) Error() string {
|
|
||||||
return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body)
|
|
||||||
}
|
|
89
vendor/golang.org/x/oauth2/transport.go
generated
vendored
89
vendor/golang.org/x/oauth2/transport.go
generated
vendored
@ -1,89 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package oauth2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
|
|
||||||
// wrapping a base RoundTripper and adding an Authorization header
|
|
||||||
// with a token from the supplied Sources.
|
|
||||||
//
|
|
||||||
// Transport is a low-level mechanism. Most code will use the
|
|
||||||
// higher-level Config.Client method instead.
|
|
||||||
type Transport struct {
|
|
||||||
// Source supplies the token to add to outgoing requests'
|
|
||||||
// Authorization headers.
|
|
||||||
Source TokenSource
|
|
||||||
|
|
||||||
// Base is the base RoundTripper used to make HTTP requests.
|
|
||||||
// If nil, http.DefaultTransport is used.
|
|
||||||
Base http.RoundTripper
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoundTrip authorizes and authenticates the request with an
|
|
||||||
// access token from Transport's Source.
|
|
||||||
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
||||||
reqBodyClosed := false
|
|
||||||
if req.Body != nil {
|
|
||||||
defer func() {
|
|
||||||
if !reqBodyClosed {
|
|
||||||
req.Body.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.Source == nil {
|
|
||||||
return nil, errors.New("oauth2: Transport's Source is nil")
|
|
||||||
}
|
|
||||||
token, err := t.Source.Token()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req2 := cloneRequest(req) // per RoundTripper contract
|
|
||||||
token.SetAuthHeader(req2)
|
|
||||||
|
|
||||||
// req.Body is assumed to be closed by the base RoundTripper.
|
|
||||||
reqBodyClosed = true
|
|
||||||
return t.base().RoundTrip(req2)
|
|
||||||
}
|
|
||||||
|
|
||||||
var cancelOnce sync.Once
|
|
||||||
|
|
||||||
// CancelRequest does nothing. It used to be a legacy cancellation mechanism
|
|
||||||
// but now only it only logs on first use to warn that it's deprecated.
|
|
||||||
//
|
|
||||||
// Deprecated: use contexts for cancellation instead.
|
|
||||||
func (t *Transport) CancelRequest(req *http.Request) {
|
|
||||||
cancelOnce.Do(func() {
|
|
||||||
log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Transport) base() http.RoundTripper {
|
|
||||||
if t.Base != nil {
|
|
||||||
return t.Base
|
|
||||||
}
|
|
||||||
return http.DefaultTransport
|
|
||||||
}
|
|
||||||
|
|
||||||
// cloneRequest returns a clone of the provided *http.Request.
|
|
||||||
// The clone is a shallow copy of the struct and its Header map.
|
|
||||||
func cloneRequest(r *http.Request) *http.Request {
|
|
||||||
// shallow copy of the struct
|
|
||||||
r2 := new(http.Request)
|
|
||||||
*r2 = *r
|
|
||||||
// deep copy of the Header
|
|
||||||
r2.Header = make(http.Header, len(r.Header))
|
|
||||||
for k, s := range r.Header {
|
|
||||||
r2.Header[k] = append([]string(nil), s...)
|
|
||||||
}
|
|
||||||
return r2
|
|
||||||
}
|
|
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
61
vendor/golang.org/x/sys/unix/mkasm_darwin.go
generated
vendored
@ -1,61 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
|
|
||||||
//This program must be run after mksyscall.go.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
in1, err := ioutil.ReadFile("syscall_darwin.go")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't open syscall_darwin.go: %s", err)
|
|
||||||
}
|
|
||||||
arch := os.Args[1]
|
|
||||||
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
|
|
||||||
}
|
|
||||||
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
|
|
||||||
}
|
|
||||||
in := string(in1) + string(in2) + string(in3)
|
|
||||||
|
|
||||||
trampolines := map[string]bool{}
|
|
||||||
|
|
||||||
var out bytes.Buffer
|
|
||||||
|
|
||||||
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
|
|
||||||
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
|
|
||||||
fmt.Fprintf(&out, "\n")
|
|
||||||
fmt.Fprintf(&out, "// +build go1.12\n")
|
|
||||||
fmt.Fprintf(&out, "\n")
|
|
||||||
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
|
|
||||||
for _, line := range strings.Split(in, "\n") {
|
|
||||||
if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fn := line[5 : len(line)-13]
|
|
||||||
if !trampolines[fn] {
|
|
||||||
trampolines[fn] = true
|
|
||||||
fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
|
|
||||||
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
|
|
||||||
}
|
|
||||||
}
|
|
106
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
106
vendor/golang.org/x/sys/unix/mkpost.go
generated
vendored
@ -1,106 +0,0 @@
|
|||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// mkpost processes the output of cgo -godefs to
|
|
||||||
// modify the generated types. It is used to clean up
|
|
||||||
// the sys API in an architecture specific manner.
|
|
||||||
//
|
|
||||||
// mkpost is run after cgo -godefs; see README.md.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goos := os.Getenv("GOOS")
|
|
||||||
goarch := os.Getenv("GOARCH_TARGET")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = os.Getenv("GOARCH")
|
|
||||||
}
|
|
||||||
// Check that we are using the Docker-based build system if we should be.
|
|
||||||
if goos == "linux" {
|
|
||||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
|
||||||
os.Stderr.WriteString("In the Docker-based build system, mkpost should not be called directly.\n")
|
|
||||||
os.Stderr.WriteString("See README.md\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intentionally export __val fields in Fsid and Sigset_t
|
|
||||||
valRegex := regexp.MustCompile(`type (Fsid|Sigset_t) struct {(\s+)X__val(\s+\S+\s+)}`)
|
|
||||||
b = valRegex.ReplaceAll(b, []byte("type $1 struct {${2}Val$3}"))
|
|
||||||
|
|
||||||
// Intentionally export __fds_bits field in FdSet
|
|
||||||
fdSetRegex := regexp.MustCompile(`type (FdSet) struct {(\s+)X__fds_bits(\s+\S+\s+)}`)
|
|
||||||
b = fdSetRegex.ReplaceAll(b, []byte("type $1 struct {${2}Bits$3}"))
|
|
||||||
|
|
||||||
// If we have empty Ptrace structs, we should delete them. Only s390x emits
|
|
||||||
// nonempty Ptrace structs.
|
|
||||||
ptraceRexexp := regexp.MustCompile(`type Ptrace((Psw|Fpregs|Per) struct {\s*})`)
|
|
||||||
b = ptraceRexexp.ReplaceAll(b, nil)
|
|
||||||
|
|
||||||
// Replace the control_regs union with a blank identifier for now.
|
|
||||||
controlRegsRegex := regexp.MustCompile(`(Control_regs)\s+\[0\]uint64`)
|
|
||||||
b = controlRegsRegex.ReplaceAll(b, []byte("_ [0]uint64"))
|
|
||||||
|
|
||||||
// Remove fields that are added by glibc
|
|
||||||
// Note that this is unstable as the identifers are private.
|
|
||||||
removeFieldsRegex := regexp.MustCompile(`X__glibc\S*`)
|
|
||||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Convert [65]int8 to [65]byte in Utsname members to simplify
|
|
||||||
// conversion to string; see golang.org/issue/20753
|
|
||||||
convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
|
|
||||||
b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
|
|
||||||
|
|
||||||
// Convert [1024]int8 to [1024]byte in Ptmget members
|
|
||||||
convertPtmget := regexp.MustCompile(`([SC]n)(\s+)\[(\d+)\]u?int8`)
|
|
||||||
b = convertPtmget.ReplaceAll(b, []byte("$1[$3]byte"))
|
|
||||||
|
|
||||||
// Remove spare fields (e.g. in Statx_t)
|
|
||||||
spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
|
|
||||||
b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Remove cgo padding fields
|
|
||||||
removePaddingFieldsRegex := regexp.MustCompile(`Pad_cgo_\d+`)
|
|
||||||
b = removePaddingFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Remove padding, hidden, or unused fields
|
|
||||||
removeFieldsRegex = regexp.MustCompile(`\b(X_\S+|Padding)`)
|
|
||||||
b = removeFieldsRegex.ReplaceAll(b, []byte("_"))
|
|
||||||
|
|
||||||
// Remove the first line of warning from cgo
|
|
||||||
b = b[bytes.IndexByte(b, '\n')+1:]
|
|
||||||
// Modify the command in the header to include:
|
|
||||||
// mkpost, our own warning, and a build tag.
|
|
||||||
replacement := fmt.Sprintf(`$1 | go run mkpost.go
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s,%s`, goarch, goos)
|
|
||||||
cgoCommandRegex := regexp.MustCompile(`(cgo -godefs .*)`)
|
|
||||||
b = cgoCommandRegex.ReplaceAll(b, []byte(replacement))
|
|
||||||
|
|
||||||
// gofmt
|
|
||||||
b, err = format.Source(b)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Stdout.Write(b)
|
|
||||||
}
|
|
402
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
402
vendor/golang.org/x/sys/unix/mksyscall.go
generated
vendored
@ -1,402 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_darwin.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named errno.
|
|
||||||
|
|
||||||
A line beginning with //sysnb is like //sys, except that the
|
|
||||||
goroutine will not be suspended during the execution of the system
|
|
||||||
call. This must only be used for system calls which can never
|
|
||||||
block, as otherwise the system call could cause all goroutines to
|
|
||||||
hang.
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
plan9 = flag.Bool("plan9", false, "plan9")
|
|
||||||
openbsd = flag.Bool("openbsd", false, "openbsd")
|
|
||||||
netbsd = flag.Bool("netbsd", false, "netbsd")
|
|
||||||
dragonfly = flag.Bool("dragonfly", false, "dragonfly")
|
|
||||||
arm = flag.Bool("arm", false, "arm") // 64-bit value should use (even, odd)-pair
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
filename = flag.String("output", "", "output file name (standard output if omitted)")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goos := os.Getenv("GOOS")
|
|
||||||
if goos == "" {
|
|
||||||
fmt.Fprintln(os.Stderr, "GOOS not defined in environment")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
goarch := os.Getenv("GOARCH_TARGET")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = os.Getenv("GOARCH")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that we are using the Docker-based build system if we should
|
|
||||||
if goos == "linux" {
|
|
||||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
|
||||||
fmt.Fprintf(os.Stderr, "In the Docker-based build system, mksyscall should not be called directly.\n")
|
|
||||||
fmt.Fprintf(os.Stderr, "See README.md\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
libc := false
|
|
||||||
if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
|
|
||||||
libc = true
|
|
||||||
}
|
|
||||||
trampolines := map[string]bool{}
|
|
||||||
|
|
||||||
text := ""
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, errno error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, sysname := f[2], f[3], f[4], f[5]
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
outDecl := ""
|
|
||||||
if len(out) > 0 {
|
|
||||||
outDecl = fmt.Sprintf(" (%s)", strings.Join(out, ", "))
|
|
||||||
}
|
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outDecl)
|
|
||||||
|
|
||||||
// Check if err return available
|
|
||||||
errvar := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string
|
|
||||||
n := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
|
||||||
text += fmt.Sprintf("\t_p%d, %s = BytePtrFromString(%s)\n", n, errvar, p.Name)
|
|
||||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *byte\n", n)
|
|
||||||
text += fmt.Sprintf("\t_p%d, _ = BytePtrFromString(%s)\n", n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass dummy pointer in that case.
|
|
||||||
// Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
|
|
||||||
text += fmt.Sprintf("\tvar _p%d unsafe.Pointer\n", n)
|
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = unsafe.Pointer(&%s[0])\n\t}", p.Name, n, p.Name)
|
|
||||||
text += fmt.Sprintf(" else {\n\t\t_p%d = unsafe.Pointer(&_zero)\n\t}\n", n)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && (*openbsd || *netbsd) {
|
|
||||||
args = append(args, "0")
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else if endianness == "little-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "int64" && *dragonfly {
|
|
||||||
if regexp.MustCompile(`^(?i)extp(read|write)`).FindStringSubmatch(funct) == nil {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else if endianness == "little-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "int64" && endianness != "" {
|
|
||||||
if len(args)%2 == 1 && *arm {
|
|
||||||
// arm abi specifies 64-bit argument uses
|
|
||||||
// (even, odd) pair
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which form to use; pad args with zeros.
|
|
||||||
asm := "Syscall"
|
|
||||||
if nonblock != nil {
|
|
||||||
if errvar == "" && goos == "linux" {
|
|
||||||
asm = "RawSyscallNoError"
|
|
||||||
} else {
|
|
||||||
asm = "RawSyscall"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if errvar == "" && goos == "linux" {
|
|
||||||
asm = "SyscallNoError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(args) <= 3 {
|
|
||||||
for len(args) < 3 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else if len(args) <= 6 {
|
|
||||||
asm += "6"
|
|
||||||
for len(args) < 6 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else if len(args) <= 9 {
|
|
||||||
asm += "9"
|
|
||||||
for len(args) < 9 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s too many arguments to system call\n", path, funct)
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call number.
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = "SYS_" + funct
|
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
|
||||||
sysname = strings.ToUpper(sysname)
|
|
||||||
}
|
|
||||||
|
|
||||||
var libcFn string
|
|
||||||
if libc {
|
|
||||||
asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
|
|
||||||
sysname = strings.TrimPrefix(sysname, "SYS_") // remove SYS_
|
|
||||||
sysname = strings.ToLower(sysname) // lowercase
|
|
||||||
if sysname == "getdirentries64" {
|
|
||||||
// Special case - libSystem name and
|
|
||||||
// raw syscall name don't match.
|
|
||||||
sysname = "__getdirentries64"
|
|
||||||
}
|
|
||||||
libcFn = sysname
|
|
||||||
sysname = "funcPC(libc_" + sysname + "_trampoline)"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ")
|
|
||||||
call := fmt.Sprintf("%s(%s, %s)", asm, sysname, arglist)
|
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := ""
|
|
||||||
ret := []string{"_", "_", "_"}
|
|
||||||
doErrno := false
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" && !*plan9 {
|
|
||||||
reg = "e1"
|
|
||||||
ret[2] = reg
|
|
||||||
doErrno = true
|
|
||||||
} else if p.Name == "err" && *plan9 {
|
|
||||||
ret[0] = "r0"
|
|
||||||
ret[2] = "e1"
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i] = reg
|
|
||||||
}
|
|
||||||
if p.Type == "bool" {
|
|
||||||
reg = fmt.Sprintf("%s != 0", reg)
|
|
||||||
}
|
|
||||||
if p.Type == "int64" && endianness != "" {
|
|
||||||
// 64-bit number in r1:r0 or r0:r1.
|
|
||||||
if i+2 > len(out) {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s not enough registers for int64 return\n", path, funct)
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
|
||||||
}
|
|
||||||
ret[i] = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
|
||||||
}
|
|
||||||
if reg != "e1" || *plan9 {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
|
||||||
text += fmt.Sprintf("\t%s\n", call)
|
|
||||||
} else {
|
|
||||||
if errvar == "" && goos == "linux" {
|
|
||||||
// raw syscall without error on Linux, see golang.org/issue/22924
|
|
||||||
text += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], call)
|
|
||||||
} else {
|
|
||||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text += body
|
|
||||||
|
|
||||||
if *plan9 && ret[2] == "e1" {
|
|
||||||
text += "\tif int32(r0) == -1 {\n"
|
|
||||||
text += "\t\terr = e1\n"
|
|
||||||
text += "\t}\n"
|
|
||||||
} else if doErrno {
|
|
||||||
text += "\tif e1 != 0 {\n"
|
|
||||||
text += "\t\terr = errnoErr(e1)\n"
|
|
||||||
text += "\t}\n"
|
|
||||||
}
|
|
||||||
text += "\treturn\n"
|
|
||||||
text += "}\n\n"
|
|
||||||
|
|
||||||
if libc && !trampolines[libcFn] {
|
|
||||||
// some system calls share a trampoline, like read and readlen.
|
|
||||||
trampolines[libcFn] = true
|
|
||||||
// Declare assembly trampoline.
|
|
||||||
text += fmt.Sprintf("func libc_%s_trampoline()\n", libcFn)
|
|
||||||
// Assembly trampoline calls the libc_* function, which this magic
|
|
||||||
// redirects to use the function from libSystem.
|
|
||||||
text += fmt.Sprintf("//go:linkname libc_%s libc_%s\n", libcFn, libcFn)
|
|
||||||
text += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"/usr/lib/libSystem.B.dylib\"\n", libcFn, libcFn)
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ syscall.Errno
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
404
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
404
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.go
generated
vendored
@ -1,404 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_aix.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named err.
|
|
||||||
* If go func name needs to be different than its libc name,
|
|
||||||
* or the function is not in libc, name could be specified
|
|
||||||
* at the end, after "=" sign, like
|
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
aix = flag.Bool("aix", false, "aix")
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall_aix_ppc.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
pack := ""
|
|
||||||
text := ""
|
|
||||||
cExtern := "/*\n#include <stdint.h>\n#include <stddef.h>\n"
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
|
||||||
pack = p[1]
|
|
||||||
}
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
inps = strings.Join(in, ", ")
|
|
||||||
outps = strings.Join(out, ", ")
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
|
|
||||||
// Check if value return, err return available
|
|
||||||
errvar := ""
|
|
||||||
retvar := ""
|
|
||||||
rettype := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
} else {
|
|
||||||
retvar = p.Name
|
|
||||||
rettype = p.Type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call name.
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = funct
|
|
||||||
}
|
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
cRettype := ""
|
|
||||||
if rettype == "unsafe.Pointer" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "uintptr" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "int" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int32" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int64" {
|
|
||||||
cRettype = "long long"
|
|
||||||
} else if rettype == "uint32" {
|
|
||||||
cRettype = "unsigned int"
|
|
||||||
} else if rettype == "uint64" {
|
|
||||||
cRettype = "unsigned long long"
|
|
||||||
} else {
|
|
||||||
cRettype = "int"
|
|
||||||
}
|
|
||||||
if sysname == "exit" {
|
|
||||||
cRettype = "void"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change p.Types to c
|
|
||||||
var cIn []string
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t", "size_t")
|
|
||||||
} else if p.Type == "unsafe.Pointer" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
cIn = append(cIn, "long long")
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
cIn = append(cIn, "unsigned int")
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
cIn = append(cIn, "unsigned long long")
|
|
||||||
} else {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if funct != "fcntl" && funct != "FcntlInt" && funct != "readlen" && funct != "writelen" {
|
|
||||||
// Imports of system calls from libc
|
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
|
||||||
cIn := strings.Join(cIn, ", ")
|
|
||||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// So file name.
|
|
||||||
if *aix {
|
|
||||||
if modname == "" {
|
|
||||||
modname = "libc.a/shr_64.o"
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strconvfunc := "C.CString"
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
if outps != "" {
|
|
||||||
outps = fmt.Sprintf(" (%s)", outps)
|
|
||||||
}
|
|
||||||
if text != "" {
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string
|
|
||||||
n := 0
|
|
||||||
argN := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, "C.uintptr_t(uintptr(unsafe.Pointer("+p.Name+")))")
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
text += fmt.Sprintf("\t_p%d := uintptr(unsafe.Pointer(%s(%s)))\n", n, strconvfunc, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(unsafe.Pointer(_p%d)))", n))
|
|
||||||
n++
|
|
||||||
text += fmt.Sprintf("\tvar _p%d int\n", n)
|
|
||||||
text += fmt.Sprintf("\t_p%d = len(%s)\n", n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("C.size_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && endianness != "" {
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
}
|
|
||||||
n++
|
|
||||||
} else if p.Type == "bool" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
|
||||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
|
||||||
args = append(args, fmt.Sprintf("_p%d", n))
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
|
||||||
} else if p.Type == "unsafe.Pointer" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(uintptr(%s))", p.Name))
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
if (argN == 2) && ((funct == "readlen") || (funct == "writelen")) {
|
|
||||||
args = append(args, fmt.Sprintf("C.size_t(%s)", p.Name))
|
|
||||||
} else if argN == 0 && funct == "fcntl" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else if (argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt")) {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
args = append(args, fmt.Sprintf("C.longlong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uint(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
args = append(args, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
args = append(args, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
argN++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ")
|
|
||||||
call := ""
|
|
||||||
if sysname == "exit" {
|
|
||||||
if errvar != "" {
|
|
||||||
call += "er :="
|
|
||||||
} else {
|
|
||||||
call += ""
|
|
||||||
}
|
|
||||||
} else if errvar != "" {
|
|
||||||
call += "r0,er :="
|
|
||||||
} else if retvar != "" {
|
|
||||||
call += "r0,_ :="
|
|
||||||
} else {
|
|
||||||
call += ""
|
|
||||||
}
|
|
||||||
call += fmt.Sprintf("C.%s(%s)", sysname, arglist)
|
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := ""
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" {
|
|
||||||
reg = "e1"
|
|
||||||
} else {
|
|
||||||
reg = "r0"
|
|
||||||
}
|
|
||||||
if reg != "e1" {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify return
|
|
||||||
if sysname != "exit" && errvar != "" {
|
|
||||||
if regexp.MustCompile(`^uintptr`).FindStringSubmatch(cRettype) != nil {
|
|
||||||
body += "\tif (uintptr(r0) ==^uintptr(0) && er != nil) {\n"
|
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
|
||||||
body += "\t}\n"
|
|
||||||
} else {
|
|
||||||
body += "\tif (r0 ==-1 && er != nil) {\n"
|
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
|
||||||
body += "\t}\n"
|
|
||||||
}
|
|
||||||
} else if errvar != "" {
|
|
||||||
body += "\tif (er != nil) {\n"
|
|
||||||
body += fmt.Sprintf("\t\t%s = er\n", errvar)
|
|
||||||
body += "\t}\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
text += fmt.Sprintf("\t%s\n", call)
|
|
||||||
text += body
|
|
||||||
|
|
||||||
text += "\treturn\n"
|
|
||||||
text += "}\n"
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
imp := ""
|
|
||||||
if pack != "unix" {
|
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
|
||||||
|
|
||||||
}
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, cExtern, imp, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
602
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
602
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.go
generated
vendored
@ -1,602 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_aix.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named err.
|
|
||||||
* If go func name needs to be different than its libc name,
|
|
||||||
* or the function is not in libc, name could be specified
|
|
||||||
* at the end, after "=" sign, like
|
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
|
|
||||||
|
|
||||||
This program will generate three files and handle both gc and gccgo implementation:
|
|
||||||
- zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
|
|
||||||
- zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
|
||||||
- zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
|
|
||||||
|
|
||||||
The generated code looks like this
|
|
||||||
|
|
||||||
zsyscall_aix_ppc64.go
|
|
||||||
func asyscall(...) (n int, err error) {
|
|
||||||
// Pointer Creation
|
|
||||||
r1, e1 := callasyscall(...)
|
|
||||||
// Type Conversion
|
|
||||||
// Error Handler
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
zsyscall_aix_ppc64_gc.go
|
|
||||||
//go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
|
||||||
//go:linkname libc_asyscall libc_asyscall
|
|
||||||
var asyscall syscallFunc
|
|
||||||
|
|
||||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
|
||||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
zsyscall_aix_ppc64_ggcgo.go
|
|
||||||
|
|
||||||
// int asyscall(...)
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
func callasyscall(...) (r1 uintptr, e1 Errno) {
|
|
||||||
r1 = uintptr(C.asyscall(...))
|
|
||||||
e1 = syscall.GetErrno()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
aix = flag.Bool("aix", false, "aix")
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall_aix_ppc64.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_aix_ppc64.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
pack := ""
|
|
||||||
// GCCGO
|
|
||||||
textgccgo := ""
|
|
||||||
cExtern := "/*\n#include <stdint.h>\n"
|
|
||||||
// GC
|
|
||||||
textgc := ""
|
|
||||||
dynimports := ""
|
|
||||||
linknames := ""
|
|
||||||
var vars []string
|
|
||||||
// COMMON
|
|
||||||
textcommon := ""
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
|
||||||
pack = p[1]
|
|
||||||
}
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
inps = strings.Join(in, ", ")
|
|
||||||
outps = strings.Join(out, ", ")
|
|
||||||
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = funct
|
|
||||||
}
|
|
||||||
|
|
||||||
onlyCommon := false
|
|
||||||
if funct == "readlen" || funct == "writelen" || funct == "FcntlInt" || funct == "FcntlFlock" {
|
|
||||||
// This function call another syscall which is already implemented.
|
|
||||||
// Therefore, the gc and gccgo part must not be generated.
|
|
||||||
onlyCommon = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
|
|
||||||
textcommon += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
if !onlyCommon {
|
|
||||||
textgccgo += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
textgc += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if value return, err return available
|
|
||||||
errvar := ""
|
|
||||||
rettype := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
} else {
|
|
||||||
rettype = p.Type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sysname = regexp.MustCompile(`([a-z])([A-Z])`).ReplaceAllString(sysname, `${1}_$2`)
|
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
// GCCGO Prototype return type
|
|
||||||
cRettype := ""
|
|
||||||
if rettype == "unsafe.Pointer" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "uintptr" {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(rettype) != nil {
|
|
||||||
cRettype = "uintptr_t"
|
|
||||||
} else if rettype == "int" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int32" {
|
|
||||||
cRettype = "int"
|
|
||||||
} else if rettype == "int64" {
|
|
||||||
cRettype = "long long"
|
|
||||||
} else if rettype == "uint32" {
|
|
||||||
cRettype = "unsigned int"
|
|
||||||
} else if rettype == "uint64" {
|
|
||||||
cRettype = "unsigned long long"
|
|
||||||
} else {
|
|
||||||
cRettype = "int"
|
|
||||||
}
|
|
||||||
if sysname == "exit" {
|
|
||||||
cRettype = "void"
|
|
||||||
}
|
|
||||||
|
|
||||||
// GCCGO Prototype arguments type
|
|
||||||
var cIn []string
|
|
||||||
for i, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t", "size_t")
|
|
||||||
} else if p.Type == "unsafe.Pointer" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
if (i == 0 || i == 2) && funct == "fcntl" {
|
|
||||||
// These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
|
||||||
cIn = append(cIn, "uintptr_t")
|
|
||||||
} else {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
cIn = append(cIn, "long long")
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
cIn = append(cIn, "unsigned int")
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
cIn = append(cIn, "unsigned long long")
|
|
||||||
} else {
|
|
||||||
cIn = append(cIn, "int")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !onlyCommon {
|
|
||||||
// GCCGO Prototype Generation
|
|
||||||
// Imports of system calls from libc
|
|
||||||
cExtern += fmt.Sprintf("%s %s", cRettype, sysname)
|
|
||||||
cIn := strings.Join(cIn, ", ")
|
|
||||||
cExtern += fmt.Sprintf("(%s);\n", cIn)
|
|
||||||
}
|
|
||||||
// GC Library name
|
|
||||||
if modname == "" {
|
|
||||||
modname = "libc.a/shr_64.o"
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: only syscall using libc are available\n", funct)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
sysvarname := fmt.Sprintf("libc_%s", sysname)
|
|
||||||
|
|
||||||
if !onlyCommon {
|
|
||||||
// GC Runtime import of function to allow cross-platform builds.
|
|
||||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic %s %s \"%s\"\n", sysvarname, sysname, modname)
|
|
||||||
// GC Link symbol to proc address variable.
|
|
||||||
linknames += fmt.Sprintf("//go:linkname %s %s\n", sysvarname, sysvarname)
|
|
||||||
// GC Library proc address variable.
|
|
||||||
vars = append(vars, sysvarname)
|
|
||||||
}
|
|
||||||
|
|
||||||
strconvfunc := "BytePtrFromString"
|
|
||||||
strconvtype := "*byte"
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
if outps != "" {
|
|
||||||
outps = fmt.Sprintf(" (%s)", outps)
|
|
||||||
}
|
|
||||||
if textcommon != "" {
|
|
||||||
textcommon += "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
textcommon += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outps)
|
|
||||||
|
|
||||||
// Prepare arguments tocall.
|
|
||||||
var argscommon []string // Arguments in the common part
|
|
||||||
var argscall []string // Arguments for call prototype
|
|
||||||
var argsgc []string // Arguments for gc call (with syscall6)
|
|
||||||
var argsgccgo []string // Arguments for gccgo call (with C.name_of_syscall)
|
|
||||||
n := 0
|
|
||||||
argN := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
|
||||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr ", n))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
textcommon += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
|
||||||
textcommon += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else if m := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); m != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
textcommon += fmt.Sprintf("\tvar _p%d *%s\n", n, m[1])
|
|
||||||
textcommon += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("len(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("_p%d uintptr", n), fmt.Sprintf("_lenp%d int", n))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("_p%d", n), fmt.Sprintf("uintptr(_lenp%d)", n))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(_p%d)", n), fmt.Sprintf("C.size_t(_lenp%d)", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && endianness != "" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses int64 with 32 bits mode. Case not yet implemented\n")
|
|
||||||
} else if p.Type == "bool" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses bool. Case not yet implemented\n")
|
|
||||||
} else if regexp.MustCompile(`^_`).FindStringSubmatch(p.Type) != nil || p.Type == "unsafe.Pointer" {
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else if p.Type == "int" {
|
|
||||||
if (argN == 0 || argN == 2) && ((funct == "fcntl") || (funct == "FcntlInt") || (funct == "FcntlFlock")) {
|
|
||||||
// These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
|
|
||||||
} else {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "int32" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int32", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
} else if p.Type == "int64" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int64", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.longlong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint32" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uint32", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uint(%s)", p.Name))
|
|
||||||
} else if p.Type == "uint64" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uint64", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.ulonglong(%s)", p.Name))
|
|
||||||
} else if p.Type == "uintptr" {
|
|
||||||
argscommon = append(argscommon, p.Name)
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s uintptr", p.Name))
|
|
||||||
argsgc = append(argsgc, p.Name)
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.uintptr_t(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
argscommon = append(argscommon, fmt.Sprintf("int(%s)", p.Name))
|
|
||||||
argscall = append(argscall, fmt.Sprintf("%s int", p.Name))
|
|
||||||
argsgc = append(argsgc, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
argsgccgo = append(argsgccgo, fmt.Sprintf("C.int(%s)", p.Name))
|
|
||||||
}
|
|
||||||
argN++
|
|
||||||
}
|
|
||||||
nargs := len(argsgc)
|
|
||||||
|
|
||||||
// COMMON function generation
|
|
||||||
argscommonlist := strings.Join(argscommon, ", ")
|
|
||||||
callcommon := fmt.Sprintf("call%s(%s)", sysname, argscommonlist)
|
|
||||||
ret := []string{"_", "_"}
|
|
||||||
body := ""
|
|
||||||
doErrno := false
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" {
|
|
||||||
reg = "e1"
|
|
||||||
ret[1] = reg
|
|
||||||
doErrno = true
|
|
||||||
} else {
|
|
||||||
reg = "r0"
|
|
||||||
ret[0] = reg
|
|
||||||
}
|
|
||||||
if p.Type == "bool" {
|
|
||||||
reg = fmt.Sprintf("%s != 0", reg)
|
|
||||||
}
|
|
||||||
if reg != "e1" {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ret[0] == "_" && ret[1] == "_" {
|
|
||||||
textcommon += fmt.Sprintf("\t%s\n", callcommon)
|
|
||||||
} else {
|
|
||||||
textcommon += fmt.Sprintf("\t%s, %s := %s\n", ret[0], ret[1], callcommon)
|
|
||||||
}
|
|
||||||
textcommon += body
|
|
||||||
|
|
||||||
if doErrno {
|
|
||||||
textcommon += "\tif e1 != 0 {\n"
|
|
||||||
textcommon += "\t\terr = errnoErr(e1)\n"
|
|
||||||
textcommon += "\t}\n"
|
|
||||||
}
|
|
||||||
textcommon += "\treturn\n"
|
|
||||||
textcommon += "}\n"
|
|
||||||
|
|
||||||
if onlyCommon {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// CALL Prototype
|
|
||||||
callProto := fmt.Sprintf("func call%s(%s) (r1 uintptr, e1 Errno) {\n", sysname, strings.Join(argscall, ", "))
|
|
||||||
|
|
||||||
// GC function generation
|
|
||||||
asm := "syscall6"
|
|
||||||
if nonblock != nil {
|
|
||||||
asm = "rawSyscall6"
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(argsgc) <= 6 {
|
|
||||||
for len(argsgc) < 6 {
|
|
||||||
argsgc = append(argsgc, "0")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call", funct)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
argsgclist := strings.Join(argsgc, ", ")
|
|
||||||
callgc := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, argsgclist)
|
|
||||||
|
|
||||||
textgc += callProto
|
|
||||||
textgc += fmt.Sprintf("\tr1, _, e1 = %s\n", callgc)
|
|
||||||
textgc += "\treturn\n}\n"
|
|
||||||
|
|
||||||
// GCCGO function generation
|
|
||||||
argsgccgolist := strings.Join(argsgccgo, ", ")
|
|
||||||
callgccgo := fmt.Sprintf("C.%s(%s)", sysname, argsgccgolist)
|
|
||||||
textgccgo += callProto
|
|
||||||
textgccgo += fmt.Sprintf("\tr1 = uintptr(%s)\n", callgccgo)
|
|
||||||
textgccgo += "\te1 = syscall.GetErrno()\n"
|
|
||||||
textgccgo += "\treturn\n}\n"
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
imp := ""
|
|
||||||
if pack != "unix" {
|
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64.go
|
|
||||||
err := ioutil.WriteFile("zsyscall_aix_ppc64.go",
|
|
||||||
[]byte(fmt.Sprintf(srcTemplate1, cmdLine(), buildTags(), pack, imp, textcommon)),
|
|
||||||
0644)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64_gc.go
|
|
||||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
|
||||||
vardecls += " syscallFunc"
|
|
||||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gc.go",
|
|
||||||
[]byte(fmt.Sprintf(srcTemplate2, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, textgc)),
|
|
||||||
0644)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print zsyscall_aix_ppc64_gccgo.go
|
|
||||||
err = ioutil.WriteFile("zsyscall_aix_ppc64_gccgo.go",
|
|
||||||
[]byte(fmt.Sprintf(srcTemplate3, cmdLine(), buildTags(), pack, cExtern, imp, textgccgo)),
|
|
||||||
0644)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate1 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
||||||
const srcTemplate2 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
// +build !gccgo
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
type syscallFunc uintptr
|
|
||||||
|
|
||||||
var (
|
|
||||||
%s
|
|
||||||
)
|
|
||||||
|
|
||||||
// Implemented in runtime/syscall_aix.go.
|
|
||||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
|
||||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
||||||
const srcTemplate3 = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
// +build gccgo
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
%s
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%s
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
335
vendor/golang.org/x/sys/unix/mksyscall_solaris.go
generated
vendored
@ -1,335 +0,0 @@
|
|||||||
// Copyright 2019 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
/*
|
|
||||||
This program reads a file containing function prototypes
|
|
||||||
(like syscall_solaris.go) and generates system call bodies.
|
|
||||||
The prototypes are marked by lines beginning with "//sys"
|
|
||||||
and read like func declarations if //sys is replaced by func, but:
|
|
||||||
* The parameter lists must give a name for each argument.
|
|
||||||
This includes return parameters.
|
|
||||||
* The parameter lists must give a type for each argument:
|
|
||||||
the (x, y, z int) shorthand is not allowed.
|
|
||||||
* If the return parameter is an error number, it must be named err.
|
|
||||||
* If go func name needs to be different than its libc name,
|
|
||||||
* or the function is not in libc, name could be specified
|
|
||||||
* at the end, after "=" sign, like
|
|
||||||
//sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
b32 = flag.Bool("b32", false, "32bit big-endian")
|
|
||||||
l32 = flag.Bool("l32", false, "32bit little-endian")
|
|
||||||
tags = flag.String("tags", "", "build tags")
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksyscall_solaris.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return *tags
|
|
||||||
}
|
|
||||||
|
|
||||||
// Param is function parameter
|
|
||||||
type Param struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// usage prints the program usage
|
|
||||||
func usage() {
|
|
||||||
fmt.Fprintf(os.Stderr, "usage: go run mksyscall_solaris.go [-b32 | -l32] [-tags x,y] [file ...]\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParamList parses parameter list and returns a slice of parameters
|
|
||||||
func parseParamList(list string) []string {
|
|
||||||
list = strings.TrimSpace(list)
|
|
||||||
if list == "" {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return regexp.MustCompile(`\s*,\s*`).Split(list, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseParam splits a parameter into name and type
|
|
||||||
func parseParam(p string) Param {
|
|
||||||
ps := regexp.MustCompile(`^(\S*) (\S*)$`).FindStringSubmatch(p)
|
|
||||||
if ps == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "malformed parameter: %s\n", p)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return Param{ps[1], ps[2]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Usage = usage
|
|
||||||
flag.Parse()
|
|
||||||
if len(flag.Args()) <= 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "no files to parse provided\n")
|
|
||||||
usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
endianness := ""
|
|
||||||
if *b32 {
|
|
||||||
endianness = "big-endian"
|
|
||||||
} else if *l32 {
|
|
||||||
endianness = "little-endian"
|
|
||||||
}
|
|
||||||
|
|
||||||
pack := ""
|
|
||||||
text := ""
|
|
||||||
dynimports := ""
|
|
||||||
linknames := ""
|
|
||||||
var vars []string
|
|
||||||
for _, path := range flag.Args() {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(file)
|
|
||||||
for s.Scan() {
|
|
||||||
t := s.Text()
|
|
||||||
t = strings.TrimSpace(t)
|
|
||||||
t = regexp.MustCompile(`\s+`).ReplaceAllString(t, ` `)
|
|
||||||
if p := regexp.MustCompile(`^package (\S+)$`).FindStringSubmatch(t); p != nil && pack == "" {
|
|
||||||
pack = p[1]
|
|
||||||
}
|
|
||||||
nonblock := regexp.MustCompile(`^\/\/sysnb `).FindStringSubmatch(t)
|
|
||||||
if regexp.MustCompile(`^\/\/sys `).FindStringSubmatch(t) == nil && nonblock == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line must be of the form
|
|
||||||
// func Open(path string, mode int, perm int) (fd int, err error)
|
|
||||||
// Split into name, in params, out params.
|
|
||||||
f := regexp.MustCompile(`^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$`).FindStringSubmatch(t)
|
|
||||||
if f == nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s:%s\nmalformed //sys declaration\n", path, t)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
funct, inps, outps, modname, sysname := f[2], f[3], f[4], f[5], f[6]
|
|
||||||
|
|
||||||
// Split argument lists on comma.
|
|
||||||
in := parseParamList(inps)
|
|
||||||
out := parseParamList(outps)
|
|
||||||
|
|
||||||
inps = strings.Join(in, ", ")
|
|
||||||
outps = strings.Join(out, ", ")
|
|
||||||
|
|
||||||
// Try in vain to keep people from editing this file.
|
|
||||||
// The theory is that they jump into the middle of the file
|
|
||||||
// without reading the header.
|
|
||||||
text += "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n"
|
|
||||||
|
|
||||||
// So file name.
|
|
||||||
if modname == "" {
|
|
||||||
modname = "libc"
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call name.
|
|
||||||
if sysname == "" {
|
|
||||||
sysname = funct
|
|
||||||
}
|
|
||||||
|
|
||||||
// System call pointer variable name.
|
|
||||||
sysvarname := fmt.Sprintf("proc%s", sysname)
|
|
||||||
|
|
||||||
strconvfunc := "BytePtrFromString"
|
|
||||||
strconvtype := "*byte"
|
|
||||||
|
|
||||||
sysname = strings.ToLower(sysname) // All libc functions are lowercase.
|
|
||||||
|
|
||||||
// Runtime import of function to allow cross-platform builds.
|
|
||||||
dynimports += fmt.Sprintf("//go:cgo_import_dynamic libc_%s %s \"%s.so\"\n", sysname, sysname, modname)
|
|
||||||
// Link symbol to proc address variable.
|
|
||||||
linknames += fmt.Sprintf("//go:linkname %s libc_%s\n", sysvarname, sysname)
|
|
||||||
// Library proc address variable.
|
|
||||||
vars = append(vars, sysvarname)
|
|
||||||
|
|
||||||
// Go function header.
|
|
||||||
outlist := strings.Join(out, ", ")
|
|
||||||
if outlist != "" {
|
|
||||||
outlist = fmt.Sprintf(" (%s)", outlist)
|
|
||||||
}
|
|
||||||
if text != "" {
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
text += fmt.Sprintf("func %s(%s)%s {\n", funct, strings.Join(in, ", "), outlist)
|
|
||||||
|
|
||||||
// Check if err return available
|
|
||||||
errvar := ""
|
|
||||||
for _, param := range out {
|
|
||||||
p := parseParam(param)
|
|
||||||
if p.Type == "error" {
|
|
||||||
errvar = p.Name
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare arguments to Syscall.
|
|
||||||
var args []string
|
|
||||||
n := 0
|
|
||||||
for _, param := range in {
|
|
||||||
p := parseParam(param)
|
|
||||||
if regexp.MustCompile(`^\*`).FindStringSubmatch(p.Type) != nil {
|
|
||||||
args = append(args, "uintptr(unsafe.Pointer("+p.Name+"))")
|
|
||||||
} else if p.Type == "string" && errvar != "" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
text += fmt.Sprintf("\t_p%d, %s = %s(%s)\n", n, errvar, strconvfunc, p.Name)
|
|
||||||
text += fmt.Sprintf("\tif %s != nil {\n\t\treturn\n\t}\n", errvar)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "string" {
|
|
||||||
fmt.Fprintf(os.Stderr, path+":"+funct+" uses string arguments, but has no error return\n")
|
|
||||||
text += fmt.Sprintf("\tvar _p%d %s\n", n, strconvtype)
|
|
||||||
text += fmt.Sprintf("\t_p%d, _ = %s(%s)\n", n, strconvfunc, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n))
|
|
||||||
n++
|
|
||||||
} else if s := regexp.MustCompile(`^\[\](.*)`).FindStringSubmatch(p.Type); s != nil {
|
|
||||||
// Convert slice into pointer, length.
|
|
||||||
// Have to be careful not to take address of &a[0] if len == 0:
|
|
||||||
// pass nil in that case.
|
|
||||||
text += fmt.Sprintf("\tvar _p%d *%s\n", n, s[1])
|
|
||||||
text += fmt.Sprintf("\tif len(%s) > 0 {\n\t\t_p%d = &%s[0]\n\t}\n", p.Name, n, p.Name)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(unsafe.Pointer(_p%d))", n), fmt.Sprintf("uintptr(len(%s))", p.Name))
|
|
||||||
n++
|
|
||||||
} else if p.Type == "int64" && endianness != "" {
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s>>32)", p.Name), fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name), fmt.Sprintf("uintptr(%s>>32)", p.Name))
|
|
||||||
}
|
|
||||||
} else if p.Type == "bool" {
|
|
||||||
text += fmt.Sprintf("\tvar _p%d uint32\n", n)
|
|
||||||
text += fmt.Sprintf("\tif %s {\n\t\t_p%d = 1\n\t} else {\n\t\t_p%d = 0\n\t}\n", p.Name, n, n)
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(_p%d)", n))
|
|
||||||
n++
|
|
||||||
} else {
|
|
||||||
args = append(args, fmt.Sprintf("uintptr(%s)", p.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nargs := len(args)
|
|
||||||
|
|
||||||
// Determine which form to use; pad args with zeros.
|
|
||||||
asm := "sysvicall6"
|
|
||||||
if nonblock != nil {
|
|
||||||
asm = "rawSysvicall6"
|
|
||||||
}
|
|
||||||
if len(args) <= 6 {
|
|
||||||
for len(args) < 6 {
|
|
||||||
args = append(args, "0")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: too many arguments to system call\n", path)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actual call.
|
|
||||||
arglist := strings.Join(args, ", ")
|
|
||||||
call := fmt.Sprintf("%s(uintptr(unsafe.Pointer(&%s)), %d, %s)", asm, sysvarname, nargs, arglist)
|
|
||||||
|
|
||||||
// Assign return values.
|
|
||||||
body := ""
|
|
||||||
ret := []string{"_", "_", "_"}
|
|
||||||
doErrno := false
|
|
||||||
for i := 0; i < len(out); i++ {
|
|
||||||
p := parseParam(out[i])
|
|
||||||
reg := ""
|
|
||||||
if p.Name == "err" {
|
|
||||||
reg = "e1"
|
|
||||||
ret[2] = reg
|
|
||||||
doErrno = true
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i] = reg
|
|
||||||
}
|
|
||||||
if p.Type == "bool" {
|
|
||||||
reg = fmt.Sprintf("%d != 0", reg)
|
|
||||||
}
|
|
||||||
if p.Type == "int64" && endianness != "" {
|
|
||||||
// 64-bit number in r1:r0 or r0:r1.
|
|
||||||
if i+2 > len(out) {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: not enough registers for int64 return\n", path)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if endianness == "big-endian" {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i, i+1)
|
|
||||||
} else {
|
|
||||||
reg = fmt.Sprintf("int64(r%d)<<32 | int64(r%d)", i+1, i)
|
|
||||||
}
|
|
||||||
ret[i] = fmt.Sprintf("r%d", i)
|
|
||||||
ret[i+1] = fmt.Sprintf("r%d", i+1)
|
|
||||||
}
|
|
||||||
if reg != "e1" {
|
|
||||||
body += fmt.Sprintf("\t%s = %s(%s)\n", p.Name, p.Type, reg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ret[0] == "_" && ret[1] == "_" && ret[2] == "_" {
|
|
||||||
text += fmt.Sprintf("\t%s\n", call)
|
|
||||||
} else {
|
|
||||||
text += fmt.Sprintf("\t%s, %s, %s := %s\n", ret[0], ret[1], ret[2], call)
|
|
||||||
}
|
|
||||||
text += body
|
|
||||||
|
|
||||||
if doErrno {
|
|
||||||
text += "\tif e1 != 0 {\n"
|
|
||||||
text += "\t\terr = e1\n"
|
|
||||||
text += "\t}\n"
|
|
||||||
}
|
|
||||||
text += "\treturn\n"
|
|
||||||
text += "}\n"
|
|
||||||
}
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
file.Close()
|
|
||||||
}
|
|
||||||
imp := ""
|
|
||||||
if pack != "unix" {
|
|
||||||
imp = "import \"golang.org/x/sys/unix\"\n"
|
|
||||||
|
|
||||||
}
|
|
||||||
vardecls := "\t" + strings.Join(vars, ",\n\t")
|
|
||||||
vardecls += " syscallFunc"
|
|
||||||
fmt.Printf(srcTemplate, cmdLine(), buildTags(), pack, imp, dynimports, linknames, vardecls, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const srcTemplate = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package %s
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
%s
|
|
||||||
var (
|
|
||||||
%s
|
|
||||||
)
|
|
||||||
|
|
||||||
%s
|
|
||||||
`
|
|
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
190
vendor/golang.org/x/sys/unix/mksysnum.go
generated
vendored
@ -1,190 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
// Generate system call table for DragonFly, NetBSD,
|
|
||||||
// FreeBSD, OpenBSD or Darwin from master list
|
|
||||||
// (for example, /usr/src/sys/kern/syscalls.master or
|
|
||||||
// sys/syscall.h).
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
goos, goarch string
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmdLine returns this programs's commandline arguments
|
|
||||||
func cmdLine() string {
|
|
||||||
return "go run mksysnum.go " + strings.Join(os.Args[1:], " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildTags returns build tags
|
|
||||||
func buildTags() string {
|
|
||||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkErr(err error) {
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// source string and substring slice for regexp
|
|
||||||
type re struct {
|
|
||||||
str string // source string
|
|
||||||
sub []string // matched sub-string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match performs regular expression match
|
|
||||||
func (r *re) Match(exp string) bool {
|
|
||||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
|
|
||||||
if r.sub != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetchFile fetches a text file from URL
|
|
||||||
func fetchFile(URL string) io.Reader {
|
|
||||||
resp, err := http.Get(URL)
|
|
||||||
checkErr(err)
|
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
checkErr(err)
|
|
||||||
return strings.NewReader(string(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
// readFile reads a text file from path
|
|
||||||
func readFile(path string) io.Reader {
|
|
||||||
file, err := os.Open(os.Args[1])
|
|
||||||
checkErr(err)
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
func format(name, num, proto string) string {
|
|
||||||
name = strings.ToUpper(name)
|
|
||||||
// There are multiple entries for enosys and nosys, so comment them out.
|
|
||||||
nm := re{str: name}
|
|
||||||
if nm.Match(`^SYS_E?NOSYS$`) {
|
|
||||||
name = fmt.Sprintf("// %s", name)
|
|
||||||
}
|
|
||||||
if name == `SYS_SYS_EXIT` {
|
|
||||||
name = `SYS_EXIT`
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Get the OS (using GOOS_TARGET if it exist)
|
|
||||||
goos = os.Getenv("GOOS_TARGET")
|
|
||||||
if goos == "" {
|
|
||||||
goos = os.Getenv("GOOS")
|
|
||||||
}
|
|
||||||
// Get the architecture (using GOARCH_TARGET if it exists)
|
|
||||||
goarch = os.Getenv("GOARCH_TARGET")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = os.Getenv("GOARCH")
|
|
||||||
}
|
|
||||||
// Check if GOOS and GOARCH environment variables are defined
|
|
||||||
if goarch == "" || goos == "" {
|
|
||||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
file := strings.TrimSpace(os.Args[1])
|
|
||||||
var syscalls io.Reader
|
|
||||||
if strings.HasPrefix(file, "https://") || strings.HasPrefix(file, "http://") {
|
|
||||||
// Download syscalls.master file
|
|
||||||
syscalls = fetchFile(file)
|
|
||||||
} else {
|
|
||||||
syscalls = readFile(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
var text, line string
|
|
||||||
s := bufio.NewScanner(syscalls)
|
|
||||||
for s.Scan() {
|
|
||||||
t := re{str: line}
|
|
||||||
if t.Match(`^(.*)\\$`) {
|
|
||||||
// Handle continuation
|
|
||||||
line = t.sub[1]
|
|
||||||
line += strings.TrimLeft(s.Text(), " \t")
|
|
||||||
} else {
|
|
||||||
// New line
|
|
||||||
line = s.Text()
|
|
||||||
}
|
|
||||||
t = re{str: line}
|
|
||||||
if t.Match(`\\$`) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t = re{str: line}
|
|
||||||
|
|
||||||
switch goos {
|
|
||||||
case "dragonfly":
|
|
||||||
if t.Match(`^([0-9]+)\s+STD\s+({ \S+\s+(\w+).*)$`) {
|
|
||||||
num, proto := t.sub[1], t.sub[2]
|
|
||||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
|
||||||
text += format(name, num, proto)
|
|
||||||
}
|
|
||||||
case "freebsd":
|
|
||||||
if t.Match(`^([0-9]+)\s+\S+\s+(?:NO)?STD\s+({ \S+\s+(\w+).*)$`) {
|
|
||||||
num, proto := t.sub[1], t.sub[2]
|
|
||||||
name := fmt.Sprintf("SYS_%s", t.sub[3])
|
|
||||||
text += format(name, num, proto)
|
|
||||||
}
|
|
||||||
case "openbsd":
|
|
||||||
if t.Match(`^([0-9]+)\s+STD\s+(NOLOCK\s+)?({ \S+\s+\*?(\w+).*)$`) {
|
|
||||||
num, proto, name := t.sub[1], t.sub[3], t.sub[4]
|
|
||||||
text += format(name, num, proto)
|
|
||||||
}
|
|
||||||
case "netbsd":
|
|
||||||
if t.Match(`^([0-9]+)\s+((STD)|(NOERR))\s+(RUMP\s+)?({\s+\S+\s*\*?\s*\|(\S+)\|(\S*)\|(\w+).*\s+})(\s+(\S+))?$`) {
|
|
||||||
num, proto, compat := t.sub[1], t.sub[6], t.sub[8]
|
|
||||||
name := t.sub[7] + "_" + t.sub[9]
|
|
||||||
if t.sub[11] != "" {
|
|
||||||
name = t.sub[7] + "_" + t.sub[11]
|
|
||||||
}
|
|
||||||
name = strings.ToUpper(name)
|
|
||||||
if compat == "" || compat == "13" || compat == "30" || compat == "50" {
|
|
||||||
text += fmt.Sprintf(" %s = %s; // %s\n", name, num, proto)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "darwin":
|
|
||||||
if t.Match(`^#define\s+SYS_(\w+)\s+([0-9]+)`) {
|
|
||||||
name, num := t.sub[1], t.sub[2]
|
|
||||||
name = strings.ToUpper(name)
|
|
||||||
text += fmt.Sprintf(" SYS_%s = %s;\n", name, num)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(os.Stderr, "unrecognized GOOS=%s\n", goos)
|
|
||||||
os.Exit(1)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err := s.Err()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
fmt.Printf(template, cmdLine(), buildTags(), text)
|
|
||||||
}
|
|
||||||
|
|
||||||
const template = `// %s
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build %s
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
const(
|
|
||||||
%s)`
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user